MCP 无状态了,安全谁来管

摘要:MCP 2026-07-28 规范正式发布,协议层从此无状态。意味着会话劫持、弱认证等旧风险被消除——但五个新攻击面由开发者全权负责。Akamai 安全预警已发,Java 团队如正在集成 MCP 服务,这篇文章梳理 12 个月过渡期内该做什么。


7 月 28 日,MCP 2026-07-28 规范正式发布。

如果你在集成 AI Agent 到业务系统,这可能是这个月最值得关注的技术事件。

一次发布,两张面孔。

第一张面孔是"基础设施级"的。MCP 从本地单用户的 AI 集成协议,正式转型为企业级的云原生平台。无状态核心、基于 HTTP 头的路由、多轮请求(MRTR)、OAuth 2.1 强制——这些都是工程团队期盼多年的特性。

第二张面孔是"安全债务"的。Akamai 的同一天发布了详细安全分析,结论很直接:MCP 把安全责任从协议层移交给了开发者。 那些以前由协议兜底的安全边界,现在完全取决于你的实现质量。

两个月前我给一个正在集成 MCP 服务的团队做咨询,当时他们用的还是旧版有状态协议。他们的安全负责人问了一个我现在觉得很有先见之明的问题:

"MCP 做大了之后,谁保证这个协议不出安全漏洞?"

答案也许在今天揭晓了:协议自己提供基础保障,剩下的,开发者自己扛。

一次跨越 12 个月的架构迁移

MCP 的这次升级是一次完整的架构翻新,从协议核心到底层传输都换了。

最核心的变化:MCP 协议层不再维护会话状态。

旧模型的工作方式是:客户端和服务器通过一次握手(initialize/initialized)建立长连接,用 Mcp-Session-Id 维护会话,通过 Server-Sent Events 双向通信。状态由协议管理,安全由协议兜底。

