Ошибки MCP-сервера
Как обрабатывать ошибки, возвращаемые foura-mcp server.
Каждый ответ об ошибке от любого из трех инструментов (foura_single, foura_proxy, foura_browser) структурирован. LLM-агенты могут читать поле code для логики повторных запросов без необходимости парсинга текста.
Структура ответа
Каждая ошибка (isError: true) содержит блок structuredContent. Минимальный набор полей для каждой ошибки:
{
"service": "single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
При ошибках вышестоящего сервера (upstream) с HTTP-статусом также присутствует поле status. При ошибках rate limit и превышения емкости в структуру добавляются поля retryAfter, current.{concurrency, rpm} и limits.{maxConcurrency, maxRpm} в том же формате, что и в базовых ошибках REST API.
Стабильные значения code
| Code | HTTP | Значение | Безопасно для повтора? |
|---|---|---|---|
ssrf_blocked |
n/a | Целевой IP находится в приватном или зарезервированном диапазоне (RFC 5735, RFC 6598, зарезервированные IPv6) | Нет, измените URL |
upstream_non_json |
варьируется | Вышестоящий сервер вернул тело, не являющееся валидным JSON | Возможно, требуется анализ |
output_validation_failed |
n/a | Схема outputSchema MCP-сервера отклонила ответ вышестоящего сервера (баг сервера или неожиданный формат ответа) |
Возможно, сообщите об ошибке |
bad_request |
400 | Формат входных данных отклонен FourA API | Нет, исправьте аргументы |
auth_failed |
401 | Ключ отсутствует, недействителен или деактивирован | Нет, исправьте ключ |
forbidden |
403 | Целевой ресурс отклонил запрос (антибот, геоблокировка) | Нет, или переключитесь на 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 |
другое | Резервный код, на практике возникать не должен | Требуется анализ |
Ошибки HTTP-уровня от MCP-сервера
Некоторые сбои происходят на транспортном уровне MCP до вызова какого-либо инструмента. В этих случаях возвращаются необработанные ошибки JSON-RPC (без structuredContent):
| HTTP | Когда | Что вы видите |
|---|---|---|
| 400 | Неподдерживаемый header 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 | Отсутствующий или некорректный header Authorization |
JSON-RPC ошибка + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
| 403 | Запрещенный header Origin или Host (защита от DNS-rebinding, CVE-2025-66414) |
Origin <value> is not in the allowlist или Host <value> is not in the allowlist |
| 405 | GET или DELETE для /mcp (stateless-режим) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | Тело request > 256 КБ | Стандартная ошибка 413 от Express |
Разрешенные списки (allowlists) для ошибки 403 могут быть настроены через переменные окружения для self-host решений с помощью FOURA_MCP_ALLOWED_HOSTS и FOURA_MCP_ALLOWED_ORIGINS.
Стратегия повторных запросов
Три категории:
- Ожидание и повтор:
rate_limited,at_capacity,service_unavailable,upstream_error. Учитывайте значениеretryAfter, если оно указано (подсказка сервера в секундах). В противном случае используйте экспоненциальную задержку со случайным отклонением (jitter). - Без повтора, исправьте входные данные:
bad_request,auth_failed,not_found,ssrf_blocked. - Смена инструмента:
forbiddenвfoura_single(переключитесь наfoura_proxy). Если для страницы также требуется JavaScript, используйтеfoura_browser. Еслиfoura_browserвозвращаетforbidden, сначала выполните цепочку сfoura_proxyи передайте полученный IDproxyв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, три инструмента и их схемы
- MCP Recipes, шаблоны рабочих процессов (prompts), поставляемые с сервером
- API Errors, аналогичная структура на уровне базового REST API