Erros do Servidor MCP
Erros do MCP Server
Como tratar erros retornados pelo servidor foura-mcp.
Cada resposta de erro de qualquer uma das quatro ferramentas (foura_auto, foura_single, foura_proxy, foura_browser) é estruturada. Agentes de LLM podem ler o campo code para lógica de repetição sem analisar texto corrido.
Formato do envelope
Todo erro (isError: true) contém um bloco structuredContent. Campos mínimos em cada erro:
{
"service": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Em erros de upstream com status HTTP, status também está presente. Quando o limite compartilhado da plataforma recusa uma chamada, o envelope adiciona retryAfter, current.{concurrency, rpm} e limits.{maxConcurrency, maxRpm}, no mesmo formato dos erros da REST API subjacentes.
Quando um dos limites do seu próprio plano recusa uma chamada, o código É esse limite: plan_limit_ seguido por credits, bandwidth, rate, concurrency, browser_daily, premium ou feature. retryAfter traz o tempo de espera quando a espera resolve o problema, e fica ausente para um limite que a espera não pode resolver, como um recurso que o plano não inclui. plan_limit_browser_daily também não traz retryAfter: ele é redefinido à meia-noite UTC.
Em foura_auto, um limite de plano atingido dentro de sua escala retorna como rate_limited ou forbidden, com o código do plano em reason.
Valores estáveis de code
| Código | HTTP | Significado | Seguro tentar novamente? |
|---|---|---|---|
ssrf_blocked |
n/a | O destino é um endereço privado ou reservado (RFC 5735, RFC 6598, IPv6 reservado), a URL não é http(s) ou o nome do host não foi resolvido | Não, verifique a URL. Uma resolução que falhou temporariamente pode ser repetida |
upstream_non_json |
varia | O upstream retornou um corpo que não era um JSON válido | Talvez, investigue |
output_validation_failed |
n/a | O outputSchema do servidor MCP rejeitou a resposta do upstream, ou a ferramenta não conseguiu concluir a chamada (nenhuma chave de API configurada, API inacessível) |
Talvez: verifique a configuração e depois reporte |
bad_request |
400 | Formato de entrada rejeitado pela API da FourA | Não, corrija os argumentos |
auth_failed |
401 | A chave de API da FourA está ausente, inválida ou desativada; isso não se refere às credenciais do site de destino | Não, corrija a chave da FourA |
forbidden |
403 | O destino rejeitou a requisição (uma verificação do site, uma restrição de país) | Não, ou mude para foura_proxy |
not_found |
404 | A URL ou endpoint de destino não existe | Não |
rate_limited |
429 | O limite compartilhado por minuto da plataforma, ou um 429 do destino que seu validate rejeitou. No foura_auto também pode ser o limite de créditos, tráfego ou taxa do seu plano (veja reason) |
Sim, aguarde retryAfter quando presente, caso contrário faça backoff |
at_capacity |
503 | Limite de simultaneidade atingido (current.concurrency > limits.maxConcurrency) |
Sim, aguarde retryAfter segundos |
service_disabled |
503 | O serviço está desligado para manutenção. Uma ferramenta não incluída no seu plano retorna como plan_limit_feature |
Contate o suporte |
service_unavailable |
503 | 503 genérico do upstream | Sim, backoff curto |
upstream_error |
500+ ou 0 | O destino respondeu com erro de servidor, ou em foura_proxy, foura_browser e foura_auto nunca responderam |
Sim, backoff exponencial |
upstream_client_error |
4xx | Outro 4xx não coberto acima | Geralmente não |
upstream_unknown |
outro | A requisição foi executada mas não produziu resposta aceita: em foura_single o destino nunca respondeu (timeout, conexão recusada), e em qualquer ferramenta seu validate rejeitou uma resposta 2xx ou 3xx. Leia status e error |
Investigue |
no_eligible_proxy |
n/a | Nenhum proxy corresponde à allowlist restrita de exitCountries; details.exitCountries contém o escopo normalizado |
Tente novamente mais tarde; altere o escopo apenas explicitamente |
plan_limit_credits |
429 | Os créditos mensais do seu plano acabaram | Sim, após retryAfter, ou altere o plano |
plan_limit_bandwidth |
429 | O limite de tráfego do seu plano acabou para este período de cobrança | Sim, após retryAfter, ou altere o plano |
plan_limit_rate |
429 | Limite de requisições por minuto do seu plano para esse endpoint | Sim, após retryAfter |
plan_limit_concurrency |
429 | Limite de requisições simultâneas do seu plano para esse endpoint | Sim, após retryAfter |
plan_limit_browser_daily |
429 | O limite diário de Browser do seu plano acabou | Sim, amanhã, ou use foura_single / foura_proxy |
plan_limit_premium |
403 | Você enviou exitClass: "premium" em um plano que não inclui saídas premium |
Não, remova o parâmetro ou altere o plano |
plan_limit_feature |
403 | O plano não contempla esse endpoint ou essa funcionalidade | Não, altere o plano |
Erros de nível HTTP do servidor MCP
Algumas falhas acontecem na camada de transporte do MCP, antes que qualquer ferramenta seja chamada. Elas retornam erros brutos de JSON-RPC (sem structuredContent):
| HTTP | Quando | O que você vê |
|---|---|---|
| 400 | Header MCP-Protocol-Version não suportado |
Unsupported MCP-Protocol-Version: <value>. Supported: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07. |
| 401 | Chamada de ferramenta ou leitura de recurso sem chave de API. Listar ferramentas e prompts funciona sem ela | Erro de JSON-RPC + WWW-Authenticate: Bearer realm="foura-mcp" |
| 403 | Header Origin ou Host não permitido (defesa contra DNS-rebinding, CVE-2025-66414) |
Origin <value> is not in the allowlist ou Host <value> is not in the allowlist |
| 405 | GET ou DELETE em /mcp (modo stateless) |
Method not allowed in stateless mode. Use POST /mcp. |
| 413 | Corpo da requisição > 256 KB | 413 padrão do Express |
As allowlists para 403 são configuráveis via variáveis de ambiente para quem utiliza self-hosting por meio de FOURA_MCP_ALLOWED_HOSTS e FOURA_MCP_ALLOWED_ORIGINS.
Perfis de navegador recusados
Um perfil de navegador que o catálogo não pode fornecer, ou um perfil enviado com unblocker definido como false, retorna como uma falha upstream com o motivo em error e a requisição nunca sai do FourA. A mensagem informa o que está disponível, portanto, tente novamente com uma das combinações listadas em vez da mesma.
Estas são recusas, não interrupções do serviço: repetir a requisição idêntica não terá sucesso, e nenhum outro navegador foi utilizado em seu lugar.
Estratégia de repetição
Cinco categorias:
- O seu próprio plano recusou, não o destino: qualquer código
plan_limit_*. O mesmo trabalho por meio de outra ferramenta também será recusado, portanto, alternar endpoints apenas desperdiça tempo. Aguarde oretryAfterquando houver um; caso contrário, o plano precisa mudar.plan_limit_premiumé o único que você mesmo pode resolver, removendoexitClass. - Aguarde e tente novamente:
rate_limited,at_capacity,service_unavailable,upstream_error. RespeiteretryAfterquando presente. Use backoff exponencial com jitter quando não estiver presente. Não responda a isso reenviando todas as chamadas de ferramentas em fila de uma só vez: em vez disso, reduza quantas você executa em paralelo. - Preserve o escopo e tente novamente mais tarde:
no_eligible_proxy. Não removaexitCountriesnem substitua por outro país silenciosamente. Altere ou amplie a allowlist apenas quando o usuário alterar explicitamente o requisito. - Não tente novamente até que a entrada ou a credencial seja corrigida:
bad_request,auth_failed,not_found,ssrf_blocked. Paraauth_failed, verifique a chave de API do FourA, não as credenciais do site de destino. - Alterne a ferramenta quando o conteúdo exigir:
forbiddenemfoura_singlepode justificar uma tentativa limitada defoura_proxy. Usefoura_browserquando o conteúdo desejado precisar de JavaScript. Após uma seleção bem-sucedida de proxy, passe o IDproxyretornado parafoura_browser.proxyem vez de iniciar uma nova seleção.
Exemplo de repetição (TypeScript, lado do 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");
}
Relacionados
- MCP Server, as quatro ferramentas e seus schemas
- MCP Recipes, prompts de fluxo de trabalho incluídos com o servidor
- Erros de API, mesmo envelope na camada REST API subjacente
- Rate Limits, os limites de conta e plataforma por trás de
rate_limitedeat_capacity