Serveur MCP

Serveur MCP

Utilisez FourA depuis n'importe quel client Model Context Protocol (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) sous forme de quatre outils natifs et de six invites de flux de travail. Aucun code d'intégration, aucun client HTTP personnalisé.

Open source sur GitHub ; sur npm sous le nom de @fouradata/mcp. Version actuelle : 0.5.0.

Démarrage rapide : stdio local (recommandé pour Claude Desktop)

Récupérez une clé sur foura.ai/dashboard#api-keys (en un clic, affichée une seule fois à la création, format pk_live_...). Ajoutez ceci à la configuration de votre client MCP :

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

Piège de Claude Desktop : quittez complètement Claude Desktop (Cmd+Q sur macOS) avant de modifier le fichier de configuration. Si l'application est toujours en cours d'exécution, elle écrasera vos modifications avec sa configuration en mémoire à la fermeture.

La commande npx télécharge @fouradata/mcp lors du premier lancement et l'exécute en tant que sous-processus de votre client MCP. Aucune installation globale n'est nécessaire.

Client Emplacement de la configuration
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 (définissez d'abord FOURA_API_KEY dans l'environnement)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (extension MCP) .vscode/mcp.json

Redémarrez le client. Les outils (foura_auto, foura_single, foura_proxy, foura_browser) et six prompts apparaissent dans votre liste d'outils.

Démarrage rapide : hébergé (Streamable HTTP)

Pour les clients qui prennent en charge le transport Streamable HTTP (Cursor, Windsurf, VS Code, Claude Code avec --transport http), dirigez-les vers l'endpoint hébergé au lieu d'exécuter un sous-processus local :

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

Pour Claude Desktop, utilisez la configuration stdio ci-dessus ou connectez le endpoint hébergé via mcp-remote:

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

Référence du endpoint hébergé

