<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Protocol on 鬼哥的空间</title><link>https://luoli523.github.io/tags/protocol/</link><description>Recent content in Protocol on 鬼哥的空间</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 29 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://luoli523.github.io/tags/protocol/index.xml" rel="self" type="application/rss+xml"/><item><title>天下苦旧 MCP 久矣：Anthropic新MCP协议终于开始治病了</title><link>https://luoli523.github.io/p/mcp-stateless-core/</link><pubDate>Wed, 29 Jul 2026 00:00:00 +0000</pubDate><guid>https://luoli523.github.io/p/mcp-stateless-core/</guid><description>&lt;img src="https://luoli523.github.io/" alt="Featured image of post 天下苦旧 MCP 久矣：Anthropic新MCP协议终于开始治病了" /&gt;&lt;p&gt;你们在公司里落地 MCP 时，是不是也碰到过这些尴尬？&lt;/p&gt;
&lt;p&gt;本地跑得丝滑，一上 Kubernetes、扩成两个实例，session 偶尔就找不到亲妈了；网关团队问“这次到底调用了哪个工具”，你只能指着一坨 POST 里的 JSON 说“答案在里面，请自行考古”；Agent 一遍遍调用 &lt;code&gt;tools/list&lt;/code&gt;，工具一个没变，token 和请求倒是烧得很稳定；高风险操作想让用户确认一下，结果业务问题还没解决，先和长连接、代理超时打了一架。&lt;/p&gt;
&lt;p&gt;鬼哥自己做 MCP 接入和应用时，这几种场面基本都见过。&lt;/p&gt;
&lt;p&gt;开发同学觉得协议能跑，平台同学觉得它不好扩，安全同学觉得它看不懂，运维同学觉得它需要特殊照顾。最后大家围着一条本来应该很普通的工具调用链，开出了联合国大会的气势。&lt;/p&gt;
&lt;p&gt;如果你也经历过，恭喜，我们算是对上暗号了：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;天下开发者，苦旧 MCP 久矣。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它不是不能用。恰恰相反，旧 MCP 特别擅长证明一件事：模型可以调用工具。&lt;/p&gt;
&lt;p&gt;但从“模型能调用工具”，到“公司敢让模型调用生产工具”，中间隔着负载均衡、网关、缓存、鉴权、审计、超时、扩容，以及安全团队那句永恒的灵魂拷问：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;出事了算谁的？&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="MCP 2026-07-28 从插件协议走向基础设施协议" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://luoli523.github.io/p/mcp-stateless-core/cover.webp" srcset="https://luoli523.github.io/p/mcp-stateless-core/cover_hu_34f0676b8c03858e.webp 800w, https://luoli523.github.io/p/mcp-stateless-core/cover.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;p&gt;2026 年 7 月 28 日，官方发布了新的 Model Context Protocol 规范：&lt;code&gt;2026-07-28&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;看完这版规范，鬼哥最大的感受只有一句：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新的 MCP，终于开始像一个基础设施协议了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这次不是往协议里再塞几个功能，而是把那些真正妨碍 MCP 进入公司生产环境的东西，一件件拆掉：协议核心无状态、请求可路由、列表可缓存、授权更严谨、长流程不再绑死长连接、扩展也有了正式边界。&lt;/p&gt;
&lt;p&gt;Anthropic 官方文档提到，Tier 1 SDK 每月下载量已经接近 5 亿，TypeScript 和 Python SDK 累计下载量都超过了 10 亿。生态跑到这个规模，再拿“demo 能跑”当成功标准，就多少有点不礼貌了。&lt;/p&gt;
&lt;p&gt;下面不照着 release note 念。鬼哥直接拿公司里碰到的场景，讲讲这次到底改掉了什么。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="两个实例一扩session-先迷路了"&gt;两个实例一扩，session 先迷路了
&lt;/h2&gt;&lt;p&gt;鬼哥在公司里接远程 MCP 时，最典型的尴尬就是：&lt;strong&gt;单实例一切正常，一横向扩容，问题开始玄学。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;旧版 MCP 在远程 HTTP 场景里，客户端先 &lt;code&gt;initialize&lt;/code&gt;，服务端给出 &lt;code&gt;Mcp-Session-Id&lt;/code&gt;，后续请求带着这个 session 继续走。&lt;/p&gt;
&lt;p&gt;开发环境只有一个实例，当然岁月静好。到了生产环境，前面挂上 load balancer，后面跑多个实例，请求第一次落到 Server A，第二次被分到 Server B，B 一脸茫然：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;你谁？&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;接下来无非几条路：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配 sticky session，让同一个客户端尽量黏住同一个实例；&lt;/li&gt;
&lt;li&gt;搭共享 session store，让所有实例交换记忆；&lt;/li&gt;
&lt;li&gt;在服务间同步上下文；&lt;/li&gt;
&lt;li&gt;祈祷扩容、重启和故障转移时别出怪事。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;能做，当然都能做。但为了调用一个 tool，先给负载均衡器安排一段刻骨铭心的长期关系，这个工程成本明显不太对。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2026-07-28&lt;/code&gt; 直接砍掉了这层协议会话：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移除 &lt;code&gt;initialize&lt;/code&gt; / &lt;code&gt;initialized&lt;/code&gt; 交换；&lt;/li&gt;
&lt;li&gt;移除协议层 &lt;code&gt;Mcp-Session-Id&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;每个请求自己携带协议版本、客户端身份和能力；&lt;/li&gt;
&lt;li&gt;需要提前发现服务端能力时，可以调用可选的 &lt;code&gt;server/discover&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;旧模式：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;先握手 → 拿 session → 请求必须找到“熟悉你的实例”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;新模式：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;请求自描述 → 任意实例都能处理 → 普通 round-robin 就能跑
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img alt="有状态 MCP 到无状态 MCP 的部署变化" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://luoli523.github.io/p/mcp-stateless-core/stateless-before-after.webp" srcset="https://luoli523.github.io/p/mcp-stateless-core/stateless-before-after_hu_931b910630e27225.webp 800w, https://luoli523.github.io/p/mcp-stateless-core/stateless-before-after.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;p&gt;改完之后，MCP server 才真正像一个普通 HTTP 服务：实例随便扩，坏了随便换，请求落到谁家谁处理。Kubernetes、serverless、API Gateway、WAF、rate limiter 和 observability 这些现成基础设施，不用再围着 MCP 单独学一套脾气。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一个协议如果要求负载均衡器记住你，说明它还没学会在公司里做人。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="状态可以有但别藏在桌子底下"&gt;状态可以有，但别藏在桌子底下
&lt;/h2&gt;&lt;p&gt;看到“无状态”，很多人会立刻问：那浏览器会话、代码沙箱、购物车和长任务上下文怎么办？&lt;/p&gt;
&lt;p&gt;鬼哥在公司做这类工具时也遇到过。比如 Agent 创建了一个代码工作区，后面还要继续执行命令、读取结果。状态显然不能丢。&lt;/p&gt;
&lt;p&gt;问题不在于“有没有状态”，而在于&lt;strong&gt;状态藏在哪里&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;旧方式把关键状态藏进 transport session。客户端和模型知道“连接还在”，却不一定看得见自己正在操作哪个工作区。连接断了、实例换了，业务上下文也容易跟着失忆。&lt;/p&gt;
&lt;p&gt;新方式更接近正常 API：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;create_workspace → 返回 workspace_id
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;run_command(workspace_id, command)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;read_result(workspace_id)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;服务端返回显式 handle，模型在后续 tool call 中把它作为参数传回来。&lt;/p&gt;
&lt;p&gt;体验上的变化很直接：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;以前&lt;/th&gt;
 &lt;th&gt;现在&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;状态依附于连接&lt;/td&gt;
 &lt;td&gt;状态依附于明确的业务 ID&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;模型看不见 session 里藏了什么&lt;/td&gt;
 &lt;td&gt;模型能读取和传递 &lt;code&gt;workspace_id&lt;/code&gt; / &lt;code&gt;task_id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;断线恢复依赖原会话&lt;/td&gt;
 &lt;td&gt;换实例后仍可按 handle 继续&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;排查时先猜“会话怎么了”&lt;/td&gt;
 &lt;td&gt;日志里直接按业务 ID 追踪&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这不只是方便运维，也更适合 Agent 推理。模型看得见状态，才能引用状态、组合状态、接着做下一步。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;状态不是不能有，不能装神弄鬼。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="要用户点个确认没必要拿长连接祭天"&gt;要用户点个确认，没必要拿长连接祭天
