Files
mock-server/docs/mcp-implementation.md
CNWei cfcebbe300 feat(mcp): 实现HTTP统一方案并添加MCP文档
- 将MCP服务和Mock API合并到单个HTTP服务器(8080端口)
- 添加POST /mcp端点,使用无状态StreamableHttpService
- 新增docs/mcp-implementation.md文档
2026-03-29 22:30:29 +08:00

12 KiB
Raw Permalink Blame History

rmcp 0.11 MCP Server 实现指南

本文档详细介绍了如何使用 rmcp 0.11 实现 MCP Server包括核心概念、关键代码模式和常见陷阱。

目录


核心概念

rmcp 简介

rmcp 是 Rust 官方的 MCP SDK提供了实现 MCP (Model Context Protocol) 服务器和客户端的完整工具链。

MCP 协议

MCP (Model Context Protocol) 是一个开放协议,用于连接 AI 助手与外部系统。它定义了一套标准化的接口,允许 AI 模型:

  • Tools: 调用外部工具/函数
  • Resources: 访问外部资源
  • Prompts: 使用预定义的提示模板

依赖配置

# 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 块上:

#[tool_router]
impl MockMcpServer {
    // tool 方法...
}

2. tool_router: ToolRouter<Self> 字段

在结构体中必须包含此字段:

#[derive(Clone)]
pub struct MockMcpServer {
    manager: Arc<MockManager>,
    tool_router: ToolRouter<Self>,  // 必需字段
}

3. #[tool_handler]

放在 ServerHandler trait 实现块上:

#[tool_handler]
impl ServerHandler for MockMcpServer {
    fn get_info(&self) -> ServerInfo {
        // ...
    }
}

重要: 缺少 #[tool_handler] 会导致 tools/list 返回空数组 {"tools": []}


完整代码示例

结构体定义

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<MockManager>,
    tool_router: ToolRouter<Self>,  // 必需字段
}

请求参数结构体

/// 使用 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<String>,
}

Tool 方法实现

#[tool_router]
impl MockMcpServer {
    pub fn new(manager: Arc<MockManager>) -> Self {
        Self {
            manager,
            tool_router: Self::tool_router(),  // 初始化 tool_router
        }
    }

    /// 无参数 tool
    #[tool(description = "List all groups (directories)")]
    async fn list_groups(&self) -> Result<CallToolResult, McpError> {
        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<T> 包装器
    #[tool(description = "Get a specific mock rule by group and name")]
    async fn get_mock_rule(
        &self,
        params: Parameters<GetRuleRequest>,
    ) -> Result<CallToolResult, McpError> {
        match self.manager.get(&params.0.group, &params.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<ListRulesRequest>,
    ) -> Result<CallToolResult, McpError> {
        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 实现

#[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]

解决方案:

// 错误 - 缺少宏
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

解决方案:

// 错误
ServerInfo {
capabilities: ServerCapabilities::default (),
...
}

// 正确
ServerInfo {
capabilities: ServerCapabilities::builder()
.enable_tools()
.build(),
...
}

3. 使用 #[tool(aggr)]

症状: 编译错误

原因: rmcp 0.11 不支持 aggr 参数

解决方案:

// 错误 - rmcp 0.11 不支持
#[tool(aggr)]
async fn my_tool(&self, params: MyRequest) -> Result<...>

// 正确 - 使用 Parameters<T> 包装器
#[tool(description = "...")]
async fn my_tool(&self, params: Parameters<MyRequest>) -> Result<...>

4. 使用 #[tool(tool_box)]

症状: 编译错误

原因: rmcp 0.11 使用不同的宏名称

解决方案:

// 错误
#[tool(tool_box)]
impl MockMcpServer { ... }

// 正确
#[tool_router]
impl MockMcpServer { ... }

HTTP 传输配置

StreamableHttpService 无状态模式

适用于简单的 HTTP 集成,无需维护会话状态:

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<MockManager>,
) -> StreamableHttpService<MockMcpServer, NeverSessionManager> {
    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 集成

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<Duration> SSE 连接保活间隔
stateful_mode bool 是否维护会话状态
cancellation_token CancellationToken 用于优雅关闭

客户端配置

Claude Code 配置

在 Claude Code 的 settings.json 中添加:

{
  "mcpServers": {
    "mock-server": {
      "type": "http",
      "url": "http://127.0.0.1:8080/mcp"
    }
  }
}

Claude Desktop 配置

在 Claude Desktop 的配置文件中添加:

{
  "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>           │
│                                                             │
│   ┌─────────────────┐    ┌─────────────────────────────┐   │
│   │   MockMcpServer │    │     NeverSessionManager     │   │
│   │                 │    │     (无状态)                 │   │
│   │ - tool_router   │    │                             │   │
│   │ - manager       │    │                             │   │
│   └─────────────────┘    └─────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────────┐
│                    MockManager (Arc)                        │
│                                                             │
│   共享于 HTTP MCP 端点和 Mock API handler                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

参考资源