MCP 上个月把自己推翻重写了:Session 没了、Sampling 废了------你学的教程还停在 2025
📦 本文属于「AI Agent 全栈实战」系列支线 A 辑。所有工程细节均来自我的真实开源项目: Ticnix/weather-travel-recommend-system ------ 基于气象大数据的出行推荐系统,AI Agent 全栈项目。FastAPI + PostgreSQL(TimescaleDB/pgvector/PostGIS) + Redis;LangGraph + MCP + Skill + RAG,对接 DeepSeek API。
TL;DR :2026 年 7 月 28 日,MCP 发布了史上最大的一次规范改版:整个协议从有状态双向流转向 stateless 请求/响应模型 ------initialize 握手没了(SEP-2575)、Mcp-Session-Id 头删了(SEP-2567);Sampling 和 Roots 两个客户端特性被正式废弃 ;服务端反向请求用户输入重构成了 MRTR (多轮往返请求)。这篇写于改版约两个月后的 9 月底:规范本身没有再出新版(下一代还在 draft),但生态已经跑起来了 ------SDK 全线升 2.x、FastMCP 4 删掉了旧接口、废弃特性有了明确的迁移截止线(2027-07-28)。以及一个诚实的好消息:如果你的服务和我一样只用基础工具调用,大部分改动其实碰不到你。
目录
- 协议为什么要对自己动刀
- Stateless 化:把会话状态塞回每次请求里
- 三项废弃:Roots、Sampling、Logging
- MRTR:把"工具反问人类"变成幂等重放
- Elicitation 双模式:为什么密码绝不能走 Form
- 我的项目要不要动?------逐项对表
- 协议演化的元思考:MCP 在重走 HTTP 的路
- 可复用清单
1. 协议为什么要对自己动刀
先讲清楚动机,不然你会以为规范委员会闲得慌。
MCP 在 2025-06-18 那版之前的架构是有状态双向流 :客户端和服务端先 initialize 握手、协商能力、拿到一个 Mcp-Session-Id,之后所有请求靠这个 ID 找到同一条会话流。这个模型在"一个客户端连一个服务端"的本地场景很好用,但 2025 年 MCP 被生产环境大规模采用后,两个结构性问题爆了:
运维税:会话粘住了连接。负载均衡器必须做 sticky session,任何一台实例重启,挂在它上面的会话全部作废;你要横向扩容,就得给所有实例配共享存储来同步会话状态。
安全债:Agent 生态跑得太快,授权这块在野蛮生长中暴露了一堆结构性漏洞------官方自己也承认,"authorization 是实现时最需要花时间的区域"。
2026-07-28 这版的开刀思路就一句话:把"智能"从基础设施挪进每一次请求里。连接不再承载任何状态,于是任何请求可以被负载均衡扔给任何一台实例------round-robin,不需要共享存储。
这个剧情你眼熟吗?Web 开发史上,session 会话被 JWT 这样的无状态令牌取代,走的是同一条路。协议工程没什么新鲜的,全是架构史的回放。
2. Stateless 化:把会话状态塞回每次请求里
具体改动清单(全是 2025 版里你熟悉的"老朋友"):
| 2025-06-18 | 2026-07-28 |
|---|---|
initialize / initialized 握手 |
移除 (SEP-2575)。每个请求自带协议版本、客户端身份、能力声明(放在 _meta 里) |
Mcp-Session-Id 头 |
删除(SEP-2567) |
| 客户端提前问能力 | 新增 server/discover RPC(可选) |
| 网关要解析 JSON body 才知道你在调什么 | 方法名和工具名放进 Mcp-Method / Mcp-Name 头,网关和防火墙按头路由 |
最后一条看着小,含义不小:以前中间件要嗅探你的请求体才能做审计和路由,现在 HTTP 头就够了------这意味着 MCP 流量可以被现有的网关体系直接纳管,而不用为它开发专门的解析层。协议为基础设施让路,是它走向"企业可用"的标志。
stateless 化还有两个安静的破坏性变更,媒体很少提但会咬人:
- 错误码搬家了 :
resource-not-found从-32002改为标准错误码-32602。新规范下服务端不得再发-32002------如果你的客户端错误处理逻辑按旧码写的,不会报错,只会静默失灵(又一个"出错了也不报错",第 14 篇的四类看不见的耦合里"配置生效"类的协议版)。 - Tasks API 重设计 :旧的阻塞式
tasks/result改成了轮询模式(tasks/get/tasks/update/tasks/cancel),tasks/list直接移除,列表响应新增ttlMs让客户端决定何时重新拉取。和 MRTR 是同一个逻辑:等待不再占用连接。
3. 三项废弃:Roots、Sampling、Logging
这版最让老用户意外的决定:SEP-2577 把 Roots (告诉服务端"我能给你哪些目录")、Sampling (服务端反向借用客户端的 LLM)、Logging 三个特性标记为废弃。
注意措辞:deprecated ≠ removed 。按新的特性生命周期政策(SEP-2596),官方维护着一份公开的废弃特性登记表(我 9 月底核对过最新状态),每一项都有明确的最早移除时间:
| 废弃特性 | 迁移路径 | 最早移除时间 |
|---|---|---|
| Roots | 路径走工具参数 / 资源 URI / 服务端配置 | 2027-07-28 起的首个规范版 |
| Sampling | 直连 LLM provider API | 2027-07-28 起的首个规范版 |
| Logging | stdio 走 stderr;可观测走 OpenTelemetry | 2027-07-28 起的首个规范版 |
| Dynamic Client Registration | Client ID Metadata Documents(CIMD) | 2027-07-28 起的首个规范版 |
| HTTP+SSE 老传输 | Streamable HTTP | SEP-2596 定稿后 3 个月 |
登记表最后有一行值得抄下来:"No features have been removed under this policy yet." (该政策下至今没有任何特性被真正移除。)也就是说,到 9 月底为止这是一张未来时的时间表------你的存量代码都还能跑,你拥有到 2027 年 7 月的迁移跑道。deprecation 和 breakage 的区别就在这一行字里。
但有一个信号让你不敢躺平:工具生态跑在了教程前面 。FastMCP(最流行的 Python MCP 框架)的 4.x 版本已经直接删掉了 ctx.sample()------旧接口在框架层没了,你哪怕懒得读规范,升级依赖时也会被迫迁移。废弃不是断崖,但依赖一升级,缓冲期就到头了。
Roots 和 Sampling 废弃的理由也值得各记一句:官方文档里本就承认 roots 从来不是访问控制 ,只是"受信任双方之间的礼貌提示",真正的权限边界你得自己做;Sampling 的本质是"服务端借用客户端的模型、Key 和账单"------当模型 API 人人可接,代理模型的存在价值就崩了。当一件事人人都能自己做,协议就不该再替你做。
4. MRTR:把"工具反问人类"变成幂等重放
这版我认为最有意思的设计:Multi Round-Trip Requests(MRTR,SEP-2322),取代原来的服务端反向请求(sampling / elicitation 的旧回调形式)。
旧模型里,"工具执行到一半要问用户一个问题"需要一条持续打开的双向流------服务端顺着流把问题推过来,客户端顺着流把答案推回去。新的模型完全不同:
看清这个模式的本质了吗?一次"需要人类输入的调用"被拆成了两次普通的请求-响应 。中间的会话状态被压缩成一个不透明的 requestState 由客户端保管,服务端不需要为"等你回答"保持任何连接。它带来的性质是:
- 无状态可代理:等待用户输入的几十秒里,服务端不占连接;
- 幂等重放语义:第二次请求是第一次的"续拍",出错就整体重来,不需要复杂的流恢复逻辑;
- 防火墙友好:没有反向通道,就不需要为 MCP 打穿任何入站规则。
我第一次看懂时拍了一下桌子------这和"把同步 RPC 改成异步任务 + 轮询"的重构是同构的,而后者是每个后端工程师都经历过的成人礼。
5. Elicitation 双模式:为什么密码绝不能走 Form
Elicitation(服务端通过客户端向用户要信息)是唯一被保留且还在演进的客户端特性,2026 版给了它两种模式:
- Form 模式:结构化数据收集,可带 JSON Schema 校验。适合"选个日期、填个城市名"这类常规输入。
- URL 模式 (SEP-1036 新增):服务端给一个外部 URL,敏感交互在带外完成------用户跳转到浏览器操作,敏感数据根本不经过 MCP 客户端。
规范里有一条红线值得单独抄下来:Form 模式禁止收集密码和密钥。原因是结构化的:客户端 UI 收集的东西会进入对话上下文、会进日志、会被模型"看见"------你不可能既让 API key 经过模型的手,又指望它保密。而 URL 模式下模型从头到尾不知道你输了什么,只看到"授权完成"。
这个设计体现的是一种成熟的安全观:最好的防护不是加密传输,是让秘密根本不进入那条链路。 和我们前端常说的"敏感操作永远重定向到支付机构页面,不经手你的服务器"是同一个原则。
6. 我的项目要不要动?------逐项对表
诚实盘点我自己的 MCP 用法(mcp_server/server.py + mcp_client.py,7 个工具,stdio 传输):
| 我用到的 | 受影响吗 |
|---|---|
@mcp.tool() 定义 + 工具调用 |
不受影响------工具调用是全协议支持度最高的部分,新规范兼容 |
| stdio 传输 | 短期没事,但要留意:老的 HTTP+SSE 传输已被废弃(同样 12 个月),如果以后上远程 MCP 必须直接用新传输 |
| Roots / Sampling | 没用过------幸运地躲过了废弃名单 |
| 反向用户输入 | 没做过------如果做,直接按 MRTR 设计,别碰旧回调 |
| 会话管理 | stdio 本地进程对子进程,无 session 概念;上远程才需要关心 |
结论:现在的代码一行都不用改,但两件事要进待办------
一是 SDK 的版本现实。 生态已经拆出新旧两条线:TypeScript 拆成 @modelcontextprotocol/client@2 和 server@2 两个包,Python 升到 mcp-sdk>=2.0.0,Go 是 go-mcp/v2------1.x 旧线只为存量服务维护。你升级依赖的那天就是被迫对表新规范的那天,所以别把"升级 SDK"当成无脑操作,当成一次小型迁移来排期。
二是任何"远程 MCP"的规划直接按新规范设计(stateless + MRTR + Streamable HTTP),不要做一版 2025 风格的实现然后重写------给未来省下的正是这次改版让所有人补交的学费。
这里藏着一个对所有协议使用者的通用教训:你的代码不受影响,往往不是因为你写得好,而是因为你用得浅。 用得越深,协议改版付的账越多------这也是"最小依赖面"原则在协议层的体现。
7. 协议演化的元思考:MCP 在重走 HTTP 的路
最后说点自己的观察。把 MCP 这一年半的演化排开看:
- 2024-11:stdio + 本地进程,玩具期
- 2025-03:Streamable HTTP,远程化
- 2025-06:授权补课,OAuth 细化
- 2025-11:能力元数据、枚举标准化、tasks 实验特性
- 2026-07:stateless 大重构,废弃三大特性
- 2026-08~09(改版后两个月):SDK 全线 2.x、FastMCP 删旧接口、官方废弃登记表上线------生态追赶规范
这条轨迹和 HTTP 协议的演化惊人地同构:先满足"能用",再满足"能传",最后回头解决"能扩"------而"能扩"的答案永远是同一个:砍状态。HTTP 用了十几年才想明白要拥抱无状态 REST,MCP 只用了一年半,因为它可以直接抄作业。
对普通开发者的启示有两条。第一,别把任何协议的当前形态当成理所当然 。我 02 篇写的 MCP 基础(工具定义、传输、客户端连接)今天依然成立,因为那是协议的"稳定内核";但凡是涉及会话、传输细节、反向通道的内容,半年就得重新核对一遍。第二,更精炼的版本来自我读到的一个 field log 的自嘲:"工具跑在了教程前面"------当你搜一个特性的教程还有一大把、而它的官方框架实现已经删掉时,别信搜索结果的新鲜度,去读 changelog 和废弃登记表。写涉及协议的博客尤其如此:我这次动笔前把官方 spec 站的当前版本号、废弃登记表(9 月 3 日抓取的快照)和 9 月的生态动态逐条核了一遍,就是为了不把两个月前的"常识"当现状教给读者。
8. 可复用清单
- MCP 2026-07-28 是史上最大改版:stateless 化 + MRTR + 三项废弃,截至 9 月底仍是现行最新版(下一代在 draft)
- Session 没了 :SEP-2575 移除握手、SEP-2567 删会话头、能力进
_meta;实例可任意横向扩容 - 安静的破坏 :
resource-not-found错误码-32002→-32602(客户端按旧码写会静默失灵);Tasks 改轮询、tasks/list移除 - Roots / Sampling / Logging 已废弃 :最早 2027-07-28 移除,登记表原话"至今零移除"------跑道还在,但 FastMCP 4 已删
ctx.sample(),依赖一升级缓冲就没了 - MRTR :把"工具反问人类"拆成两次普通请求 + 不透明
requestState------human-in-the-loop 的无状态化 - 密码密钥禁走 Form 模式:敏感交互走 URL 带外完成,让秘密不进入模型链路
- SDK 已分新旧两条线 :TS
client@2/server@2、Pythonmcp-sdk>=2.0、Gogo-mcp/v2;升级依赖 = 对表新规范的那天 - 工具跑在教程前面:搜到教程多 ≠ 特性还活着,信 changelog 和废弃登记表,不信搜索结果的新鲜度
下一篇预告
MCP 解决的是"Agent 和工具之间"的通信,还有一个更隐蔽的问题在 Agent 内部:多个 Agent 之间,上下文怎么分?我自己的 multi-agent 已经在做"每个领域 Agent 一个全新窗口"的隔离------但也悄悄付了一笔代价。下一篇 A7 聊四框架里最难也最强的 Isolate。
参考资料
- MCP Specification --- Deprecated Features 登记表 ------ 本文废弃时间表与"至今零移除"的官方状态源(含 SEP-2596 生命周期政策)
- MCP Specification --- 2025-11-25 Changelog ------ 2026-07-28 版相对 2025-06-18 的完整变更清单
- ByteIota --- MCP Goes Stateless: What Breaks and How to Fix It ------ SEP-2575/2567 编号、错误码变更、Tasks 轮询重设计、SDK 2.x 拆分细节
- DevMoment --- MCP sampling in 2026: deprecated one revision after it grew ------ 9 月 3 日登记表快照、"工具跑在教程前面"(FastMCP 4 删
ctx.sample())、sampling 与 elicitation 命运分叉的对照 - Techzine --- MCP becomes stateless: major update makes servers more scalable ------ stateless 改版与 MRTR 的报道
- GPTMap --- MCP Client Features Today: Elicitation Stays, Roots and Sampling Deprecated (SEP-2577) ------ 三项废弃的条款级解读与迁移路径
- 本系列 02-MCP 实战:把工具层从 Agent 里解耦 ------ 本文的前篇,MCP 稳定内核部分
- 项目源码(仍在更新中) :Ticnix/weather-travel-recommend-system ------
backend/mcp_server/{server,tools}.py、mcp_client.py