&lt;/h2&gt;&lt;p&gt;公司里的 Agent 一旦能写数据，human-in-the-loop 就绕不过去。&lt;/p&gt;
&lt;p&gt;鬼哥碰到过的真实需求很普通：Agent 准备删除数据、修改配置、调用付费服务，执行前必须让用户确认。业务上就是一个“确定吗”，技术上却可能变成一条长时间挂着的双向流。&lt;/p&gt;
&lt;p&gt;旧思路里，服务端执行到一半，通过打开的连接反向问客户端：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;准备删除 3 条记录，确认吗？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;听起来合理，直到它穿过公司的代理、网关和超时策略。用户去倒杯水，回来点“确认”，连接已经先替他回答了：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;不确认，我没了。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;MRTR，Multi Round-Trip Requests，解决的就是这个问题。它把中途交互拆成普通的多轮 request/response：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Client 调用 tool
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Server 返回 input_required
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Client 收集用户确认或补充参数
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Client 带着 inputResponses 重试原调用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. 任意 Server 实例继续处理
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img alt="MRTR 把中途确认改成多轮请求响应" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://luoli523.github.io/p/mcp-stateless-core/mrtr-flow.webp" srcset="https://luoli523.github.io/p/mcp-stateless-core/mrtr-flow_hu_69dc483d528c6698.webp 800w, https://luoli523.github.io/p/mcp-stateless-core/mrtr-flow.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;p&gt;这样一来，删除确认、参数追问、二次授权、用户选择，都不再要求服务端死守一条连接。请求可以暂停，可以恢复，可以重试，也可以由另一个实例接着处理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;确认是业务流程，不该是连接保活挑战。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="网关终于能看懂你到底想干什么"&gt;网关终于能看懂：你到底想干什么
&lt;/h2&gt;&lt;p&gt;鬼哥把 MCP 接进公司网关时，还有一个非常现实的问题：&lt;strong&gt;所有请求看起来都差不多。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;安全团队想对删除类工具做更严格的授权，平台团队想给昂贵工具单独限流，运维想统计每个 tool 的错误率。结果网关看到的往往只是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST /mcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;至于这是 &lt;code&gt;tools/call&lt;/code&gt; 还是 &lt;code&gt;resources/read&lt;/code&gt;，调用的是 &lt;code&gt;search&lt;/code&gt; 还是 &lt;code&gt;delete_database&lt;/code&gt;，答案埋在 JSON-RPC body 里。&lt;/p&gt;
&lt;p&gt;过去网关看 MCP，就像保安看一群都戴着口罩、穿着同款外套的人：知道有人进来了，不知道进来的是谁。&lt;/p&gt;
&lt;p&gt;新规范要求 Streamable HTTP 请求带上 &lt;code&gt;Mcp-Method&lt;/code&gt; 和 &lt;code&gt;Mcp-Name&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Mcp-Method: tools/call
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Mcp-Name: search
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;于是很多公司里的基础设施能力终于可以直接工作：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;公司里的需求&lt;/th&gt;
 &lt;th&gt;改进后的体验&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;删除类 tool 单独审批&lt;/td&gt;
 &lt;td&gt;网关按 &lt;code&gt;Mcp-Name&lt;/code&gt; 匹配策略&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;搜索和写入使用不同限流&lt;/td&gt;
 &lt;td&gt;不解析 body，header 直接分流&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;按方法做权限控制&lt;/td&gt;
 &lt;td&gt;安全层读取 &lt;code&gt;Mcp-Method&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;统计各 tool 成本和错误率&lt;/td&gt;
 &lt;td&gt;观测系统直接按 header 分桶&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;对高风险调用做 WAF 规则&lt;/td&gt;
 &lt;td&gt;请求到应用前就能拦截&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这两个 header 看起来只是两行字符，实际上是 MCP 对企业世界的一次低头。&lt;/p&gt;
