Servidor MCP

Servidor MCP

Use o FourA a partir de qualquer cliente Model Context Protocol (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) como quatro ferramentas nativas e seis prompts de fluxo de trabalho. Sem código de integração, sem cliente HTTP personalizado.

Código aberto no GitHub; no npm como @fouradata/mcp. Versão atual: 0.7.3.

Início rápido: stdio local (recomendado para Claude Desktop)

Obtenha uma chave em foura.ai/dashboard#api-keys (um clique, exibida uma única vez na criação, formato pk_live_...). Insira isto na configuração do seu cliente MCP:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "@fouradata/mcp"],
      "env": { "FOURA_API_KEY": "pk_live_..." }
    }
  }
}

Atenção no Claude Desktop: feche totalmente o Claude Desktop (Cmd+Q no macOS) antes de editar o arquivo de configuração. Se o aplicativo ainda estiver em execução, ele sobrescreverá suas alterações com a configuração da memória ao fechar.

O comando npx baixa o @fouradata/mcp na primeira inicialização e o executa como um subprocesso do seu cliente MCP. Não é necessária instalação global.

Cliente Onde fica o arquivo de configuração
Claude Desktop (macOS) ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop (Windows) %APPDATA%\Claude\claude_desktop_config.json
Claude Code claude mcp add foura -- npx -y @fouradata/mcp (defina FOURA_API_KEY no env primeiro)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (extensão MCP) .vscode/mcp.json

Reinicie o cliente. As ferramentas (foura_auto, foura_single, foura_proxy, foura_browser) e seis prompts aparecerão na sua lista de ferramentas.

Início rápido: hospedado (Streamable HTTP)

Para clientes com suporte ao transporte Streamable HTTP (Cursor, Windsurf, VS Code, Claude Code com --transport http), aponte para o endpoint hospedado em vez de executar um subprocesso local:

{
  "mcpServers": {
    "foura": {
      "url": "https://mcp.foura.ai/mcp",
      "headers": {
        "Authorization": "Bearer pk_live_..."
      }
    }
  }
}

Para o Claude Desktop, use a configuração de stdio acima ou faça o bridge do endpoint hospedado por meio do mcp-remote:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.foura.ai/mcp", "--header", "Authorization: Bearer pk_live_..."]
    }
  }
}

Referência do endpoint hospedado