新模型完全抛弃了这套机制。每次请求都是独立的,自带协议版本、客户端身份和能力声明(通过 _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":"otter"},
   "_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}

熟悉 RESTful 设计的工程师看到这个应该会觉得很亲切。是的,MCP 现在变得更像一个普通的 HTTP API 了。

伴随无状态化,此次规范还有几项关键变化:

  • 多轮请求(MRTR):取代旧的服务器主动推送模式,服务器可以在需要用户确认时返回 input_required,客户端重试时附带答案
  • 基于 HTTP 头的路由Mcp-MethodMcp-Name 头部让网关、WAF 无需解析 Body 即可路由
  • 可缓存列表tools/list 等响应携带 ttlMscacheScope,客户端可以缓存工具目录
  • 授权安全加固:强制 OAuth 2.1,验证 iss 参数,废弃动态客户端注册(DCR)
  • 扩展框架正式化:Tasks 从实验状态移出,成为正式扩展

同时被标记废弃的功能包括:Roots、Sampling、Logging、HTTP+SSE 传输、动态客户端注册。官方给出了 12 个月的最低支持窗口期,旧功能在这期间仍然可用,但新实现不应再采用。

五个新攻击面

Akamai 的安全研究团队对这次规范升级做了详细分析。结论可以总结为一句话:MCP 消除了协议层的六类旧风险,但引入了五个依赖实现质量的新攻击面。

旧风险中,最值得关注的三个已消除:

  • 会话劫持:旧版 Mcp-Session-Id 是高价值攻击目标,获取后即可冒充认证用户。无状态化彻底移除了这个攻击向量。
  • 服务器主动推送:旧版允许服务器通过 SSE 随时向客户端推送未请求的提示。新规范严格限制了这一行为。
  • 弱认证方法:强制 OAuth 2.1 移除了大量基于弱凭证的认证风险。

新风险中,最需要关注的五个:

1. 工作流劫持与跨租户访问

无状态化后,状态管理从协议层移到了应用层。服务器通过"跟踪标识符"和"状态对象"来维护会话。如果这些标识符可预测,攻击者可以:

  • 劫持正在进行的工作流
  • 访问其他 Agent 的数据
  • 触发未授权的跨租户操作

2. 头部/主体不一致攻击(Desync)

Mcp-MethodMcp-Name 头部让路由层不用解析 Body——但这也意味着头部和 Body 可能不一致。网关认为在处理 tools/list,服务器实际执行的是 tools/call。这是经典的反向代理漏洞的 MCP 版本。

3. 敏感信息通过 x-mcp-header 泄漏

如果开发者不小心把 API 密钥、Token 或 PII 映射到了自定义头部,"这些密钥会直接推入头部。一旦到了那里,沿途的每个负载均衡器、代理和日志系统都能看到。"——Akamai 安全预警。

4. 异步任务的 DoS 攻击

新规范引入的长任务机制有一个结构性缺陷:任务创建对客户端是廉价的,但对服务端是资源密集的。攻击者可以发送单个请求启动一个昂贵的操作(消耗 CPU、内存或数据库存储),然后立即断开连接。服务器还在处理,账单还在走,客户端已经跑没影了。

5. MCP UI 面板的 XSS 攻击

MCP Apps 成为一等扩展后,MCP 服务器可以提供 UI 界面。这意味着传统 Web 安全攻击面——存储型 XSS、界面伪装钓鱼——现在进了 MCP 协议范畴。

对 Java 团队意味着什么

这里有一个值得注意的问题:MCP 的 Tier 1 SDK 只包括 TypeScript、Python、Go 和 C#。目前没有官方的 Java SDK。

如果你正在用社区驱动的 mcp-java-sdk 或自实现,以下变更必须关注:

架构层面

  • 不能依赖 Mcp-Session-Id 维护状态
  • Spring Controller 必须处理完全独立的请求
  • 需要解析 Mcp-MethodMcp-Name 头部来路由
  • 需要实现 MRTR 逻辑来处理需要用户确认的场景

安全层面

  • 跟踪标识符必须使用加密随机数生成,不能简单递增
  • 自定义头部不要绑定敏感数据
  • 对长任务设置资源上限和超时
  • UI 面板的输出必须做上下文转义(context-escape)

迁移层面

  • Roots、Sampling、Logging 已废弃——12 个月内迁移
  • HTTP+SSE 传输已废弃——切换为 Streamable HTTP
  • 动态客户端注册废弃——切换为 CIMD

12 个月过渡期该做什么

如果你所在团队正在或计划集成 MCP,这是按优先级排列的行动清单:

P0 - 立即做(本周)

  • 盘点当前使用的 MCP 版本,确认是否涉及废弃功能
  • 确认社区 Java SDK 的更新状态
  • 阅读 Akamai 安全分析全文

P1 - 规划(第一个月)

  • 制定无状态迁移方案:状态移出协议层后放哪里
  • 设计跟踪标识符生成策略(加密随机数、包含租户信息)
  • 评估长任务资源消耗模型,设置超时和上限

P2 - 实现(前三个月)

  • 替换初始化流程,移除 initialize/initialized
  • 迁移 HTTP+SSE 为 Streamable HTTP
  • 添加 Mcp-MethodMcp-Name 头部
  • 建立头部/主体一致性校验

P3 - 持续(12 个月内)

  • 替换废弃的 Roots、Sampling、Logging 功能
  • 从 DCR 迁移到 CIMD
  • 更新 OAuth 流程以验证 iss 参数
  • 对 MCP UI 面板做安全审计

结语

MCP 的无状态化是一个正确的架构决定。它解决了有状态协议在企业级部署中的一系列问题——弹性伸缩、负载均衡、故障恢复。这层基础设施升级对于 MCP 成为真正的企业级标准是必要的。

但安全代价不是零。

Akamai 在报告中的一段话值得反复读:"安全决策之前由协议执行,现在被委托给了 MCP 服务器开发者和平台运营者。同样的动作,换个实现者,安全结果天差地别。"

Java 团队的优势在于对这类"安全边界转移"并不陌生——Spring Security 把安全委托给过滤器链、OAuth 把认证委托给授权服务器、微服务把通信安全委托给服务网格。MCP 这次只是把这套逻辑又复制了一遍。

只是这次,AI Agent 在那一头等着调用你的服务。


作者:唐悦玮 | 从后端出发,用 AI 拓展到全栈的工程师。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容