MCP 2026-07-28 把协议核心改成无状态。对维护旧版 MCP 服务的人来说,真正的问题不是“要不要删掉 session”,而是原先由连接、初始化握手和服务端内存暗中维持的约定,现在要由每个请求明确携带。
这次规范不是一次字段微调。变更清单明确删除了 Streamable HTTP 的Mcp-Session-Id、initialize与notifications/initialized握手;协议版本和客户端能力转入每次请求的_meta。如果只把旧字段删掉,服务或许能启动,却可能在能力判断、列表缓存、长任务和通知订阅上留下很难复现的错误。
先画出旧状态藏在哪里
迁移前先别改代码,查一次状态来源。常见的隐式状态有四类:初始化阶段保存的客户端能力、连接级身份、按会话变化的工具列表,以及跨调用任务进度。新版规范给它们安排了不同去处,并非统一改成“不保存”。
协议版本与客户端能力跟随请求。服务端若要声明自己支持哪些版本和能力,应实现强制的server/discover。业务流程确实需要跨调用状态时,由服务端生成显式句柄,再把句柄当作普通工具参数传回。长任务则进入官方 Tasks 扩展,扩展需要双方协商,不能假定所有客户端都会理解任务句柄。
可以先做一张迁移映射:
| 旧实现依赖 | 新版承载方式 | 迁移时要证明的事 |
|---|---|---|
Mcp-Session-Id | 自包含请求或业务句柄 | 任意实例接手请求仍能得到相同结果 |
initialize中的能力 | 每次请求_meta | 中间请求不会误用上一次连接的能力 |
| 连接内可变列表 | 列表不再按连接变化 | 相同身份与参数下列表结果一致 |
| HTTP GET 事件流 | subscriptions/listen | 只收到明确订阅的变更类型 |
| 阻塞式任务取结果 | Tasks 的tasks/get轮询 | 客户端不支持扩展时能明确降级 |
| 服务端主动反向请求 | MRTR 的input_required | 重试时能关联补充输入且不重复副作用 |
这张表是测试范围,不是规范原文提供的部署模板。它的作用是把“删除连接状态”拆成可观察行为。
六组兼容测试不要混在一起跑
第一组测版本协商。分别发送受支持版本、未知版本、缺失版本的请求。新版规定版本不匹配返回UnsupportedProtocolVersionError。还要调用server/discover,核对服务声明与实际处理能力是否一致。STDIO 客户端可把该方法作为兼容性探针,但旧服务不支持它时,客户端也要能识别旧协议,而不是把网络错误当成协议拒绝。
第二组测实例切换。准备两个不共享内存的服务实例,让负载均衡器交替处理同一业务链的请求。若第二步只能在第一步落到同一进程时成功,说明实现仍依赖连接内状态。确需延续上下文时,检查句柄是否由服务端生成、是否有过期和访问边界,以及调用者能否显式携带。
第三组测列表稳定性。规范写明tools/list、resources/list、prompts/list不再按连接变化。用同一个已授权身份从不同实例查询,再比较分页结果、游标与权限过滤。如果列表取决于租户或用户,依赖应来自可验证的授权上下文,不能来自“这条连接之前初始化成谁”。
第四组测通知。2026-07-28 删除旧 HTTP GET 端点以及resources/subscribe、resources/unsubscribe,改用subscriptions/listen的长连接 POST 响应流。测试应确认客户端只订阅所需类型,服务端返回订阅标识,取消连接后能清理资源。notifications/progress等请求级通知仍走对应请求的响应流,不能误塞进全局订阅流。
第五组测需要补充输入的调用。新版用 Multi Round-Trip Requests 取代服务端直接发起roots/list、sampling/createMessage或elicitation/create一类反向请求。服务先返回resultType: "input_required"和inputRequests,客户端补齐后重试原请求。测试重点是幂等:第一次处理已经写入一半时,重试不能再创建一份订单或再发一封邮件。
第六组测日志。logging/setLevel被移除,日志级别改为请求_meta中的io.modelcontextprotocol/logLevel。规范还要求,没有携带该字段的请求,服务端不得为它发出notifications/message。这能测出服务是否仍沿用连接级日志设置,也能避免一个用户提高日志级别后影响后续其他请求。
用故障注入证明“无状态”成立
正常路径通过还不够。可以在请求之间强制重启实例、清空本地内存、改变路由目标,再观察业务句柄、任务查询和订阅恢复是否符合设计。把失败分为三类:协议错误应有明确错误类型;扩展不支持应能降级或拒绝;业务句柄失效应给出可解释的过期结果,不能表现为随机 500。
下面这份验收记录足以支持一次迁移评审:
用例编号: 客户端协议版本与能力: 服务端 discover 声明: 请求落点:实例 A / 实例 B 是否依赖旧 session 或初始化缓存: 是否使用业务句柄,句柄归属与有效期: 扩展协商结果:Apps / Tasks / 无 预期 resultType:complete / input_required / error 实际结果与副作用次数: 故障注入:重启 / 换实例 / 断开订阅 / 重试上线门可以很直接:仍读取Mcp-Session-Id、仍靠initialize缓存能力、跨实例结果不一致,任一项出现就先不要宣称支持新规范。Apps、Tasks 和 Claude 产品中的新版支持正在逐步推出,测试时也应记录实际客户端版本,不能用官方“开始推出”替代本地兼容结果。
官方来源:MCP《2026-07-28 Key Changes》、MCP 2026-07-28 规范首页,以及 Claude 官方文章《Bringing MCP 2026-07-28 to Claude》(2026-07-28)。