7 月 28 日,Model Context Protocol 发布了自协议诞生以来最大的一次修订版本 2026-07-28。这次把协议的核心通信模型从"有状态的双向长连接"彻底改造成了"无状态的请求/响应"模型。TypeScript、Python、Go、C# 四个 Tier 1 SDK 同步发布,Rust SDK 也进入 beta。
对于那些实际在给企业客户接入 MCP Server 的人来说,这次升级几乎影响到服务端架构的每一个决策点:要不要用负载均衡、Session 怎么管、网关怎么路由、鉴权怎么加固。这篇文章按照六个维度,逐一拆解升级前后客户端和服务端的实现差异。
升级前
MCP 规范强制要求一次 initialize / initialized 握手,服务端在握手后生成一个 Mcp-Session-Id,后续所有请求都必须携带这个 Session ID 才能被正确处理。这意味着:
升级后
initialize/initialized 握手和 Mcp-Session-Id 被正式移除。每一个请求都是自描述的——协议版本、客户端身份、客户端能力全部塞进请求的 _meta 字段里,不再依赖服务端记住"你是谁"。如果客户端确实想提前拿到服务端能力列表,可以调用新增的 server/discover RPC,但这是可选的,不再是强制前置步骤。
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"}}}}
服务端不再持有会话,任意请求可以被路由到集群里的任意一台实例,普通的轮询负载均衡就能用。
如果业务确实需要跨调用的状态怎么办?
规范给出的建议方式是"显式 handle"模式:服务端在某次工具调用的返回值里生成一个类似 basket_id 的句柄,模型看到这个句柄后,会在后续调用里把它当作普通参数传回来。相比藏在传输层里的隐式 Session,这种方式的好处是模型能"看见"状态、可以主动决定要不要携带、方便调试。
对做企业身份对接的场景来说,这意味着像 SAML/OAuth 授权码这类中间状态,以后要显式建模成工具入参,而不是指望协议层帮你兜底。
升级前
请求的实际操作(调用哪个工具、哪个方法)完全埋在 JSON-RPC 的请求体里。网关、WAF、限流器如果想按"调用了哪个工具"做路由或计费,必须解析并理解 JSON-RPC 负载,这对纯四层/七层网络设备很不友好。
升级后
Streamable HTTP 请求现在必须携带 Mcp-Method 和 Mcp-Name 两个 HTTP Header,分别对应方法名和工具/资源名。网关、限流器可以直接基于 Header 做路由、鉴权、计费,完全不用碰 JSON 内容。
同时,tools/list、prompts/list、resources/list、resources/read 的返回结果新增了 ttlMs 和 cacheScope 字段,客户端可以据此判断工具目录能缓存多久、缓存范围是什么,减少不必要的重复拉取。
这是这次升级里最能体现"无状态"设计哲学的一个新机制。
升级前
服务端如果需要中途向客户端要东西——比如让用户确认一个操作(elicitation)、请求模型帮忙生成一段内容(sampling)、或者拉取客户端的 roots 列表——走的是服务端主动发起的 elicitation/create、sampling/createMessage、roots/list 请求,这要求底层必须有一条常驻打开的 SSE 流,双向通信,状态和连接强绑定。
升级后
Multi Round-Trip Requests(MRTR)把这套"服务端反向调用"改造成了纯粹的请求/响应重试模式:服务端在需要用户输入时,直接在原始调用的返回里给出 resultType: "input_required",并附上需要回答的问题;客户端拿到答案后,用同一个原始调用、把答案塞进 inputResponses 字段重新发起请求。整个过程不需要保持连接常开,天然契合无状态架构。
对做 Secure Link 这类"外部用户临时访问确认"场景的同学来说,MRTR 基本就是给"二次确认"这类交互提供了协议层的官方模式,不用再自己拿 WebSocket 或 SSE 攒一套。
升级前
长任务(Tasks)一直是实验性功能,挂在协议核心里,状态更新走的是老式的 HTTP GET 轮询端点,语义比较模糊。
升级后
Tasks 被正式移出协议核心,归入 io.modelcontextprotocol/tasks 扩展,新增基于轮询的 tasks/get 和用于状态更新的 tasks/update。变更通知也统一收敛到一个新的 subscriptions/listen 流,客户端按通知类型自主订阅,而不是被动接收全部推送。
与此同时,MCP Apps(交互式服务端渲染界面)和 Enterprise Managed Authorization(EMA,企业托管鉴权)也一起被正式纳入这套扩展框架。换句话说,协议核心变薄了,能力通过"扩展"挂载,后续增加新能力不必再动核心规范。
这部分是这次升级里工程上最"硬核"的部分,几乎每一条都对应一个真实的攻击面:
iss 参数,客户端在兑换 code 前必须校验它,堵住了"授权服务器混淆攻击"(authorization-server mix-up)这个洞。application_type 显式声明:客户端在动态注册(DCR)时声明自己是 native 还是 web 应用,授权服务器就不会再把桌面端/CLI 客户端的 localhost 回调当成可疑请求拒绝掉——这解释了不少人踩过的"CLI 客户端 OAuth 流程莫名 redirect_uri 报错"的坑。这几条基本是把过去一年企业客户在 SSO/OAuth 集成里踩过的坑,一次性在协议层做了修补。
官方给出了明确的十二个月最低窗口期的正式弃用政策,这次进入弃用名单的包括:
如果你的 MCP Server 现在还依赖 sampling(让服务端反向调用客户端模型生成内容),需要提前规划迁移到 MRTR 或其他等价方案。
| 维度 | 升级前 | 升级后 |
|---|---|---|
| 连接模型 | 有状态,握手 + Session ID | 无状态,每请求自描述 |
| 跨调用状态 | 隐式 Session | 显式 handle 参数 |
| 路由依据 | 解析 JSON-RPC Body | Mcp-Method / Mcp-Name Header |
| 列表缓存 | 无标准机制 | ttlMs + cacheScope |
| 服务端反向请求 | 常驻双向流(elicitation/sampling/roots) | MRTR:input_required + 重试 |
| 扩展能力 | Tasks 实验性,混在核心里 | Tasks/MCP Apps/EMA 归入正式扩展框架 |
| 鉴权安全 | 无 issuer 校验,DCR 为主 | RFC 9207 issuer 校验 + CIMD |
| 弃用功能 | — | Roots、Sampling、Logging、legacy HTTP+SSE(12 个月窗口) |
这次升级的底层逻辑其实和 Anthropic 自家 Messages API 的设计如出一辙:把状态从服务端搬到"线"上,用带宽换运维简单性。对正在做企业级 MCP Server 部署、或者已经在生产环境里用负载均衡撑 MCP 流量的团队来说,这是值得立刻评估迁移成本的一次大版本升级。
参考:
No comments yet. Be the first!