2026 年 7 月 28 日,Model Context Protocol 发布第五个规范版本。改动最大的一条是:协议层的 session 没了。
这不是一次加特性的小版本。传输层重做,握手删除,三个老特性进入弃用倒计时。Anthropic 同日发了 Claude 侧的公告,说支持会陆续上线,但没给日期。
一、被拆掉的:initialize 握手和 Mcp-Session-Id
旧模型的流程是:客户端 POST 一个 initialize,服务端铸一个 Mcp-Session-Id 返回,之后每个请求都带这个 header。服务端在内存里保存这段会话的协议版本、客户端能力、订阅状态。
生产环境里的后果很具体。多副本部署时,第一个请求经负载均衡打到 Pod A,A 在本地内存记下会话并返回 session ID;下一个请求打到 Pod B,B 完全不认识这个 ID,返回 404,而且没有任何有用的诊断信息。
绕过方式只有两种:负载均衡开 sticky session(牺牲弹性伸缩和滚动发布),或者把会话状态外置到 Redis(多一套要运维的组件)。New Relic 那篇文章的说法是——一个用来简化 AI 集成的协议,悄悄变成了基础设施更复杂的理由。
新规范把 initialize / notifications/initialized 握手和 Mcp-Session-Id header 一起删掉。每个请求自带上下文,放在 _meta 里:
io.modelcontextprotocol/protocolVersion— 协议版本io.modelcontextprotocol/clientCapabilities— 客户端能力io.modelcontextprotocol/clientInfo— 客户端身份(SHOULD)
服务端也 SHOULD 在每个结果的 _meta 里回 io.modelcontextprotocol/serverInfo。版本对不上返回 UnsupportedProtocolVersionError。
一个请求现在长这样:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"},
"_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}
结果是任何请求可以落在任何实例上。轮询负载均衡、自动扩缩容、Serverless 容器、跨区域部署——这些原本需要额外适配的部署形态,现在默认就能跑,不用预置会话存储,也不用在发版时排空连接。
代价写在明面上:能力协商信息从「每会话一次」变成「每请求一次」,payload 会变大一点。
顺带删掉的还有 ping、logging/setLevel、notifications/roots/list_changed。日志级别改成按请求在 _meta 里带 io.modelcontextprotocol/logLevel,并且服务端 MUST NOT 对没带这个字段的请求发 notifications/message。
二、server/discover:版本协商的新入口
握手没了,版本协商还得有。新规范加了 server/discover,服务端 MUST 实现,用来声明自己支持的协议版本、能力和身份。
客户端 MAY 在其他任何请求之前调它做前置版本选择,也可以在 STDIO 上把它当作向后兼容探测——老服务器不认识这个方法,客户端据此回退。
它和 initialize 的本质区别:initialize 建立一段有状态会话,server/discover 只是一次可缓存的元数据查询。
三、头部路由:Mcp-Method 和 Mcp-Name
Streamable HTTP 的 POST 请求现在必须带两个标准头:
Mcp-Method—tools/call、resources/read、prompts/get之类Mcp-Name— 具体的工具名或资源名
受益方不是应用代码,是中间层。网关、WAF、API 管理平台不用解 JSON-RPC body 就知道这个请求要干什么,于是可以做按工具限流、把不同资源路由到不同后端、在边缘层做授权判断。
同一个 SEP 还加了 x-mcp-header,允许把工具参数映射成自定义 HTTP 头。头部和 body 对不上会返回 HeaderMismatchError。
四、MRTR:服务端不再回头找客户端
旧协议里,服务端处理一次工具调用的中途可以反过来向客户端发请求:sampling/createMessage 要一次 LLM 补全,elicitation/create 问用户一个问题,roots/list 查客户端暴露了哪些目录。这套东西需要一条双向的、开着的流。
新规范用 Multi Round-Trip Requests(MRTR)替代:服务端返回一个 InputRequiredResult(resultType: "input_required"),inputRequests 字段说明还需要什么信息,同时带一个不透明的 requestState。客户端把答案放进 inputResponses,重新发起原来那个请求。
配套改动是所有 result 现在都有必填的 resultType 字段,取值 "complete" 或 "input_required"。老服务器返回的结果没有这个字段,客户端 MUST 当作 "complete" 处理。
notifications/elicitation/complete 和 URL 模式 elicitation 的 elicitationId 一起被删——客户端重试原请求就能拿到结果,服务端主动通知这条路不再需要;要跨重试关联同一次交互,服务端自己在 requestState 里编码标识。
五、真需要跨调用状态怎么办
无状态是协议层的事,不是应用层的。浏览器会话、文件编辑上下文这类跨调用状态照样存在,只是换了承载方式:服务端在工具返回值里给出一个自己铸造的 handle,Agent 在后续调用里把它当普通参数传回来。
副作用比性能更值得说。状态从传输层的隐式会话变成了 payload 里的显式参数:对模型可见,在日志里可审计,出问题时能直接从请求体看出当时的上下文是什么。
六、订阅收敛成一条 subscriptions/listen
HTTP GET 端点和 resources/subscribe / resources/unsubscribe 被替换成单一的 subscriptions/listen——一条长连的 POST 响应流,客户端按类型显式 opt-in:toolsListChanged、promptsListChanged、resourcesListChanged、resourceSubscriptions。服务端确认订阅,并给推送的通知打上 io.modelcontextprotocol/subscriptionId。
请求作用域的通知(notifications/progress、notifications/message)不走这条流,仍然走它们所属请求的响应流。
同时被删的是 SSE 的断流恢复:Last-Event-ID header 和 SSE event ID 都没了。响应流断了就是断了,在途请求丢失,客户端 MUST 用新的 request ID 重发。这是无状态的直接后果——恢复重放要求服务端记住发过什么,而这正是要拆掉的东西。
七、list 结果可以缓存了
tools/list、prompts/list、resources/list、resources/read、resources/templates/list 的返回值现在必须带两个字段(新的 CacheableResult 接口):
ttlMs— 新鲜度提示,毫秒cacheScope—"public"或"private",控制共享中间层能不能缓存
这两个字段和已有的 listChanged 通知互补,不是替代关系。
规范另外建议 tools/list 以确定性顺序返回工具。理由不是洁癖:工具列表进的是 LLM 的 prompt,顺序不稳定会打掉 prompt cache 命中率。
这几条和协议层去 session 是同一个方向——list 端点不再随连接变化,所以才可能缓存。
八、三个扩展转正
新规范立了正式的扩展框架,ClientCapabilities 和 ServerCapabilities 加了 extensions 字段。三个扩展从实验状态转正:
Tasks(io.modelcontextprotocol/tasks):从核心协议挪进扩展。tools/call 可以返回 task handle 而不是立即结果,客户端用 tasks/get 轮询、tasks/update 回传输入、tasks/cancel 取消。阻塞式的 tasks/result 被移除,tasks/list 也删了;服务端现在可以不经每请求 opt-in 就主动返回 task handle。适用场景是文件处理、代码生成、批处理这类长任务——过程中不用挂着一条 socket。
MCP Apps:服务端下发交互式 HTML 界面,在沙箱 iframe 里渲染。工具需要提前声明 UI 模板供 host 做安全审查,所有用户操作仍走标准 JSON-RPC 路径,因此可审计。
Enterprise Managed Authorization:组织侧集中管理 MCP 服务器访问,基于 Identity Assertion JWT Authorization Grants,带完整审计链路。
九、授权收紧
- 授权服务器 SHOULD 在授权响应里带
iss参数(RFC 9207),客户端 MUST 在兑换 authorization code 之前校验它与记录的 issuer 一致 - 客户端动态注册时 MUST 指定合适的
application_type,避免 OIDC 的 redirect URI 冲突(桌面 / CLI 应用的 localhost 回调) - 客户端凭据绑定到签发它的授权服务器:MUST 按 issuer 标识存储,MUST NOT 跨授权服务器复用,授权服务器变了必须重新注册
- OAuth 2.0 动态客户端注册(RFC 7591)被弃用,改用 Client ID Metadata Documents(CIMD);DCR 仅作为对不支持 CIMD 的授权服务器的兼容手段保留
十、可观测性交给 OpenTelemetry
Logging 特性被弃用,建议的迁移路径是 stdio 场景写 stderr,其余场景用 OpenTelemetry。规范同时把 OTel 的 trace context 传播写成 _meta 的约定键:traceparent、tracestate、baggage(W3C Trace Context)。
实际意义在于打通链路。MCP 原来那套私有日志通道是孤岛,一次工具调用失败没法和应用其他部分对上,只能手工交叉比对时间戳。改用 W3C Trace Context 之后,Agent 发起调用 → MCP 服务器 → 外部 API → 数据库,这一串在任何 OTel 后端里是一条完整的 trace。
不过规范做的是「弃用私有 Logging,并把 OTel 传播写成 _meta 约定」,而不是把 OTel 定为强制替代品。New Relic 的文章把这一步描述为迁移到 OpenTelemetry,方向没错,落到规范条文上的强度要温和一些。
十一、弃用清单和时间窗
规范这次确立了特性生命周期政策:Active / Deprecated / Removed 三态,弃用窗口最少 12 个月,并维护一份弃用特性登记表。
当前处于 Deprecated 状态的:
| 特性 | 建议替代 |
|---|---|
| Roots | 用工具参数、resource URI 或服务端配置传目录 |
| Sampling | 直接对接 LLM 提供商 API |
| Logging | stdio 写 stderr,或用 OpenTelemetry |
| HTTP+SSE 传输 | Streamable HTTP |
| OAuth 2.0 DCR(RFC 7591) | Client ID Metadata Documents |
includeContext 的 "thisServer" / "allServers" |
省略该字段或用 "none" |
还有一组错误码调整。resource not found 从 -32002 改成 -32602(Invalid Params,向 JSON-RPC 对齐);服务端错误码区间做了划分,-32000-32019 留给实现自定义(现有 SDK 用法沿用),-32020-32099 归规范所有。本版新增的几个跟着重编号:HeaderMismatch -32001→-32020,MissingRequiredClientCapability -32003→-32021,UnsupportedProtocolVersion -32004→-32022。
十二、代价
The Register 的报道里,MCP 共同作者 David Soria Parra 的说法是:自己写了实现的人,「要做到正确会有相当大的工作量」。底层传输机制是整个重做的。
另一句更值得记:协议现在「线上传的东西比以前复杂了一点」。无状态不等于更简单——状态没有消失,只是从服务端内存挪到了每一个请求的 body 里。这是设计哲学的取舍,不是纯粹的简化。
兼容性上,Stacklok 的企业就绪指南提醒:新旧要通,得双方共享一个受支持的协议世代,或者其中一方主动做回退和翻译。新版服务端不会自动兼容老客户端,反之亦然。这一点在企业部署里比在个人项目里麻烦得多。
弃用窗口是「最少 12 个月」,不是确定的日期。这个措辞给了规范方灵活性,也给使用方留下了不确定性。
十三、Claude 那边的进度
Anthropic 在 7 月 28 日同步发了 Claude 侧公告,口径是支持会在 Claude 产品线陆续上线,没有给具体日期,也没有说明 Claude.ai / Claude Code / API / Agent SDK / Desktop 各自的时间表和向后兼容策略。
Tier 1 SDK 已经跟上:TypeScript、Python、Go、C# 支持 2026-07-28,Rust 是 beta。
生态数字:MCP 月度 SDK 下载量超过 4 亿次,年内增长 4 倍;Claude 的连接器目录收录了 950+ MCP 服务器;公开提到的生态伙伴包括 Figma、Intuit、Netlify、PostHog、Xero、Zoom。
该做什么
只跑本地 stdio 的:影响有限。无状态主要针对负载均衡后面的远程服务器,本地工具和桌面集成本来就没有这个问题。但 Roots / Sampling / Logging 的弃用同样适用,12 个月窗口从现在开始算。
有远程服务器、且用了 sticky session 或 Redis 存会话的:这次收益最大,那套外置状态可以准备拆掉。改造成本也最大——传输层是重写的。
自己实现协议而没有用官方 SDK 的:按 Parra 的说法工作量不小,优先考虑迁到 Tier 1 SDK。
用了 sampling / elicitation / roots 的:三条路都要改。sampling 直接调 LLM API,elicitation 走 MRTR,roots 改成工具参数或 resource URI。
所有人:把 _meta 里的 traceparent 接进现有 OTel 链路。成本低,收益是终于能看到一条完整的调用链,而不是一堆对不上的日志片段。
参考:
- MCP is going stateless — New Relic
- The 2026-07-28 Specification — MCP Blog
- 规范变更日志 — modelcontextprotocol.io
- Bringing MCP 2026-07-28 to Claude — Anthropic
- Model Context Protocol prepares to break with its stateful past — The Register
关于
关注我获取更多资讯