Some checks failed
CI / Rust Check (push) Has been cancelled
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
style: 统一代码格式和注释风格 docs: 更新多个功能文档的完整度和状态 feat(runtime): 添加路径验证工具支持 fix(pipeline): 改进条件判断和变量解析逻辑 test(types): 为ID类型添加全面测试用例 chore: 更新依赖项和Cargo.lock文件 perf(mcp): 优化MCP协议传输和错误处理
181 lines
4.9 KiB
Rust
181 lines
4.9 KiB
Rust
//! MCP (Model Context Protocol) support
|
|
//!
|
|
//! Implements MCP client and server for tool/resource integration.
|
|
|
|
use async_trait::async_trait;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use zclaw_types::Result;
|
|
|
|
// Re-export McpServerConfig from mcp_transport
|
|
pub use crate::mcp_transport::McpServerConfig;
|
|
|
|
/// MCP tool definition
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpTool {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub input_schema: serde_json::Value,
|
|
}
|
|
|
|
/// MCP resource definition
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpResource {
|
|
pub uri: String,
|
|
pub name: String,
|
|
pub description: Option<String>,
|
|
pub mime_type: Option<String>,
|
|
}
|
|
|
|
/// MCP prompt definition
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpPrompt {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub arguments: Vec<McpPromptArgument>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpPromptArgument {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub required: bool,
|
|
}
|
|
|
|
/// MCP server info
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpServerInfo {
|
|
pub name: String,
|
|
pub version: String,
|
|
pub protocol_version: String,
|
|
}
|
|
|
|
/// MCP client configuration
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpClientConfig {
|
|
pub server_url: String,
|
|
pub server_info: McpServerInfo,
|
|
pub capabilities: McpCapabilities,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
pub struct McpCapabilities {
|
|
pub tools: Option<McpToolCapabilities>,
|
|
pub resources: Option<McpResourceCapabilities>,
|
|
pub prompts: Option<McpPromptCapabilities>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpToolCapabilities {
|
|
pub list_changed: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpResourceCapabilities {
|
|
pub subscribe: bool,
|
|
pub list_changed: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpPromptCapabilities {
|
|
pub list_changed: bool,
|
|
}
|
|
|
|
/// MCP tool call request
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpToolCallRequest {
|
|
pub name: String,
|
|
pub arguments: HashMap<String, serde_json::Value>,
|
|
}
|
|
|
|
/// MCP tool call response
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpToolCallResponse {
|
|
pub content: Vec<McpContent>,
|
|
pub is_error: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum McpContent {
|
|
Text { text: String },
|
|
Image { data: String, mime_type: String },
|
|
Resource { resource: McpResourceContent },
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct McpResourceContent {
|
|
pub uri: String,
|
|
pub mime_type: Option<String>,
|
|
pub text: Option<String>,
|
|
pub blob: Option<String>,
|
|
}
|
|
|
|
/// MCP Client trait
|
|
#[async_trait]
|
|
pub trait McpClient: Send + Sync {
|
|
/// List available tools
|
|
async fn list_tools(&self) -> Result<Vec<McpTool>>;
|
|
|
|
/// Call a tool
|
|
async fn call_tool(&self, request: McpToolCallRequest) -> Result<McpToolCallResponse>;
|
|
|
|
/// List available resources
|
|
async fn list_resources(&self) -> Result<Vec<McpResource>>;
|
|
|
|
/// Read a resource
|
|
async fn read_resource(&self, uri: &str) -> Result<McpResourceContent>;
|
|
|
|
/// List available prompts
|
|
async fn list_prompts(&self) -> Result<Vec<McpPrompt>>;
|
|
|
|
/// Get a prompt
|
|
async fn get_prompt(&self, name: &str, arguments: HashMap<String, String>) -> Result<String>;
|
|
}
|
|
|
|
/// Basic MCP client implementation using stdio transport
|
|
pub struct BasicMcpClient {
|
|
transport: crate::mcp_transport::McpTransport,
|
|
}
|
|
|
|
impl BasicMcpClient {
|
|
/// Create new MCP client with server configuration
|
|
pub fn new(config: McpServerConfig) -> Self {
|
|
Self {
|
|
transport: crate::mcp_transport::McpTransport::new(config),
|
|
}
|
|
}
|
|
|
|
/// Initialize the MCP connection
|
|
pub async fn initialize(&self) -> Result<()> {
|
|
self.transport.initialize().await
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl McpClient for BasicMcpClient {
|
|
async fn list_tools(&self) -> Result<Vec<McpTool>> {
|
|
McpClient::list_tools(&self.transport).await
|
|
}
|
|
|
|
async fn call_tool(&self, request: McpToolCallRequest) -> Result<McpToolCallResponse> {
|
|
McpClient::call_tool(&self.transport, request).await
|
|
}
|
|
|
|
async fn list_resources(&self) -> Result<Vec<McpResource>> {
|
|
McpClient::list_resources(&self.transport).await
|
|
}
|
|
|
|
async fn read_resource(&self, uri: &str) -> Result<McpResourceContent> {
|
|
McpClient::read_resource(&self.transport, uri).await
|
|
}
|
|
|
|
async fn list_prompts(&self) -> Result<Vec<McpPrompt>> {
|
|
McpClient::list_prompts(&self.transport).await
|
|
}
|
|
|
|
async fn get_prompt(&self, name: &str, arguments: HashMap<String, String>) -> Result<String> {
|
|
McpClient::get_prompt(&self.transport, name, arguments).await
|
|
}
|
|
}
|