Propriété Valeur
URL https://mcp.foura.ai/mcp
Transport HTTP en continu (POST /mcp, responses SSE)
Authentification Authorization: Bearer pk_live_... par request
MCP-Protocol-Version Selon @modelcontextprotocol/sdk (actuellement 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
Défi 401 WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth"

Le serveur hébergé est sans état. Chaque request apporte sa propre clé, que le serveur transmet à l'API FourA comme X-API-Key. Une clé ouvre les quatre outils.

Pour la protection contre le DNS-rebinding (CVE-2025-66414), le serveur valide le header Host (doit être mcp.foura.ai ou localhost) et le header Origin s'il est présent (liste blanche : mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Les appelants de serveur à serveur (curl, clients MCP en mode pont stdio) n'envoient pas de Origin et passent outre.

Outils

Les quatre outils sont annotés readOnlyHint: true et openWorldHint: true selon la spécification MCP du 2025-06-18. Les clients qui approuvent automatiquement les outils en lecture seule de confiance les appellent sans fenêtre de confirmation par request.

foura_auto est l'option par défaut intelligente : donnez-lui une URL et il retourne le contenu en choisissant la méthode de récupération pour vous. Les trois autres sont les primitives de plus bas niveau qu'il orchestre. Utilisez-les quand vous voulez un contrôle explicite.

foura_auto

Donnez-lui une URL quand vous voulez que FourA choisisse la méthode de request. Il effectue des tentatives limitées à travers les chemins HTTP, proxy et navigateur disponibles. Passez validate sur les cibles protégées pour que la response doive contenir du contenu qui identifie la vraie page. Si aucune tentative ne satisfait la validation, l'outil retourne une erreur au lieu de présenter une page de défi comme un succès.

La response inclut les détails d'achèvement dans meta et, par défaut, une session réutilisable avec proxy, cookies et userAgent. Pour un suivi simple, appelez foura_single avec session.proxy comme proxy, sérialisez les cookies comme header Cookie et envoyez session.userAgent comme header User-Agent. Pour le rendu JavaScript, passez les valeurs de session aux champs foura_browser correspondants.

foura_single

Une HTTP request, une response en retour. Reflète fidèlement POST /api/single/.

À utiliser pour les pages statiques, les API JSON et le HTML rendu par le serveur.

Choisir le navigateur que vous présentez

Une request présente le dernier Google Chrome par défaut. Quand une cible accepte un navigateur et en refuse un autre, définissez browser (Chrome, Edge, Safari, Firefox ou Tor), os (Windows, macOS, Android ou iOS), ou version, ou passez un identifiant profile exact :

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

La version la plus récente l'emporte lorsque plusieurs profils correspondent. Une combinaison inexistante renvoie une erreur listant ce qui est disponible, afin qu'une request ne soit jamais envoyée en tant que navigateur que vous n'avez pas choisi. La sélection nécessite unblocker, qui est activé par défaut. Le catalogue est publié sur GET /api/profiles et ne nécessite aucune clé API.

Les quatre mêmes champs se trouvent dans l'objet request de foura_proxy.

foura_proxy

Acheminez une request HTTP via des proxies rotatifs avec réessai automatique. Utilisez-le lorsque foura_single est bloqué ou que la cible nécessite un pays de sortie spécifique.

Définissez exitCountries sur une liste d'autorisation stricte de codes pays à deux lettres visibles par la cible, fournis par l'utilisateur ou par les exigences de la cible :

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

Les valeurs sont rognées, mises en majuscules et dédupliquées. Les proxys avec des sorties inconnues sont exclus, et la requête ne se rabat jamais sur un pays non demandé. La sélection utilise les métadonnées les plus récentes du pays visible par la cible, normalement mises à jour dans les dix minutes ; ce n'est pas une recherche de géolocalisation en direct pendant la requête. Ne déduisez pas le pays de service à partir de l'adresse de l'hôte du proxy.

Un succès ciblé retourne exitCountry et l'ID proxy réutilisable. Vérifiez que exitCountry appartient à l'allowlist demandée. Si le pool actuel n'a aucune correspondance, l'outil retourne code: "no_eligible_proxy" avec la portée normalisée dans details.exitCountries. Conservez cette portée et réessayez plus tard. Ne la modifiez ou ne l'élargissez que lorsque l'utilisateur modifie explicitement l'exigence.

Si la page sélectionnée a besoin de JavaScript par la suite, passez l'ID proxy retourné à foura_browser.proxy pour que le navigateur réutilise la même sortie.

foura_browser

Session complète du navigateur. JavaScript s'exécute, le DOM s'affiche, les cookies reviennent. Reflète POST /api/browser/.

Utilisez-le pour les applications monopages, le contenu chargé de manière asynchrone, ou les pages derrière des défis anti-bot qui nécessitent un vrai navigateur pour passer.

Pour les structures d'entrée, les valeurs par défaut et les règles de validation de chaque outil, référez-vous à la référence de l'endpoint REST. Les schémas des outils correspondent à l'API REST champ par champ, plus l'option offload_large réservée à MCP (voir ci-dessous).

Lorsqu'une cible exécute une vérification de bot

foura_single et foura_proxy retournent defense lorsque la cible a exécuté une vérification de bot sur le chemin vers le corps. defense.solved: true signifie que la vérification a été réussie et que data est la vraie page ; false signifie que le corps peut être une page de défi. Réessayez avec un navigateur, un système d'exploitation ou une version différente, ou passez à foura_proxy ou foura_browser, au lieu de traiter la page de défi comme du contenu.

Réponses typées

Chaque réponse de l'outil inclut à la fois content (résumé textuel lisible par un humain) et structuredContent (JSON typé et validé selon le outputSchema de l'outil). Chaque outil a sa propre structure unique :

  • foura_auto : { status, headers, data } à structure unique plus meta ({ rung, solved, attempts, credits }, toujours présent, où rung est l'un de cache, probe, proxy, browser, fail) et, par défaut, session ({ proxy, cookies, userAgent }) pour rejouer à travers les outils de bas niveau. Pas de total_time.
  • foura_single : { status, headers, data, total_time, ... } (les headers sont un tableau, une entrée par saut de redirection)
  • foura_proxy : identique à single plus { proxy, total } ; un succès ciblé inclut également exitCountry
  • foura_browser : structure distincte { status, headers: object, body, cookies, userAgent } (remarque : body peut être une chaîne de caractères ou un objet selon le content-type)

Les clients qui supportent structuredContent peuvent passer l'objet typé directement au LLM au lieu de lui demander de parser du JSON à partir d'un texte.

Headers de réponse à valeurs multiples

Les headers qui apparaissent plusieurs fois (Set-Cookie, Link, WWW-Authenticate) reviennent sous forme de tableaux :

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

Cela est important pour les sites qui définissent des cookies de session, de suivi et de consentement dans une seule réponse (la majorité du commerce en ligne).

Réponses volumineuses : offload_large (par défaut : en ligne)

Par défaut (depuis la v0.2.0), les corps de réponse complets sont renvoyés en ligne dans structuredContent quelle que soit leur taille. Cela fonctionne dans chaque client MCP sans configuration préalable.

Si votre client prend en charge MCP resources/read ET que vous souhaitez économiser des jetons sur les grandes pages, transmettez offload_large: true par appel d'outil. Les réponses >= 50 Ko sont ensuite écrites sur le disque, renvoyées sous forme de resource_link, et votre client récupère le corps uniquement lorsqu'il en a réellement besoin. Les données en cache expirent après 1 heure.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Client offload_large: true
Claude Desktop pas encore, laissez la valeur par défaut false
Claude Code, Cursor, Windsurf pris en charge
VS Code MCP extension pris en charge

Isolé par locataire : chaque clé API obtient son propre espace de noms (sha256(apiKey)[:16]). Seule la clé qui a stocké un payload peut le relire. Les lectures inter-locataires renvoient Payload not found sans fuite d'existence.

Prompts intégrés

Six modèles de workflow apparaissent sous /prompts dans n'importe quel client MCP. Chacun prend des arguments nommés et renvoie un message utilisateur basé sur un modèle, orchestrant un ou plusieurs outils.

Prompt Arguments Ce qu'il fait
smart_fetch url, must_contain facultatif, extract Fetch automatique (choisit la méthode, gère la protection contre les bots), puis renvoie ou extrait le contenu
scrape_product_page url Fetch par navigateur, puis extrait le titre du produit, le prix, l'image, le stock, le SKU en JSON
extract_article url Requête unique avec fallback sur proxy, puis supprime la navigation et les publicités et renvoie l'article propre en JSON
monitor_pricing url, target_price facultatif Fetch par proxy, extrait le prix actuel, le compare à la cible
check_endpoint_health url, expected_text facultatif Requête unique avec validation stricte, renvoie l'accessibilité et les temps d'exécution
bulk_fetch_urls urls (séparés par des virgules) Requêtes uniques parallèles, fallback automatique sur proxy par URL, renvoie uniquement les métadonnées

Les prompts coûtent zéro token au repos. Seuls les prompts invoqués entrent dans le contexte LLM.

Texte intégral plus prompts de fallback manuel : Recettes MCP.

Enveloppe d'erreur

Chaque erreur (isError: true) comporte une enveloppe structuredContent. Champs minimums pour chaque erreur :

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

En cas d'erreurs en amont avec un statut HTTP, status est également présent. En cas d'erreurs de limite de débit (rate limit) et de capacité, l'enveloppe amont ajoute retryAfter, current.{concurrency, rpm} et limits.{maxConcurrency, maxRpm}. Consultez Erreurs API pour la forme REST sous-jacente.

Valeurs code stables :

Code HTTP Signification Tentative sûre ?
ssrf_blocked n/a Adresse IP cible dans une plage privée ou réservée (RFC 5735, 6598, IPv6 réservé) Non, modifiez l'URL
upstream_non_json varie L'amont a renvoyé un corps malformé Peut-être, enquêtez
output_validation_failed n/a Le outputSchema du serveur MCP a rejeté la réponse en amont (bug du serveur ou forme inattendue en amont) Peut-être, signalez
bad_request 400 Forme d'entrée rejetée Non, corrigez les arguments
auth_failed 401 Clé manquante, invalide ou désactivée Non, corrigez la clé
forbidden 403 Authentifié mais non autorisé Non, ou passez à foura_proxy
not_found 404 Cible ou endpoint manquant Non
rate_limited 429 Limite RPM atteinte Oui, attendez retryAfter
at_capacity 503 Limite de concurrence atteinte Oui, attendez retryAfter
service_disabled 503 Fenêtre de maintenance ou votre plan n'inclut pas cet outil Contactez le support
service_unavailable 503 503 générique Oui, délai d'attente court
upstream_error 500+ 5xx en amont Oui, délai d'attente exponentiel
upstream_client_error 4xx Autre 4xx Généralement non
upstream_unknown autre Défensif, ne devrait pas se produire en pratique Enquêtez
no_eligible_proxy n/a Aucun proxy ne correspond à la portée exitCountries stricte Réessayez plus tard ; modifiez la portée uniquement de manière explicite

Les agents LLM peuvent lire code directement pour la logique de nouvelle tentative sans analyser le texte. Procédure d'authentification : Authentification.

Limites

  • Corps en ligne par défaut. Avec offload_large: true, les réponses >= 50 Ko vont sur le disque + resource_link (par locataire, TTL de 1 heure).
  • Les cibles privées sont refusées (RFC 5735, RFC 6598, blocs réservés IPv6) au niveau de la couche MCP. Seuls les hôtes publics sont transférés.
  • Limite du corps de la requête de 256 Ko sur les requêtes /mcp entrantes (les vrais payloads MCP font < 4 Ko).
  • Les limites de débit sont appliquées par l'API FourA pour chaque service. Consultez Limites de débit.

Auto-hébergement

Le code source complet du serveur est public sur GitHub sous @fouradata/mcp. Clonez le dépôt, npm install, npm run build, et exécutez node dist/http.js pour configurer votre propre instance. S'exécute sans état dans un seul conteneur derrière n'importe quel répartiteur de charge.

Environnement configurable :

Variable Défaut Objectif
PORT 3076 Port d'écoute HTTP
FOURA_API_BASE https://api.foura.ai/api URL de base REST FourA en amont
FOURA_MCP_PAYLOADS_DIR /data/payloads Où les response >= 50 Ko sont mises en cache sur le disque (avec offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Liste blanche de noms d'hôtes pour le header Host (défense contre le DNS-rebinding)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Liste blanche d'origines pour les appels depuis le navigateur
FOURA_MCP_RESOURCE_METADATA_URL https://foura.ai/docs/mcp/server#auth URL renvoyée dans WWW-Authenticate lors d'une erreur 401

Le conteneur officiel s'exécute en tant que uid 1001 (non-root). Le montage hôte /data/payloads doit être accessible en écriture par cet uid.

Mettez à l'échelle horizontalement derrière n'importe quel équilibreur de charge. Les clients fournissent leur clé à chaque request, il n'y a donc pas de session persistante.

Mis à jour : 6 août 2026