← 全部文章

MCP 无状态协议迁移指南:2026-07-28 版本变更对 AI 网关的影响

MCP 2026-07-28 规范移除了会话 ID 和 initialize 握手。本迁移指南逐步讲解前后代码对比、负载均衡器配置变更、SDK 升级、显式句柄模式以及回滚路径。

· TheRouter

MCP 无状态协议迁移指南:2026-07-28 版本变更对 AI 网关的影响

MCP 2026-07-28 规范移除了会话 ID 和 initialize 握手。如果你运行 MCP 服务器、代理或网关,现在每个请求都是自包含的,任何服务器实例都可以处理它。本指南逐步讲解迁移过程——前后代码对比、基础设施变更、SDK 升级以及回滚路径——帮助你在 7 月 28 日最终规范发布前完成迁移。

我们撰写这篇指南是因为 MCP 无状态变更直接影响网关路由 AI 流量的方式。TheRouter 通过配置的 provider 路由 OpenAI 兼容请求,当网关运维人员调整 MCP 流量处理方式时,路由和 fallback 策略也需要同步调整。来源:MCP 2026-07-28 Release Candidate,检索于 2026-07-20。

核心变更:前后对比

MCP 2026-07-28 的核心变更是移除了两个强制有状态部署的协议特性:

  1. initialize/initialized 握手(由 SEP-2575 移除)。协议版本、客户端信息和能力声明现在通过每个请求的 _meta 字段传递。新增的 server/discover 方法替代了原来的能力交换。
  2. Mcp-Session-Id header 和协议级会话(由 SEP-2567 移除)。不再需要会话固定,不再需要共享会话存储。

变更前(2025-11-25): 客户端必须先发送 initialize 请求,获取会话 ID,然后在后续每个调用中携带 Mcp-Session-Id header:

// 第一步:Initialize 握手
POST /mcp
{"jsonrpc":"2.0","id":1,"method":"initialize",
 "params":{"protocolVersion":"2025-11-25","capabilities":{},
 "clientInfo":{"name":"my-app","version":"1.0"}}}

// 服务器返回 Mcp-Session-Id: 1868a90c-3a3f-4f5b

// 第二步:后续每个调用都必须携带会话 header
POST /mcp
Mcp-Session-Id: 1868a90c-3a3f-4f5b
{"jsonrpc":"2.0","id":2,"method":"tools/call",
 "params":{"name":"search","arguments":{"q":"otters"}}}

变更后(2026-07-28): 单个自包含请求,任何实例都能处理:

POST /mcp
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json

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

没有握手,没有会话 ID,没有任何固定。来源:MCP 2026-07-28 Release Candidate,检索于 2026-07-20。

迁移清单:基础设施

  1. 替换三个值,不是三个 SDK。在现有 OpenAI 客户端里改 api_key、base_url、model。请求与响应代码保持不变。
  2. 显式映射 model ID。目标供应商的 model id 几乎不会和 OpenAI 完全一致。 在业务代码之外维护一份 { openai_id: target_id } 映射。
  3. 验证流式格式。SSE 分片必须遵循 OpenAI 的 data: {...} + data: [DONE] 契约。切生产前先跑一次流式调用。
  4. 检查限流响应头。部分供应商不返回 x-ratelimit-*。 在包装层 做缺省兜底,缺头不要崩。
  5. 留回滚路径。用 feature flag 切流;新旧 endpoint 影子并行 24 小时,再正式切换。

第一步:移除粘性会话和会话亲和性

如果你的负载均衡器(NGINX、HAProxy、AWS ALB、Azure App Service ARR)使用基于 Mcp-Session-Id 的粘性路由或 cookie 亲和性,请禁用它。协议现在是无状态的,任何服务器实例都可以处理任何请求。

NGINX 变更前:

upstream mcp_backend {
    ip_hash;  # 或 sticky cookie
    server mcp1:8080;
    server mcp2:8080;
}

NGINX 变更后:

upstream mcp_backend {
    # 轮询,不需要粘性会话
    server mcp1:8080;
    server mcp2:8080;
}

Azure App Service: 在 ARM 模板或 App Service 配置中设置 clientAffinityEnabled: false。来源:Microsoft Tech Community — MCP Stateless on App Service,检索于 2026-07-20。

第二步:基于 Mcp-Method header 进行路由

