首页 / 文章

将MCP服务器迁移至2026-07-28规范:二十分钟,逐步指导

在大约二十分钟内将MCP服务器升级到2026-07-28版本:会话功能已移除,需了解的五项变更,Python SDK 2.0的操作步骤以及MRTR的重新编写。

发布者:REACTAPP.TOP阅读约 10 分钟2207 词

来源: Your MCP Server Is Running on a Deprecated Spec. Here’s the 20-Minute Migration.

没有任何东西出故障,而这恰恰令人不安。2026年7月28日,Model Context Protocol发布了其2026-07-28版本规范,这是远程MCP首次出现以来的最大变动。服务器们依赖的某个头部信息已被废弃,传输模型也发生了变化,但兼容性依然得以保持。服务器们继续运行,没有出现堆栈跟踪、警报或红色构建提示。

这就是那种隐蔽的技术债务。它一直隐藏着,直到有人需要扩展系统,或者12个月的废弃周期结束导致某个依赖项不再得到维护。仍在使用2025-11-25版本规范的服务器已经落后于当前标准;而那些采用旧版HTTP+SSE传输方式的服务器则在使用已被废弃的技术,此外还有三项功能可能即将停止支持。

接下来的内容将介绍有哪些变化、维护者为何做出这些改变以及如何跟上进度。对于大多数服务器而言,所需时间约为二十分钟。不过有一项变更实际上是对某些服务器的彻底重写,最好提前说明这一点。

会话机制为何被废弃

工程上的考量解释了其余所有问题。MCP于2024年底作为一种以会话为导向的协议推出:客户端通过initialize握手启动连接,服务器会生成一个,之后的所有请求都会携带该标识。这种设计最初适用于同一台机器上通过标准输入输出连接的一个客户端和一个服务器的场景。

后来服务器迁移到了真正的基础设施上,设计便遇到了瓶颈。谷歌的工程师在他们关于无状态更新的文档中描述了这一问题:原本非常适合单个本地客户端的设计,在MCP服务器分散到云原生基础设施后便不再适用了。

想想会话 ID 需要什么条件:要么采用粘性路由,让同一个客户端始终连接到同一个实例;要么使用所有实例都能查询的共享会话存储。一个普通的 HTTP 服务若要实现任何实用功能,首先就需要具备考虑连接亲和性的负载均衡机制,以及类似 Redis 这样的工具来处理传输层问题。

David Soria Parra 和 Den Delimarsky 在发布文章中直截了当地指出:MCP 从一种双向、有状态的协议变成了无状态的请求/响应协议,而这正是那些希望提升系统可靠性和扩展性的开发者们最迫切希望看到的变更之一。如此高的需求源于其庞大的使用规模——一级 SDK 每月的下载量接近五亿次,而 TypeScript 和 Python SDK 的总下载量则均已突破十亿次。在如此大规模的应用场景下,不可能每次部署时都去解决会话亲和性问题。

因此会话概念不复存在。每个请求都会携带自身的协议版本、客户端身份及能力信息,这意味着在任何没有共享存储的简单轮询负载均衡器背后,任何请求都能到达任意实例。后续所有内容均基于此原则。

需要理解的五项变化

1. 无需握手,也无会话头部

initialize与initialized之间的信息交换以及Mcp-Session-Id头部已被正式废弃(SEP-2575和SEP-2567)。每个请求都是独立的,其版本、客户端身份及能力信息都包含在_meta字段中。符合新规范的一个请求格式如下:

POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search

{"jsonrpc":"2.0","id":1,"method":"tools/call",
 "params":{"name":"search","arguments":{"q":"otters"},
 "_meta":{"io.modelcontextprotocol/clientInfo":
              {"name":"my-app",
                "version":"1.0"}
          }}}

如果客户端希望事先了解服务器的功能,可以使用新的 server/discover RPC,该功能为可选项,已不再属于强制性的握手流程。

人们普遍担心应用程序将无法保持状态,但实际上它们仍然可以。从协议中移除会话信息并不意味着应用程序就必须是无状态的。当服务器需要保持连续性时,相关工具应生成一个明确的标识符,随后由模型将该标识符作为参数传回。这种方式比将状态嵌入传输层更有效,因为模型可以看到该标识符并将其在各个工具之间传递。可见的状态总比不可见的状态更好。

2. 两个强制性的头部信息

从现在开始,Streamable的HTTP请求必须包含Mcp-Method和Mcp-Name字段(SEP-2243),服务器需确认这些字段与请求内容匹配。这样做的好处是:网关、速率限制器或WAF可以通过这些头部信息来路由请求并统计流量,从而无需解析JSON。那些因为工具名称隐藏在请求载荷中而放弃在边缘层实施按工具单独限制速率的做法的人,现在有了解决方案。

3. 可缓存的列表响应

