上周我帮朋友调试一个本地 MCP server顺手把 SDK 升到了最新。结果老服务连上来直接报错错得特别抽象我一度以为是 OAuth 配置问题绕了大半个中午才发现不是我的代码坏了是 MCP 协议把 Session 和 Sampling 这两块内容从规范里拿掉了。说实话作为一个从 2024 年就开始碰 MCP 的人我那一刻有点恍惚。更让我恍惚的是我手边几篇“看起来很新”的教程还在讲怎么维护 session、怎么用 sampling 让服务器调用大模型。也就是说很多人正在学的那套东西在最权威的协议定义层面已经不再是今天的 MCP 了。用一句话描述 MCP模型上下文协议Model Context Protocol。它给大模型应用客户端和外部工具/数据服务器定了一套统一的对接方式。你把 MCP 理解成 AI 世界的 USB-C 口就行各种带“MCP 插件”的东西都可以通过同一套协议被接入同一个智能体流程。过去一年里几乎所有大模型 SDK、开发框架和 Agent 中间件都在往 MCP 上靠。但越是被广泛采用协议本身就越不能一直保持“草稿状态”。最近这轮调整说白了就是一次正式报到前的狠心瘦身。1. 上个月的“推翻重写”到底删了什么先看官方变更记录我建议所有还在用 MCP 的人第一件事都不是去刷博客而是打开 MCP 官方仓库的 specification 和 CHANGELOG。这次大家口中的“推翻重写”其实指向 2025 年 3 月到 5 月之间几次非常明确的协议修订。1.1 三个关键字sessionId、requestId、Sampling旧版 MCP 规范里客户端和服务器建立会话之后需要维护一个sessionId。这个 ID 会贯穿后续的 JSON-RPC 请求服务器也靠它记住“这个客户端刚才初始化过”。新规范把这个协议层面的会话机制删掉了。不是说服务器不能有状态而是说“状态维护”不再是协议替你承担的责任。你想要跨请求保留用户上下文可以但得靠自己的存储和业务逻辑协议层不会再强制要求握手建会话。requestId也一起动了手术。旧版消息信封里有请求 ID 的强约定新版把请求和响应的对应关系做了降级处理。具体场景里你可能会发现很多 HTTP 客户端库不再关心 requestId因为底层已经变成“一次 POST 一次响应”的简单模型。最敏感的是 Sampling。旧规范允许服务器主动向客户端发起一个“帮我用大模型生成一段文字”的请求也就是服务器端可以反向要求客户端调一次模型补全。这在设计上很像是“服务器也长出了嘴巴”能让工具在执行过程中随时调用智能体能力。新规范直接把 Sampling 移除了。1.2 运输层从“握手长连接”变成“单次 POST”旧版常见的接入套路是 HTTP SSE 两段式客户端先和服务端建立会话拿到一个 SSE 地址然后挂在长连接上等服务器推送消息。这套模式在本地工具场景够用一旦上了生产环境和分布式部署问题就来了会话要粘滞、连接要保活、断线要重建每一条都是运维噩梦。Streamable HTTP 传输方式成为主线之后一个POST /mcp端点就能解决所有消息交换。客户端把 JSON-RPC 消息 POST 过去服务器可以返回普通 JSON也可以返回 SSE 流如果服务器想持续推送多条消息流式返回让这件事依然可能。但每一次请求都不再依赖“之前握过手”的隐式状态。1.3 旧教程所谓“推翻重写”其实还留下了大量地基刚才说了一堆删掉的也得说说没变的免得刚接触 MCP 的同学以为整套协议都换了。MCP 的基础骨架还是 JSON-RPC 2.0 消息还是围绕initialize、ping、resources/list、tools/list、tools/call、prompts/list这些核心方法展开。服务器还是负责暴露能力工具、资源、提示模板客户端还是负责发起调用和组织整个智能体流程。换句话说这次调整更像是一次“职责边界回归”协议不再试图替你做会话管理也不再把“服务器能不能调用大模型”塞进核心规范。服务器就是工具提供方客户端就是决策方。谁该干什么边界比以前清晰多了。我拿一张表快速看得更明白维度2025 年之前常见教程描述的 MCP当前规范的 MCP传输方式HTTP SSE 两段式握手Streamable HTTP 单端点 POST会话维护协议层要求 sessionId协议层不维护会话可选 HTTP 头关联服务器调模型Sampling 请求已移除交还给客户端流程请求标识消息体内强调 requestId降级/迁移关注响应对应核心能力tools/resources/promptstools/resources/prompts 仍是主线看完这张表你就明白为什么那么多教程“还停在 2025”很危险它们教的东西不是某个 SDK 的旧版本写法而是协议设计思路本身的旧版本。2. session 没了从“握完手不散”到“每次请求都是陌生人”Session 的删除是我这一周实际写代码时感受最深的变动。因为它不是改个字段名那么简单它会改变你设计 MCP 服务器的方式。2.1 旧协议是怎么维护会话的最早接触 MCP 时我对它的印象是“这很像自己当年写 WebSocket 服务”。第一次连接客户端发initialize服务器返回初始化能力列表随后建立 SSE 通道之后所有工具调用都带着同一个会话身份。你可以在服务器内存里挂一个 map给每个 sessionId 存一堆临时变量。本地联调很爽因为一切都在一起断线重连后也能直接拿到上下文。但这里有个问题这个 sessionId 本身没有统一的过期策略、没有恢复机制、没有跨节点同步方案。每个 MCP 服务器厂商都自己实现一套。结果就是客户端根本不知道服务器到底会记多久、会不会把会话存进数据库、重启之后还在不在。协议一旦对“服务器端的私有状态”失去约束力互操作性就只能靠猜。2.2 Streamable HTTP 下的新规矩可用但不依赖新规范下的初始化还是在 POST 请求里完成服务器返回 capabilities。区别在于这个请求不再绑定一个长期连接之后客户端再发tools/call理论上是另一个完全独立的 HTTP 请求。如果你需要跨请求保留某些临时状态协议允许服务器在响应头里放一个不透明的Mcp-Session-Id客户端后续可以在请求头带回来。但请注意一个关键措辞这个标识只是服务器自己的钩子没有协议语义客户端有权利不接受、不回应、不使用。翻译成人话就是别再写“没有 sessionId 就拒绝服务”的代码了。客户端完全可以做到无状态地反复调用你你应该把它当作一种正常情况来设计。2.3 无状态化对服务器开发者的直接影响Session 退出协议层带来最实在的三个变化。第一个变化工具必须幂等。以前你可以依赖“这个工具调用一定发生在某个会话里”现在不行。网络超时、客户端重试、负载均衡切换都可能让同一个请求被执行两遍。如果你的工具会在数据库里插入一条订单记录那就要考虑重复调用会不会制造脏数据。你可以在工具参数里带上幂等键也可以让任务本身天然可重放反正不能再寄希望于“反正只有一个连接”。第二个变化状态要显式传递。以前 session 能帮你隐藏一部分业务状态比如“用户当前在编辑哪个文件”。现在你应该把这种情况做成工具参数比如file_path直接传进来。会话层面的东西一旦变成参数好处是这个工具就变成可测试、可并发、可重放的纯函数了。第三个变化重新连接的恢复能力要靠业务层完成。客户端断线重连后不再会自动找回之前的 session。如果你的服务器重启了或者客户端换了一台机器你需要让协议里的 resources 和 prompts 能重新被读取让用户自己把必要的上下文重新传给工具。Session 的退出本质上是把“恢复现场”的责任交回给了应用开发者。这轮 session 变动我建议所有做 MCP 插件的人重新读一遍官方仓库里关于传输层的部分尤其是“Streamable HTTP”和“HTTP Header”相关章节。因为很多现在还在流传的“MCP session 管理教程”讲的是上一个时代的东西。3. Sampling 为什么被“废”服务器反向调用大模型逻辑上就埋着三个死穴如果说 Session 的删除是运输层的一次“去重”那 Sampling 的删除就是控制层的一次“正名”。我接触过的很多初学者在学 MCP 时都觉得 Sampling 很酷因为这意味着服务器能像客户端一样思考。可冷静看下来这条设计从一开始就不太对劲。3.1 Sampling 过去是怎么用的旧规范中服务器可以在处理某个工具请求时向客户端发起类似“请帮我调用模型生成一段摘要”的请求。客户端如果允了就调用本端配置的大模型拿到结果再返回给服务器。听起来是不是很像“服务器也长了脑子”实际用起来问题特别多。第一个死穴服务器根本不了解客户端那边的模型能力。客户端可能接的是带视觉的旗舰模型也可能接的是只能跑简单文本的小模型可能是云端 API也可能是本地蒸馏模型。Sampling 请求一旦发过去服务器无法预判模型质量也就无法保证生成结果的格式和可靠性。这就像你打电话让厨房做菜但你不清楚厨房今天用的是哪套厨具也不知道厨师什么水平。第二个死穴谁来为这次模型调用买单客户端自己调本地模型可能免费调云端 API 要花钱还有隐私和合规约束。服务器发起采样请求等于把一个成本责任不明、不可审计的模型调用强加给客户端。很多客户端选择直接拒绝导致 Sampling 在真实生态里的普及率一直很低。第三个死穴无限循环和不可控延迟。服务器请求采样采样结果回来后又触发新的工具调用工具调用又请求新的采样……这个循环如果没有强约束很容易变成不可控的“套娃”。而用户只看到任务一直转圈不知道钱烧到了哪里也不知道模型到底被引导到了哪个方向。3.2 没有 Sampling 之后服务器该把“上下文需求”放哪现在协议不再提供“服务器调模型”的通道了。那如果服务器真的需要一句话摘要怎么办我的建议是分三类处理。第一把摘要的事情交还给客户端。服务器老老实实返回结构化结果例如原始文本段落、数据库记录、文件片段客户端的大模型自然会在 agent 流程里对这些结果做加工。你不需要在工具内部把“总结”做完你只需要把“原料”交付干净。第二用 prompt templates 提供引导。服务器可以在prompts/list里暴露设计好的提示词模板客户端调用这些模板再把填充好的内容丢给模型。这不仅避免了 Sampling 的越权还让“人味”的提示词沉淀在服务器端任何人都能复用。第三需要额外上下文时把“上下文来源”做成资源或工具参数。比如某个分析工具需要一份用户画像你可以让调用方把画像内容作为参数传进来也可以把它变成一个资源端点供客户端读取。关键原则是上下文由谁提供、何时提供、以什么格式提供都应该在调用链路上清晰可见而不是藏在服务器的一次隐形模型请求里。现在的 MCP 越来越像一个清晰的“设备层”服务器提供设备客户端负责驾驶。模型永远待在客户端这一侧想怎么组合、怎么调用、怎么配上下文是客户端自己的事。这个边界一旦清晰开发者的心理负担小很多。3.3 用 Sampling 老思想写出的代码现在该停手了如果你看到一篇 2025 年年中的教程还在教你“如何让 MCP 服务器请求模型补全”那基本可以判定那段代码抄不得。不是它不能跑而是它正在教你和未来的规范对着干。我后来删掉了一大批服务器端的“智能”逻辑把大部分生成任务改成了返回原始数据或结构化中间结果。实测下来稳定性和可排查性都好了不少。服务器代码里少一点“替模型思考”的黑魔法整个链路的日志才真正变得可读。4. 教程还停在 2025那你手头这套集成姿势先别急着照抄很多同学问我既然 MCP 变这么快那 2025 年的正确姿势到底是什么其实答案不复杂只是比复制粘贴多了一步分清楚哪些是协议教条哪些是行业流俗。4.1 先搭一个“最小可信基线”不管外面怎么吵我建议你把这几个动作当成 2025 年学习 MCP 的基线用最新稳定版 SDK 建一个只有tools/list和tools/call的服务器。客户端通过唯一一个 HTTP 端点完成消息交换不写任何 session 管理代码。工具参数尽量自包含重要业务标识都显式传。不把“让服务器调用大模型”写进设计文档改由客户端主导模型决策。只要这条基线是干净的你后面再加 resources、prompts、streaming、OAuth都不会被老思路带偏。反之如果你先学了一套“带 session 的工具调用”再想迁移到新模型等于要重构整个思维特别痛苦。4.2 旧教程的四个“危险残留区”我把自己踩过的坑整理成四个危险信号你在看文章时可以直接对照教程里的说法危险程度我的处理“先建立 session 再调用工具”高改成单次 POST不维护会话“服务器通过 sampling 请求模型补全”高删掉采样改为返回结构化原料“用 requestId 严格配对请求和响应”中跟随 SDK 新传输层看官方示例“必须保持 SSE 长连接才能收到推送”中根据场景选 SSE 流式或普通 JSON 返回这四个信号不一定每个都会让你编译失败但一定会让你在未来升级时多踩几个坑。早点清理比晚点清理划算。4.3 把自己的代码仓库也当作“教程”来治理既然协议在快速演进我养成了一个习惯在仓库根目录的 README 里写清楚“本仓库基于 MCP 规范的哪个版本”。这个习惯救过我很多次。因为 SDK 是跟着规范同步更新的但你某个分支可能锁在旧版本上。跑起来报错时先看版本号再判断是代码 bug 还是协议差异排查思路完全不一样。你甚至可以在服务器的启动日志里带上规范版本号或者暴露一个/version接口给客户端。谁看了都知道这个服务是什么时代的产物。5. 规范更新太快怎么办我现在的入坑姿势就三条最后分享一点这段时间我自己的方法论可能对同样被 MCP 快速演进搞得焦虑的人有点用。5.1 只信官方 changelog不把教程时间线当导航MCP 的官方仓库有非常清晰的变更记录。遇到问题时我第一反应永远是打开 changelog搜一下自己正在用的概念还在不在。如果某个词从规范里消失了那无论有多少博客还在用这个词无论这个概念多么“经典”你都应该以官方为准。注意我这里说的是“以官方为准”不是“以最新讨论帖为准”。社区讨论有滞后性一些成名已久的博文作者可能已经几个月没更新 MCP 相关内容了。他们不是不专业只是没跟上变化。5.2 锁版本、看差异、小步迁移不要一看到新版 SDK 发布就无脑升级。尤其在大版本跨越的时候先拉一个分支读 changelog 里 breaking changes 的部分再跑一遍现有测试最后再合入。我一般还会顺手写一个“协议迁移记录”文档把旧的 session 代码、旧的 sampling 调用、旧的 transport 写法列成一张表每条标注迁到新架构之后对应的做法。这张表以后就是团队培训材料能避免别人重复踩坑。5.3 感慨一下MCP 真正成熟恰恰是从“少承诺”开始的我最近在改一个老项目时突然明白了一件事协议删掉 Session 和 Sampling不是因为开发者不需要这些能力而是因为协议不应该替开发者规定“你必须用这套状态方案”“你必须允许服务器调模型”。制度越少互操作空间越大。这轮变动之后我写 MCP server 的心态反而轻松了。我只需要把工具边界做好把输入输出定义清楚把业务状态显式参数化剩下的怎么调度、怎么绕模型、怎么组织上下文都留给客户端。如果你现在正准备学 MCP反而不用恐慌。你现在学到的最新规范比任何一个老教程都更接近终点。把 session 和 sampling 那两章从脑子里清掉好好拥抱无状态、工具化、客户端主导这套新节奏你会比大多数“还停在 2025”的资料领先一大截。