MCP 限流和工具失败还没完全统一:接 LLM Gateway 与中转 API 前先做这份兼容清单
MCP 2026-07-28 已让请求更适合无状态扩展,但限流错误和工具失败分类仍在演进。本文按协议层、HTTP 层和上游模型层拆开说明,帮助你在接入 LLM Gateway 或中转 API 时避免误重试、吞错和成本失控。
正文
MCP 限流和工具失败还没完全统一:接 LLM Gateway 与中转 API 前先做这份兼容清单
如果你把 MCP Server 接到 LLM Gateway、AI 编程代理或第三方中转 API,最容易遇到的并不是“工具能不能被发现”,而是失败之后,客户端到底应该怎么判断:
- HTTP 429 是网关限流、上游模型限额,还是某个工具自己的配额耗尽?
- HTTP 返回 200,但 JSON-RPC 里是 error,应该重试还是修正请求?
tools/call返回isError: true,是工具执行失败,还是 MCP 协议本身失败?- 一个请求经过多层代理后,重试会不会让 Agent 重复扣费或重复执行副作用操作?
截至 2026 年 9 月 29 日,MCP 的 2026-07-28 规范已经把传输层推向无状态、把 Mcp-Method 和 Mcp-Name 放进 HTTP 头,方便网关和限流器识别请求;但“限流错误标准化”和“工具失败结构化分类”仍处在提案或讨论阶段。换句话说,现在最稳妥的方案不是盲目追新规范,而是把 HTTP、JSON-RPC、工具结果和上游 API 错误分层记录,再按证据决定是否重试。
先说结论:不要把所有失败都当成 429 或 500
接入前可以先采用下面这套判断顺序:
| 层级 | 典型信号 | 首要动作 | 是否默认重试 |
|---|---|---|---|
| HTTP 传输层 | 400、401、403、413、429、502、503、504 | 先看响应头、鉴权和网关日志 | 仅对明确的瞬态错误重试 |
| JSON-RPC 协议层 | -32600、-32601、-32602 等 |
修正版本、方法、参数或工具名 | 通常不重试 |
| MCP 工具结果层 | result.isError: true |
把错误交给模型或上层业务判断 | 不要自动重放有副作用的调用 |
| 上游模型/API 层 | provider 返回的 429、额度、超时或模型不存在 | 保留 provider、模型、分组和请求 ID | 根据上游语义和幂等性决定 |
这一层级很重要,因为同一个“调用失败”可能同时带有多个状态。例如 Google Cloud 的 MCP 网关文档明确区分了传输失败和协议失败:协议或应用错误可以通过 HTTP 200 携带 JSON-RPC 错误返回;而真正的 HTTP 层错误仍可能是 400、401、403、405 或 413。若客户端只看 HTTP 状态码,就可能把 HTTP 200 + JSON-RPC error 当成成功;若只看 JSON-RPC,又可能漏掉网关层的鉴权和请求体限制。
2026-07-28 规范改变了网关的路由方式
MCP 官方在 2026-07-28 规范中做了几个与网关直接相关的调整:
- 协议层不再依赖
initialize/initialized握手和Mcp-Session-Id会话头。 - 请求携带协议版本、客户端信息和能力,服务端可以通过
server/discover提供能力发现。 - Streamable HTTP 请求使用
Mcp-Method,涉及工具、资源或提示词名称时还使用Mcp-Name。 tools/list、prompts/list、resources/list等结果可以携带 TTL 和缓存范围提示。
对 LLM Gateway 来说,这意味着路由、计量和限流可以在不解析 JSON-RPC 请求体的情况下读取方法和工具名。对中转 API 使用者来说,收益是更容易按工具、租户或模型分组观测流量;代价是旧客户端、旧 SDK 和旧代理可能仍按有会话的方式处理请求,兼容层不能只看一个版本字符串。
建议把以下字段写进每条请求的观测记录:
MCP-Protocol-VersionMcp-Method、Mcp-Name- MCP client/server 标识
- provider、模型 ID、渠道或分组
- HTTP 状态、JSON-RPC code、
result.isError - 请求是否有副作用、是否已经执行
- 重试次数、退避时间、最终计费结果
这样才能把“协议升级导致的失败”和“渠道本身的失败”分开。不要因为同一个模型在另一个中转渠道可以工作,就直接认定当前错误一定来自渠道;反过来也一样。
限流标准化提案说明了什么
MCP 社区在 2026 年 8 月提交过 SEP-3304,试图把限流映射为 -32023 / RateLimited,并在响应中提供 retryAfterMs 和可选配额字段,同时与 HTTP 429 绑定。提案给出的动机很实际:不同 SDK 对 HTTP 429 的处理并不一致,有的保留状态码,有的压成内部错误,有的只把信息写进字符串,还有实现甚至无法可靠识别非 JSON 的 429 响应。
但需要注意,该提案在 2026 年 9 月 22 日被关闭,维护者建议先经过对应 Working Group 再重新推进。因此,文章发布时不应把 -32023 写成所有 MCP 客户端已经支持的正式标准。当前接入策略应该是:
- 兼容 HTTP
429,读取Retry-After,同时保留响应体。 - 如果存在
retryAfterMs或类似字段,记录但不要假设所有 SDK 都认识它。 - 没有明确退避提示时,使用有上限的指数退避和随机抖动。
- 只对幂等的发现、列表、读取操作自动重试。
- 对
tools/call先判断是否已经产生副作用,再决定是否重放。 - 把 provider 的配额、渠道倍率和 MCP 工具限流分成三条指标,不要合并成一个“API 不稳定”。
Google 的开发者文档给出的通用建议是,对 429 使用带 jitter 的截断指数退避;同时将 RESOURCE_EXHAUSTED 与 UNAVAILABLE 等状态分开处理。AWS 的 MCP 指南进一步建议,限流可以按 MCP Server 或按工具设置,并将限流信息通过响应头返回给客户端;当整体负载过高而不是单一用户超额时,还应考虑 load shedding。
工具失败分类仍在演进,先定义自己的最小字段
另一个值得关注的信号是 MCP 社区的 ToolFailure 提案。SEP-3313 试图为 CallToolResult 增加结构化的失败分类,它目前仍是开放的提案,不是已经普遍落地的规范。这个方向解决的是一个常见问题:工具调用“返回了结果”,不等于工具“成功完成了业务”。
例如下面三种情况不应该混为一谈:
{
"result": {
"content": [{"type": "text", "text": "余额不足,未创建订单"}],
"isError": true
}
}
- 参数错误:模型可以修正参数后再调用。
- 权限或余额错误:需要换凭证、渠道或让用户处理,不应该无限重试。
- 工具执行到一半的上游超时:可能需要查询执行状态,而不是再次创建任务。
在标准化分类正式落地前,可以在自己的网关日志中保留一个内部枚举,但不要把它伪装成 MCP 公共字段。例如:
failure_layer = transport | protocol | tool | upstream
failure_kind = invalid_input | auth | rate_limit | quota | timeout |
unavailable | unknown_tool | side_effect_unknown
retryable = true | false | conditional
execution_state = not_started | completed | partial | unknown
尤其要保留 execution_state。对于充值、下单、发送消息、修改代码、删除资源等工具,超时不代表没有执行成功。此时自动重试可能造成重复操作;更合适的做法是先调用查询工具、使用幂等键,或让 Agent 请求用户确认。
接入中转 API 时,模型层错误要单独核验
MCP 只描述工具和客户端之间的协议,并不会替你验证上游模型渠道的价格、可用性或计费准确性。一个请求经由中转 API 到达模型后,至少还要核对以下信息:
- 模型 ID 是否真的被该渠道支持:不要只看前台下拉框或宣传页,实际请求记录要能对应到模型 ID。
- 错误是否来自上游:区分渠道返回的 429、上游模型限额、余额不足、模型不存在和本地超时。
- 重试是否会重复计费:同一次 Agent 循环可能触发多次模型请求,工具失败重试还可能继续消耗输入和输出 Token。
- MCP 工具描述是否被缓存:工具列表缓存过期后,客户端可能继续调用已经下线或改名的工具。
- 降级是否改变能力:从支持工具调用的模型切换到不支持相同 schema 的模型,不能只替换
model字符串。
如果你正在比较多个中转渠道,建议用相同的 MCP Server、相同的工具描述、相同的模型任务和相同的重试策略做对照。一次成功请求只能说明“这次可用”,不能证明长期稳定,也不能推出某个渠道一定最便宜或最安全。价格、倍率、充值门槛、模型覆盖和限额要分别记录,并注明核验时间。
一份可以直接执行的兼容清单
上线前按下面顺序做一次小规模验证:
1. 版本和路由
- 明确客户端、SDK、网关和 MCP Server 各自支持的协议版本。
- 记录是否使用
Mcp-Method和Mcp-Name。 - 分别测试
server/discover、工具列表、普通工具调用和长任务。 - 确认旧客户端是否仍需要会话亲和性,避免把新旧流量混在同一条假设里。
2. 错误映射
- 构造非法 JSON、未知方法、未知工具、无效参数和不支持版本。
- 分别观察 HTTP status、JSON-RPC code、
result.isError和响应头。 - 确认 HTTP 200 内的 JSON-RPC error 不会被监控系统标成成功。
- 确认网关不会把上游错误正文直接暴露为用户凭证或内部地址。
3. 限流和重试
- 分别触发 MCP Server 限流、工具限流、provider 限流和网关总负载保护。
- 检查
Retry-After、剩余配额、重置时间是否被保留。 - 给发现/读取类请求和有副作用的工具设置不同重试策略。
- 为每次重试绑定原始请求 ID,统计“首请求失败”和“重试成功”,不要只看最终成功率。
4. 成本和执行状态
- 记录每次模型请求的输入、输出、缓存和工具相关 Token(若渠道提供)。
- 记录工具调用是否在模型重试前已经执行。
- 比较不同渠道时固定模型、提示词、工具集和时间窗口。
- 对动态价格、倍率、优惠、额度和模型状态注明核验日期,不用旧快照推断今天的成本。
结语:现在最值得做的是“兼容层”,不是押注某个提案
MCP 正在从“能连接工具”进入“能被网关可靠运营”的阶段。2026-07-28 规范已经为无状态请求、按方法和工具路由、缓存提示提供了更好的基础;但限流错误和工具失败分类仍在演进,且不同 SDK 的实际行为存在差异。
因此,接入 LLM Gateway 或中转 API 时,优先做三件事:分层记录错误、按幂等性重试、把模型渠道成本独立核算。等正式规范和 SDK 支持稳定后,再逐步把自定义字段迁移到公共字段。这样即使客户端、网关或 provider 其中一层升级,也不会因为一个状态码变化就丢掉定位问题所需的证据。
如果你正在选择 MCP 可用的模型渠道,先查看模型支持、接口兼容性、限额和公开计费说明,再用小额、低风险请求验证;不要仅凭“支持 MCP”四个字判断完整兼容。
参考来源
- Model Context Protocol:2026-07-28 Specification:https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/blog/content/posts/2026-07-28-spec-ga/index.md
- Model Context Protocol:The New MCP Roadmap(2026-08-22):https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/blog/content/posts/2026-08-22-mcp-roadmap.md
- MCP SEP-3304:Standardizing Rate-Limiting Errors(2026-08-25 提案,2026-09-22 关闭):https://github.com/modelcontextprotocol/modelcontextprotocol/pull/3304
- MCP SEP-3313:Structured Tool-Failure Classification(开放提案):https://github.com/modelcontextprotocol/modelcontextprotocol/pull/3313
- Google Cloud:Configure Model Context Protocol | API Gateway(页面标注更新于 2026-09-24):https://docs.cloud.google.com/api-gateway/docs/mcp-configure
- Google for Developers:Error handling, rate limiting, and quota management:https://developers.google.com/knowledge/error-handling-and-limits
- AWS Prescriptive Guidance:Model Context Protocol strategies:https://docs.aws.amazon.com/pdfs/prescriptive-guidance/latest/mcp-strategies/mcp-strategies.pdf
资料核验时间:2026 年 9 月 29 日。SEP-3304 和 SEP-3313 的状态属于社区提案状态,不能当作所有 MCP 客户端已经实现的正式能力。