tools/list、prompts/list、resources/list以及resources/read的返回结果现在包含了ttlMs和cacheScope字段(SEP-2549),并且会以固定的顺序返回。客户端可以缓存您的工具目录,从而在重新连接时保持上游提示词缓存的稳定性。由于智能体的大部分令牌消耗都来自于反复发送的工具定义,这一功能同时也起到了控制成本的作用。

4. 更严格的授权机制

共有四项变更生效,其中一项或许能解释您之前遇到的某个漏洞:

  • 授权服务器应返回RFC 9207中定义的iss参数,客户端在兑换代码前必须对其进行验证(SEP-2468),从而堵住混淆攻击的漏洞。
  • 在动态客户端注册过程中,客户端会设置application_type(SEP-837),因此授权服务器不再拒绝桌面应用和命令行工具的localhost重定向请求。如果命令行工具的OAuth流程曾因redirect_uri错误而失败,很可能是这个原因。
  • 客户端凭证与创建它们的发行方绑定,无法在不同的授权服务器之间重复使用(SEP-2352)。
  • 动态客户端注册功能本身已被正式废弃,取而代之的是客户端ID元数据文档。该功能目前仍可用,但将在后续版本中移除。

5. 废弃功能列表

此处“废弃”一词意义重大。Roots、Sampling和Logging(SEP-2577)虽已被废弃但仍可正常使用,还有至少十二个月的过渡时间,新的实现不应采用这些功能。传统的HTTP+SSE传输方式也被废弃,同样有十二个月的过渡期。

Tasks并未被废弃,而是被迁移了位置。它从实验性核心模块升级为io.modelcontextprotocol/tasks扩展模块,可通过tasks/get进行查询,并通过新的tasks/update方法进行更新(SEP-2663)。现在,变更通知会通过一个统一的subscriptions/listen流传递,客户端可自行选择是否订阅。

最令人欣慰的是有了正式的废弃政策,且至少会提前十二个月通知。Real Python的报道还指出,90天的通知期限仅适用于存在活跃安全风险的情况,这一通知时间比以往任何时候都要长。这项政策或许比该版本中的其他任何内容都更为重要,因为它将仅供试验的协议与可用于构建商业产品的协议区分开来。

逐步迁移指南

该指南使用的是 Python SDK,其在四者中重命名带来的影响最为显著,不过 TypeScript、Go 和 C# 的实现方式则相同。

0 到 2 分钟:做出决策。如果服务器使用的是采样、引导或根节点机制,就需要进行彻底的重写,具体内容见下文。如果它仅提供工具和资源,可继续下一步。

2 到 5 分钟:升级 SDK。在规范发布的当天,Python SDK 已升级到 2.0.0 版本,现在执行 pip install mcp 即可获取 2.x 系列的版本。

pip install --upgrade "mcp>=2"

有一个需要了解的变更:SDK已从 httpx 更改为 httpx2。如果您的依赖树中其他地方仍使用了 httpx,请立即处理。

第5到10分钟:重命名该类。所有Python服务器都会受到影响。FastMCP现在变为 MCPServer,不再有别名,也不会提供废弃过渡方案:

# Before, on mcp 1.x
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Demo")

# After, on mcp 2.x
from mcp.server.mcpserver import MCPServer

mcp = MCPServer("Demo")

同一版本中还有三个名称被更改:

# Wire types are snake_case now
result.isError        # → result.is_error
tool.inputSchema      # → tool.input_schema

# The error class matches the new capitalisation
except McpError:      # → except MCPError:

mcp-types 现在已独立成包,但 mcp.types 仍然是支持的导入路径,因此原有的导入方式依然有效。需注意:那些使用独立版 fastmcp 包而非官方 SDK 的用户不会受到影响。那是另一个拥有自己 3.x 版本的项目,进行重命名的原因之一就是为了将两者区分开来。

10 至 15 分钟:移除会话相关功能。 可以删除会话字典、清理定时器以及专门用于存储会话状态的 Redis 实例。如果确实需要保证多次调用之间的连续性,可使用处理程序模式:

# Instead of hiding state in a session the model can't see:
@mcp.tool()
def open_dataset(path: str) -> str:
    """Open a dataset and return a handle for subsequent calls."""
    handle = register_dataset(path)     # your own store, your own TTL
    return handle                        # the model now HOLDS this

@mcp.tool()
def query_dataset(handle: str, query: str) -> list[dict]:
    """Query a previously opened dataset."""
    return lookup(handle).query(query)

第15至18分钟:验证新头部信息。服务器必须检查传入的Mcp-Method和Mcp-Name是否与请求一致。SDK已处理常规情况,但在自定义网关或手动编写的传输层背后,需要进行端到端验证。

