一旦请求必须返回创建会话的原实例,服务端就要承担会话黏性的全部代价:sticky session、共享 session store,以及实例故障后的上下文丢失。MCP 的远程调用此前也受此约束。
在旧版 Streamable HTTP 里,客户端先发送 initialize,服务端返回 Mcp-Session-Id,后续每次工具调用都要携带这个 ID。一次普通的 tools/call,因此依赖于创建会话的实例。
MCP 2026-07-28 规范删掉了这套握手与协议 session。协议版本、客户端信息与能力改为随请求携带,任何实例都能独立处理每次调用。
这项变更的核心,是将 MCP 的部署模型从会话绑定改为单次请求自包含。
无状态不是没有状态
购物篮、浏览器页面和长任务都包含业务状态。无状态架构要求这些状态不依赖连接,也不驻留于单个实例的内存中。
新版 MCP 的做法与普通后端服务一致:工具创建购物篮后返回 basket_id,创建浏览器环境后返回 browser_id,下一次调用把 handle 作为普通参数传回。handle 由工具返回,也作为入参传回,和普通字符串、数字参数没有区别。
变化不在于把全部状态塞进 ID,而是把状态的引用纳入工具契约。过去由传输层维护的 session 对模型不可见,也无法被网关直接识别;现在模型会在步骤之间传递 handle,服务端可以把实际状态放进签名 handle 或外部存储,并设置有效期、权限和租户边界。日志也能明确记录一次操作作用于哪个资源。
我用两个不共享内存的 Node 实例做了最小实验:create_basket 由实例 A 执行,携带 basket_id 的 add_item 由实例 B 执行;终止实例 A 后,实例 B 仍可读取购物篮中的 book。这只是架构模拟,不是 SDK 兼容性测试或性能测试。实验表明,业务状态的延续不依赖同一服务实例持续存活。

调整后,业务状态仍然存在,但传输层不再依赖特定实例。
部署模型的工程收益
横向扩容方面,请求不再依赖创建 session 的实例,可以直接采用 round-robin 负载均衡,无需 sticky session 或共享 session store。
故障恢复方面,实例处理中断后,客户端携带同一个 handle 重试,另一台实例继续处理。需要用户确认的多轮调用也不再长期占用 SSE 连接;服务端返回 requestState,客户端拿到答案后重新发起请求。
可运营性方面,新规范要求使用 Mcp-Method 和 Mcp-Name 头,网关无需解析 JSON 正文就能按工具路由、限流。tools/list 等结果增加了缓存语义,W3C Trace Context 也能把一次工具调用串进完整链路。
路由、缓存和追踪都是成熟的服务端能力,协议 session 却增加了这些机制的实现复杂度。
从 Session 到 Handle 的迁移
第一,盘点 session 中记录的内容。协议版本和客户端信息可以随请求携带,浏览器、事务、长任务等真实业务状态则要显式建模。
第二,把真实状态改成不透明 handle。handle 必须绑定用户或租户,设置 TTL,每次调用重新鉴权。显式 handle 仍需满足安全约束;可猜测的 browser_id 可能导致越权访问。
第三,执行跨实例重放测试。将连续两次调用分配到不同实例,终止第一个实例后重试;流程仍能完成,才能确认请求不再依赖协议 session。
第四,补齐网关与观测。检查路由头、缓存范围和 trace 是否贯通;仅删除内存中的 session map,不能据此判定迁移完成。
业务状态仍然存在,但归属已经改变:协议 session 不再代管状态,业务层必须显式负责。这套原则在服务端工程中早已成熟。MCP 将其纳入协议设计,意味着 Agent 工具连接开始具备基础设施所需的部署与运维条件。
