MCP-Server-Fehler
MCP-Server-Fehler
So behandelst du Fehler, die vom foura-mcp server zurückgegeben werden.
Jede Fehler-Response von einem der vier Tools (foura_auto, foura_single, foura_proxy, foura_browser) ist strukturiert. LLM-Agents können das code-Feld für 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": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Bei Upstream-Fehlern mit HTTP-Status ist status ebenfalls vorhanden. Wenn das geteilte Kontingent der Plattform einen Aufruf ablehnt, enthält der Envelope zusätzlich retryAfter, current.{concurrency, rpm} und limits.{maxConcurrency, maxRpm}, im selben Format wie die zugrundeliegenden REST-API-Fehler.
Wenn eines der Limits deines eigenen Tarifs einen Aufruf ablehnt, entspricht der Code genau diesem Limit: plan_limit_ gefolgt von credits, bandwidth, rate, concurrency, browser_daily, premium oder feature. retryAfter enthält die Wartezeit, sofern Warten das Problem behebt, und fehlt bei Limits, die sich nicht durch Warten lösen lassen, wie etwa ein im Tarif nicht enthaltenes Feature. plan_limit_browser_daily enthält ebenfalls kein retryAfter: Es wird um Mitternacht UTC zurückgesetzt.
Bei foura_auto wird ein Tariflimit innerhalb seiner Stufe als rate_limited oder forbidden zurückgegeben, mit dem Tarif-Code in reason.
Stabile code-Werte
| Code | HTTP | Bedeutung | Retry sicher? |
|---|---|---|---|
ssrf_blocked |
k. A. | Das Ziel ist eine private oder reservierte Adresse (RFC 5735, RFC 6598, IPv6-reserviert), die URL ist nicht http(s) oder ihr Hostname konnte nicht aufgelöst werden | Nein, prüfe die URL. Ein kurzzeitig fehlgeschlagener Lookup kann wiederholt werden |
upstream_non_json |
variiert | Upstream hat einen Body zurückgegeben, der kein gültiges JSON war | Vielleicht, analysieren |
output_validation_failed |
k. A. | Der outputSchema des MCP-Servers hat die Upstream-Response abgelehnt oder das Tool konnte den Aufruf gar nicht abschließen (kein API-Key konfiguriert, API nicht erreichbar) |
Vielleicht: Setup prüfen, dann melden |
bad_request |
400 | Eingabeformat von der FourA-API abgelehnt | Nein, Argumente korrigieren |
auth_failed |
401 | Der FourA-API-Key fehlt, ist ungültig oder deaktiviert; dies betrifft nicht die Zugangsdaten der Zielseite | Nein, FourA-Key korrigieren |
forbidden |
403 | Ziel hat den Request abgelehnt (Site-Check, Länderbeschränkung) | Nein, oder zu foura_proxy wechseln |
not_found |
404 | Ziel-URL oder Endpoint existiert nicht | Nein |
rate_limited |
429 | Geteiltes Minutenkontingent der Plattform oder ein 429 vom Ziel, das dein validate abgelehnt hat. Bei foura_auto können es auch Credits, Traffic oder Rate-Limits deines Tarifs sein (siehe reason) |
Ja, warte retryAfter ab, falls vorhanden, sonst Backoff nutzen |
at_capacity |
503 | Concurrency-Limit erreicht (current.concurrency > limits.maxConcurrency) |
Ja, warte retryAfter Sekunden |
service_disabled |
503 | Der Dienst ist wegen Wartungsarbeiten deaktiviert. Ein Tool, das dein Tarif nicht enthält, wird als plan_limit_feature zurückgegeben |
Support kontaktieren |
service_unavailable |
503 | Generischer 503 vom Upstream | Ja, kurzer Backoff |
upstream_error |
500+ oder 0 | Das Ziel hat mit einem Serverfehler geantwortet, oder bei foura_proxy haben foura_browser und foura_auto nie geantwortet |
Ja, exponentieller Backoff |
upstream_client_error |
4xx | Sonstige 4xx, die oben nicht abgedeckt sind | Meistens nein |
upstream_unknown |
sonstige | Request lief, ergab aber keine akzeptierte Antwort: Bei foura_single hat das Ziel nie geantwortet (Timeout, Verbindung abgelehnt), und bei jedem Tool hat dein validate eine 2xx- oder 3xx-Response abgelehnt. Lies status und error |
Analysieren |
no_eligible_proxy |
k. A. | Kein Proxy entspricht der strikten exitCountries-Allowlist; details.exitCountries enthält den normalisierten Scope |
Später erneut versuchen; Scope nur explizit ändern |
plan_limit_credits |
429 | Die monatlichen Credits deines Tarifs sind aufgebraucht | Ja, nach retryAfter, oder Tarif wechseln |
plan_limit_bandwidth |
429 | Das Traffic-Kontingent deines Tarifs ist für diesen Abrechnungszeitraum aufgebraucht | Ja, nach retryAfter, oder Tarif wechseln |
plan_limit_rate |
429 | Requests pro Minute deines Tarifs für diesen Endpoint | Ja, nach retryAfter |
plan_limit_concurrency |
429 | Parallele Requests deines Tarifs für diesen Endpoint | Ja, nach retryAfter |
plan_limit_browser_daily |
429 | Tägliches Browser-Kontingent deines Tarifs ist aufgebraucht | Ja, morgen, oder foura_single / foura_proxy nutzen |
plan_limit_premium |
403 | Du hast exitClass: "premium" in einem Tarif gesendet, der keine Premium-Exits enthält |
Nein, Parameter weglassen oder Tarif wechseln |
plan_limit_feature |
403 | Der Tarif enthält diesen Endpoint oder dieses Feature nicht | Nein, Tarif wechseln |
HTTP-Fehler vom MCP-Server
Manche Fehler treten auf der MCP-Transportschicht auf, bevor ein Tool aufgerufen wird. Diese geben reine 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 | Ein Tool-Aufruf oder Ressourcen-Lesevorgang ohne API key. Das Auflisten von Tools und Prompts funktioniert ohne Key | JSON-RPC-Fehler + WWW-Authenticate: Bearer realm="foura-mcp" |
| 403 | Unzulässiger 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 Default 413 |
Die Allowlists für 403 sind für Self-Hoster über FOURA_MCP_ALLOWED_HOSTS und FOURA_MCP_ALLOWED_ORIGINS per Umgebungsvariable konfigurierbar.
Abgelehnte Browser-Profile
Ein Browser-Profil, das der Katalog nicht bereitstellen kann, oder ein Profil, das mit unblocker auf false gesendet wurde, wird als Upstream-Fehler mit dem Grund in error zurückgegeben und der Request verlässt FourA nie. Die Meldung nennt verfügbare Optionen. Wiederhole den Versuch mit einer der aufgelisteten Kombinationen statt mit derselben.
Dies sind Ablehnungen, keine Ausfälle: Ein erneuter identischer Request kann nicht erfolgreich sein, und es wurde kein anderer Browser als Ersatz verwendet.
Retry-Strategie
Fünf Kategorien:
- Dein eigener Plan hat abgelehnt, nicht das Ziel: Jeder
plan_limit_*Code. Dieselbe Aktion über ein anderes Tool wird ebenfalls abgelehnt, ein Wechsel der Endpoints kostet also nur Zeit. WarteretryAfterab, falls vorhanden; andernfalls muss der Plan geändert werden.plan_limit_premiumkannst du selbst beheben, indem duexitClassentfernst. - Warten und wiederholen:
rate_limited,at_capacity,service_unavailable,upstream_error. BeachteretryAfter, falls vorhanden. Nutze Exponential Backoff mit Jitter, wenn kein Wert vorliegt. Reagiere nicht damit, alle anstehenden Tool-Aufrufe sofort erneut zu senden: Reduziere stattdessen die Anzahl paralleler Requests. - Scope beibehalten und später wiederholen:
no_eligible_proxy. EntferneexitCountriesnicht und ersetze Länder nicht stillschweigend. Ändere oder erweitere die Allowlist nur, wenn der Nutzer die Anforderung explizit anpasst. - Nicht wiederholen, bis Input oder Zugangsdaten korrigiert sind:
bad_request,auth_failed,not_found,ssrf_blocked. Prüfe beiauth_failedden FourA API key, nicht die Zugangsdaten der Zielseite. - Tool wechseln, wenn der Inhalt es erfordert:
forbiddenauffoura_singlekann einen begrenzten Versuch mitfoura_proxyrechtfertigen. Nutzefoura_browser, wenn der gewünschte Inhalt JavaScript benötigt. Übergib nach erfolgreicher Proxy-Auswahl die zurückgegebeneproxyID anfoura_browser.proxy, statt eine neue Auswahl zu starten.
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 vier Tools und ihre Schemas
- MCP Recipes, mit dem Server ausgelieferte Workflow-Prompts
- API Errors, dieselbe Envelope auf der zugrunde liegenden REST-API-Ebene
- Rate Limits, die Account- und Plattform-Limits hinter
rate_limitedundat_capacity