MCP Server 错误
如何处理 foura-mcp server 返回的错误。
来自三个工具(foura_single、foura_proxy、foura_browser)中任何一个的每个错误响应都是结构化的。LLM agent 可以读取 code 字段以进行重试逻辑,而无需解析正文。
外层结构
每个错误(isError: true)都包含一个 structuredContent 块。每个错误的最少字段如下:
{
"service": "single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
对于带有 HTTP 状态码的上游错误,还会提供 status。对于 rate-limit 和容量错误,外层结构会添加 retryAfter、current.{concurrency, rpm} 和 limits.{maxConcurrency, maxRpm},其格式与底层的 REST API 错误 相同。
固定的 code 值
| Code | HTTP | 含义 | 是否可安全重试? |
|---|---|---|---|
ssrf_blocked |
n/a | 目标 IP 处于私有或保留范围内(RFC 5735、RFC 6598、IPv6 保留地址) | 否,请修改 URL |
upstream_non_json |
变化 | 上游返回了非有效 JSON 的主体 | 也许,请排查 |
output_validation_failed |
n/a | MCP server 的 outputSchema 拒绝了上游响应(服务端 bug 或非预期的上游结构) |
也许,请报告 |
bad_request |
400 | 输入结构被 FourA API 拒绝 | 否,请修正参数 |
auth_failed |
401 | Key 缺失、无效或已停用 | 否,请修正 Key |
forbidden |
403 | 目标拒绝了请求(反爬虫、地理位置屏蔽) | 否,或者切换到 foura_proxy |
not_found |
404 | 目标 URL 或 endpoint 不存在 | 否 |
rate_limited |
429 | 触发了每个 Key 的 RPM 上限 | 是,等待 retryAfter 秒 |
at_capacity |
503 | 触发了并发上限(current.concurrency > limits.maxConcurrency) |
是,等待 retryAfter 秒 |
service_disabled |
503 | 您的账户已禁用该服务(套餐限制或系统维护) | 联系支持团队 |
service_unavailable |
503 | 来自上游的通用 503 错误 | 是,进行短暂退避 |
upstream_error |
500+ | 上游 5xx 错误 | 是,进行指数退避 |
upstream_client_error |
4xx | 未在上方列出的其他 4xx 错误 | 通常否 |
upstream_unknown |
其他 | 防御性错误,实际中不应发生 | 排查原因 |
来自 MCP server 的 HTTP 级别错误
某些失败发生在 MCP 传输层,在调用任何工具之前。这些失败会返回原始的 JSON-RPC 错误(不含 structuredContent):
| HTTP | 触发时机 | 呈现内容 |
|---|---|---|
| 400 | 不支持的 MCP-Protocol-Version header |
Unsupported MCP-Protocol-Version: <value>. Supported: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07. |
| 401 | Authorization header 缺失或格式错误 |
JSON-RPC 错误 + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
| 403 | 不允许的 Origin 或 Host header(DNS 重绑定防御,CVE-2025-66414) |
Origin <value> is not in the allowlist 或 Host <value> is not in the allowlist |
| 405 | 对 /mcp 执行 GET 或 DELETE(无状态模式) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | 请求体 > 256 KB | Express 默认 413 错误 |
对于自托管用户,403 的白名单可以通过环境变量 FOURA_MCP_ALLOWED_HOSTS 和 FOURA_MCP_ALLOWED_ORIGINS 进行配置。
重试策略
分为以下三类:
- 等待并重试:
rate_limited、at_capacity、service_unavailable、upstream_error。如果存在retryAfter,请遵循其指示(服务端提示,单位为秒)。如果不存在,请使用带抖动的指数退避。 - 无需重试,修正输入:
bad_request、auth_failed、not_found、ssrf_blocked。 - 切换工具:在
foura_single上遇到forbidden→ 升级到foura_proxy。如果页面还需要 JavaScript,请使用foura_browser。如果foura_browser报告forbidden,请先与foura_proxy链式调用,并将返回的proxyID 传入foura_browser.proxy。
重试示例(TypeScript,MCP 端)
async function callWithRetry(call: () => Promise<any>, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const r = await call();
if (!r.isError) return r;
const code = r.structuredContent?.code;
const wait = r.structuredContent?.retryAfter ?? Math.min(2 ** attempt, 30);
if (["rate_limited", "at_capacity", "service_unavailable", "upstream_error"].includes(code)) {
await new Promise((res) => setTimeout(res, wait * 1000));
continue;
}
// Non-retryable, surface to caller
throw new Error(`${code}: ${r.structuredContent?.error}`);
}
throw new Error("max retries exceeded");
}
相关内容
- MCP Server,三个工具及其 schema
- MCP Recipes,随服务端一同提供的 workflow prompt
- API Errors,底层 REST API 层采用相同的响应外壳