Błędy serwera MCP

Jak obsługiwać błędy zwracane przez serwer foura-mcp.

Każda odpowiedź błędu z dowolnego z trzech narzędzi (foura_single, foura_proxy, foura_browser) jest ustrukturyzowana. Agenci LLM mogą odczytać pole code w celu wdrożenia logiki ponawiania prób, bez konieczności analizowania tekstu.

Struktura odpowiedzi

Każdy błąd (isError: true) zawiera blok structuredContent. Minimalne pola w każdym błędzie:

{
  "service": "single | proxy | browser",
  "code": "rate_limited",
  "error": "Rate limit exceeded"
}

W przypadku błędów upstream ze statusem HTTP, obecne jest również pole status. Przy błędach rate-limit oraz limitu wydajności, odpowiedź zawiera dodatkowo retryAfter, current.{concurrency, rpm} oraz limits.{maxConcurrency, maxRpm}, zachowując tę samą strukturę co bazowe błędy REST API.

Stabilne wartości code

Code HTTP Znaczenie Czy można ponowić?
ssrf_blocked n/a Docelowy adres IP znajduje się w sieci prywatnej lub zarezerwowanej (RFC 5735, RFC 6598, IPv6 zarezerwowane) Nie, zmień URL
upstream_non_json różne Serwer upstream zwrócił treść, która nie jest poprawnym JSON Może, sprawdź szczegóły
output_validation_failed n/a Schemat outputSchema serwera MCP odrzucił odpowiedź upstream (błąd serwera lub nieoczekiwany format upstream) Może, zgłoś błąd
bad_request 400 Format wejściowy odrzucony przez API FourA Nie, popraw argumenty
auth_failed 401 Brak klucza, jest nieprawidłowy lub został dezaktywowany Nie, popraw klucz
forbidden 403 Cel odrzucił żądanie (zabezpieczenie anty-bot, blokada geograficzna) Nie, lub przełącz na foura_proxy
not_found 404 Docelowy URL lub endpoint nie istnieje Nie
rate_limited 429 Osiągnięto limit RPM dla klucza Tak, odczekaj retryAfter s
at_capacity 503 Osiągnięto limit współbieżności (current.concurrency > limits.maxConcurrency) Tak, odczekaj retryAfter s
service_disabled 503 Usługa wyłączona dla Twojego konta (plan lub konserwacja) Skontaktuj się ze wsparciem
service_unavailable 503 Ogólny błąd 503 z upstream Tak, krótki backoff
upstream_error 500+ Błąd 5xx z upstream Tak, wykładniczy backoff
upstream_client_error 4xx Inny błąd 4xx nieopisany wyżej Zazwyczaj nie
upstream_unknown inne Kod zabezpieczający, nie powinien wystąpić w praktyce Sprawdź szczegóły

Błędy na poziomie HTTP z serwera MCP

Niektóre awarie występują na warstwie transportowej MCP, zanim zostanie wywołane jakiekolwiek narzędzie. Zwracają one surowe błędy JSON-RPC (bez structuredContent):

HTTP Kiedy Co widzisz
400 Niewspierany nagłówek MCP-Protocol-Version Unsupported MCP-Protocol-Version: <value>. Supported: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07.
401 Brakujący lub nieprawidłowy nagłówek Authorization JSON-RPC error + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth"
403 Niedozwolony nagłówek Origin lub Host (ochrona przed DNS-rebinding, CVE-2025-66414) Origin <value> is not in the allowlist lub Host <value> is not in the allowlist
405 GET lub DELETE na /mcp (tryb bezstanowy) Method not allowed in stateless mode. Use POST /mcp.
413 Treść żądania > 256 KB Domyślny błąd 413 z Express

Listy dozwolonych (allowlists) dla błędu 403 mogą być konfigurowane przez zmienne środowiskowe w przypadku samodzielnego hostowania (self-hosting) za pomocą FOURA_MCP_ALLOWED_HOSTS i FOURA_MCP_ALLOWED_ORIGINS.

Strategia ponawiania prób

Trzy kategorie:

  • Odczekaj i ponów: rate_limited, at_capacity, service_unavailable, upstream_error. Uwzględniaj retryAfter, jeśli jest obecny (wskazówka serwera, w sekundach). W przeciwnym razie użyj wykładniczego backoffu z losowym opóźnieniem (jitter).
  • Nie ponawiaj, popraw dane wejściowe: bad_request, auth_failed, not_found, ssrf_blocked.
  • Zmień narzędzie: forbidden w foura_single → przełącz na foura_proxy. Jeśli strona wymaga również JavaScript, użyj foura_browser. Jeśli foura_browser zgłosi forbidden, najpierw połącz go z foura_proxy i przekaż zwrócony identyfikator proxy do foura_browser.proxy.

Przykład ponawiania prób (TypeScript, po stronie 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");
}

Powiązane

  • Serwer MCP, trzy narzędzia i ich schematy
  • Przepisy MCP, prompty procesów (workflows) dostarczane z serwerem
  • Błędy API, ten sam format odpowiedzi na poziomie bazowego REST API
Aktualizacja: 1 lipca 2026