MCP Server
MCP Server
Nutze FourA von jedem Model Context Protocol-Client (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) aus als vier native Tools und sechs Workflow-Prompts. Kein Integrationscode, kein benutzerdefinierter HTTP-Client.
Open Source auf GitHub; auf npm als @fouradata/mcp. Aktueller Release: 0.7.3.
Quickstart: Lokales stdio (empfohlen für Claude Desktop)
Hole dir einen Key unter foura.ai/dashboard#api-keys (ein Klick, wird bei der Erstellung einmalig angezeigt, Format pk_live_...). Fügen dies in die Konfiguration deines MCP-Clients ein:
{
"mcpServers": {
"foura": {
"command": "npx",
"args": ["-y", "@fouradata/mcp"],
"env": { "FOURA_API_KEY": "pk_live_..." }
}
}
}
Claude Desktop Fallstrick: Schließe Claude Desktop vollständig (
Cmd+Qunter macOS), bevor du die Konfigurationsdatei bearbeitest. Wenn die App noch läuft, überschreibt sie deine Änderungen beim Beenden mit ihrer In-Memory-Konfiguration.
Der Befehl npx lädt @fouradata/mcp beim ersten Start herunter und führt es als Subprozess deines MCP-Clients aus. Keine globale Installation erforderlich.
| Client | Speicherort der Konfiguration |
|---|---|
| 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 (setze zuerst FOURA_API_KEY in der Umgebung) |
| Cursor | ~/.cursor/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| VS Code (MCP-Erweiterung) | .vscode/mcp.json |
Starte den Client neu. Die Tools (foura_auto, foura_single, foura_proxy, foura_browser) und sechs Prompts erscheinen in deiner Tool-Liste.
Schnellstart: Hosted (Streamable HTTP)
Für Clients, die den Streamable-HTTP-Transport unterstützen (Cursor, Windsurf, VS Code, Claude Code mit --transport http), verweise direkt auf den gehosteten Endpoint, anstatt einen lokalen Subprozess auszuführen:
{
"mcpServers": {
"foura": {
"url": "https://mcp.foura.ai/mcp",
"headers": {
"Authorization": "Bearer pk_live_..."
}
}
}
}
Nutze für Claude Desktop die obige stdio-Konfiguration oder binde den gehosteten Endpoint über mcp-remote an:
{
"mcpServers": {
"foura": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.foura.ai/mcp", "--header", "Authorization: Bearer pk_live_..."]
}
}
}
Hosted Endpoint Referenz
| Eigenschaft | Wert |
|---|---|
| URL | https://mcp.foura.ai/mcp |
| Transport | Streamable HTTP (POST /mcp, SSE-Antworten) |
| Authentifizierung | Authorization: Bearer pk_live_... pro Request |
| MCP-Protocol-Version | Gemäß @modelcontextprotocol/sdk (aktuell 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07) |
| 401 Challenge | WWW-Authenticate: Bearer realm="foura-mcp" |
Die 401 Challenge enthält absichtlich keinen RFC 9728 resource_metadata Parameter. Wird dieser angegeben, startet ein OAuth-fähiger Client einen Flow, den dieser Server nicht implementiert. Sende deinen pk_live_ Key als Bearer-Token, und der 401 verschwindet.
Der gehostete Server ist zustandslos. Jeder Request enthält seinen eigenen Key, den der Server als X-API-Key an die FourA API weiterleitet. Ein Key schaltet alle vier Tools frei.
Zum Schutz vor DNS-Rebinding (CVE-2025-66414) validiert der Server den Host Header (muss mcp.foura.ai oder localhost sein) sowie den Origin Header, falls vorhanden (Allowlist: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Server-to-Server-Aufrufer (curl, MCP-Clients im stdio-Bridge-Modus) senden keinen Origin und werden durchgelassen.
Tools
Alle vier Tools sind gemäß der MCP-Spezifikation vom 18.06.2025 als readOnlyHint: true und openWorldHint: true annotiert. Clients, die vertrauenswürdige Read-Only-Tools automatisch freigeben, rufen sie ohne Bestätigungsdialog pro Request auf.
foura_auto ist der smarte Standard: Übergib eine URL und das Tool liefert den Inhalt, wobei es die Abrufmethode automatisch wählt. Die anderen drei sind die Low-Level-Primitive, die es orchestriert; nutze sie, wenn du explizite Kontrolle benötigst.
foura_auto
Übergib eine URL, wenn FourA die Request-Methode wählen soll. Es führt begrenzte Versuche über die verfügbaren HTTP-, Proxy- und Browser-Pfade durch. Übergib validate bei geschützten Zielen, damit die Response Inhalte enthalten muss, die die echte Seite identifizieren. Wenn kein Versuch die Validierung erfüllt, gibt das Tool einen Fehler zurück, anstatt eine Challenge-Seite als Erfolg zu werten.
Die Response enthält Details zur Ausführung in meta und standardmäßig eine wiederverwendbare session mit proxy, cookies und userAgent. Für ein einfaches Follow-up rufe foura_single mit session.proxy als proxy auf, serialisiere die Cookies als Cookie Header und sende session.userAgent als User-Agent Header. Für JavaScript-Rendering übergib die Session-Werte an die passenden foura_browser Felder.
foura_single
Ein HTTP-Request, Response zurück. Bildet POST /api/single/ eins-zu-eins ab.
Verwende dies für statische Seiten, JSON-APIs und Server-gerendertes HTML.
Auswahl des simulierten Browsers
Ein Request nutzt standardmäßig das aktuelle Google Chrome. Wenn ein Ziel einen Browser akzeptiert und einen anderen ablehnt, setze browser (Chrome, Edge, Safari, Firefox oder Tor), os (Windows, macOS, Android oder iOS) oder version, oder übergib eine exakte profile ID:
{
"method": "GET",
"url": "https://example.com",
"browser": "Firefox",
"os": "Windows"
}
Passen mehrere Profile, gewinnt die neueste Version. Eine nicht existierende Kombination gibt einen Fehler mit den verfuegbaren Optionen zurueck. So wird ein Request nie als Browser gesendet, den du nicht gewaehlt hast. Die Auswahl erfordert unblocker, was standardmaessig aktiv ist. Der Katalog ist unter GET /api/profiles veroeffentlicht und erfordert keinen API-Key.
Dieselben vier Felder befinden sich im request-Objekt von foura_proxy.
foura_proxy
Leite einen HTTP-Request ueber rotierende Proxys mit automatischem Retry weiter. Nutze dies, wenn foura_single blockiert ist oder das Ziel ein bestimmtes Exit-Land erfordert.
Setze exitCountries auf eine strikte Allowlist aus zweistelligen Laendercodes, die fuer das Ziel sichtbar sein sollen (vom Nutzer bereitgestellt oder durch Zielanforderungen vorgegeben):
{
"maxTries": 5,
"exitCountries": ["CZ", "GB"],
"request": {
"method": "GET",
"url": "https://example.com/pricing",
"browser": "Chrome",
"os": "Windows"
}
}
Werte werden getrimmt, in Großbuchstaben umgewandelt und dedupliziert. Proxys mit unbekannten Exits werden ausgeschlossen, und der Request fällt niemals auf ein nicht angefordertes Land zurück. Die Auswahl nutzt die neuesten verfügbaren ziel-sichtbaren Ländermetadaten, die normalerweise innerhalb von zehn Minuten aktualisiert werden; es handelt sich nicht um einen Live-Geolocation-Lookup während des Requests. Leite das bereitstellende Land nicht von der Proxy-Host-Adresse ab.
Ein zielgerichteter Erfolg gibt exitCountry und die wiederverwendbare proxy-ID zurück. Prüfe, ob exitCountry zur angeforderten Allowlist gehört. Wenn der aktuelle Pool keine Übereinstimmung hat, gibt das Tool code: "no_eligible_proxy" mit dem normalisierten Scope in details.exitCountries zurück. Behalte diesen Scope bei und versuche es später erneut. Ändere oder erweitere ihn nur, wenn der Benutzer die Anforderung explizit ändert. Country-Scoping ist ab dem Startup-Plan enthalten. Bei einem Plan ohne dieses Feature wird ein Aufruf, der exitCountries sendet, mit 403 und X-FourA-Limit: plan_limit_feature abgelehnt.
Wenn die ausgewählte Seite später JavaScript benötigt, übergib die zurückgegebene proxy-ID an foura_browser.proxy, damit der Browser denselben Exit wiederverwendet.
Setze exitClass: "premium" für ein Ziel, das der Standard-Pool nicht erreichen kann, egal wie viele Exits versucht werden. Es ist eine Erlaubnis, keine Anweisung: Der Standard-Pool konkurriert weiterhin um die Antwort und gewinnt meistens, und ein Request, den er beantwortet, bevor ein Premium-Exit versucht wird, kostet keinen Premium-Traffic. Ein Premium-Versuch zählt den übertragenen Traffic, selbst wenn er fehlschlägt. Die Response meldet exitClass zurück, premium oder standard, sodass du pro Request sehen kannst, welche Klasse dich bedient hat. standard ist auch die Antwort, sobald der in deinem Plan enthaltene Premium-Traffic aufgebraucht ist, und stellt ein normales Ergebnis statt eines Fehlers dar. exitClass: "standard" verbietet die Eskalation vollständig. exitClass: "premium" auf einem Plan ohne Premium-Exits wird mit code: "plan_limit_premium" abgelehnt. Siehe exitClass.
Musste die Rotation zu einer anderen Browser-Familie wechseln, um eine Antwort zu erhalten, enthält eine erfolgreiche Response profile mit der gewählten Familie. Wiederhole den Request damit, sonst verwendet der nächste Aufruf erneut die Version, die fehlgeschlagen ist.
Eine fehlgeschlagene Rotation enthält attemptReport neben dem Fehler: einen summary-Satz sowie Zähler, die Exits trennen, die nie geantwortet haben (noResponse), Exits, die eine Bot-Prüfung abgelehnt hat (defense, mit den Anbietern in vendors), Seiten, die empfangen und nur durch deine eigene validate.data verworfen wurden (contentRejected), statusRejected und other. profilesTried listet die vom Task gesendeten Browser in der Reihenfolge ihrer ersten Verwendung auf, wobei default bedeutet, dass der Request genau wie angegeben gesendet wurde. Ein hoher contentRejected-Wert bedeutet, dass FourA echte Seiten geliefert hat und deine eigene Regel sie verworfen hat. Siehe Why a Proxy Request Ran Out of Tries.
foura_browser
Vollständige Browser-Session. JavaScript wird ausgeführt, das DOM wird gerendert, Cookies werden zurückgegeben. Spiegelt POST /api/browser/ wider.
Verwende dies für Single-Page-Apps, Lazy-Loaded-Inhalte oder Seiten mit einer Prüfung, die einen echten Browser erfordert.
Informationen zu Input-Formaten, Standardwerten und Validierungsregeln für jedes Tool findest du in der REST-Endpoint-Referenz. Tool-Schemas stimmen Feld für Feld mit der REST-API überein, zuzüglich des MCP-exklusiven Opt-ins offload_large (siehe unten).
Wenn ein Ziel einen Bot-Check durchführt
foura_single und foura_proxy geben defense zurück, wenn das Ziel vor der Auslieferung des Bodys einen Bot-Check durchgeführt hat. defense.solved: true bedeutet, dass der Check bestanden wurde und data die echte Seite ist; false bedeutet, dass der Body eine Challenge-Seite sein kann. Wiederhole die Anfrage mit einem anderen Browser, Betriebssystem oder einer anderen Version oder wechsle zu foura_proxy oder foura_browser, anstatt die Challenge-Seite als Inhalt zu verarbeiten.
Typisierte Responses
Jede Tool-Response enthält sowohl content (menschenlesbare Textzusammenfassung) als auch structuredContent (typisiertes JSON, validiert gegen das outputSchema des Tools). Jedes Tool hat seine eigene Struktur:
foura_auto: Einzelformat{ status, headers, data }plusmeta({ rung, solved, attempts, credits }, immer vorhanden, wobeirungeines voncache,probe,proxy,browser,warmup,failist) und standardmäßigsession({ proxy, cookies, userAgent }) für das Replay über Low-Level-Tools. Keintotal_time.foura_single:{ status, headers, data, total_time, ... }(Headers ist ein Array, ein Eintrag pro Redirect-Hop)foura_proxy: identisch mit single, plus{ proxy, total }; ein scoped Erfolg enthält zudemexitCountry, ein Request mit Klassenangabe enthältexitClass, eine Rotation mit Wechsel der Browser-Familie enthältprofileund ein Fehlschlag enthältattemptReportfoura_browser: eigenständiges Format{ status, headers: object, body, cookies, userAgent }(Hinweis:bodykann je nach Content-Type ein String oder Objekt sein)
Jedes Tool gibt außerdem an, was der Aufruf gekostet hat und wie er nachverfolgt werden kann, ausgelesen aus den Response-Headern der API:
credits: Für diesen Aufruf verbrauchte Credits. Auch bei Fehlern vorhanden, da die Arbeit in jedem Fall ausgeführt wurde. Dir werden nur erfolgreiche Aufrufe berechnet, ein Fehlschlag zeigt seine Credits hier also an, kostet dich aber nichts.request_id: FourA-ID für den Aufruf. Gib diese bei einer Support-Anfrage an.exitClass:premium, wenn ein Premium-Exit den Aufruf bedient hat. Beifoura_singleundfoura_browserpassiert das, wennproxyeinen vonfoura_proxygefundenen Exit wiederverwendet.
Jeder Wert fehlt, wenn die API nichts zurückgemeldet hat, sodass ein Client für eine frühere Version unverändert weiterfunktioniert. Dieselben Werte sind unter Response Headers dokumentiert.
Clients mit Unterstützung für structuredContent können das typisierte Objekt direkt an das LLM übergeben, anstatt JSON aus Fließtext parsen zu müssen.
Mehrwertige Response-Header
Header, die mehrfach vorkommen (Set-Cookie, Link, WWW-Authenticate), werden als Arrays zurückgegeben:
{
"headers": [
{
"result": { "version": "HTTP/2", "code": 200, "reason": "" },
"content-type": "text/html",
"set-cookie": ["a=1; Path=/", "b=2; Path=/"]
}
]
}
Das ist wichtig für Websites, die Session-, Tracking- und Consent-Cookies in einer einzigen Response setzen (der Großteil des E-Commerce).
Große Responses: offload_large (Standard: inline)
Standardmäßig (seit v0.2.0) werden vollständige Response Bodies unabhängig von ihrer Größe inline in structuredContent zurückgegeben. Das funktioniert in jedem MCP-Client direkt nach der Installation.
Wenn dein Client MCP-resources/read unterstützt UND du bei großen Seiten Token sparen möchtest, übergib offload_large: true pro Tool-Aufruf. Responses >= 50 KB werden dann auf die Festplatte geschrieben, als resource_link zurückgegeben und dein Client ruft den Body nur ab, wenn er ihn tatsächlich benötigt. Auf dem gehosteten Server laufen zwischengespeicherte Payloads nach 1 Stunde ab. Auf deiner eigenen Instanz löscht nichts gespeicherte Payloads: Lösche Dateien, die älter als eine Stunde sind, selbst aus dem Payload-Verzeichnis.
{
"method": "GET",
"url": "https://en.wikipedia.org/wiki/Web_scraping",
"offload_large": true
}
| Client | offload_large: true |
|---|---|
| Claude Desktop | noch nicht, Standard false belassen |
| Claude Code, Cursor, Windsurf | unterstützt |
| VS Code MCP-Erweiterung | unterstützt |
Mandantenisoliert: Jeder API-Key erhält seinen eigenen Namespace (sha256(apiKey)[:16]). Nur der Key, der ein Payload gespeichert hat, kann es wieder lesen. Mandantenübergreifende Lesezugriffe geben Payload not found ohne Existenz-Leak zurück.
Integrierte Prompts
Sechs Workflow-Vorlagen stehen unter /prompts in jedem MCP-Client zur Verfügung. Jede Vorlage akzeptiert benannte Argumente und gibt eine vorformatierte User Message zurück, die ein oder mehrere Tools orchestriert.
| Prompt | Argumente | Funktion |
|---|---|---|
smart_fetch |
url, optional must_contain, extract |
Auto-Fetch (wählt die Methode, umgeht Bot-Protection), gibt dann den Inhalt zurück oder extrahiert ihn |
scrape_product_page |
url |
Browser-Fetch, extrahiert dann Produkttitel, Preis, Bild, Verfügbarkeit und SKU als JSON |
extract_article |
url |
Single-Request mit Proxy-Fallback, entfernt dann Navigation/Werbung und gibt sauberes Artikel-JSON zurück |
monitor_pricing |
url, optional target_price |
Proxy-Fetch, extrahiert aktuellen Preis, vergleicht mit Zielpreis |
check_endpoint_health |
url, optional expected_text |
Single-Request mit strikter Validierung, gibt Erreichbarkeit und Timing zurück |
bulk_fetch_urls |
urls (kommagetrennt) |
Paralleler Single-Request, automatischer Proxy-Fallback pro URL, gibt nur Metadaten zurück |
Prompts kosten im Ruhezustand null Tokens. Nur aufgerufene Prompts gelangen in den LLM-Kontext.
Vollständiger Text sowie manuelle Fallback-Prompts: MCP Recipes.
Error-Envelope
Jeder Fehler (isError: true) enthält ein structuredContent-Envelope. Mindestfelder bei jedem Fehler:
{
"service": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
Bei Upstream-Fehlern mit HTTP-Status ist status ebenfalls vorhanden. Bei Rate-Limit- und Kapazitätsfehlern fügt der Upstream-Envelope retryAfter, current.{concurrency, rpm} und limits.{maxConcurrency, maxRpm} hinzu. Siehe API Errors für die zugrunde liegende REST-Struktur.
Stabile code-Werte:
| Code | HTTP | Bedeutung | Retry sicher? |
|---|---|---|---|
ssrf_blocked |
n/a | Das Ziel ist eine private oder reservierte Adresse (RFC 5735, 6598, IPv6 reserviert), die URL ist nicht http(s) oder ihr Hostname konnte nicht aufgelöst werden | Nein, prüfe die URL. Ein kurzzeitig fehlgeschlagener Lookup kann wiederholt werden |
upstream_non_json |
variiert | Upstream hat fehlerhaften Body zurückgegeben | Eventuell, untersuchen |
output_validation_failed |
n/a | outputSchema des MCP-Servers hat die Upstream-Antwort abgelehnt oder das Tool konnte den Call überhaupt nicht abschließen (kein API-Key konfiguriert, API nicht erreichbar) |
Eventuell: Setup prüfen, dann melden |
bad_request |
400 | Input-Format abgelehnt | Nein, Argumente korrigieren |
auth_failed |
401 | Key fehlt, ist ungültig oder deaktiviert | Nein, Key korrigieren |
forbidden |
403 | Das Ziel hat mit 403 geantwortet und dein validate hat es abgelehnt (ein Site-Check, eine Länderbeschränkung) |
Nein, oder wechsle zu foura_proxy |
not_found |
404 | Ziel oder Endpoint fehlt | Nein |
rate_limited |
429 | RPM-Limit erreicht | Ja, warte retryAfter |
at_capacity |
503 | Concurrency-Limit erreicht | Ja, warte retryAfter |
service_disabled |
503 | Der Dienst ist wegen Wartungsarbeiten deaktiviert. Ein Tool, das dein Plan nicht enthält, wird als plan_limit_feature zurückgegeben |
Support kontaktieren |
service_unavailable |
503 | Generischer 503-Fehler | Ja, kurzes Backoff |
upstream_error |
500+ oder 0 | Das Ziel hat mit einem Serverfehler geantwortet, oder bei foura_proxy haben foura_browser und foura_auto nie geantwortet |
Ja, exponentielles Backoff |
upstream_client_error |
4xx | Sonstige 4xx | Normalerweise nein |
upstream_unknown |
sonstige | Der Request lief, lieferte aber keine akzeptierte Antwort: Bei foura_single hat das Ziel nie geantwortet (Timeout, Verbindung abgelehnt), und bei jedem Tool hat dein validate eine 2xx- oder 3xx-Antwort abgelehnt. Lies status und error |
Untersuchen |
no_eligible_proxy |
n/a | Kein Proxy entspricht dem strikten exitCountries-Scope |
Später wiederholen; Scope nur explizit ändern |
plan_limit_* |
403 oder 429 | Eines der Limits deines Plans hat den Call abgelehnt: plan_limit_ gefolgt von feature, premium, concurrency, rate, browser_daily, credits oder bandwidth. Siehe MCP Server Errors |
Warte retryAfter falls vorhanden; andernfalls nicht vor Reset des Limits oder Planänderung |
LLM-Agents können code für Retry-Logik direkt auslesen, ohne Fließtext zu parsen. Authentifizierungs-Anleitung: Authentication.
Limits
- Standardmäßig Inline-Body. Mit
offload_large: truewerden Responses >= 50 KB auf der Festplatte gespeichert +resource_link(pro Tenant, 1 Stunde TTL). - Private Ziele werden auf der MCP-Ebene abgelehnt (RFC 5735, RFC 6598, IPv6-reservierte Blöcke). Nur öffentliche Hosts werden weitergeleitet.
- Request-Body-Limit von 256 KB für eingehende
/mcp-Requests (tatsächliche MCP-Payloads sind < 4 KB). - Rate Limits werden von der FourA API pro Service durchgesetzt. Siehe Rate Limits.
Self-Hosting
Der vollständige Server-Quellcode ist öffentlich auf GitHub unter @fouradata/mcp verfügbar. Klone das Repo, führe npm install sowie npm run build aus und starte node dist/http.js, um deine eigene Instanz aufzusetzen. Läuft zustandslos in einem einzelnen Container hinter jedem Load Balancer.
Konfigurierbare Umgebungsvariablen:
| Variable | Standard | Zweck |
|---|---|---|
PORT |
3076 |
HTTP-Listen-Port |
FOURA_API_BASE |
https://api.foura.ai/api |
Upstream-FourA-REST-Basis-URL |
FOURA_MCP_PAYLOADS_DIR |
ein foura-mcp-payloads-Ordner im temporären Systemverzeichnis (die mitgelieferte Docker-Compose-Datei setzt /data/payloads) |
Speicherort für auf Festplatte gecachte Responses >= 50 KB (mit offload_large: true) |
FOURA_MCP_ALLOWED_HOSTS |
mcp.foura.ai,localhost,127.0.0.1,[::1] |
Hostname-Allowlist für den Host-Header (Schutz vor DNS-Rebinding) |
FOURA_MCP_ALLOWED_ORIGINS |
https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com |
Origin-Allowlist für Browser-Aufrufer |
Der offizielle Container läuft als uid 1001 (non-root). Der /data/payloads-Host-Bind-Mount muss für diese UID beschreibbar sein.
Skaliere horizontal hinter jedem beliebigen Load Balancer. Clients übergeben ihren Schlüssel bei jedem Request, daher sind keine Sticky Sessions erforderlich.