MCP Serverエラー
foura-mcp serverから返されるエラーの処理方法。
3つのツール(foura_single、foura_proxy、foura_browser)のいずれかからのすべてのエラーresponseは構造化されています。LLMエージェントは、散文を解析することなく、リトライロジックのためにcodeフィールドを読み取ることができます。
エンベロープ構造
すべてのエラー(isError: true)にはstructuredContentブロックが含まれます。各エラーの最小フィールドは以下の通りです。
{
"service": "single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
HTTP statusを伴うアップストリームのエラーでは、statusも存在します。rate limitおよびキャパシティのエラーでは、エンベロープにretryAfter、current.{concurrency, rpm}、およびlimits.{maxConcurrency, maxRpm}が追加され、これは基盤となるREST API errorsと同じ形状です。
安定した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がアップストリームのresponseを拒否しました(サーバーのバグまたは予期しないアップストリームの形状) |
おそらく可能、報告してください |
bad_request |
400 | 入力形状がFourA APIによって拒否されました | いいえ、引数を修正してください |
auth_failed |
401 | キーが見つからない、無効、または無効化されています | いいえ、キーを修正してください |
forbidden |
403 | ターゲットがrequestを拒否しました(アンチボット、ジオブロック) | いいえ、またはfoura_proxyに切り替えてください |
not_found |
404 | ターゲットのURLまたはendpointが存在しません | いいえ |
rate_limited |
429 | キーごとの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 | Requestボディが256 KB超 | Expressのデフォルトの413 |
403の許可リストは、セルフホストの場合、FOURA_MCP_ALLOWED_HOSTSおよびFOURA_MCP_ALLOWED_ORIGINSを介して環境変数で設定可能です。
リトライ戦略
3つのバケットに分類されます。
- 待機してリトライ:
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:3つのツールとそのスキーマ
- MCP Recipes:サーバーに同梱されているワークフロープロンプト
- API Errors:基盤となるREST APIレイヤーでの同じエンベロープ