MCP 的错误分两条完全不同的路:协议层错误走 JSON-RPC 的 error 对象,工具执行错误则是”成功响应 + isError 标记”。把这两类搞混是服务端开发最常见的坑——前者模型基本无法自愈,后者才是给模型看、让它改参数重试的。分清楚,错误处理就对了一半。
协议错误 vs 工具执行错误
| 类型 | 表现 | 典型场景 | 该给模型看吗 |
|---|---|---|---|
| 协议错误 | 标准 JSON-RPC error(code + message) | 未知工具、请求不符合 schema 、方法不存在 | 可以给,但自愈概率低 |
| 工具执行错误 | 正常响应体里带 isError: true | 参数校验失败、上游 API 挂了、业务逻辑不满足 | 必须给,这是自愈的唯一入口 |
协议错误的形式是固定的:响应里带 error 字段,含整数 code 和 message,可选 data 承载嵌套信息;id 必须与对应请求一致(请求格式错误到读不出 id 的情况除外)。工具执行错误则长这样:响应体是正常 result,但里面标记了 isError: true,附带一段可执行的反馈文本。
错误码该怎么选
MCP 沿用 JSON-RPC 2.0 的标准错误码:-32700 解析错误、-32600 无效请求、-32601 方法不存在、-32602 参数无效、-32603 内部错误。自定义错误码的区间有明确划分:
- -32000 到 -32019:遗留区间,早期实现分配的,新代码绝不能在这里分配新码,接收方也不应假定这些码有特定含义。
- -32020 到 -32099:为 MCP 规范保留,由规范定义。自己扩展时应避开这一段,避免与未来的规范码冲突。
实践建议:优先用标准码;确实需要业务语义时,把细节放进 data 而不是发明新码。发明私有错误码的代价是客户端无法理解,最终只能退化成一句 message 。
让模型能自愈的报错文案
工具执行错误的文本是给模型看的,写法直接决定它能不能自己改对。三条要求:
- 说清错在哪、期望是什么、当前是什么:比如”出发日期无效:必须是未来日期,当前日期是 2026-08-08″,比”参数错误”有用一百倍。
- 给出可执行的修正方向:能列举合法取值范围就列举,能提示正确格式就提示格式。
- 不要泄露内部细节:堆栈、内网地址、上游凭证一律不进 message 。
超时、取消与重试
- 超时:客户端应实现工具调用超时,服务端也要给自身操作设上限。超时后要明确表态:是幂等地重试,还是已经被部分执行需要回滚。
- 取消:长时间运行的工具要能响应取消通知,并在取消后清理临时状态。
- 部分副作用:这是最危险的情况。脚本或工具在中途失败但已经产生了副作用时,必须在返回里说明已经提交了哪些改动,让模型能如实报告而不是假装无事发生。
服务端必须做的安全动作
- 校验所有工具输入,不信任任何来自模型的参数。
- 实施访问控制与速率限制,避免被调用打穿。
- 清理(sanitize)工具输出,防止把恶意内容直接喂回模型。
- 记录工具调用用于审计。
和已有实践串起来
错误处理的落地要落到你的调用端代码里,Python SDK 的写法见MCP 客户端开发入门;错误日志不要走协议内日志(已弃用),正确的日志与监控方案见MCP 服务器日志与监控;如果错误来自传输层(stdio 断连、 HTTP 超时),先确认你的传输方式选型,参考MCP 传输 stdio 与 HTTP 对比。










评论 (0)