# rmcp 0.11 MCP Server 实现指南 本文档详细介绍了如何使用 rmcp 0.11 实现 MCP Server,包括核心概念、关键代码模式和常见陷阱。 ## 目录 - [核心概念](#核心概念) - [Tool 注册三要素](#tool-注册三要素) - [完整代码示例](#完整代码示例) - [常见错误和解决方案](#常见错误和解决方案) - [HTTP 传输配置](#http-传输配置) - [客户端配置](#客户端配置) --- ## 核心概念 ### rmcp 简介 rmcp 是 Rust 官方的 MCP SDK,提供了实现 MCP (Model Context Protocol) 服务器和客户端的完整工具链。 ### MCP 协议 MCP (Model Context Protocol) 是一个开放协议,用于连接 AI 助手与外部系统。它定义了一套标准化的接口,允许 AI 模型: - **Tools**: 调用外部工具/函数 - **Resources**: 访问外部资源 - **Prompts**: 使用预定义的提示模板 ### 依赖配置 ```toml # Cargo.toml [dependencies] rmcp = { version = "0.11", features = ["server", "transport-streamable-http-server", "transport-streamable-http-server-session"] } schemars = "1.0" tokio-util = { version = "0.7", features = ["io"] } ``` --- ## Tool 注册三要素 要使 MCP tools 在 rmcp 0.11 中正常工作,**必须**同时具备以下三个要素: ### 1. `#[tool_router]` 宏 放在包含 tool 方法的 impl 块上: ```rust #[tool_router] impl MockMcpServer { // tool 方法... } ``` ### 2. `tool_router: ToolRouter` 字段 在结构体中必须包含此字段: ```rust #[derive(Clone)] pub struct MockMcpServer { manager: Arc, tool_router: ToolRouter, // 必需字段 } ``` ### 3. `#[tool_handler]` 宏 放在 `ServerHandler` trait 实现块上: ```rust #[tool_handler] impl ServerHandler for MockMcpServer { fn get_info(&self) -> ServerInfo { // ... } } ``` > **重要**: 缺少 `#[tool_handler]` 会导致 `tools/list` 返回空数组 `{"tools": []}`! --- ## 完整代码示例 ### 结构体定义 ```rust use std::sync::Arc; use rmcp::{ handler::server::tool::ToolRouter, handler::server::wrapper::Parameters, model::*, tool, tool_handler, tool_router, ErrorData as McpError, ServerHandler, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; /// MCP Server for Mock Server management #[derive(Clone)] pub struct MockMcpServer { manager: Arc, tool_router: ToolRouter, // 必需字段 } ``` ### 请求参数结构体 ```rust /// 使用 schemars 和 serde 自动生成 JSON Schema #[derive(Debug, Deserialize, Serialize, JsonSchema)] pub struct GetRuleRequest { #[schemars(description = "Group name (directory name)")] pub group: String, #[schemars(description = "Rule name")] pub name: String, } #[derive(Debug, Deserialize, Serialize, JsonSchema)] pub struct ListRulesRequest { #[schemars(description = "Optional group name to filter by")] pub group: Option, } ``` ### Tool 方法实现 ```rust #[tool_router] impl MockMcpServer { pub fn new(manager: Arc) -> Self { Self { manager, tool_router: Self::tool_router(), // 初始化 tool_router } } /// 无参数 tool #[tool(description = "List all groups (directories)")] async fn list_groups(&self) -> Result { let groups = self.manager.list_groups(); let result = serde_json::to_string_pretty(&groups) .map_err(|e| McpError::internal_error(e.to_string(), None))?; Ok(CallToolResult::success(vec![Content::text(result)])) } /// 带参数 tool - 使用 Parameters 包装器 #[tool(description = "Get a specific mock rule by group and name")] async fn get_mock_rule( &self, params: Parameters, ) -> Result { match self.manager.get(¶ms.0.group, ¶ms.0.name) { Some(rule) => { let result = serde_json::to_string_pretty(&rule) .map_err(|e| McpError::internal_error(e.to_string(), None))?; Ok(CallToolResult::success(vec![Content::text(result)])) } None => Ok(CallToolResult::error(vec![Content::text( format!("Rule not found: {}/{}", params.0.group, params.0.name), )])), } } /// 可选参数 #[tool(description = "List all mock rules, optionally filtered by group")] async fn list_mock_rules( &self, params: Parameters, ) -> Result { let rules = self.manager.list(params.0.group.as_deref()); let result = serde_json::to_string_pretty(&rules) .map_err(|e| McpError::internal_error(e.to_string(), None))?; Ok(CallToolResult::success(vec![Content::text(result)])) } } ``` ### ServerHandler 实现 ```rust #[tool_handler] // 关键宏! impl ServerHandler for MockMcpServer { fn get_info(&self) -> ServerInfo { ServerInfo { capabilities: ServerCapabilities::builder() .enable_tools() // 必须启用 tools 能力 .build(), instructions: Some("Mock Server MCP - Manage mock API rules.".to_string()), ..Default::default() } } } ``` --- ## 常见错误和解决方案 ### 1. Missing `#[tool_handler]` **症状**: `tools/list` 返回空数组 `{"tools": []}` **原因**: 没有在 `ServerHandler` impl 块上添加 `#[tool_handler]` 宏 **解决方案**: ```rust // 错误 - 缺少宏 impl ServerHandler for MockMcpServer { fn get_info(&self) -> ServerInfo { ... } } // 正确 #[tool_handler] impl ServerHandler for MockMcpServer { fn get_info(&self) -> ServerInfo { ... } } ``` ### 2. Missing `enable_tools()` **症状**: Tools 不被广播,客户端无法发现 tools **原因**: `ServerCapabilities` 没有启用 tools **解决方案**: ```rust // 错误 ServerInfo { capabilities: ServerCapabilities::default (), ... } // 正确 ServerInfo { capabilities: ServerCapabilities::builder() .enable_tools() .build(), ... } ``` ### 3. 使用 `#[tool(aggr)]` **症状**: 编译错误 **原因**: rmcp 0.11 不支持 `aggr` 参数 **解决方案**: ```rust // 错误 - rmcp 0.11 不支持 #[tool(aggr)] async fn my_tool(&self, params: MyRequest) -> Result<...> // 正确 - 使用 Parameters 包装器 #[tool(description = "...")] async fn my_tool(&self, params: Parameters) -> Result<...> ``` ### 4. 使用 `#[tool(tool_box)]` **症状**: 编译错误 **原因**: rmcp 0.11 使用不同的宏名称 **解决方案**: ```rust // 错误 #[tool(tool_box)] impl MockMcpServer { ... } // 正确 #[tool_router] impl MockMcpServer { ... } ``` --- ## HTTP 传输配置 ### StreamableHttpService 无状态模式 适用于简单的 HTTP 集成,无需维护会话状态: ```rust use rmcp::transport::streamable_http_server::{ StreamableHttpService, StreamableHttpServerConfig, session::never::NeverSessionManager, }; use tokio_util::sync::CancellationToken; /// 创建无状态 MCP HTTP 服务 pub fn create_mcp_http_service( manager: Arc, ) -> StreamableHttpService { StreamableHttpService::new( // 每次请求创建新的 server 实例 move || Ok(MockMcpServer::new(manager.clone())), // 无状态会话管理器 Arc::new(NeverSessionManager::default()), StreamableHttpServerConfig { sse_keep_alive: None, // SSE 保活配置(可选) stateful_mode: false, // 无状态模式 cancellation_token: CancellationToken::new(), }, ) } ``` ### 与 Axum 集成 ```rust use axum::{ routing::post, Router, body::Body, http::Request, }; let mcp_service = create_mcp_http_service(manager); let app = Router::new() .route("/mcp", post({ let service = mcp_service.clone(); move | req: Request < Body > | { let service = service.clone(); async move { service.handle(req).await } } })); ``` ### 配置选项说明 | 选项 | 类型 | 说明 | |----------------------|---------------------|------------| | `sse_keep_alive` | `Option` | SSE 连接保活间隔 | | `stateful_mode` | `bool` | 是否维护会话状态 | | `cancellation_token` | `CancellationToken` | 用于优雅关闭 | --- ## 客户端配置 ### Claude Code 配置 在 Claude Code 的 `settings.json` 中添加: ```json { "mcpServers": { "mock-server": { "type": "http", "url": "http://127.0.0.1:8080/mcp" } } } ``` ### Claude Desktop 配置 在 Claude Desktop 的配置文件中添加: ```json { "mcpServers": { "mock-server": { "url": "http://127.0.0.1:8080/mcp" } } } ``` --- ## 架构说明 ``` ┌─────────────────────────────────────────────────────────────┐ │ HTTP Server (Axum) │ │ Port 8080 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ POST /mcp │ /* (fallback) │ │ ├─ tools/list │ Mock API endpoints │ │ ├─ tools/call │ │ │ └─ other MCP methods │ │ │ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ StreamableHttpService │ │ │ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │ │ MockMcpServer │ │ NeverSessionManager │ │ │ │ │ │ (无状态) │ │ │ │ - tool_router │ │ │ │ │ │ - manager │ │ │ │ │ └─────────────────┘ └─────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ MockManager (Arc) │ │ │ │ 共享于 HTTP MCP 端点和 Mock API handler │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 参考资源 - [rmcp GitHub Repository](https://github.com/anthropics/rmcp) - [MCP Specification](https://spec.modelcontextprotocol.io/) - [schemars Documentation](https://docs.rs/schemars/)