MCP 协议深度解析:从 JSON-RPC 到多连接池的生产级实践
MCP 协议深度解析:从 JSON-RPC 到多连接池的生产级实践
一、引言
2024 年 11 月,Anthropic 发布了 Model Context Protocol(MCP)的初始规范。不到两年时间,MCP 已经成为 AI Agent 领域的事实标准工具协议。Cursor、Claude Desktop、Zed、VS Code 等主流 AI 客户端相继接入,GitHub 上的 MCP 服务器数量从几十个增长到数千个。
MCP 解决的是一个本质问题:在 MCP 之前,每个 AI 客户端都要为每个工具单独编写适配代码。一个天气工具如果要在 Claude Desktop、Cursor、Zed 三个平台上使用,需要写三套不同的集成代码。MCP 的出现相当于定义了一个"USB-C 接口"——工具开发者只需要实现一次 MCP 协议,任何支持 MCP 的客户端都可以直接使用。
本文将从协议设计、传输层、生命周期、工程实践四个维度,深入解析 MCP 协议的技术细节,并结合生产级的客户端实现讨论关键设计取舍。
二、协议层:JSON-RPC 2.0 之上
MCP 的所有消息都基于 JSON-RPC 2.0。选择 JSON-RPC 而非 REST 或 gRPC 是一个值得思考的设计决策:REST 的资源模型与 Agent 的"动作调用"语义不匹配,gRPC 的 IDL 虽然严谨但增加了工具动态发现的复杂度。JSON-RPC 在简洁性和灵活性之间取得了平衡。
协议定义了三种消息类型:
- Request:包含
id、method、params,接收方必须回复 - Response:包含与请求相同的
id,以及result或error - Notification:无
id,单向消息,接收方不回复
一个典型的工具调用请求(Request):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search",
"arguments": { "q": "MCP protocol" }
}
}
对应的成功响应(Response):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{ "type": "text", "text": "搜索结果..." }]
}
}
这个协议核心自 2024 年发布以来基本保持稳定。MCP 的演进体现在传输层和生命周期管理上,而非 JSON-RPC 消息格式本身。
三、传输层:两条标准路径
MCP 定义了两个标准传输方式,选择哪个取决于使用场景。
3.1 stdio:本地进程间通信
stdio 传输中,客户端以子进程形式启动 MCP 服务器,通过标准输入/输出进行通信:
- 客户端向服务器
stdin写入 JSON-RPC 消息(以换行符分隔) - 服务器从
stdout输出 JSON-RPC 响应 - 服务器向
stderr输出日志(客户端可捕获或忽略)
这种方式的最大优势是零配置——不需要网络端口、不需要认证、不需要服务发现。用户只需要指定一个命令(如 npx @modelcontextprotocol/server-filesystem),客户端负责进程生命周期管理。这对于本地运行的开发工具(文件系统访问、Git 操作、数据库查询)来说是理想选择。
3.2 Streamable HTTP:远程服务调用
对于远程服务,MCP 在 2025 年 11 月用 Streamable HTTP 替代了早期的 HTTP+SSE 传输。客户端通过 HTTP POST 发送请求,服务器同步返回响应,对于需要流式返回的场景则通过 SSE 通道输出。
Streamable HTTP 支持两种请求模式:
- 同步模式:客户端发送 POST,服务器在同一个 HTTP 响应中返回完整结果
- 流式模式:客户端发送 POST,服务器通过 SSE 持续推送结果
这种设计让简单的工具调用不需要维持持久连接,同时保留了流式输出的能力。
3.3 客户端实现中的传输抽象
一个生产级的 MCP 客户端需要同时支持两种传输。在代码层面,核心设计是将传输抽象为统一的接口:
enum Transport {
Http { url: String, client: HttpClient },
Stdio { process: StdioProcess },
}
不同的传输方式只是消息投递路径的差异,对上层来说是完全透明的。两种传输共享相同的 JSON-RPC 消息格式、相同的方法命名空间、相同的错误处理逻辑。
四、生命周期管理与能力协商
MCP 的生命周期分为三个阶段。
4.1 初始化阶段
在通信开始前,客户端和服务器通过 initialize 请求进行能力协商。客户端声明自己支持的能力集,服务器回复自己支持的能力集。如果双方的能力交集为空,连接将被终止。
能力协商是 MCP 的一个重要设计:协议允许渐进增强。客户端和服务器只需声明自己实际支持的功能,不需要为不使用的功能付出实现成本。例如,一个只提供工具(Tools)的服务器不需要实现资源(Resources)或提示(Prompts)接口。
4.2 操作阶段
初始化完成后进入操作阶段。客户端可以:
- 通过
tools/list获取服务器提供的工具列表 - 通过
tools/call调用具体工具 - 通过
resources/list获取可用资源 - 通过
resources/read读取资源内容
服务器可以主动发送通知(如资源变更通知)。
4.3 终止阶段
客户端或服务器可以随时终止会话。对于 stdio 传输,关闭 stdin 即可触发终止;对于 HTTP 传输,简单关闭网络连接即可。
4.4 2026 年的重要演进
2026 年 7 月,MCP 规范迎来了最大的一次修订。最重要的变化是协议层无状态化——移除了 initialize 握手和 Mcp-Session-Id 会话标识。这意味着:
- 每个请求都携带完整的能力声明和元数据,无需依赖会话状态
- 远程 MCP 服务器可以部署在普通的轮询负载均衡器后面,不需要粘性会话
- 引入
Mcp-Method和Mcp-NameHTTP 头,网关层无需解析 JSON 体即可路由请求 - 工具列表响应可以设置
ttlMs缓存时间,客户端可以缓存tools/list结果
对于服务器需要跨请求维护状态的场景,规范推荐了"显式句柄模式":工具返回一个标识符,模型在后续调用中将该标识符作为参数传回。这使得状态对模型可见,而不是隐藏在服务端的会话存储中——这通常会让模型对多步操作的推理更可靠。
五、生产级客户端的设计要点
一个生产级的 MCP 客户端实现要比协议规范复杂得多。以下是在工程实践中需要关注的设计要点。
5.1 连接管理与健康检查
MCP 客户端需要管理多个服务端连接。一个典型的架构如下:
Hub
├── Server A (连接池: 1~N 个客户端)
│ ├── Client 1
│ └── Client 2 ← 轮询负载均衡
├── Server B (连接池: 1~N 个客户端)
└── Server C ...
每个服务端维护一个连接池,通过轮询(Round-Robin)在多个客户端之间分发请求。后台运行健康检查任务,定期调用 tools/list 验证连接是否可用。当健康检查失败时,触发自动重连:
- 采用指数退避策略(1s → 2s → 4s → 8s → 16s → max 30s)
- 重连成功后重置退避计数器
- 连接状态变化通过事件广播通知上层
5.2 工具注册与命名空间
不同 MCP 服务器可能暴露同名的工具。为了避免命名冲突,在生产中通常引入命名空间前缀:
mcp.filesystem.read_file
mcp.database.query
mcp.github.create_issue
当 MCP 工具注册到 Agent 的工具注册表时,自动添加上 mcp.{server_name}. 前缀,确保全局唯一性。同时保留原始工具名,以便向 MCP 服务器发送调用请求时使用原名称。
5.3 运行时动态管理
生产环境中,MCP 服务器不应该在 Agent 启动时一次性绑定。需要支持运行时的动态管理:
- 添加服务器:随时接入新的 MCP 服务端,无需重启 Agent
- 移除服务器:安全断开某个服务端连接
- 更新配置:变更服务端地址、认证信息等
- 状态订阅:上层 UI 可以通过广播通道实时获取连接状态变更
这种设计让 MCP 更像微服务架构中的服务发现,而不是静态配置的插件系统。
5.4 错误处理
远程 MCP 服务器可能会不可用、超时、返回错误。客户端需要优雅处理这些情况:
- 对临时故障(网络抖动、服务重启),允许自动重连
- 对永久故障(配置错误、认证失败),上报错误状态但不影响其他服务端
- 工具执行失败时,将 MCP 标准错误码映射为 Agent 可理解的错误类型
六、从协议到生态的思考
MCP 从诞生到如今成为事实标准,有几个关键的设计理念值得思考:
“服务器应该极其易构建”。MCP 将复杂性集中在客户端和宿主应用中,服务器只需要实现一个 JSON-RPC 端点。这直接导致了 MCP 服务器数量的爆发式增长——任何能写一个 HTTP 端点的人都能构建 MCP 服务器。
“服务器不应该看到完整对话”。MCP 的设计原则明确要求服务器只收到其所需的最少上下文。这与某些 Agent 框架的"把所有工具调用历史都扔给工具函数"的做法形成鲜明对比,也体现了 MCP 对安全性的重视。
“能力协商而非版本号”。MCP 没有采用传统的 API 版本号策略,而是通过能力协商实现兼容性。这种设计更适合快速演进的 AI 工具生态——客户端和服务器可以各自独立升级,只要声明自己的能力集即可找到交集。
2026 年的无状态化演进进一步降低了 MCP 的运维门槛。远程 MCP 服务器现在可以像普通 HTTP 服务一样部署和扩展,这在一年前还需要粘性会话和共享存储。协议的演进方向表明,MCP 正在从一个"AI 工具协议"向通用的"服务间协作协议"演变——未来的 AI 原生基础设施中,MCP 可能扮演类似 HTTP 在 Web 中的角色。
更多推荐



所有评论(0)