MCP 7/28 最大改版实测:扒开真实 HTTP 请求,无状态化到底改了什么

MCP 7/28 最大改版实测:扒开真实 HTTP 请求,无状态化到底改了什么 2026年7月28日MCPModel Context Protocol正式发布 2026-07-28 版本规范官方称之为自发布以来最大规模的协议修订。本文搭建了新旧两套规范的服务端实例通过真实 HTTP 报文拆解本次改版的核心变化、设计逻辑与生产迁移路径。1. MCP 是什么 这次改版为什么是大地震简单来说MCP 是 AI 工具调用的“通用接口协议”——无论你使用的是 Claude、GPT 还是 Gemini 类大模型都可以通过同一套协议标准调用外部工具、访问数据源与对接服务。举一个最基础的调用示例// AI 客户端通过 MCP 协议调用搜索工具 const result await client.callTool({ name: search, arguments: { q: otters } });自2025年底发布以来MCP 迅速成为 AI Agent 生态的主流工具调用协议GitHub、主流 AI 开发编辑器等均已原生支持被大量企业用于内部 AI Agent 落地。Anthropic 已将协议捐赠给 Linux 基金会推动其成为行业通用标准。而本次 7/28 改版的核心是彻底移除了协议层的有状态设计旧版本依赖initialize握手 Mcp-Session-Id维持会话所有请求必须绑定到固定服务实例新版本转为完全无状态架构每个请求自包含全部必要信息任意实例均可独立处理。这不是简单删一个字段的改动它从底层改变了 MCP 服务的部署架构、网关路由方式、缓存策略与水平扩展模式。2. 旧规范的设计与生产痛点2.1 旧规范的完整请求流程旧规范2025-11-25采用经典的“握手-会话”模式和传统 Web 的 Cookie/Session 机制逻辑一致注HTTP 协议本身是无状态的会话能力是应用层基于协议扩展实现的。完整请求时序如下客户端 服务端 │ │ │── POST /mcp ──────────────────────────→│ │ method: initialize │ │ params: { protocolVersion, │ │ capabilities, clientInfo } │ │ │ │←── 200 OK ─────────────────────────────│ │ Mcp-Session-Id: UUID ← 服务端分配会话 │ result: { 协议版本、服务端能力等 } │ │ │ │ 后续所有请求必须携带 Mcp-Session-Id │ │ │ │── POST /mcp ──────────────────────────→│ │ Mcp-Session-Id: UUID │ │ method: tools/list │ │ │ │←── 200 OK ─────────────────────────────│ │ result: { tools: [...] } │ │ │ │── POST /mcp ──────────────────────────→│ │ Mcp-Session-Id: UUID │ │ method: tools/call │ │ params: { name, arguments } │ │ │ │←── 200 OK ─────────────────────────────│ │ result: { content: [...] } │2.2 生产环境三大核心痛点这套设计在单实例场景下简单易用但放到分布式生产环境中会带来三个难以回避的问题痛点一负载均衡被会话绑定若采用内存级 Session 存储负载均衡必须配置 sticky session粘性会话将同一 Session 的请求固定路由到同一实例。一旦对应实例宕机该实例上的所有会话会全部失效客户端必须重新握手建立连接。痛点二水平扩展依赖共享存储要解决单点故障问题必须引入 Redis 等外部存储统一保存 Session 状态。每个请求都需要额外一次 Session 查询开销同时还要处理 Session 过期、续期、存储宕机降级等一系列运维问题。痛点三网关路由必须解析请求体如果要按方法做路由比如把tools/call路由到执行集群、resources/list路由到目录服务网关必须解析 JSON-RPC 请求体才能拿到method字段。Nginx 原生不支持该能力需要引入 Lua 或 NJS 扩展即使是专业 API 网关每次请求解析 JSON 也会带来额外性能开销与配置复杂度。2.3 真实 HTTP 请求旧规范实测以下是基于旧规范实现的服务端真实请求与响应报文步骤1initialize 握手请求POST /mcp HTTP/1.1 Content-Type: application/json { jsonrpc: 2.0, id: 1785172985193, method: initialize, params: { protocolVersion: 2025-11-25, capabilities: {}, clientInfo: { name: demo-client, version: 1.0 } } }握手响应返回会话IDHTTP/1.1 200 OK Content-Type: application/json Mcp-Session-Id: ce843e95-50bc-471f-bd8b-dcbcf75dc998 { jsonrpc: 2.0, id: 1785172985193, result: { protocolVersion: 2025-11-25, capabilities: { tools: { listChanged: true } }, serverInfo: { name: old-mcp-server, version: 1.0.0 } } }步骤2携带会话调用 tools/listPOST /mcp HTTP/1.1 Mcp-Session-Id: ce843e95-50bc-471f-bd8b-dcbcf75dc998 Content-Type: application/json { jsonrpc: 2.0, id: 1785172985206, method: tools/list, params: {} }步骤3不带会话直接请求被拒绝HTTP/1.1 400 Bad Request Content-Type: application/json { jsonrpc: 2.0, id: 4, error: { code: -32600, message: Missing or invalid Mcp-Session-Id } }可以看到旧规范下会话是一切请求的前提没有有效 Session 连工具列表都无法查询。3. 新规范核心协议层无状态化3.1 核心变更总览新规范从协议层面彻底移除了会话机制核心变化可以总结为三点旧规范2025-11-25新规范2026-07-28架构影响必须先 initialize 握手无握手直接发请求连接成本降低支持短连接请求所有请求携带 Mcp-Session-Id无会话ID请求自包含任意实例可处理任意请求支持轮询负载均衡clientInfo 在握手阶段传递clientInfo 放在请求 params._meta 中每个请求独立携带上下文不依赖服务端存储通俗来讲旧规范是“先登记开户再凭号办事”新规范是“带齐材料直接办谁接都能处理”。3.2 真实 HTTP 请求新规范实测以下是基于新规范实现的服务端真实请求与响应报文步骤1发送 initialize 握手直接被拒绝POST /mcp HTTP/1.1 MCP-Protocol-Version: 2026-07-28 Content-Type: application/json { jsonrpc: 2.0, id: 1785172986531, method: initialize, params: {} }响应明确告知方法已移除HTTP/1.1 200 OK Content-Type: application/json { jsonrpc: 2.0, id: 1785172986531, error: { code: -32601, message: initialize handshake removed in 2026-07-28 } }注JSON-RPC 协议标准下方法不存在属于业务层面错误通常返回 HTTP 200 状态码 错误体部分实现会使用 400 状态码二者均被兼容。步骤2直接请求 tools/list无会话POST /mcp HTTP/1.1 MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/list Content-Type: application/json { jsonrpc: 2.0, id: 1785172986550, method: tools/list, params: {} }响应携带缓存控制信息HTTP/1.1 200 OK Content-Type: application/json MCP-Tool-Cache: ttlMs300000; cacheScopeshared { jsonrpc: 2.0, id: 1785172986550, result: { tools: [ { name: search, description: 通用文本搜索工具, inputSchema: { type: object, properties: { q: { type: string, description: 搜索关键词 } }, required: [q] } } ], _meta: { cacheControl: { ttlMs: 300000, cacheScope: shared } } } }步骤3调用工具_meta 携带客户端信息POST /mcp HTTP/1.1 MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/call Mcp-Name: search Content-Type: application/json { jsonrpc: 2.0, id: 1785172986551, method: tools/call, params: { name: search, arguments: { q: otters }, _meta: { io.modelcontextprotocol.clientInfo: { name: demo-client, version: 1.0 } } } }整个流程没有任何会话依赖每个请求独立完整打到任意一个服务实例都能正常处理。3.3 头体一致性校验机制新规范新增了 HTTP 头与请求体的一致性校验Mcp-Method头的值必须和 JSON-RPC body 中的method字段完全一致Mcp-Name头的值必须和params.name字段一致。如果二者不匹配服务端会直接拒绝请求HTTP/1.1 400 Bad Request Content-Type: application/json { jsonrpc: 2.0, id: 1785172986552, error: { code: -32602, message: Header Mcp-Method (tools/call) disagrees with body method (tools/list) } }这个设计的核心作用是保障网关路由的正确性网关按头路由到对应处理集群后服务端再做一次校验避免路由错误导致请求被错误处理。4. Mcp-Method 头网关层的协议友好设计4.1 新旧路由方式对比旧规范下网关要实现按方法路由必须深度解析请求体收到请求 → 读取完整Body → 解析JSON → 提取method字段 → 路由到对应后端Nginx 原生不支持该能力必须引入第三方模块配置复杂且性能有损耗。新规范下方法名直接放在 HTTP 头中网关只需读取头字段即可路由收到请求 → 读取 Mcp-Method 头 → 路由到对应后端Nginx 原生配置示例map $http_mcp_method $mcp_backend { tools/list backend_catalog; tools/call backend_executor; default backend_default; } server { location /mcp { proxy_pass http://$mcp_backend; proxy_set_header Host $host; } }4.2 不止是路由生产级附加价值把方法名放到头里带来的收益远不止配置简化可观测性日志、监控系统可以直接记录Mcp-Method字段无需解析请求体就能统计每个方法的调用量、耗时与错误率。安全管控WAF、网关可以直接按方法做限流、权限拦截与风控策略无需引入 JSON 解析能力。缓存适配CDN 与网关缓存可以直接用Mcp-Method作为缓存 Key 的一部分适配只读类接口的缓存策略。5. tools/list 原生缓存减少重复请求5.1 旧规范的问题旧规范中tools/list没有任何缓存机制客户端每次需要确认工具列表时都要发起请求。但实际生产中大多数 MCP 服务的工具列表更新频率很低可能几天甚至几周才变更一次大量重复请求属于无效开销。在高并发 AI Agent 场景下tools/list甚至会成为占比最高的请求占用不必要的服务资源。5.2 新规范的缓存机制新规范在协议层面原生支持缓存控制tools/list等只读接口可以同时通过两种方式返回缓存策略HTTP 响应头 ****MCP-Tool-Cache方便网关、CDN 直接读取处理响应体 ****_meta.cacheControl方便客户端业务层读取使用两个核心字段含义ttlMs缓存有效期单位毫秒cacheScope缓存范围shared表示可跨客户端共享private表示仅单客户端可用5.3 缓存优先级与边界优先级HTTP 头 响应体字段二者不一致时以响应头为准。适用范围仅幂等的只读类接口如tools/list、resources/list支持缓存写入类、执行类接口不允许缓存。失效机制服务端更新工具列表后可通过调整ttlMs控制生效时间客户端也可主动跳过缓存重新请求。6. 两大扩展能力适配无状态改造6.1 MCP Apps服务端渲染交互式UIMCP AppsSEP-1865是本次新增的能力允许服务端返回交互式 HTML 界面由客户端在沙箱 iframe 中渲染替代旧规范的 Roots 能力。核心设计UI 模板提前声明工具在tools/list阶段就声明自己的 UI 模板地址客户端可以预取、缓存与安全审查。沙箱隔离运行HTML 在受限 iframe 中执行无法直接访问宿主环境与用户数据。统一审计路径所有 UI 触发的操作仍然走标准 JSON-RPC 调用流程经过客户端的权限确认与审计。适用场景包括数据可视化仪表盘、复杂表单输入、向导式多步操作等。6.2 Tasks长任务从长连接改为轮询旧规范中长时间运行的任务通过 SSE 长连接流式推送状态天然和单个服务实例绑定和有状态会话深度耦合。新规范将 Tasks 重构为无状态轮询模型客户端 服务端 │ │ │── tools/call 触发任务 ────────────────→│ │ │ │←── 返回 taskHandle 任务句柄 ────────────│ │ │ │ 客户端按间隔轮询任务状态 │ │── tasks/get?handlexxx ───────────────→│ 可打到任意实例 │←── { status: running, progress: 40 } ──│ │ │ │── tasks/get?handlexxx ───────────────→│ 可打到不同实例 │←── { status: completed, result: ... } ──│任务状态统一存储在共享存储Redis/数据库中任意实例都可以查询任务状态完全摆脱了实例绑定。7. 6 个 SEP 协同实现无状态化本次无状态化改造不是单个变更而是由 6 个 SEP规范增强提案共同配合完成的完整体系SEP 编号名称核心作用变更类型破坏性SEP-2575移除 initialize 握手取消握手流程clientInfo 移入请求 _meta核心协议变更是SEP-2567移除 Mcp-Session-Id删除协议层会话机制请求完全自包含核心协议变更是SEP-2243Mcp-Method / Mcp-Name 头方法与工具名提升到 HTTP 头支持网关原生路由核心协议变更是SEP-2549可缓存结果规范定义统一的缓存控制字段与头格式兼容新增否SEP-2322多轮往返请求(MRTR)服务端需要用户输入时返回不透明状态令牌替代 SSE 长连接交互核心协议变更是SEP-2663Tasks 扩展重构长任务改为句柄轮询模式适配无状态架构扩展能力变更是使用Tasks的服务完整逻辑链路删握手 → 去会话 → 网关可路由 → 接口可缓存 → 交互无长连接 → 长任务无绑定 → 全链路无状态。除此之外本次更新还包含授权硬化OAuth 2.1 PKCE 强制要求、废弃 Roots/Sampling/Logging 三项旧能力、JSON Schema 版本升级等配套变更。8. 迁移指南与生产落地建议8.1 必须修改的 5 项核心变更序号变更点迁移方式1移除 initialize 握手删除客户端握手逻辑直接发起业务请求2移除 Mcp-Session-Id删除会话管理、续期、失效处理逻辑3新增协议版本头每个请求携带MCP-Protocol-Version: 2026-07-284新增路由头推荐每个请求携带Mcp-Method、Mcp-Name头5clientInfo 位置变更从握手参数移入每个请求的params._meta中8.2 废弃功能与迁移窗口以下功能设置了 12 个月的兼容过渡期过渡期后将正式移除Roots→ 迁移至 MCP AppsSampling→ 迁移至 MCP Apps Tasks 组合方案Logging→ 迁移至 OpenTelemetry 等标准可观测方案HTTPSSE 传输→ 迁移至标准 HTTP 请求 轮询/流式响应模式8.3 生产级双版本兼容方案不建议生产环境一刀切升级推荐通过版本头做兼容网关读取MCP-Protocol-Version头存在且为新版本则路由到新服务集群。缺失版本头则默认走旧规范逻辑兼容存量客户端。业务逻辑层抽成公共模块新旧协议层分别做请求解析与响应封装。8.4 无状态后的业务会话方案协议层移除会话不代表业务不能有会话客户端生成业务会话 ID放在请求_meta中传递。服务端基于业务会话 ID 从共享存储读取上下文不依赖协议层 Session。鉴权信息通过Authorization头携带每个请求独立校验。8.5 迁移检查清单删除 initialize 握手与会话管理代码所有请求添加协议版本头与方法头clientInfo 移入每个请求的 _meta 字段SSE 长连接交互迁移为 MRTR 或 Tasks 轮询检查并迁移 Roots / Sampling / Logging 废弃能力inputSchema 升级为 JSON Schema 2020-12 兼容错误码对齐 JSON-RPC 标准码远程部署服务接入 OAuth 2.1 PKCE 授权9. 实战新规范服务端完整实现以下是符合 2026-07-28 规范的最小可用服务端代码包含所有必要的校验与错误处理import http from node:http; const PORT 3102; const PROTOCOL_VERSION 2026-07-28; const MAX_BODY_SIZE 1024 * 1024; // 1MB 请求体限制 // 工具定义 const tools [ { name: search, description: 通用文本搜索工具, inputSchema: { type: object, properties: { q: { type: string, description: 搜索关键词 } }, required: [q] } } ]; // 统一响应工具 function sendJson(res, statusCode, id, resultOrError) { res.writeHead(statusCode, { Content-Type: application/json }); res.end(JSON.stringify({ jsonrpc: 2.0, id: id ?? null, ...resultOrError })); } function sendError(res, statusCode, id, code, message) { sendJson(res, statusCode, id, { error: { code, message } }); } const server http.createServer((req, res) { // 仅处理 POST /mcp if (req.url ! /mcp) { return sendError(res, 404, null, -32601, Endpoint not found); } if (req.method ! POST) { return sendError(res, 405, null, -32601, Method not allowed); } // 校验 Content-Type const contentType req.headers[content-type]; if (!contentType || !contentType.includes(application/json)) { return sendError(res, 415, null, -32600, Unsupported Media Type); } // 校验协议版本 const protocolVersion req.headers[mcp-protocol-version]; if (!protocolVersion || protocolVersion ! PROTOCOL_VERSION) { return sendError(res, 400, null, -32600, Unsupported protocol version. Expected ${PROTOCOL_VERSION}); } // 读取请求体限制大小 let body ; let bodySize 0; req.on(data, chunk { bodySize chunk.length; if (bodySize MAX_BODY_SIZE) { req.destroy(); return sendError(res, 413, null, -32600, Payload too large); } body chunk; }); req.on(end, () { // 解析 JSON let json; try { json JSON.parse(body); } catch (e) { return sendError(res, 400, null, -32700, Parse error); } const { id, method, params {} } json; // 校验 Mcp-Method 头一致性 const headerMethod req.headers[mcp-method]; if (headerMethod headerMethod ! method) { return sendError(res, 400, id, -32602, Header Mcp-Method (${headerMethod}) disagrees with body method (${method})); } // 路由处理 switch (method) { case initialize: return sendError(res, 200, id, -32601, initialize handshake removed in 2026-07-28); case server/discover: return sendJson(res, 200, id, { result: { serverInfo: { name: demo-mcp-server, version: 1.0.0 }, protocolVersion: PROTOCOL_VERSION, capabilities: { tools: {} } } }); case tools/list: res.setHeader(MCP-Tool-Cache, ttlMs300000; cacheScopeshared); return sendJson(res, 200, id, { result: { tools, _meta: { cacheControl: { ttlMs: 300000, cacheScope: shared } } } }); case tools/call: { const { name, arguments: args } params; // 校验 Mcp-Name 头一致性 const headerName req.headers[mcp-name]; if (headerName headerName ! name) { return sendError(res, 400, id, -32602, Header Mcp-Name (${headerName}) disagrees with body name (${name})); } // 校验工具是否存在 const tool tools.find(t t.name name); if (!tool) { return sendError(res, 200, id, -32601, Tool not found: ${name}); } // 基础参数校验 if (!args || typeof args.q ! string || args.q.trim() ) { return sendError(res, 200, id, -32602, Invalid params: q is required); } // 执行工具逻辑 return sendJson(res, 200, id, { result: { content: [ { type: text, text: 搜索结果找到 3 条关于 ${args.q} 的内容 } ] } }); } default: return sendError(res, 200, id, -32601, Method not found: ${method}); } }); }); server.listen(PORT, () { console.log(MCP Server running at http://localhost:${PORT}/mcp); console.log(Protocol version: ${PROTOCOL_VERSION}); });10. 新旧规范核心差异总览维度旧规范 2025-11-25新规范 2026-07-28连接模式先握手后会话绑定无握手直接请求会话机制强制携带 Mcp-Session-Id无协议层会话网关路由需解析 JSON Body读取 Mcp-Method 头即可客户端信息握手时一次性传递每个请求 _meta 自包含工具列表缓存无原生支持协议级 ttl 作用域控制负载均衡必须粘性会话轮询即可无实例绑定长任务实现SSE 长连接绑定实例任务句柄轮询无状态交互UIRoots 客户端渲染MCP Apps 服务端渲染沙箱隔离授权基础 OAuth可选 PKCE强制 OAuth 2.1 PKCEJSON Schemadraft-072020-12错误码大量自定义错误码回归 JSON-RPC 标准码扩展机制内置核心功能独立扩展反向DNS标识11. 常见面试考点Q1MCP 2026-07-28 无状态化的核心设计是什么核心是彻底移除协议层会话机制取消 initialize 握手删除 Mcp-Session-Id每个请求自包含全部必要信息。由此服务端任意实例都可以处理任意请求负载均衡不再需要粘性会话水平扩展能力大幅提升。Q2Mcp-Method 头的设计价值是什么将方法名从请求体提升到 HTTP 头让网关、负载均衡、CDN、WAF 等基础设施无需解析 JSON 就能识别请求类型原生支持路由、限流、缓存、监控等能力大幅降低了 MCP 服务的生产部署门槛。Q3为什么 Tasks 要从 SSE 改成轮询模式旧方案 SSE 长连接天然绑定单个服务实例和有状态会话深度耦合无法适配无状态架构。改为任务句柄 轮询模式后任务状态存储在共享存储中任意实例都可查询完全支持水平扩展与故障转移。Q4无状态化后业务需要会话怎么办协议层移除会话不代表业务不能维护会话。业务可以通过客户端传递业务会话ID、服务端从共享存储读取上下文的方式实现会话能力只是这部分逻辑下沉到业务层不再由协议强制约束架构更灵活。Q5本次改版的破坏性变更有哪些核心破坏性变更包括移除 initialize 握手、移除 Mcp-Session-Id、新增强制协议版本头、clientInfo 位置变更、MRTR 替代 SSE 交互、Tasks 重构。废弃功能有 12 个月过渡期不属于立即破坏性变更。参考资料MCP 官方规范文档modelcontextprotocol.ioSEP-2575 Remove Initialize HandshakeSEP-2567 Remove Session IDSEP-2243 HTTP Method HeadersSEP-2549 Cacheable ResultsSEP-2322 Multi-Round Trip RequestsSEP-2663 Tasks ExtensionSEP-2352 Authorization Hardening