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. Beachte retryAfter, 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: forbidden bei foura_single → Eskalation zu foura_proxy. Wenn die Seite auch JavaScript benötigt, foura_browser. Wenn foura_browser den Fehler forbidden meldet, schalte zuerst foura_proxy vor und übergib die zurückgegebene proxy-ID an foura_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
Aktualisiert: 1. Juli 2026