Servidor MCP

Servidor MCP

Usa FourA desde cualquier cliente Model Context Protocol (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) como cuatro herramientas nativas y seis prompts de flujo de trabajo. Sin código de integración, sin un cliente HTTP personalizado.

De código abierto en GitHub; en npm como @fouradata/mcp. Versión actual: 0.5.0.

Inicio rápido: stdio local (recomendado para Claude Desktop)

Obtén una clave en foura.ai/dashboard#api-keys (un clic, se muestra una vez al crearla, formato pk_live_...). Agrega esto en la configuración de tu cliente MCP:

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

Advertencia sobre Claude Desktop: cierra completamente Claude Desktop (Cmd+Q en macOS) antes de editar el archivo de configuración. Si la aplicación sigue en ejecución, sobrescribirá tus ediciones con su configuración en memoria al salir.

El comando npx descarga @fouradata/mcp en el primer inicio y lo ejecuta como un subproceso de tu cliente MCP. No se necesita instalación global.

Cliente Dónde se encuentra la configuración
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 (configura FOURA_API_KEY en env primero)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (extensión MCP) .vscode/mcp.json

Reinicia el cliente. Las herramientas (foura_auto, foura_single, foura_proxy, foura_browser) y seis prompts aparecerán en tu lista de herramientas.

Inicio rápido: alojado (Streamable HTTP)

Para los clientes que soportan el transporte Streamable HTTP (Cursor, Windsurf, VS Code, Claude Code con --transport http), apúntalos al endpoint alojado en lugar de ejecutar un subproceso local:

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

Para Claude Desktop, usa la configuración de stdio anterior o conecta el endpoint alojado a través de mcp-remote:

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

Referencia del endpoint alojado