Streamable HTTP 传输层现在要求每个请求包含 Mcp-Method header,工具调用、资源读取和 prompt 获取请求还要求包含 Mcp-Name(SEP-2243)。这意味着你的网关可以直接在 header 层路由、限流或记录 MCP 流量,无需解析 JSON-RPC body。

NGINX 示例——按 Mcp-Method 路由:

location /mcp {
    # 对 tools/call 和 tools/list 分别限流
    if ($http_mcp_method = "tools/call") {
        set $rate_zone tool_calls;
    }
    if ($http_mcp_method = "tools/list") {
        set $rate_zone tool_lists;
    }
    proxy_pass http://mcp_backend;
}

服务器会拒绝 header 与 body 不一致的请求。确保反向代理在转发时保留 Mcp-Method 和 Mcp-Name header。

第三步:下线共享会话存储

如果你运行 Redis、Memcached 或数据库来跨 MCP 服务器实例共享 Mcp-Session-Id → 状态映射,该基础设施不再需要用于协议状态。你可以将其下线或改用于应用级状态(参见下面的显式句柄模式)。来源:4sysops — MCP 2026-07-28 Overview,检索于 2026-07-20。

第四步:启用响应缓存

列表和资源读取结果现在包含 ttlMs 和 cacheScope 字段(SEP-2549),参照 HTTP Cache-Control 设计。你的网关可以按 ttlMs 指定的时间缓存 tools/list 响应,cacheScope 会告诉你该响应是否可以跨用户共享("global")还是仅限单用户。

这样就不再需要保持 SSE 长连接来检测工具列表变更。

迁移清单:SDK 和服务器代码

第五步:升级你的 MCP SDK

四个一级 SDK 的 beta 版本现已发布。来源:Beta SDKs for the 2026-07-28 MCP Spec Release Candidate,检索于 2026-07-20。

SDKBeta 版本安装命令
Pythonv2.0.0b1uv add "mcp[cli]==2.0.0b1" 或 pip install "mcp[cli]==2.0.0b1"
TypeScriptv2 betanpm install @modelcontextprotocol/server@beta
Gov1.7.0-pre.1使用现有模块的 pre-release 标签
C#2.0.0-preview.1安装 ModelContextProtocol preview 包

库作者注意: 如果你发布的库依赖 Python mcp 包,现在就添加上限约束(如 mcp>=1.27,<2),避免 v2 正式发布时影响用户。

第六步:移除 initialize 握手代码

如果你的服务器实现了自定义的 initialize 处理器,现在可以移除。在新模型中:

  • 客户端信息来自每个请求的 _meta.io.modelcontextprotocol/clientInfo
  • 协议版本来自 MCP-Protocol-Version HTTP header
  • 服务器能力通过新的 server/discover 方法提供,替代 initialize 响应

Python v1(变更前):

@app.handle("initialize")
async def handle_initialize(params):
    return {"protocolVersion": "2025-11-25",
            "capabilities": {"tools": {}},
            "serverInfo": {"name": "my-server", "version": "1.0"}}

Python v2(变更后):

from mcp.server import MCPServer

mcp = MCPServer("my-server")

@mcp.tool()
def search(q: str) -> str:
    """搜索内容。"""
    return f"Results for {q}"
# server/discover 由 SDK 自动处理

第七步:为有状态工具采用显式句柄模式

移除协议级会话并不意味着你的应用不能有状态。如果你的工具需要跨调用保持状态,创建一个显式句柄并让模型作为参数传递:

@mcp.tool()
def create_session(config: dict) -> dict:
    """创建工作会话并返回句柄。"""
    session_id = store.create(config)  # 持久化到 Redis/数据库
    return {"session_id": session_id}

@mcp.tool()
def continue_work(session_id: str, action: str) -> dict:
    """在已有会话中继续工作。"""
    state = store.get(session_id)  # 从共享存储中获取
    result = process(state, action)
    store.update(session_id, state)
    return result

这种模式比隐式会话状态更强大:模型可以看到句柄、跨工具组合使用、推理,并在步骤之间传递。来源:MCP 2026-07-28 Release Candidate — Stateless Protocol, Stateful Applications,检索于 2026-07-20。

第八步:更新错误码处理

资源未找到的错误码从 MCP 自定义的 -32002 改为 JSON-RPC 标准的 -32602(Invalid Params),参照 SEP-2164。更新所有匹配 -32002 字面值的客户端代码。

- if error.code == -32002:
-     handle_resource_not_found()
+ if error.code == -32602:
+     handle_resource_not_found()

