了解 MCP 的通信机制

在模型上下文协议(MCP)中,传输层提供了客户端和服务器之间通信的基础。传输层处理消息的发送和接收的底层机制。

消息格式

MCP 使用 JSON-RPC 2.0 作为其传输格式。传输层负责将 MCP 协议消息转换为 JSON-RPC 格式进行传输,并将接收到的 JSON-RPC 消息转换回 MCP 协议消息。

有三种类型的 JSON-RPC 消息:

请求

  1. {
  2. jsonrpc: "2.0",
  3. id: number | string,
  4. method: string,
  5. params?: object
  6. }

响应

  1. {
  2. jsonrpc: "2.0",
  3. id: number | string,
  4. result?: object,
  5. error?: {
  6. code: number,
  7. message: string,
  8. data?: unknown
  9. }
  10. }

通知

  1. {
  2. jsonrpc: "2.0",
  3. method: string,
  4. params?: object
  5. }

内置传输类型

MCP 包含两种标准的传输实现:

标准输入/输出(stdio)

stdio 传输通过标准输入和输出流进行通信。这对于本地集成和命令行工具非常有用。

使用 stdio 时:

  • 构建命令行工具
  • 实现本地集成
  • 需要简单的进程通信
  • 与 shell 脚本协作
  1. const server = new Server({
  2. name: "example-server",
  3. version: "1.0.0"
  4. }, {
  5. capabilities: {}
  6. });
  7. const transport = new StdioServerTransport();
  8. await server.connect(transport);

服务器发送事件(SSE)

SSE 传输通过 HTTP POST 请求为客户端与服务器之间的通信提供流式传输。

使用 SSE 时:

  • 仅需要服务器到客户端的流式传输
  • 在受限网络中工作
  • 实现简单的更新
  1. import express from "express";
  2. const app = express();
  3. const server = new Server({
  4. name: "example-server",
  5. version: "1.0.0"
  6. }, {
  7. capabilities: {}
  8. });
  9. let transport: SSEServerTransport | null = null;
  10. app.get("/sse", (req, res) => {
  11. transport = new SSEServerTransport("/messages", res);
  12. server.connect(transport);
  13. });
  14. app.post("/messages", (req, res) => {
  15. if (transport) {
  16. transport.handlePostMessage(req, res);
  17. }
  18. });
  19. app.listen(3000);

自定义传输

MCP 使得为特定需求实现自定义传输变得非常简单。任何传输实现只需符合传输接口:

你可以为以下内容实现自定义传输:

  • 自定义网络协议
  • 专用通信通道
  • 与现有系统的集成
  • 性能优化
  1. interface Transport {
  2. // 启动消息处理
  3. start(): Promise<void>;
  4. // 发送 JSON-RPC 消息
  5. send(message: JSONRPCMessage): Promise<void>;
  6. // 关闭连接
  7. close(): Promise<void>;
  8. // 回调
  9. onclose?: () => void;
  10. onerror?: (error: Error) => void;
  11. onmessage?: (message: JSONRPCMessage) => void;
  12. }

错误处理

传输实现应处理各种错误场景:

  1. 连接错误
  2. 消息解析错误
  3. 协议错误
  4. 网络超时
  5. 资源清理

示例错误处理:

  1. class ExampleTransport implements Transport {
  2. async start() {
  3. try {
  4. // 连接逻辑
  5. } catch (error) {
  6. this.onerror?.(new Error(`连接失败:${error}`));
  7. throw error;
  8. }
  9. }
  10. async send(message: JSONRPCMessage) {
  11. try {
  12. // 发送逻辑
  13. } catch (error) {
  14. this.onerror?.(new Error(`发送消息失败:${error}`));
  15. throw error;
  16. }
  17. }
  18. }

最佳实践

在实现或使用 MCP 传输时:

  1. 正确处理连接生命周期
  2. 实现适当的错误处理
  3. 在连接关闭时清理资源
  4. 使用适当的超时设置
  5. 发送前验证消息
  6. 日志传输事件以便调试
  7. 在适当情况下实现重连逻辑
  8. 处理消息队列中的背压
  9. 监控连接健康状态
  10. 实现适当的安全措施

安全考虑

在实现传输时:

身份验证与授权

  • 实现适当的身份验证机制
  • 验证客户端凭证
  • 使用安全的令牌处理
  • 实现授权检查

数据安全

  • 使用 TLS 进行网络传输
  • 加密敏感数据
  • 验证消息完整性
  • 实现消息大小限制
  • 清理输入数据

网络安全

  • 实现速率限制
  • 使用适当的超时
  • 处理拒绝服务场景
  • 监控异常模式
  • 实现适当的防火墙规则

调试传输

调试传输问题的技巧:

  1. 启用调试日志
  2. 监控消息流
  3. 检查连接状态
  4. 验证消息格式
  5. 测试错误场景
  6. 使用网络分析工具
  7. 实现健康检查
  8. 监控资源使用情况
  9. 测试边缘案例
  10. 使用适当的错误追踪