Propiedad Valor
URL https://mcp.foura.ai/mcp
Transporte HTTP transmisible (POST /mcp, respuestas SSE)
Autenticación Authorization: Bearer pk_live_... por request
MCP-Protocol-Version Según @modelcontextprotocol/sdk (actualmente 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
Desafío 401 WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth"

El servidor alojado no tiene estado. Cada request trae su propia clave, que el servidor reenvía a la API de FourA como X-API-Key. Una clave abre las cuatro herramientas.

Para protegerse contra la revinculación de DNS (CVE-2025-66414), el servidor valida el header Host (debe ser mcp.foura.ai o localhost) y el header Origin cuando está presente (lista permitida: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Las llamadas de servidor a servidor (curl, clientes MCP en modo puente stdio) no envían Origin y pasan directamente.

Herramientas

Las cuatro herramientas están anotadas como readOnlyHint: true y openWorldHint: true según la especificación MCP 2025-06-18. Los clientes que aprueban automáticamente herramientas de solo lectura confiables las llaman sin un modal de confirmación por request.

foura_auto es la opción predeterminada inteligente: dale una URL y devuelve el contenido, eligiendo el método de obtención por ti. Las otras tres son las primitivas de nivel inferior que orquesta; úsalas cuando quieras un control explícito.

foura_auto

Pásale una URL cuando quieras que FourA elija el método del request. Realiza intentos limitados a través de las rutas HTTP, proxy y de navegador disponibles. Pasa validate en objetivos protegidos para que la response deba contener contenido que identifique la página real. Si ningún intento satisface la validación, la herramienta devuelve un error en lugar de presentar una página de desafío como éxito.

La response incluye detalles de finalización en meta y, de forma predeterminada, una session reutilizable con proxy, cookies y userAgent. Para un seguimiento simple, llama a foura_single con session.proxy como proxy, serializa las cookies como un header Cookie y envía session.userAgent como el header User-Agent. Para la renderización con JavaScript, pasa los valores de sesión a los campos foura_browser coincidentes.

foura_single

Un request HTTP, y su response correspondiente. Refleja POST /api/single/ uno a uno.

Úsalo para páginas estáticas, API JSON y HTML renderizado en el servidor.

Cómo elegir qué navegador presentas

Un request presenta la versión más reciente de Google Chrome de forma predeterminada. Cuando un objetivo acepta un navegador y rechaza otro, configura browser (Chrome, Edge, Safari, Firefox o Tor), os (Windows, macOS, Android o iOS) o version, o bien pasa un id exacto profile:

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

La versión más reciente gana cuando coinciden varios perfiles. Una combinación que no existe devuelve un error que enumera lo que está disponible, por lo que nunca se envía un request como un navegador que no elegiste. La selección necesita unblocker, que está activado por defecto. El catálogo se publica en GET /api/profiles y no necesita una clave de API.

Los mismos cuatro campos se encuentran dentro del objeto request de foura_proxy.

foura_proxy

Enruta un request HTTP a través de proxies rotativos con reintento automático. Úsalo cuando foura_single esté bloqueado o el objetivo requiera un país de salida específico.

Configura exitCountries con una lista de permitidos estricta de códigos de país de dos letras visibles para el objetivo, proporcionada por el usuario o por los requisitos del objetivo:

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

Los valores se recortan, se pasan a mayúsculas y se deduplican. Los proxies con salidas desconocidas se excluyen y la request nunca recurre a un país no solicitado. La selección usa los últimos metadatos de país visibles por el destino, normalmente actualizados en diez minutos; no es una búsqueda de geolocalización en vivo durante la request. No deduzcas el país de servicio a partir de la dirección host del proxy.

Un éxito con scope devuelve exitCountry y el ID reusable proxy. Comprueba que exitCountry pertenece a la allowlist solicitada. Si el pool actual no tiene coincidencias, la herramienta devuelve code: "no_eligible_proxy" con el scope normalizado en details.exitCountries. Conserva ese scope y reintenta más tarde. Cámbialo o amplíalo solo cuando el usuario cambie explícitamente el requisito.

Si la página seleccionada luego necesita JavaScript, pasa el ID proxy devuelto a foura_browser.proxy para que el navegador reutilice la misma salida.

foura_browser

Sesión de navegador completa. JavaScript se ejecuta, el DOM se renderiza, las cookies regresan. Refleja POST /api/browser/.

Úsalo para apps de una sola página, contenido de carga diferida o páginas tras desafíos anti-bots que necesitan un navegador real para resolverse.

Para formas de entrada, valores por defecto y reglas de validación en cada herramienta, consulta la referencia del endpoint REST. Los esquemas de la herramienta coinciden con la API REST campo por campo, más la opción offload_large exclusiva de MCP (ver abajo).

Cuando un destino ejecuta una comprobación de bots

foura_single y foura_proxy devuelven defense cuando el destino ejecutó una comprobación de bots de camino al body. defense.solved: true significa que se cumplió la comprobación y data es la página real; false significa que el body podría ser una página de desafío. Reintenta con un navegador, os o versión diferente, o sube a foura_proxy o foura_browser, en lugar de tratar la página de desafío como contenido.

Respuestas tipadas

Toda respuesta de la herramienta incluye tanto content (resumen de texto legible por humanos) como structuredContent (JSON tipado validado contra el outputSchema de la herramienta). Cada herramienta tiene su propia forma única:

  • foura_auto: { status, headers, data } de forma única más meta ({ rung, solved, attempts, credits }, siempre presente, donde rung es uno de cache, probe, proxy, browser, fail) y, por defecto, session ({ proxy, cookies, userAgent }) para la repetición mediante las herramientas de nivel inferior. Sin total_time.
  • foura_single: { status, headers, data, total_time, ... } (headers es un array, una entrada por salto de redirección)
  • foura_proxy: igual que el único más { proxy, total }; un éxito con scope también incluye exitCountry
  • foura_browser: forma distinta { status, headers: object, body, cookies, userAgent } (nota: body puede ser un string o un objeto según el content-type)

Los clientes que soportan structuredContent pueden pasar el objeto tipado directamente al LLM en lugar de exigirle que parsee el JSON desde la prosa.

Headers de response con valores múltiples

Los headers que aparecen varias veces (Set-Cookie, Link, WWW-Authenticate) regresan como arrays:

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

Esto importa para los sitios que establecen cookies de sesión + rastreo + consentimiento en una sola response (la mayoría del comercio electrónico).

Responses grandes: offload_large (por defecto: en línea)

Por defecto (desde la v0.2.0), los cuerpos completos de la response se devuelven en línea en structuredContent sin importar su tamaño. Esto funciona en cualquier cliente MCP sin configuración adicional.

Si tu cliente soporta MCP resources/read Y quieres ahorrar tokens en páginas grandes, pasa offload_large: true por cada llamada a la herramienta. Las responses >= 50 KB se escriben en el disco, se devuelven como un resource_link, y tu cliente obtiene el cuerpo solo cuando realmente lo necesita. Los payloads en caché caducan después de 1 hora.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Cliente offload_large: true
Claude Desktop aún no, deja el valor predeterminado false
Claude Code, Cursor, Windsurf compatible
Extensión MCP para VS Code compatible

Aislado por inquilino: cada clave de API obtiene su propio espacio de nombres (sha256(apiKey)[:16]). Solo la clave que almacenó un payload puede leerlo. Las lecturas entre diferentes inquilinos devuelven Payload not found sin revelar su existencia.

Prompts integrados

Seis plantillas de flujo de trabajo aparecen bajo /prompts en cualquier cliente MCP. Cada una acepta argumentos con nombre y devuelve un mensaje de usuario en plantilla que orquesta una o más herramientas.

Prompt Argumentos Qué hace
smart_fetch url, must_contain opcional, extract Auto fetch (elige el método, maneja la protección contra bots), y luego devuelve o extrae el contenido
scrape_product_page url Browser fetch, y luego extrae el título del producto, precio, imagen, inventario y SKU en JSON
extract_article url Single con proxy de respaldo, y luego elimina la navegación/anuncios y devuelve el artículo limpio en JSON
monitor_pricing url, target_price opcional Proxy fetch, extrae el precio actual y lo compara con el objetivo
check_endpoint_health url, expected_text opcional Single con validación estricta, devuelve accesibilidad y tiempos
bulk_fetch_urls urls (separado por comas) Parallel single, respaldo automático a proxy por URL, devuelve solo metadatos

Los prompts cuestan cero tokens cuando están inactivos. Solo los prompts invocados entran en el contexto del LLM.

Texto completo y prompts de respaldo manual: Recetas MCP.

Envoltorio de error

Cada error (isError: true) lleva un envoltorio structuredContent. Campos mínimos en cada error:

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

En errores del upstream con estado HTTP, status también está presente. En errores de rate limit y capacidad, el envelope del upstream añade retryAfter, current.{concurrency, rpm} y limits.{maxConcurrency, maxRpm}. Consulta API Errors para ver la estructura REST subyacente.

Valores code estables:

Code HTTP Significado ¿Seguro reintentar?
ssrf_blocked n/a IP de destino en rango privado o reservado (RFC 5735, 6598, IPv6 reservado) No, cambia la URL
upstream_non_json varía El upstream devolvió un body malformado Quizás, investigar
output_validation_failed n/a outputSchema del servidor MCP rechazó la response del upstream (bug del servidor o estructura inesperada) Quizás, reportar
bad_request 400 Estructura de entrada rechazada No, corrige los argumentos
auth_failed 401 Key faltante, inválida o desactivada No, corrige la key
forbidden 403 Autenticado pero no permitido No, o cambia a foura_proxy
not_found 404 Falta el destino o endpoint No
rate_limited 429 Límite de RPM alcanzado Sí, espera retryAfter
at_capacity 503 Límite de concurrencia alcanzado Sí, espera retryAfter
service_disabled 503 Ventana de mantenimiento o tu plan no incluye esta herramienta Contactar soporte
service_unavailable 503 503 genérico Sí, backoff corto
upstream_error 500+ Upstream 5xx Sí, backoff exponencial
upstream_client_error 4xx Otro 4xx Normalmente no
upstream_unknown otro Defensivo, no debería ocurrir en la práctica Investigar
no_eligible_proxy n/a Ningún proxy coincide con el scope estricto exitCountries Reintentar luego; cambia el scope de forma explícita

Los agentes LLM pueden leer code directamente para la lógica de reintento sin analizar texto. Guía de autenticación: Authentication.

Límites

  • Body en línea por defecto. Con offload_large: true, las responses >= 50 KB van a disco + resource_link (por inquilino, TTL de 1 hora).
  • Los destinos privados son rechazados (RFC 5735, RFC 6598, bloques reservados de IPv6) en la capa MCP. Solo se reenvían hosts públicos.
  • Límite del body de request de 256 KB en requests /mcp entrantes (los payloads reales de MCP son < 4 KB).
  • Los rate limits son aplicados por la API de FourA por servicio. Consulta Rate Limits.

Autoalojamiento

El código fuente completo del servidor es público en GitHub bajo @fouradata/mcp. Clona el repositorio, npm install, npm run build y ejecuta node dist/http.js para levantar tu propia instancia. Se ejecuta sin estado en un solo contenedor detrás de cualquier balanceador de carga.

Entorno configurable:

Variable Predeterminado Propósito
PORT 3076 Puerto de escucha HTTP
FOURA_API_BASE https://api.foura.ai/api URL base REST upstream de FourA
FOURA_MCP_PAYLOADS_DIR /data/payloads Dónde se almacenan en caché en disco las respuestas >= 50 KB (con offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Lista de permitidos de hostname para el encabezado Host (defensa contra DNS-rebinding)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Lista de permitidos de origin para clientes de navegador
FOURA_MCP_RESOURCE_METADATA_URL https://foura.ai/docs/mcp/server#auth URL devuelta en WWW-Authenticate en un 401

El contenedor oficial se ejecuta como uid 1001 (no root). El montaje host bind de /data/payloads debe tener permisos de escritura para ese uid.

Escala horizontalmente detrás de cualquier balanceador de carga. Los clientes proporcionan su clave en cada request, por lo que no hay sticky session.

Actualizado: 6 de agosto de 2026