Propriedade Valor
URL https://mcp.foura.ai/mcp
Transporte HTTP com suporte a streaming (POST /mcp, respostas SSE)
Autenticação Authorization: Bearer pk_live_... por request
MCP-Protocol-Version Conforme @modelcontextprotocol/sdk (atualmente 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
Desafio 401 WWW-Authenticate: Bearer realm="foura-mcp"

O desafio 401 não inclui o parâmetro RFC 9728 resource_metadata, intencionalmente. Informar um faz com que um cliente compatível com OAuth inicie um fluxo que este servidor não implementa. Envie sua chave pk_live_ como um token Bearer e o 401 desaparece.

O servidor hospedado é stateless. Cada request traz sua própria chave, que o servidor encaminha para a API FourA como X-API-Key. Uma única chave libera todas as quatro ferramentas.

Para proteção contra DNS-rebinding (CVE-2025-66414), o servidor valida o header Host (deve ser mcp.foura.ai ou localhost) e o header Origin quando presente (na lista de permissões: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Chamadores server-to-server (curl, clientes MCP em modo ponte stdio) não enviam Origin e passam diretamente.

Ferramentas

Todas as quatro ferramentas são anotadas com readOnlyHint: true e openWorldHint: true de acordo com a especificação MCP 2025-06-18. Clientes que aprovam automaticamente ferramentas confiáveis de somente leitura as executam sem uma janela modal de confirmação a cada request.

foura_auto é o padrão inteligente: forneça uma URL e ele retorna o conteúdo, escolhendo o método de busca por você. As outras três são as primitivas de nível mais baixo que ele orquestra; utilize-as quando quiser controle explícito.

foura_auto

Forneça uma URL quando você quiser que a FourA escolha o método de request. Ela faz tentativas limitadas entre os caminhos disponíveis de HTTP, proxy e navegador. Passe validate em alvos protegidos para que a response precise conter conteúdo que identifique a página real. Se nenhuma tentativa atender à validação, a ferramenta retorna um erro em vez de apresentar uma página de desafio como sucesso.

A response inclui detalhes de conclusão em meta e, por padrão, uma session reutilizável com proxy, cookies e userAgent. Para uma requisição de acompanhamento simples, chame foura_single com session.proxy como proxy, serialize os cookies como um header Cookie e envie session.userAgent como o header User-Agent. Para renderização em JavaScript, passe os valores da sessão para os campos correspondentes de foura_browser.

foura_single

Um request HTTP, retorno da response. Espelha POST /api/single/ de forma direta.

Use para páginas estáticas, APIs JSON, HTML renderizado no servidor.

Escolhendo qual navegador você apresenta

Um request apresenta o Google Chrome mais recente por padrão. Quando um destino aceita um navegador e recusa outro, defina browser (Chrome, Edge, Safari, Firefox ou Tor), os (Windows, macOS, Android ou iOS), ou version, ou passe um id profile exato:

{
  "method": "GET",
  "url": "https://example.com",
  "browser": "Firefox",
  "os": "Windows"
}

A versão mais recente tem prioridade quando vários perfis correspondem. Uma combinação que não existe retorna um erro listando o que está disponível, para que uma request nunca seja enviada como um navegador que você não escolheu. A seleção precisa de unblocker, que fica ativado por padrão. O catálogo é publicado em GET /api/profiles e não requer chave de API.

Os mesmos quatro campos ficam dentro do objeto request de foura_proxy.

foura_proxy

Encaminhe uma request HTTP por meio de proxies rotativos com repetição automática. Use-o quando foura_single estiver bloqueado ou o destino exigir um país de saída específico.

Defina exitCountries com uma allowlist restrita de códigos de país de duas letras visíveis ao destino, fornecidos pelo usuário ou pelos requisitos do destino:

{
  "maxTries": 5,
  "exitCountries": ["CZ", "GB"],
  "request": {
    "method": "GET",
    "url": "https://example.com/pricing",
    "browser": "Chrome",
    "os": "Windows"
  }
}

Os valores são normalizados (espaços removidos), convertidos para maiúsculas e deduplicados. Proxies com saídas desconhecidas são excluídos, e a request nunca faz fallback para um país não solicitado. A seleção usa os metadados de país visíveis ao destino mais recentes disponíveis, normalmente atualizados em até dez minutos; não se trata de uma consulta de geolocalização em tempo real durante a request. Não deduza o país de atendimento a partir do endereço de host do proxy.

Um sucesso com escopo retorna exitCountry e o ID reutilizável proxy. Verifique se exitCountry pertence à allowlist solicitada. Se o pool atual não tiver correspondências, a ferramenta retornará code: "no_eligible_proxy" com o escopo normalizado em details.exitCountries. Mantenha esse escopo e tente novamente mais tarde. Altere ou amplie o escopo apenas quando o usuário alterar explicitamente o requisito. O escopo por país está incluído a partir do plano Startup. Em um plano sem esse recurso, uma chamada que enviar exitCountries será recusada com 403 e X-FourA-Limit: plan_limit_feature.

Se a página selecionada precisar de JavaScript posteriormente, passe o ID proxy retornado para foura_browser.proxy para que o navegador reutilize a mesma saída.

Defina exitClass: "premium" para um destino que o pool padrão não consegue alcançar, independentemente de quantas saídas sejam tentadas. Trata-se de uma permissão, não de uma instrução: o pool padrão ainda disputa para obter a resposta e geralmente vence, e uma request respondida por ele antes que qualquer saída premium seja tentada não consome tráfego premium. Uma tentativa premium contabiliza o tráfego transportado mesmo quando falha. A response informa exitClass de volta, premium ou standard, para que você possa ver por request qual classe atendeu você. standard também é a resposta quando o tráfego premium incluído no seu plano se esgota, sendo um resultado normal e não um erro. exitClass: "standard" proíbe o escalonamento diretamente. exitClass: "premium" em um plano sem saídas premium é recusado com code: "plan_limit_premium". Consulte exitClass.

Quando a rotação precisou mudar para outra família de navegadores para obter uma resposta, uma response bem-sucedida trará profile com a família definida. Repita a chamada com ela, caso contrário a próxima chamada repetirá a versão que falhou.

Uma rotação com falha traz attemptReport ao lado do erro: uma frase em summary, além de contagens que separam saídas que nunca responderam (noResponse), saídas que uma verificação de bot recusou (defense, com os fornecedores em vendors), páginas que chegaram e foram rejeitadas apenas pelo seu próprio validate.data (contentRejected), statusRejected e other. profilesTried lista os navegadores que a tarefa enviou, em ordem de primeiro uso, com default significando que a request foi enviada exatamente como escrita. Um valor alto de contentRejected significa que a FourA entregou páginas reais e sua própria regra as descartou. Consulte Why a Proxy Request Ran Out of Tries.

foura_browser

Sessão completa de navegador. O JavaScript é executado, o DOM é renderizado, os cookies são retornados. Espelha POST /api/browser/.

Use para single-page applications, conteúdo carregado sob demanda (lazy loading) ou páginas com uma verificação que exige um navegador real para ser concluída.

Para formatos de entrada, padrões e regras de validação em cada ferramenta, consulte a referência de endpoints REST. Os esquemas das ferramentas correspondem campo a campo à API REST, além do opt-in offload_large exclusivo do MCP (veja abaixo).

Quando um alvo executa uma verificação de bot

foura_single e foura_proxy retornam defense quando o alvo executou uma verificação de bot a caminho do body. defense.solved: true significa que a verificação foi aprovada e data é a página real; false significa que o body pode ser uma página de desafio. Tente novamente com um navegador, sistema operacional ou versão diferente, ou mude para foura_proxy ou foura_browser, em vez de tratar a página de desafio como conteúdo.

Respostas tipadas

Cada resposta de ferramenta inclui content (resumo de texto legível por humanos) e structuredContent (JSON tipado e validado em relação ao outputSchema da ferramenta). Cada ferramenta tem seu próprio formato exclusivo:

  • foura_auto: { status, headers, data } em formato único mais meta ({ rung, solved, attempts, credits }, sempre presente, onde rung é um de cache, probe, proxy, browser, warmup, fail) e, por padrão, session ({ proxy, cookies, userAgent }) para repetição por meio das ferramentas de nível inferior. Sem total_time.
  • foura_single: { status, headers, data, total_time, ... } (headers é um array, uma entrada por salto de redirecionamento)
  • foura_proxy: igual ao single mais { proxy, total }; um sucesso com escopo definido também inclui exitCountry, uma solicitação que especificou uma classe inclui exitClass, uma rotação que alterou a família do navegador inclui profile e uma falha inclui attemptReport
  • foura_browser: formato distinto { status, headers: object, body, cookies, userAgent } (observação: body pode ser uma string ou um objeto dependendo do content-type)

Cada ferramenta também informa o custo da chamada e como rastreá-la, lidos dos headers de resposta da API:

  • credits, créditos gastos nesta chamada. Presente também em falhas, pois o trabalho foi executado de qualquer forma. Você é cobrado apenas por chamadas bem-sucedidas; portanto, uma falha mostra seus créditos aqui, mas não custa nada a você.
  • request_id, identificador da FourA para a chamada. Mencione-o em uma solicitação de suporte.
  • exitClass, premium quando uma saída premium atendeu à chamada. No foura_single e foura_browser, isso acontece quando o proxy repete uma saída encontrada pelo foura_proxy.

Cada um é omitido quando a API não reporta nada, portanto, um cliente desenvolvido para uma versão anterior continua funcionando sem alterações. Os mesmos valores estão documentados em Response Headers.

Clientes que suportam structuredContent podem passar o objeto tipado diretamente para o LLM em vez de exigir que ele analise o JSON a partir de texto puro.

Headers de resposta com múltiplos valores

Headers que aparecem várias vezes (Set-Cookie, Link, WWW-Authenticate) retornam como arrays:

{
  "headers": [
    {
      "result": { "version": "HTTP/2", "code": 200, "reason": "" },
      "content-type": "text/html",
      "set-cookie": ["a=1; Path=/", "b=2; Path=/"]
    }
  ]
}

Isso é importante para sites que definem cookies de sessão + rastreamento + consentimento em uma única response (a maior parte do e-commerce).

Large responses: offload_large (default: inline)

Por padrão (desde a v0.2.0), os corpos completos de response são retornados inline em structuredContent independentemente do tamanho. Isso funciona em qualquer cliente MCP nativamente.

Se o seu cliente suporta MCP resources/read E você deseja economizar tokens em páginas grandes, passe offload_large: true por chamada de ferramenta. Responses >= 50 KB são então gravadas em disco, retornadas como um resource_link, e seu cliente busca o body apenas quando realmente precisa dele. No servidor hospedado, payloads em cache expiram após 1 hora. Em sua própria instância nada exclui os payloads armazenados: limpe você mesmo os arquivos com mais de uma hora do diretório de payloads.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Cliente offload_large: true
Claude Desktop ainda não, mantenha o padrão false
Claude Code, Cursor, Windsurf suportado
Extensão MCP do VS Code suportado

Isolamento por tenant: cada chave de API obtém seu próprio namespace (sha256(apiKey)[:16]). Apenas a chave que armazenou um payload pode lê-lo de volta. Leituras entre tenants retornam Payload not found sem vazamento de existência.

Prompts integrados

Seis templates de fluxo de trabalho aparecem sob /prompts em qualquer cliente MCP. Cada um aceita argumentos nomeados e retorna uma mensagem de usuário com template orquestrando uma ou mais ferramentas.

Prompt Argumentos O que faz
smart_fetch url, opcional must_contain, extract Auto fetch (escolhe o método, lida com proteção contra bots), depois retorna ou extrai o conteúdo
scrape_product_page url Browser fetch, depois extrai título do produto, preço, imagem, estoque, SKU como JSON
extract_article url Single com fallback para proxy, depois remove navegação/anúncios e retorna JSON limpo do artigo
monitor_pricing url, opcional target_price Proxy fetch, extrai o preço atual, compara com o valor alvo
check_endpoint_health url, opcional expected_text Single com validação estrita, retorna acessibilidade e tempo de resposta
bulk_fetch_urls urls (separados por vírgula) Single paralelo, fallback automático para proxy por URL, retorna apenas metadados

Os prompts custam zero tokens em repouso. Apenas prompts invocados entram no contexto do LLM.

Texto completo com prompts manuais de fallback: MCP Recipes.

Envelope de erro

Todo erro (isError: true) carrega um envelope 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. Em erros de rate limit e capacidade, o envelope upstream adiciona retryAfter, current.{concurrency, rpm} e limits.{maxConcurrency, maxRpm}. Consulte API Errors para o formato REST subjacente.

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, 6598, IPv6 reservado), a URL não é http(s) ou o hostname não resolveu Não, verifique a URL. Uma resolução que falhou brevemente pode ser tentada novamente
upstream_non_json varia O upstream retornou um body malformado 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 relate
bad_request 400 Formato de entrada rejeitado Não, corrija os argumentos
auth_failed 401 Chave ausente, inválida ou desativada Não, corrija a chave
forbidden 403 O destino respondeu 403 e seu validate rejeitou isso (uma verificação do site, uma restrição de país) Não, ou mude para foura_proxy
not_found 404 Destino ou endpoint ausente Não
rate_limited 429 Limite de RPM atingido Sim, aguarde retryAfter
at_capacity 503 Limite de concorrência atingido Sim, aguarde retryAfter
service_disabled 503 O serviço está desligado para manutenção. Uma ferramenta que seu plano não inclui retorna como plan_limit_feature Entre em contato com o suporte
service_unavailable 503 503 genérico Sim, backoff curto
upstream_error 500+ ou 0 O destino respondeu com um erro de servidor, ou em foura_proxy, foura_browser e foura_auto nunca responderam Sim, backoff exponencial
upstream_client_error 4xx Outro 4xx Geralmente não
upstream_unknown outro A requisição foi executada mas não produziu uma 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 ao escopo estrito de exitCountries Tente novamente mais tarde; altere o escopo apenas explicitamente
plan_limit_* 403 ou 429 Um dos limites do seu plano recusou a chamada: plan_limit_ seguido por feature, premium, concurrency, rate, browser_daily, credits ou bandwidth. Consulte MCP Server Errors Aguarde retryAfter quando presente; caso contrário, não tente até que o limite seja redefinido ou o plano seja alterado

Agentes de LLM podem ler code diretamente para lógica de repetição sem analisar texto. Passo a passo de autenticação: Authentication.

Limites

  • Corpo inline por padrão. Com offload_large: true, respostas >= 50 KB vão para o disco + resource_link (por tenant, TTL de 1 hora).
  • Destinos privados são recusados (RFC 5735, RFC 6598, blocos reservados IPv6) na camada MCP. Apenas hosts públicos são encaminhados.
  • Limite de corpo de requisição de 256 KB em requisições /mcp de entrada (payloads reais de MCP são < 4 KB).
  • Rate limits são aplicados pela FourA API por serviço. Consulte Rate Limits.

Auto-hospedagem

O código-fonte completo do servidor é público no GitHub sob @fouradata/mcp. Clone o repositório, execute npm install, npm run build e rode node dist/http.js para subir sua própria instância. Opera sem estado em um único container atrás de qualquer balanceador de carga.

Ambiente configurável:

Variável Padrão Finalidade
PORT 3076 Porta de escuta HTTP
FOURA_API_BASE https://api.foura.ai/api URL base REST upstream da FourA
FOURA_MCP_PAYLOADS_DIR uma pasta foura-mcp-payloads no diretório temporário do sistema (o arquivo Docker Compose incluído define /data/payloads) Onde respostas >= 50 KB são armazenadas em cache no disco (com offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Lista de permissões de hostname para o cabeçalho Host (defesa contra DNS rebinding)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Lista de permissões de Origin para chamadores via navegador

O container oficial roda como uid 1001 (não root). O bind mount de host /data/payloads deve ter permissão de escrita para esse UID.

Escale horizontalmente atrás de qualquer balanceador de carga. Os clientes fornecem suas chaves em cada requisição, portanto não há necessidade de sessão persistente.

Atualizado em: 27 de setembro de 2026