//! JSON-RPC 2.0 over stdio 协议层 //! //! 职责: //! - 按行读 stdin,解析 JSON-RPC Request/Notification //! - 构造 Response / Error 对象并序列化为单行 JSON 写 stdout //! - MCP 三类方法路由(initialize / tools/list / tools/call)由上层 dispatch //! //! 不解析 batch 请求(MCP 客户端实测逐条发,单条足够)。 //! 错误码遵循 JSON-RPC 2.0 + MCP 自定义段(-32xxx 协议层 / 0xffff 工具层)。 use serde::{Deserialize, Serialize}; use serde_json::Value; // ============================================================ // JSON-RPC 2.0 错误码 // ============================================================ /// 协议层错误(JSON-RPC 2.0 预留段 -32000..-32099) pub const PARSE_ERROR: i32 = -32700; pub const INVALID_REQUEST: i32 = -32600; pub const METHOD_NOT_FOUND: i32 = -32601; pub const INVALID_PARAMS: i32 = -32602; pub const INTERNAL_ERROR: i32 = -32603; // ============================================================ // 请求 / 响应数据结构 // ============================================================ /// JSON-RPC 2.0 请求(请求与通知共用,Notification 时 id=None) #[derive(Debug, Clone, Deserialize)] pub struct Request { pub jsonrpc: Option, pub id: Option, pub method: String, #[serde(default)] pub params: Value, } /// JSON-RPC 2.0 错误对象 #[derive(Debug, Clone, Serialize)] pub struct ErrorObject { pub code: i32, pub message: String, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option, } /// JSON-RPC 2.0 响应 #[derive(Debug, Clone, Serialize)] pub struct Response { pub jsonrpc: &'static str, #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, #[serde(skip_serializing_if = "Option::is_none")] pub result: Option, #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, } impl Response { /// 成功响应 pub fn ok(id: Option, result: Value) -> Self { Self { jsonrpc: "2.0", id, result: Some(result), error: None, } } /// 错误响应 pub fn err(id: Option, code: i32, message: impl Into, data: Option) -> Self { Self { jsonrpc: "2.0", id, result: None, error: Some(ErrorObject { code, message: message.into(), data, }), } } } // ============================================================ // MCP 方法路由 — 暴露给上层 dispatch 的 enum // ============================================================ /// MCP 协议层方法(已剥离 JSON-RPC 包装)。未知方法返回 `Unknown`,由 dispatch 回 METHOD_NOT_FOUND。 #[derive(Debug, Clone)] pub enum McpMethod { /// initialize 握手:返 server info + capabilities Initialize { params: Value }, /// initialized 通知:客户端确认握手完成,无需响应 Initialized, /// tools/list:列出所有工具(MCP Tool schema) ToolsList, /// tools/call:调用某工具 ToolsCall { name: String, arguments: Value }, /// ping 心跳(MCP 2025 规范),回空 result Ping, /// 未识别的方法(回 METHOD_NOT_FOUND) Unknown(String), } impl McpMethod { /// 从 Request 路由出 MCP 语义方法。 pub fn from_request(req: &Request) -> Self { match req.method.as_str() { "initialize" => McpMethod::Initialize { params: req.params.clone() }, "notifications/initialized" => McpMethod::Initialized, "tools/list" => McpMethod::ToolsList, "tools/call" => { let name = req .params .get("name") .and_then(|v| v.as_str()) .unwrap_or("") .to_owned(); let arguments = req.params.get("arguments").cloned().unwrap_or(Value::Null); McpMethod::ToolsCall { name, arguments } } "ping" => McpMethod::Ping, other => McpMethod::Unknown(other.to_owned()), } } } // ============================================================ // MCP 协议数据结构(initialize 握手 / Tool schema / CallToolResult) // ============================================================ /// MCP initialize 握手响应结构(server info + capabilities) #[derive(Debug, Clone, Serialize)] pub struct InitializeResult { #[serde(rename = "protocolVersion")] pub protocol_version: &'static str, pub capabilities: Capabilities, #[serde(rename = "serverInfo")] pub server_info: ServerInfo, } #[derive(Debug, Clone, Serialize)] pub struct Capabilities { pub tools: ToolsCapability, } #[derive(Debug, Clone, Serialize)] pub struct ToolsCapability { #[serde(rename = "listChanged")] pub list_changed: bool, } #[derive(Debug, Clone, Serialize)] pub struct ServerInfo { pub name: &'static str, pub version: &'static str, } /// MCP Tool 描述符(tools/list 返回数组元素) #[derive(Debug, Clone, Serialize)] pub struct Tool { pub name: &'static str, pub description: &'static str, #[serde(rename = "inputSchema")] pub input_schema: Value, } /// MCP tools/call 成功响应(CallToolResult) #[derive(Debug, Clone, Serialize)] pub struct CallToolResult { pub content: Vec, #[serde(rename = "isError", skip_serializing_if = "Option::is_none")] pub is_error: Option, } /// MCP 内容块(本 server 仅用 text) #[derive(Debug, Clone, Serialize)] #[serde(tag = "type", rename_all = "camelCase")] pub enum ContentBlock { Text { text: String }, } impl CallToolResult { /// 文本成功响应 pub fn text(text: impl Into) -> Self { Self { content: vec![ContentBlock::Text { text: text.into() }], is_error: None, } } /// 文本错误响应(is_error=true 让客户端区分「工具业务错」与「协议错」) pub fn error(text: impl Into) -> Self { Self { content: vec![ContentBlock::Text { text: text.into() }], is_error: Some(true), } } }