&lt;p&gt;而这次低头，很有必要。&lt;strong&gt;基础设施不怕你复杂，怕的是你什么都藏着不说。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="工具一个没变agent-为什么还要问十遍"&gt;工具一个没变，Agent 为什么还要问十遍
&lt;/h2&gt;&lt;p&gt;鬼哥在公司跑 Agent 时，经常看到一种很浪费的行为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tools/list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tools/list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tools/list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Agent 每推进几步，就重新确认一次“你有哪些工具”。服务端老老实实返回同一份列表，客户端老老实实重新处理，大家都很勤奋，只有账单不太开心。&lt;/p&gt;
&lt;p&gt;旧 MCP 对列表缓存缺少明确语义。客户端不知道这份 tool catalog 能信多久，也不知道应该按用户、租户还是全局缓存。最稳妥的办法只能是：再问一次。&lt;/p&gt;
&lt;p&gt;新规范让 &lt;code&gt;tools/list&lt;/code&gt;、&lt;code&gt;prompts/list&lt;/code&gt;、&lt;code&gt;resources/list&lt;/code&gt;、&lt;code&gt;resources/read&lt;/code&gt; 等响应可以携带：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ttlMs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cacheScope&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有了明确的有效期和作用域，客户端可以放心复用结果。同时，确定性的列表顺序也能让上游上下文更稳定，减少 prompt cache 因为一点无意义的顺序抖动而失效。&lt;/p&gt;
&lt;p&gt;&lt;img alt="MCP list 结果缓存减少重复工具发现" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://luoli523.github.io/p/mcp-stateless-core/cacheable-lists.webp" srcset="https://luoli523.github.io/p/mcp-stateless-core/cacheable-lists_hu_52a6ef0289f5bf94.webp 800w, https://luoli523.github.io/p/mcp-stateless-core/cacheable-lists.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;p&gt;前后的差别，不只是少几次网络请求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工具发现更快；&lt;/li&gt;
&lt;li&gt;token 消耗更低；&lt;/li&gt;
&lt;li&gt;tool catalog 在上下文里更稳定；&lt;/li&gt;
&lt;li&gt;多租户缓存边界更清楚；&lt;/li&gt;
&lt;li&gt;服务端不用反复回答同一道送分题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;最贵的请求，不一定最复杂；也可能只是明知道答案没变，还要再问一遍。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="安全团队终于不只剩一句先别上"&gt;安全团队终于不只剩一句“先别上”
&lt;/h2&gt;&lt;p&gt;公司里接 MCP，真正耗时间的通常不是 tool schema，而是 authorization。&lt;/p&gt;
&lt;p&gt;鬼哥经历过类似的拉扯：开发侧已经把工具调用跑通了，接入企业身份系统时却开始连环追问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个 token 是谁签发的？&lt;/li&gt;
&lt;li&gt;Agent 代表哪个用户？&lt;/li&gt;
&lt;li&gt;credential 能不能被拿去另一个授权服务器使用？&lt;/li&gt;
&lt;li&gt;desktop / CLI 的 localhost redirect 怎么处理？&lt;/li&gt;
&lt;li&gt;出问题以后，能不能还原谁在什么时候调用了什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些问题一个都不酷，但任何一个答不清，安全团队都可以非常合理地说：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;很好，先别上。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;2026-07-28&lt;/code&gt; 对授权做了几项关键硬化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;授权服务器应返回 &lt;code&gt;iss&lt;/code&gt;，客户端在换 code 前必须验证，避免 authorization-server mix-up；&lt;/li&gt;
&lt;li&gt;DCR 增加 &lt;code&gt;application_type&lt;/code&gt;，减少 desktop / CLI 的 localhost redirect 被误拒；&lt;/li&gt;
&lt;li&gt;client credential 与 issuer 绑定，不能跨授权服务器复用；&lt;/li&gt;
&lt;li&gt;Dynamic Client Registration 被弃用，方向转向 Client ID Metadata Documents；&lt;/li&gt;
&lt;li&gt;企业托管授权等能力进入正式 extensions 框架。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;改进后的重点，不是 OAuth 流程看起来更漂亮，而是信任关系终于更容易说清楚：谁签发、谁使用、代表谁、能用在哪、出了事怎么查。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;能调工具是 demo；知道谁以谁的名义调了什么，才是生产。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="出错以后别再让日志各说各话"&gt;出错以后，别再让日志各说各话
&lt;/h2&gt;&lt;p&gt;鬼哥在公司排查 Agent 调用链时，还有一种熟悉的痛苦：一次 tool call 穿过客户端、SDK、MCP server，再调用下游 API，报错后每一层都有日志，但没有一层承认彼此认识。&lt;/p&gt;
&lt;p&gt;客户端说请求失败，MCP server 说下游超时，下游系统说自己收到过一个调用。三份日志，三个 request ID，工程师只能靠时间戳和直觉玩连连看。&lt;/p&gt;
&lt;p&gt;新规范把 W3C Trace Context 在 &lt;code&gt;_meta&lt;/code&gt; 里的传播方式正式写清楚，固定了 &lt;code&gt;traceparent&lt;/code&gt;、&lt;code&gt;tracestate&lt;/code&gt; 和 &lt;code&gt;baggage&lt;/code&gt; 的 key。这样，一条从 Agent 发起的调用，可以穿过客户端 SDK、MCP server 和下游服务，最终在兼容 OpenTelemetry 的系统里串成同一棵 span tree。&lt;/p&gt;
&lt;p&gt;改进前，问题是“这三条日志是不是一家人”；改进后，至少可以沿着一个 trace 看到请求在哪一层慢、在哪一层错、又是谁重试了几次。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;没有 trace 的 Agent 调用链，出了问题以后就不是排障，是刑侦。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="长任务别再假装自己是一次-tool-call"&gt;长任务别再假装自己是一次 tool call
&lt;/h2&gt;&lt;p&gt;鬼哥在公司做 Agent 流程时，批量处理、生成报告、扫描代码、部署环境这类任务很常见。它们可能跑几分钟，甚至更久。&lt;/p&gt;
&lt;p&gt;硬把这种工作塞进一次 tool call，体验通常是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client：还活着吗？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server：在跑。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client：跑哪了？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server：你先别断。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;网关：时间到了，我帮你们断。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;新规范把 Tasks 从 experimental core 移到 &lt;code&gt;io.modelcontextprotocol/tasks&lt;/code&gt; extension，并提供：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;poll-based &lt;code&gt;tasks/get&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tasks/update&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;subscriptions/listen&lt;/code&gt; 订阅通知&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这意味着长任务可以有明确身份、状态和更新机制，不需要伪装成一条永远不结束的普通请求。&lt;/p&gt;
&lt;p&gt;更重要的是，MCP 正式确立了 extensions 框架。新能力可以先在扩展中演进，成熟后再决定是否进入核心，core 则保持小而稳定。&lt;/p&gt;
&lt;p&gt;同时，新规范给出至少 12 个月的弃用窗口。Roots、Sampling、Logging 和 legacy HTTP+SSE transport 被标记为 deprecated，但不会第二天突然断气。&lt;/p&gt;
&lt;p&gt;这才是一个成熟协议该有的演进方式：能往前走，也不半夜掀生产系统的桌子。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心协议不是收纳箱。什么都往里塞，最后就只剩下“核心”两个字比较轻。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="这次升级公司团队该检查什么"&gt;这次升级，公司团队该检查什么
&lt;/h2&gt;&lt;p&gt;官方表示，TypeScript、Python、Go、C# 四个 Tier 1 SDK 已经支持 &lt;code&gt;2026-07-28&lt;/code&gt;，Rust SDK 也有 beta 支持。&lt;/p&gt;
&lt;p&gt;如果你在公司维护远程 MCP server，别只看完 release note 点个赞。建议直接拉开发、平台和安全团队过一遍下面这张表：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;检查项&lt;/th&gt;
 &lt;th&gt;结合现有系统要问的问题&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;协议版本&lt;/td&gt;
 &lt;td&gt;是否支持 &lt;code&gt;2026-07-28&lt;/code&gt;？旧客户端如何降级？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;session 依赖&lt;/td&gt;
 &lt;td&gt;是否依赖 &lt;code&gt;Mcp-Session-Id&lt;/code&gt;、sticky session 或共享会话存储？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;状态句柄&lt;/td&gt;
 &lt;td&gt;跨调用状态能否改成显式 &lt;code&gt;task_id&lt;/code&gt; / &lt;code&gt;workspace_id&lt;/code&gt;？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;网关路由&lt;/td&gt;
 &lt;td&gt;能否利用 &lt;code&gt;Mcp-Method&lt;/code&gt; / &lt;code&gt;Mcp-Name&lt;/code&gt; 做限流、鉴权和观测？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;list 缓存&lt;/td&gt;
 &lt;td&gt;工具、资源和 prompt 列表能否提供稳定顺序与缓存提示？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;MRTR&lt;/td&gt;
 &lt;td&gt;用户确认、补参数和二次授权能否改成 input-required / retry？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Auth&lt;/td&gt;
 &lt;td&gt;issuer 校验、credential 绑定和 DCR 迁移是否有计划？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;链路追踪&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;traceparent&lt;/code&gt; / &lt;code&gt;tracestate&lt;/code&gt; / &lt;code&gt;baggage&lt;/code&gt; 能否贯穿调用链？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;长任务与弃用项&lt;/td&gt;
 &lt;td&gt;是否应迁移到 Tasks extension？是否还依赖旧能力？&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img alt="MCP 2026-07-28 迁移检查清单" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://luoli523.github.io/p/mcp-stateless-core/migration-checklist.webp" srcset="https://luoli523.github.io/p/mcp-stateless-core/migration-checklist_hu_9df446cc227ef07e.webp 800w, https://luoli523.github.io/p/mcp-stateless-core/migration-checklist.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;p&gt;这一版真正拉开的，不再是谁能多暴露几个 tools，而是谁的 MCP server 能做到：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stateless
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;routable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cacheable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;observable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;governable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;extensible
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;过去我们评价一个 MCP server，常问的是：&lt;strong&gt;它能不能用？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接下来公司真正会问的是：&lt;strong&gt;它能不能扩，能不能管，能不能查，出了事能不能解释？&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="最后mcp-开始进入真正的淘汰赛"&gt;最后：MCP 开始进入真正的淘汰赛
&lt;/h2&gt;&lt;p&gt;过去一年，MCP 的第一阶段是“万物皆可接”：数据库、浏览器、GitHub、Slack、Figma、云服务、公司内部系统，先把工具接进来再说。&lt;/p&gt;
&lt;p&gt;这个阶段很热闹，也很重要。&lt;/p&gt;
&lt;p&gt;但工具数量决定的是 demo 看起来有多丰富，基础设施能力决定的是公司敢不敢把它留在生产环境。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2026-07-28&lt;/code&gt; 这版规范最有价值的地方，就是它终于开始正面处理那些不适合发布会截图、却每天折磨工程团队的问题：会话、扩容、路由、缓存、授权、长任务和协议演进。&lt;/p&gt;
&lt;p&gt;所以鬼哥的判断是：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MCP 的上半场，比的是谁接的工具多；下半场，比的是谁更像基础设施。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Agent 要真正进入公司，不缺会调用工具的 demo。&lt;/p&gt;
&lt;p&gt;缺的是一套能被负载均衡接住、被网关看懂、被安全系统治理、被运维团队放心扩容的协议。&lt;/p&gt;
&lt;p&gt;苦旧 MCP 久矣。&lt;/p&gt;
&lt;p&gt;这一次，新的 MCP 总算开始治病了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.modelcontextprotocol.io/posts/2026-07-28/" target="_blank" rel="noopener"
 &gt;The 2026-07-28 Specification | Model Context Protocol Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/" target="_blank" rel="noopener"
 &gt;The 2026-07-28 MCP Specification Release Candidate | Model Context Protocol Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://modelcontextprotocol.io/" target="_blank" rel="noopener"
 &gt;Model Context Protocol Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>