第18至20分钟:修正错误代码。这一环节很容易被忽略,从而导致客户端行为混乱。资源缺失错误应使用标准的JSON-RPC无效参数代码-32602,而非MCP自身的-32002。

可安全发布

单个MCPServer即可支持两个协议版本,因此2025版本的客户端仍能在已迁移的服务器上正常工作,双方均无需进行任何配置。正因如此,它可以在普通的工作日就发布,无需在所有客户端之间协调特殊发布日。

何时需要更多时间

使用采样、引导或根节点的服务器需要彻底重写代码,Real Python称这是迁移清单中最复杂的部分。此前服务器可以通过保持开放的双向流发起请求并回传给客户端。而无状态设计则没有这样的流,因此需要通过多轮往返请求(SEP-2322)来实现功能。

新的处理流程如下:服务器会返回resultType: "input_required"以及需要回答的问题,客户端则需在inputResponses中包含答案后重复发起原始请求。这改变了工具的编写方式——处理程序不能在半途暂停等待答案,对于同一逻辑操作可能需要被多次调用,且必须在输入到达时正确继续处理,因此所有在暂停期间保存在局部变量中的数据都必须存储在可被重试访问的位置。

其带来的好处是实实在在的。Supabase的产品负责人表示,虽然功能开发早已被列入规划,但由于他们的MCP服务器以无状态方式运行,此前无法实现该功能,而MRTR则解决了这一问题,使得工具能够先与用户确认相关内容,比如新项目的成本或可能删除数据的查询操作。虽然编写这类工具会稍显复杂,但如今已可实现大规模的无状态运行。

新协议带来的优势

Manufact运营着数千台MCP服务器,并维护着开源的mcp-use框架。该框架测试显示,采用新的客户端-服务器架构后,SDK v2的体积缩小了约83%,速度提升了25%。Agentic AI Foundation的生态系统综述指出,现在的服务器行为与其他HTTP服务类似,由轮询均衡器随机选择实例来响应请求,而网关则通过头部信息负责路由和速率限制。这项为期十二个月的计划意味着该协议不会再发生重大变动。

对于一个开放标准而言,其 adoption 速度相当快。短短几天内,基础设施提供商、SDK 维护者、云平台以及工具供应商就纷纷宣布提供支持,发布了迁移指南,并推出了正式版本。Cloudflare 的 Agents SDK 从一开始就遵循该规范,Amazon Bedrock AgentCore 则提供了无状态核心功能,而 Microsoft Foundry、Netlify、Figma、Supabase 和 Honeycomb 也加入了这一行列。Honeycomb 表示,目前其每月的交互查询中几乎有五分之一来自这些代理,这也解释了为何这一发展如此重要。这些代理早已超越了演示阶段。

继续使用 1.x 版本

这同样是一个合理的选择。可以选择固定版本并等待后续更新:

# Buys you time, keeps security patches coming
pip install "mcp>=1.28,<2"

在那里时要知道两件事。1.x系列目前处于维护模式,仅提供安全修复。而Tasks扩展尚未纳入Python SDK 2.0版本,因此它虽未出现在SDK中,却已脱离核心规范。对于依赖Tasks的Python用户来说,等待是正确的选择。请在日历上设置提醒,注意Roots、Sampling和Logging功能停止使用的十二个月期限,因为在它们真正停止之前,这种淘汰过程似乎永无止境。

悄然淘汰的危险

破坏性变更很显眼:它会导致构建失败,引起人们注意,随后才会被修复。而淘汰机制则是刻意设计得悄无声息的。服务器依然运行,测试也能通过,没有任何警示信号出现,但问题却在逐渐累积:传输方式有有效期,无法轻松实现水平扩展,而且随着生态系统的发展,相关依赖项也处于维护模式。MCP-Protocol-Version中的版本号其实是一个日期,值得查看一下它现在是多少了。

对于大多数服务器而言,完成这项工作最多只需一个下午的时间,实际操作时间还不到半小时。使用采样或诱导方法的服务器则需预留一天的时间,先仔细阅读MRTR规范。无论哪种方式,都应在12个月悄然过去之前完成。

相关阅读

  • 16种RAG架构对比:哪种模式适合哪种问题 —— 梳理了从标准及混合检索到智能体、图结构及联邦式设计等四类层级中的16种RAG架构模式,并给出了逐月的构建顺序。
  • ClickHouse MCP与只读访问的局限性:为智能体提供结构化访问方式 —— 只读MCP访问只能阻止写入操作,无法避免数据错误、租户信息泄露或架构暴露等问题。了解ClickHouse基准测试的结果,以及结构化指标工具如何降低相关风险。
  • 用190行TypeScript构建可搜索的工作日志MCP服务器 —— 一个基于Markdown文件的小型MCP服务器:四个基于意图的工具、提示式描述、兼具测试功能的stdio演示客户端,以及实际使用中需要注意的问题。