MCP协议新版(v5)深度解析:最大变化(无状态)、版本差异对照表与架构解读(含图)、聚焦无状态和安全重构
MCP 2026-07-28 发布第五版规范,协议内核从有状态改为无状态。本文逐项对照新旧变化,梳理架构影响与迁移路径。
一、协议变更概述
MCP(Model Context Protocol)在 2026-07-28 发布了第五版规范。这是自 2024 年 11 月协议问世以来幅度最大的一次修订——协议内核从有状态改为无状态。
MCP 最初的设计场景是桌面应用。Claude Desktop 启动一个本地 MCP 服务器进程,通过 stdio 通信,一个进程对应一个会话,生命周期明确。有状态设计在桌面场景下是合理的——握手后拿到 Session-Id,后续请求携带即可。
随着 MCP 采用量快速增长——月 SDK 下载量突破 4 亿次 [1],社区贡献了 950+ 个 MCP 服务器 [1]——服务从桌面端走向云端、从单进程走向集群时,有状态设计的局限性开始显现。
有状态协议在远程生产环境中有三个主要问题:
- 粘滞会话:客户端必须持续连接到同一个服务端实例,负载均衡器需要维护 session affinity,无法使用普通轮询负载均衡,也无法部署在 Serverless 和边缘计算架构上。
- 水平扩展受限:新增实例不持有已有会话,要么迁移会话,要么维护共享状态存储。
- 滚动发布与故障转移影响进行中会话:旧实例下线意味着所有会话中断。
2025-03-26 引入的 Streamable HTTP 传输在有状态框架下做了补丁——保留了 initialize 握手和 Mcp-Session-Id。2026-07-28 版本彻底改变了这一设计。
二、新旧对照视图
2.1 核心变更对照
| 变更项 | 旧版 | 新版 | 影响 |
|---|---|---|---|
| 会话管理 | initialize 握手 + Mcp-Session-Id | 无状态,请求头自描述 | 可水平扩展,支持普通轮询负载均衡 |
| 能力发现 | initialize 响应协商 | server/discover 方法 | 服务端必须实现新端点 |
| 请求头 | 无标准化请求头 | Mcp-Method(必需)、Mcp-Name(条件必需) | 网关层可直接路由,无需解析请求体 |
| 缓存 | 无 | ttlMs + cacheScope | 列表结果可客户端缓存 |
| Roots | 支持资源根注册 | 进入 12 个月弃用窗口 | 需迁移至工具参数或资源 URI |
| Sampling | 服务端可请求模型采样 | 进入 12 个月弃用窗口 | 改为服务端直接接入模型 API |
| Logging | 服务端日志通道 | 进入 12 个月弃用窗口 | 改用 OpenTelemetry 或 stderr |
| HTTP 传输 | HTTP GET + SSE 流 | 仅 Streamable HTTP | 旧 SSE 传输须迁移 |
| 多轮交互 | 依赖长连接 | MRTR(多轮往返请求) | 连接中断后任意实例可接手 |
2.2 请求流程对比
旧版流程:
Client → Server: initialize (protocolVersion, capabilities, clientInfo)
Server → Client: initialize (protocolVersion, capabilities, serverInfo, …)
Client → Server: notifications/initialized
— 此后所有请求携带 Mcp-Session-Id —
→ 负载均衡器必须维护 session affinity
→ 会话丢失 = 所有工具状态丢失
新版流程:
Client → Server: server/discover (查询服务端能力和版本)
Client → Server: 独立请求(每个请求自包含协议版本与能力信息)
→ 普通轮询负载均衡
→ 支持 Serverless 和边缘部署
新版中每个请求自描述,携带完整的协议信息:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search",
"arguments": {"q": "stateless MCP"},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
}
2.3 能力发现:server/discover
新版中服务端必须实现 server/discover 方法,客户端在首次连接时通过它查询服务端支持的协议版本、能力和身份,取代了旧版的 initialize 握手。
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: server/discover
{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover"
}
服务端返回:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2026-07-28",
"capabilities": {
"tools": {},
"resources": {},
"prompts": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
2.4 请求头与缓存
Mcp-Method 是所有 Streamable HTTP 请求的必需请求头。tools/call、resources/read 和 prompts/get 还必须携带 Mcp-Name。这两个字段让网关不解析 JSON 请求体即可识别请求意图,按工具配置速率限制、路由和审计策略。服务端必须校验请求头与 JSON-RPC 请求体的一致性,不一致时拒绝请求。
tools/list、resources/list 等列表操作的响应结果新增了 ttlMs 和 cacheScope 字段,客户端据此判断结果缓存时长和跨用户共享范围,减少重复查询。
三、状态管理:从会话到句柄
无状态化之后,业务状态怎么存,是每个 MCP 服务器开发者需要重新思考的问题。
3.1 句柄模式的设计逻辑
旧版协议中,状态通过 Session-Id 隐式关联到服务端会话。服务端在内存中维护一个会话上下文,客户端只要带上 Session-Id,服务端就知道"这个请求属于哪个会话"。但这个上下文对模型是透明的——模型只知道要发请求,不知道也不关心传输层维护了什么状态。
新版的做法是把状态推到业务层:工具调用返回一个显式句柄,模型在后续调用中将其作为参数传回。服务端可以把句柄对应的状态存在任何地方——数据库、对象存储、Durable Object——协议只负责传递一个标识符。
一个典型的交互流程如下:
// 工具返回句柄
{
"tool": "browser_open",
"result": {
"browser_id": "brw_7f31a2c8",
"url": "https://example.com",
"status": "loaded"
}
}
// 后续操作将句柄作为参数
{
"tool": "browser_click",
"arguments": {
"browser_id": "brw_7f31a2c8",
"selector": "#submit-btn"
}
}
3.2 这种设计好在哪
从架构角度看,句柄模式有三个值得注意的优势。
第一,句柄对模型可见。模型可以理解"这个 ID 对应刚才打开的浏览器页面",可以在多个工具之间组合和传递。旧版 Session-Id 对模型不透明,模型无法对其推理,也就无法做出"需要先打开页面再点击"这类跨工具决策。
第二,部署无关。任意服务实例只要能访问共享状态存储,就可以处理任何句柄的请求。这给了开发者选择存储方案的自由——可以用 Redis、PostgreSQL、S3、Durable Objects,取决于业务场景。
第三,语义边界清晰。句柄的作用域、权限和有效期由业务层控制,不由协议层隐式管理。一个句柄在什么条件下有效、由谁生成、可以被哪些工具使用,这些信息都可以在工具定义中明确声明。
3.3 代价
句柄模式也引入了新的复杂性。句柄需要是不可猜测的标识符(如 UUID),不能把数据库主键直接暴露给模型;工具定义需要说明句柄由哪个调用产生、可以传给哪些调用;删除、退款、支付等高风险操作不能只凭句柄授权,仍需验证用户身份;服务端还需要处理幂等——客户端在网络中断后重试时,同一操作不应被执行两次。
这些代价在旧版 Session 机制下同样存在,只是被协议层隐式处理了。新版把这些责任从协议层转移到了业务层,让开发者有了更多控制权,同时也要承担更多管理责任。从协议设计的角度看,这是合理的取舍——MCP 负责描述请求、能力和交互模式,业务状态由应用自己管理。
四、交互模式:从长连接到 MRTR
4.1 长连接的问题
某些工具调用无法一次收齐所有参数。创建云资源前要先展示价格,删除数据前需要用户确认,表单走到中途可能还需要补充字段。
旧版协议依赖长连接维持这些交互状态。服务端保持连接打开,等待客户端下一步输入。这在有状态模式下可以工作,但代价是连接必须持续存在,且始终路由到同一个服务端实例。一旦连接中断,整个交互流程必须从头开始。
4.2 MRTR 的工作原理
新版引入的 MRTR(Multi Round-Trip Requests)改变了这个模式。服务端在需要用户输入时返回 InputRequiredResult,客户端收集输入后重新发送完整请求。
// 服务端返回:需要用户确认
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "input_required",
"inputRequests": {
"confirm": {
"type": "elicitation",
"message": "将删除 3 个文件,是否继续?",
"schema": {"type": "boolean"}
}
},
"requestState": "opaque-server-state"
}
}
// 客户端重发:附带用户确认
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "delete_files",
"arguments": {"paths": ["/tmp/a", "/tmp/b", "/tmp/c"]},
"inputResponses": {
"confirm": true
},
"requestState": "opaque-server-state"
}
}
关键变化在于,任意服务实例都可以接手这次重试。它不需要持有上一次请求的连接,也不需要认识原来的协议会话。每次交互都是一个完整的请求-响应周期,无需持续维护一个长连接流。
MRTR 还给交互增加了一层安全约束:服务端只有在处理客户端请求时才能提出输入要求。客户端不会在没有用户或代理发起动作的情况下,突然收到一个服务端确认框。
五、订阅、可观测性与迁移策略
5.1 订阅机制重构
旧版的 HTTP GET 流、SSE 断点续传、Last-Event-ID 和事件重投递被移除。变更通知合并到 subscriptions/listen,客户端通过长生命周期的 POST 响应流订阅资源变化。
一个可能被忽略的细节是:MCP 移除了跨请求的协议会话,但保留了请求范围内的流式响应和显式订阅流。这意味着响应流可以在单个请求范围内持续推送数据,但不同请求之间不再有隐式的状态关联。这个边界划分很关键——它区分了"一次请求的持续响应"和"多个请求之间的会话关联"。
5.2 可观测性的提升
新版规范统一了 OpenTelemetry Trace Context 在 _meta 中的键名。结合 Mcp-Method 和 Mcp-Name 请求头,网关可以实现完整的调用链追踪。
这些变化没有工具调用本身醒目,但更接近生产团队每天要处理的问题。在旧版中,MCP 请求的追踪和路由因为 session affinity 的存在变得复杂——网关无法直接按工具类型分发请求,观测数据也难以聚合。新版让 MCP 的请求可以像普通 HTTP 服务一样被观测和管理。
5.3 迁移策略
2026-07-28 包含破坏性变更,直接升级会有兼容性问题。建议的迁移路径是分六步执行:
第一步:盘点会话依赖
搜索代码中的 Mcp-Session-Id、initialize、initialized,列出所有按会话保存的数据。
MCP 迁移检查清单 ① — 会话依赖
□ 是否使用了 initialize 握手? → 改为 server/discover
□ 是否依赖 Mcp-Session-Id? → 移除会话状态管理
□ 会话中保存了哪些数据? → 评估哪些需要跨请求保留
第二步:迁移服务端发起请求
MCP 迁移检查清单 ② — 服务端请求
□ 是否使用了 Sampling? → 改为服务端直接接入模型 API
□ 是否使用了 Roots? → 改为工具参数或资源 URI
□ 是否需要用户确认? → 改用 MRTR
□ 是否使用了进度通知? → 仍可通过响应流返回
第三步:改造传输和订阅
MCP 迁移检查清单 ③ — 传输和订阅
□ 是否使用了 HTTP GET + SSE 流? → 迁移到 Streamable HTTP
□ 是否使用了 Last-Event-ID 或事件重投递? → 应用层重试
□ 是否使用了 resources/subscribe? → 改为 subscriptions/listen
□ 是否使用了 ping? → 无需替代
□ 是否使用了 logging/setLevel? → 改为 OpenTelemetry 或 stderr
第四步:补齐网关与安全校验
MCP 迁移检查清单 ④ — 网关和安全
□ 是否为每个 Streamable HTTP POST 添加了 MCP-Protocol-Version 头?
□ 是否为 tools/call 等请求添加了 Mcp-Method 和 Mcp-Name 头?
□ 是否在服务端校验了请求头与请求体的一致性?
□ OAuth 客户端是否验证了 iss 字段?
□ 凭据存储是否按 issuer 分区?
第五步:双版本运行
过渡期内,生产端点最好同时支持 2025-11-25 和 2026-07-28:
MCP 迁移检查清单 ⑤ — 双版本兼容
□ 新客户端能否先调用 server/discover?
□ 遇到只支持旧版的服务端,能否回退到旧握手?
□ 双版本支持是否覆盖了真实客户端、网关和重试场景?
□ 协议兼容是否经过了集成测试?
第六步:流量切换
MCP 迁移检查清单 ⑥ — 切换
□ 是否先部署了无状态端点并观察了错误率?
□ 是否对比了重试率、缓存命中率和 MRTR 完成率?
□ 滚动发布期间是否有失败监控?
□ 旧会话自然排空后,是否移除了旧路由?
□ 是否给仍在使用旧 SDK 的客户端设定了明确的升级期限?
先部署无状态端点观察错误率,待旧会话自然排空后再移除旧路由。
六、SDK 与生态
| SDK 语言 | 状态 | 版本 | 备注 |
|---|---|---|---|
| TypeScript | Tier 1 稳定版 | v2.x | 拆分为 server/client 独立包 |
| Python | Tier 1 稳定版 | v2.x | 同步更新 |
| Go | Tier 1 稳定版 | v1.7.0 | 支持 2026-07-28 |
| C# | Tier 1 稳定版 | v1.0-preview | 同步更新 |
| Rust | 社区稳定版 | rmcp 3.0.0 | 已发布 |
Cloudflare Agents SDK 0.20.0 已支持 2026-07-28 客户端和服务端。Google MCP Toolbox for Databases 已支持候选规范。Figma、Intuit、Netlify、Zoom 等企业已公开支持新规范。
Claude 产品线同步推出 MCP Apps(服务端在对话中渲染交互式 UI)、EMA(企业托管认证,通过 Okta/Entra 统一配置连接器)、MCP Tunnels(研究预览,安全连接内网 MCP 服务器)。
这次改动的价值集中在远程服务的可运维性上。无状态内核让请求可经过普通负载均衡器落到任意实例;显式句柄承载业务状态;MRTR 承载用户确认;subscriptions/listen 承载持续通知;标准请求头、缓存字段和追踪字段服务于网关与观测。
从协议演进的视角看,这是一轮协议边界的重新划分——MCP 负责描述请求、能力和交互模式;业务状态、恢复策略、权限和幂等由应用自己管理。这个边界更清晰,也更适合生产环境。
参考来源:
[1] Anthropic 官方博客:Bringing MCP 2026-07-28 to Claude(2026-07-28) [2]
MCP 2026-07-28 稳定版
Release:https://github.com/modelcontextprotocol/specification/releases/tag/v2026-07-28
[3] MCP
变更日志:https://github.com/modelcontextprotocol/specification/blob/main/CHANGELOG.md
[4] MCP 官方 SDK 分级页:https://modelcontextprotocol.io/sdk [5] 涂阿燃:MCP
2026-07-28 无状态协议如何改变部署、交互与迁移(2026-07-29) [6] Cloudflare Agents SDK
0.20.0 更新说明 [7] Google MCP Toolbox for Databases 公告
更多推荐


所有评论(0)