Files
zesdex/src/app/mcp/manager.rs
T

114 lines
2.7 KiB
Rust
Raw Normal View History

use serde_json::Value;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum McpTransport {
Stdio {
command: String,
args: Vec<String>,
},
StreamableHttp {
url: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpToolInfo {
pub name: String,
pub description: String,
pub input_schema: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpServer {
pub name: String,
pub transport: McpTransport,
pub tools: Vec<McpToolInfo>,
}
impl McpServer {
pub fn new(name: String, transport: McpTransport) -> Self {
McpServer {
name,
transport,
tools: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct McpManager {
pub servers: Vec<McpServer>,
pub running: bool,
}
pub struct McpToolAdapter {
name: &'static str,
description: &'static str,
parameters: serde_json::Value,
}
impl crate::tool::Tool for McpToolAdapter {
fn name(&self) -> &'static str {
self.name
}
fn description(&self) -> &'static str {
self.description
}
fn parameters(&self) -> serde_json::Value {
self.parameters.clone()
}
fn run(&self, _ctx: &crate::tool::ToolCtx, _args: &serde_json::Value) -> anyhow::Result<String> {
Err(anyhow::anyhow!("MCP tool execution not yet implemented"))
}
}
impl McpManager {
pub fn new() -> Self {
McpManager {
servers: Vec::new(),
running: false,
}
}
pub fn add_server(&mut self, server: McpServer) {
self.servers.push(server);
}
pub fn remove_server(&mut self, name: &str) {
self.servers.retain(|s| s.name != name);
}
pub fn get_server(&self, name: &str) -> Option<&McpServer> {
self.servers.iter().find(|s| s.name == name)
}
pub fn all_tools(&self) -> Vec<&McpToolInfo> {
self.servers.iter().flat_map(|s| s.tools.iter()).collect()
}
pub fn start_all(&mut self) -> anyhow::Result<()> {
self.running = true;
Ok(())
}
pub fn stop_all(&mut self) -> anyhow::Result<()> {
self.running = false;
Ok(())
}
pub fn as_tools(&self) -> Vec<Box<dyn crate::tool::Tool>> {
self.all_tools().into_iter().map(|info| {
let name = format!("mcp__{}", info.name);
Box::new(McpToolAdapter {
name: Box::leak(name.into_boxed_str()),
description: Box::leak(info.description.clone().into_boxed_str()),
parameters: info.input_schema.clone(),
}) as Box<dyn crate::tool::Tool>
}).collect()
}
}