Ошибки сервера MCP
Ошибки сервера MCP
Как обрабатывать ошибки, возвращаемые сервером foura-mcp.
Каждый ответ с ошибкой от любого из четырех инструментов (foura_auto, foura_single, foura_proxy, foura_browser) структурирован. Агенты LLM могут читать поле code для логики повторных попыток без разбора текста.
Структура конверта
Каждая ошибка (isError: true) содержит блок structuredContent. Минимальные поля в каждой ошибке:
{
"service": "auto | 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
| Код | HTTP | Значение | Безопасно повторять? |
|---|---|---|---|
ssrf_blocked |
н/д | Целевой IP в частном или зарезервированном диапазоне (RFC 5735, RFC 6598, зарезервировано IPv6) | Нет, измените URL |
upstream_non_json |
варьируется | Upstream вернул тело, которое не является валидным JSON | Возможно, расследуйте |
output_validation_failed |
н/д | outputSchema сервера MCP отклонил ответ upstream (ошибка сервера или неожиданная структура upstream) |
Возможно, сообщите |
bad_request |
400 | Входная структура отклонена API FourA | Нет, исправьте аргументы |
auth_failed |
401 | API ключ FourA отсутствует, недействителен или деактивирован; это не касается учетных данных целевого сайта | Нет, исправьте ключ FourA |
forbidden |
403 | Цель отклонила запрос (anti-bot, geo-block) | Нет, или переключитесь на foura_proxy |
not_found |
404 | Целевой URL или endpoint не существует | Нет |
rate_limited |
429 | Достигнут лимит RPM на ключ | Да, подождите retryAfter секунд |
at_capacity |
503 | Достигнут лимит concurrency (current.concurrency > limits.maxConcurrency) |
Да, подождите retryAfter секунд |
service_disabled |
503 | Служба отключена для вашего аккаунта (тариф или обслуживание) | Обратитесь в поддержку |
service_unavailable |
503 | Обычный 503 от upstream | Да, короткий backoff |
upstream_error |
500+ | 5xx от upstream | Да, exponential backoff |
upstream_client_error |
4xx | Другие 4xx, не описанные выше | Обычно нет |
upstream_unknown |
прочее | Защитный механизм, не должно происходить на практике | Расследуйте |
no_eligible_proxy |
н/д | Ни один proxy не соответствует строгому allowlist exitCountries; details.exitCountries содержит нормализованный scope |
Повторите позже; меняйте scope только явно |
Ошибки уровня HTTP от сервера MCP
Некоторые сбои происходят на транспортном уровне MCP, до вызова какого-либо инструмента. Они возвращают сырые ошибки JSON-RPC (без structuredContent):
| HTTP | Когда | Что вы видите |
|---|---|---|
| 400 | Неподдерживаемый заголовок 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 | Отсутствует или искажен заголовок Authorization |
Ошибка JSON-RPC + WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
| 403 | Запрещенный заголовок 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 mode) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | Тело запроса > 256 KB | 413 по умолчанию для Express |
Списки разрешений для 403 настраиваются через переменные среды для self-hoster-ов с помощью FOURA_MCP_ALLOWED_HOSTS и FOURA_MCP_ALLOWED_ORIGINS.
Отклоненные профили браузера
Профиль браузера, который не может быть представлен каталогом, или профиль, отправленный с unblocker установленным в false, возвращается как ошибка upstream с причиной в error, и request никогда не покидает FourA. Сообщение указывает, что доступно, поэтому повторите попытку с одной из перечисленных комбинаций вместо той же самой.
Это отказы, а не сбои: повторная отправка идентичного request не будет успешной, и никакой другой браузер не использовался вместо него.
Стратегия повторных попыток
Четыре категории:
- Подождать и повторить:
rate_limited,at_capacity,service_unavailable,upstream_error. УчитывайтеretryAfter, если присутствует. Используйте экспоненциальную задержку с джиттером, если отсутствует. - Сохранить область видимости и повторить позже:
no_eligible_proxy. Не удаляйтеexitCountriesи не заменяйте другую страну скрыто. Изменяйте или расширяйте список разрешений только тогда, когда пользователь явно меняет требования. - Не повторять до исправления ввода или учетных данных:
bad_request,auth_failed,not_found,ssrf_blocked. Дляauth_failedпроверьте API ключ FourA, а не учетные данные целевого сайта. - Сменить инструмент, когда этого требует контент:
forbiddenнаfoura_singleможет оправдать ограниченную попыткуfoura_proxy. Используйтеfoura_browser, когда для нужного контента требуется JavaScript. После успешного выбора proxy передайте возвращенныйproxyID в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, промпты рабочих процессов, поставляемые с сервером
- API Errors, та же оболочка на базовом уровне REST API