RH
RouterHub AI API 中转站导航与平台推荐
博客

MCP 限流和工具失败还没完全统一:接 LLM Gateway 与中转 API 前先做这份兼容清单

MCP 2026-07-28 已让请求更适合无状态扩展,但限流错误和工具失败分类仍在演进。本文按协议层、HTTP 层和上游模型层拆开说明,帮助你在接入 LLM Gateway 或中转 API 时避免误重试、吞错和成本失控。

muchacha 2026-09-29 02:18:09

正文

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 规范中做了几个与网关直接相关的调整:

  1. 协议层不再依赖 initialize/initialized 握手和 Mcp-Session-Id 会话头。
  2. 请求携带协议版本、客户端信息和能力,服务端可以通过 server/discover 提供能力发现。
  3. Streamable HTTP 请求使用 Mcp-Method,涉及工具、资源或提示词名称时还使用 Mcp-Name。
  4. tools/list、prompts/list、resources/list 等结果可以携带 TTL 和缓存范围提示。

对 LLM Gateway 来说,这意味着路由、计量和限流可以在不解析 JSON-RPC 请求体的情况下读取方法和工具名。对中转 API 使用者来说,收益是更容易按工具、租户或模型分组观测流量;代价是旧客户端、旧 SDK 和旧代理可能仍按有会话的方式处理请求,兼容层不能只看一个版本字符串。

建议把以下字段写进每条请求的观测记录:

  • MCP-Protocol-Version
  • Mcp-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 到达模型后,至少还要核对以下信息:

  1. 模型 ID 是否真的被该渠道支持:不要只看前台下拉框或宣传页,实际请求记录要能对应到模型 ID。
  2. 错误是否来自上游:区分渠道返回的 429、上游模型限额、余额不足、模型不存在和本地超时。
  3. 重试是否会重复计费:同一次 Agent 循环可能触发多次模型请求,工具失败重试还可能继续消耗输入和输出 Token。
  4. MCP 工具描述是否被缓存:工具列表缓存过期后,客户端可能继续调用已经下线或改名的工具。
  5. 降级是否改变能力:从支持工具调用的模型切换到不支持相同 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”四个字判断完整兼容。

参考来源

资料核验时间:2026 年 9 月 29 日。SEP-3304 和 SEP-3313 的状态属于社区提案状态,不能当作所有 MCP 客户端已经实现的正式能力。