MCP-Serverfehler
Wie du Fehler behandelst, die vom foura-mcp server zurückgegeben werden.
Jede Fehlerantwort der drei Tools (foura_single, foura_proxy, foura_browser) ist strukturiert. LLM-Agents können das Feld code für die Retry-Logik auslesen, ohne Fließtext parsen zu müssen.
Envelope-Struktur
Jeder Fehler (isError: true) enthält einen structuredContent-Block. Mindestfelder bei jedem Fehler:
{
"service": "single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Bei Upstream-Fehlern mit HTTP-Status ist auch status vorhanden. Bei Rate-Limit- und Kapazitätsfehlern fügt der Envelope retryAfter, current.{concurrency, rpm} und limits.{maxConcurrency, maxRpm} hinzu, analog zu den zugrundeliegenden REST-API-Fehlern.
Stabile code-Werte
| Code | HTTP | Bedeutung | Retry-sicher? |
|---|---|---|---|
ssrf_blocked |
n/a | Ziel-IP liegt in einem privaten oder reservierten Bereich (RFC 5735, RFC 6598, IPv6-reserviert) | Nein, URL ändern |
upstream_non_json |
variiert | Upstream hat einen Body zurückgegeben, der kein gültiges JSON war | Eventuell, prüfen |
output_validation_failed |
n/a | Das outputSchema des MCP-Servers hat die Upstream-Antwort abgelehnt (Server-Bug oder unerwartetes Upstream-Format) |
Eventuell, melden |
bad_request |
400 | Eingabeformat von der FourA-API abgelehnt | Nein, Argumente korrigieren |
auth_failed |
401 | Key fehlt, ist ungültig oder deaktiviert | Nein, Key korrigieren |
forbidden |
403 | Ziel hat den Request abgelehnt (Anti-Bot, Geo-Block) | Nein, oder zu foura_proxy wechseln |
not_found |
404 | Ziel-URL oder -Endpoint existiert nicht | Nein |
rate_limited |
429 | RPM-Limit pro Key erreicht | Ja, retryAfter Sekunden warten |
at_capacity |
503 | Limit für gleichzeitige Requests erreicht (current.concurrency > limits.maxConcurrency) |
Ja, retryAfter Sekunden warten |
service_disabled |
503 | Dienst für dein Konto deaktiviert (Tarif oder Wartung) | Support kontaktieren |
service_unavailable |
503 | Generischer 503-Fehler vom Upstream | Ja, kurzes Backoff |
upstream_error |
500+ | Upstream-5xx-Fehler | Ja, exponentielles Backoff |
upstream_client_error |
4xx | Anderer, oben nicht aufgeführter 4xx-Fehler | Meistens nein |
upstream_unknown |
andere | Defensiv, sollte in der Praxis nicht auftreten | Prüfen |
HTTP-Fehler des MCP-Servers
Einige Fehler treten auf der MCP-Transportschicht auf, bevor ein Tool aufgerufen wird. Diese geben rohe JSON-RPC-Fehler zurück (kein structuredContent):
| HTTP | Wann | Was du siehst |
|---|---|---|
| 400 | Nicht unterstützter 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 | Fehlender oder fehlerhafter Authorization-Header |
JSON-RPC-Fehler + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
| 403 | Nicht erlaubter Origin- oder Host-Header (DNS-Rebinding-Schutz, CVE-2025-66414) |
Origin <value> is not in the allowlist oder Host <value> is not in the allowlist |
| 405 | GET oder DELETE auf /mcp (stateless Modus) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | Request-Body > 256 KB | Express-Standard-413 |
Die Allowlists für 403 sind für Self-Hoster über FOURA_MCP_ALLOWED_HOSTS und FOURA_MCP_ALLOWED_ORIGINS per Umgebungsvariable konfigurierbar.
Retry-Strategie
Drei Kategorien:
- Warten + Retry:
rate_limited,at_capacity,service_unavailable,upstream_error. BeachteretryAfter, falls vorhanden (Server-Hinweis in Sekunden). Falls nicht, nutze exponentielles Backoff mit Jitter. - Kein Retry, Eingabe korrigieren:
bad_request,auth_failed,not_found,ssrf_blocked. - Tool wechseln:
forbiddenbeifoura_single→ Eskalation zufoura_proxy. Wenn die Seite auch JavaScript benötigt,foura_browser. Wennfoura_browserden Fehlerforbiddenmeldet, schalte zuerstfoura_proxyvor und übergib die zurückgegebeneproxy-ID anfoura_browser.proxy.
Retry-Beispiel (TypeScript, MCP-seitig)
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");
}
Verwandte Themen
- MCP-Server, die drei Tools und ihre Schemata
- MCP-Rezepte, mit dem Server ausgelieferte Workflow-Prompts
- API-Fehler, gleiche Envelope-Struktur auf der zugrundeliegenden REST-API-Ebene