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

428 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<Self>` 字段
在结构体中必须包含此字段:
```rust
#[derive(Clone)]
pub struct MockMcpServer {
manager: Arc<MockManager>,
tool_router: ToolRouter<Self>, // 必需字段
}
```
### 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<MockManager>,
tool_router: ToolRouter<Self>, // 必需字段
}
```
### 请求参数结构体
```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<String>,
}
```
### Tool 方法实现
```rust
#[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 实现
```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<T> 包装器
#[tool(description = "...")]
async fn my_tool(&self, params: Parameters<MyRequest>) -> 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<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 集成
```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<Duration>` | 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> │
│ │
│ ┌─────────────────┐ ┌─────────────────────────────┐ │
│ │ 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/)