主题
MCP 服务器规范
本节包含模型上下文协议 (MCP) 服务器实现的详细规范。
概述
MCP 服务器是提供工具、资源和提示的应用程序。服务器负责:
- 接受客户端连接
- 处理客户端请求
- 提供工具、资源和提示
- 管理会话状态
服务器类型
1. 工具服务器
提供可执行工具的服务器:
- 文件系统工具: 文件读写、目录操作
- 数据库工具: 查询、更新数据库
- API 工具: 调用外部 API
- 计算工具: 数学计算、数据处理
2. 资源服务器
提供数据资源的服务器:
- 文档服务器: 提供文档内容
- 数据服务器: 提供结构化数据
- 媒体服务器: 提供图片、音频、视频
- 配置服务器: 提供配置信息
3. 提示服务器
提供提示模板的服务器:
- 模板服务器: 提供可重用的提示模板
- 工作流服务器: 提供复杂的工作流程
- 助手服务器: 提供专门的助手配置
核心组件
服务器接口
typescript
interface MCPServer {
// 启动服务器
start(): Promise<void>;
// 停止服务器
stop(): Promise<void>;
// 处理客户端连接
handleConnection(transport: Transport): Promise<void>;
// 获取服务器信息
getServerInfo(): ServerInfo;
}
请求处理器
typescript
interface RequestHandler {
// 处理初始化请求
handleInitialize(params: InitializeParams): Promise<InitializeResult>;
// 处理工具相关请求
handleListTools(): Promise<ListToolsResult>;
handleCallTool(params: CallToolParams): Promise<CallToolResult>;
// 处理资源相关请求
handleListResources(): Promise<ListResourcesResult>;
handleReadResource(params: ReadResourceParams): Promise<ReadResourceResult>;
// 处理提示相关请求
handleListPrompts(): Promise<ListPromptsResult>;
handleGetPrompt(params: GetPromptParams): Promise<GetPromptResult>;
}
能力管理
typescript
interface CapabilityManager {
// 声明服务器能力
declareCapabilities(): ServerCapabilities;
// 检查能力支持
supportsCapability(capability: string): boolean;
// 更新能力
updateCapabilities(capabilities: ServerCapabilities): void;
}
实现要求
必需功能
- [x] JSON-RPC 2.0 协议支持
- [x] 初始化握手处理
- [x] 错误响应
- [x] 基本能力声明
推荐功能
- [x] 工具提供
- [x] 资源提供
- [x] 提示提供
- [x] 进度报告
可选功能
- [ ] 流式响应
- [ ] 批量处理
- [ ] 缓存支持
- [ ] 监控指标
规范文档
基础规范
- 服务器架构 - 服务器架构设计
- 初始化流程 - 服务器初始化
- 请求处理 - 请求处理机制
功能规范
- 工具提供 - 工具实现规范
- 资源提供 - 资源实现规范
- 提示提供 - 提示实现规范
高级功能
- 流式处理 - 流式响应实现
- 批量处理 - 批量请求处理
- 缓存机制 - 缓存实现
运维规范
- 监控指标 - 监控和指标
- 日志记录 - 日志记录规范
- 性能优化 - 性能优化指南
实现示例
Python 服务器
python
import asyncio
from mcp import Server, StdioTransport
from mcp.types import Tool, TextContent
# 创建服务器实例
server = Server("my-server")
# 定义工具
@server.tool()
async def calculate(expression: str) -> str:
"""计算数学表达式"""
try:
# 安全的表达式计算
result = eval(expression, {"__builtins__": {}})
return f"结果: {result}"
except Exception as e:
return f"错误: {str(e)}"
@server.tool()
async def get_weather(city: str) -> str:
"""获取天气信息"""
# 模拟天气 API 调用
return f"{city} 的天气: 晴朗,温度 25°C"
# 定义资源
@server.resource("config://settings")
async def get_settings() -> str:
"""获取配置设置"""
return "server_name: my-server\nversion: 1.0.0\ndebug: false"
# 定义提示
@server.prompt()
async def code_review_prompt(language: str, code: str) -> str:
"""代码审查提示"""
return f"""
请审查以下 {language} 代码:
```{language}
{code}
请检查:
- 代码质量
- 潜在问题
- 改进建议 """
async def main(): # 创建传输层 transport = StdioTransport()
# 运行服务器
await server.run(transport)
if name == "main": asyncio.run(main())
### TypeScript 服务器
```typescript
import { Server, StdioTransport } from "@modelcontextprotocol/sdk";
import { Tool, Resource, Prompt } from "@modelcontextprotocol/sdk/types.js";
// 创建服务器
const server = new Server({
name: "my-server",
version: "1.0.0"
});
// 工具处理器
server.setRequestHandler("tools/list", async () => {
return {
tools: [
{
name: "file_read",
description: "读取文件内容",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "文件路径" }
},
required: ["path"]
}
},
{
name: "file_write",
description: "写入文件内容",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "文件路径" },
content: { type: "string", description: "文件内容" }
},
required: ["path", "content"]
}
}
]
};
});
server.setRequestHandler("tools/call", async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "file_read":
try {
const fs = await import("fs/promises");
const content = await fs.readFile(args.path, "utf-8");
return {
content: [{ type: "text", text: content }]
};
} catch (error) {
return {
isError: true,
content: [{
type: "text",
text: `读取文件失败: ${error.message}`
}]
};
}
case "file_write":
try {
const fs = await import("fs/promises");
await fs.writeFile(args.path, args.content, "utf-8");
return {
content: [{
type: "text",
text: `文件已写入: ${args.path}`
}]
};
} catch (error) {
return {
isError: true,
content: [{
type: "text",
text: `写入文件失败: ${error.message}`
}]
};
}
default:
return {
isError: true,
content: [{
type: "text",
text: `未知工具: ${name}`
}]
};
}
});
// 资源处理器
server.setRequestHandler("resources/list", async () => {
return {
resources: [
{
uri: "file://README.md",
name: "项目说明",
description: "项目的 README 文件",
mimeType: "text/markdown"
}
]
};
});
server.setRequestHandler("resources/read", async (request) => {
const { uri } = request.params;
if (uri === "file://README.md") {
try {
const fs = await import("fs/promises");
const content = await fs.readFile("README.md", "utf-8");
return {
contents: [{
uri,
mimeType: "text/markdown",
text: content
}]
};
} catch (error) {
throw new Error(`读取资源失败: ${error.message}`);
}
}
throw new Error(`未知资源: ${uri}`);
});
// 启动服务器
async function main() {
const transport = new StdioTransport();
await server.connect(transport);
console.error("MCP 服务器已启动");
}
main().catch(console.error);
测试指南
单元测试
python
import pytest
from unittest.mock import Mock, AsyncMock
from mcp import Server
@pytest.mark.asyncio
async def test_tool_call():
server = Server("test-server")
@server.tool()
async def test_tool(param: str) -> str:
return f"处理: {param}"
# 模拟工具调用
result = await server.call_tool("test_tool", {"param": "测试"})
assert result.content[0].text == "处理: 测试"
@pytest.mark.asyncio
async def test_resource_read():
server = Server("test-server")
@server.resource("test://resource")
async def test_resource() -> str:
return "测试资源内容"
# 模拟资源读取
result = await server.read_resource("test://resource")
assert result.contents[0].text == "测试资源内容"
集成测试
python
import asyncio
import subprocess
from mcp import Client, StdioTransport
async def test_server_integration():
# 启动服务器进程
server_process = subprocess.Popen([
"python", "-m", "my_server"
])
try:
# 连接到服务器
transport = StdioTransport("python", ["-m", "my_server"])
client = Client("test-client")
await client.connect(transport)
await client.initialize()
# 测试工具列表
tools = await client.list_tools()
assert len(tools.tools) > 0
# 测试工具调用
result = await client.call_tool(
tools.tools[0].name,
{"param": "test"}
)
assert result.content
await client.disconnect()
finally:
server_process.terminate()
server_process.wait()
最佳实践
架构设计
- 模块化: 将功能分解为独立模块
- 可扩展: 支持插件和扩展
- 可配置: 提供灵活的配置选项
- 可测试: 编写全面的测试
性能优化
- 异步处理: 使用异步 I/O
- 连接池: 复用数据库连接
- 缓存策略: 缓存频繁访问的数据
- 资源管理: 及时释放资源
安全考虑
- 输入验证: 验证所有输入参数
- 权限控制: 实施细粒度权限
- 错误处理: 安全的错误响应
- 日志记录: 记录安全相关事件
监控运维
- 健康检查: 实现健康检查端点
- 指标收集: 收集性能指标
- 日志管理: 结构化日志记录
- 告警机制: 设置关键指标告警
部署指南
Docker 部署
dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "-m", "my_server"]
Kubernetes 部署
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server
spec:
replicas: 3
selector:
matchLabels:
app: mcp-server
template:
metadata:
labels:
app: mcp-server
spec:
containers:
- name: mcp-server
image: my-mcp-server:latest
ports:
- containerPort: 8080
env:
- name: MCP_LOG_LEVEL
value: "INFO"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"