第九步:处理已弃用的特性

本版本弃用了三个特性(SEP-2577):

特性替代方案紧迫程度
Roots工具参数、资源 URI 或服务器配置低——12 个月以上仍可使用
Sampling直接集成 LLM provider API低——12 个月以上仍可使用
Loggingstdio 传输用 stderr;结构化可观测性用 OpenTelemetry低——12 个月以上仍可使用

这些只是标注性弃用。相关方法、类型和能力标志在本版本以及一年内发布的所有规范版本中继续有效。但建议现在就规划迁移。

服务端到客户端请求:Multi Round-Trip Requests(MRTR)

如果你的服务器在工具调用过程中向客户端发送提示(如通过 elicitation 确认对话),机制已经改变。不再需要保持 SSE 流打开,服务器现在返回 InputRequiredResult:

{
  "resultType": "inputRequired",
  "inputRequests": {
    "confirm": {
      "type": "elicitation",
      "message": "删除 3 个文件?",
      "schema": {"type": "boolean"}
    }
  },
  "requestState": "eyJzdGVwIjox..."
}

客户端收集答案后,携带 inputResponses 和回传的 requestState 重新发送原始调用。任何服务器实例都可以处理这个重试,因为所有需要的信息都在 payload 中。来源:MCP 2026-07-28 Release Candidate — Multi Round-Trip Requests,检索于 2026-07-20。

回滚路径

7 月 28 日不会有任何强制中断。新 SDK 支持向后兼容:

  • 新客户端连接旧服务器: 使用 2026-07-28 协议的客户端会自动 fallback 到 initialize 握手以连接 2025-11-25 或更早的服务器。
  • 新服务器接受旧客户端: Python v2 服务器同时响应旧版 initialize 握手和 server/discover,因此现有客户端可以继续连接。
  • 混合部署: 迁移期间可以同时运行 2025-11-25 和 2026-07-28 服务器实例。旧实例保持会话亲和性,新实例是无状态的。

如果迁移遇到问题,将 SDK 回退到 v1 并重新启用粘性会话即可。旧协议继续有效。

成本变化

无状态协议从三个方面降低了基础设施成本:

  1. 无需共享会话存储。 不再需要 Redis 或 Memcached 来跨实例存储协议级会话状态。
  2. 负载均衡更简单。 轮询替代粘性会话,不再需要支持亲和性的负载均衡器或高级健康检查。
  3. 响应缓存。 列表结果的 ttlMs 和 cacheScope 让网关可以缓存 tools/list 响应,减少冗余调用。

代价是:如果你的工具有复杂的有状态工作流,现在需要你显式管理状态(Redis、数据库等),而不是依赖协议。但这些状态本来就应该外部化——协议会话只是一种便利,不是解决方案。

TheRouter 集成

TheRouter 通过配置的 provider 路由 OpenAI 兼容请求,并在实际产品路径支持的情况下提供 provider/模型路由和 fallback。MCP 无状态变更影响网关运维人员在标准 LLM API 调用旁代理 MCP 流量的方式:

  • 基于 header 的路由。 Mcp-Method 和 Mcp-Name header 让你可以通过同一个网关路由 MCP 和 LLM API 流量,使用不同的限流和路由规则。
  • 统一 fallback。 如果 MCP 服务器不可用,适用于 LLM API provider 的同一套 fallback 路由模式同样适用。参阅我们的 LLM API Fallback 路由指南了解工程模式。
  • 迁移对齐。 如果你正在从 OpenAI 迁移到 TheRouter,MCP 无状态变更简化了网关层。参阅我们的 OpenAI 迁移到 TheRouter 指南了解完整流程。

时间线和后续步骤

日期事件
2026 年 5 月 21 日Release candidate 锁定
现在(2026 年 7 月)四个一级 SDK 的 beta 版本可用
2026 年 7 月 28 日最终规范发布
约 2027 年 1 月已弃用特性(Roots、Sampling、Logging)最早可能移除

行动项:

  1. 现在就用 beta SDK 测试你的工作负载。
  2. 审查负载均衡器和网关配置中的会话亲和性设置。
  3. 排查所有依赖 Mcp-Session-Id、initialize 或错误码 -32002 的代码。
  4. 规划有状态工具的显式句柄迁移。
  5. 更新监控,跟踪新的 Mcp-Method header 用于可观测性。

来源

帮助与联系