Serwer MCP

Serwer MCP

Używaj FourA z dowolnego klienta Model Context Protocol (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) w postaci czterech natywnych narzędzi i sześciu promptów workflow. Bez kodu integracyjnego, bez własnego klienta HTTP.

Open source na GitHub; w npm jako @fouradata/mcp. Aktualne wydanie: 0.7.3.

Szybki start: lokalne stdio (zalecane dla Claude Desktop)

Pobierz klucz na foura.ai/dashboard#api-keys (jedno kliknięcie, widoczny tylko raz przy tworzeniu, format pk_live_...). Wklej to do konfiguracji swojego klienta MCP:

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

Ważna uwaga dotycząca Claude Desktop: zamknij całkowicie Claude Desktop (Cmd+Q na macOS) przed edycją pliku konfiguracyjnego. Jeśli aplikacja nadal działa, nadpisze Twoje zmiany konfiguracją z pamięci podczas zamykania.

Polecenie npx pobiera @fouradata/mcp przy pierwszym uruchomieniu i uruchamia je jako podproces Twojego klienta MCP. Globalna instalacja nie jest wymagana.

Klient Lokalizacja konfiguracji
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 (najpierw ustaw FOURA_API_KEY w env)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (rozszerzenie MCP) .vscode/mcp.json

Uruchom ponownie klienta. Narzędzia (foura_auto, foura_single, foura_proxy, foura_browser) oraz sześć promptów pojawią się na liście narzędzi.

Szybki start: wersja hostowana (Streamable HTTP)

W przypadku klientów obsługujących transport Streamable HTTP (Cursor, Windsurf, VS Code, Claude Code z --transport http), wskaż hostowany endpoint zamiast uruchamiać lokalny podproces:

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

W przypadku Claude Desktop użyj powyższej konfiguracji stdio lub przekieruj hostowany endpoint przez mcp-remote:

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

Dokumentacja hostowanego endpointu

Właściwość Wartość
URL https://mcp.foura.ai/mcp
Transport Strumieniowalne HTTP (POST /mcp, odpowiedzi SSE)
Uwierzytelnianie Authorization: Bearer pk_live_... na żądanie
MCP-Protocol-Version Zgodnie z @modelcontextprotocol/sdk (obecnie 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
Wyzwanie 401 WWW-Authenticate: Bearer realm="foura-mcp"

Wyzwanie 401 celowo nie zawiera parametru resource_metadata wg RFC 9728. Jego rozgłaszanie powoduje, że klient obsługujący OAuth rozpoczyna przepływ, którego ten serwer nie implementuje. Wyślij swój klucz pk_live_ jako token Bearer, a błąd 401 zniknie.

Hostowany serwer jest bezstanowy. Każde żądanie przekazuje własny klucz, który serwer przesyła dalej do FourA API jako X-API-Key. Jeden klucz odblokowuje wszystkie cztery narzędzia.

W celu ochrony przed atakami DNS-rebinding (CVE-2025-66414) serwer weryfikuje nagłówek Host (musi mieć wartość mcp.foura.ai lub localhost) oraz nagłówek Origin, gdy jest obecny (dozwolone: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Wywołania server-to-server (curl, klienci MCP w trybie mostka stdio) nie wysyłają nagłówka Origin i są przepuszczane.

Narzędzia

Wszystkie cztery narzędzia są oznaczone jako readOnlyHint: true i openWorldHint: true zgodnie ze specyfikacją MCP z 2025-06-18. Klienci automatycznie zatwierdzający zaufane narzędzia tylko do odczytu wywołują je bez modala potwierdzenia przy każdym żądaniu.

foura_auto to inteligentny wybór domyślny: podaj mu URL, a zwróci zawartość, dobierając metodę pobierania za Ciebie. Pozostałe trzy to niskopoziomowe elementy pierwotne, którymi zarządza; sięgnij po nie, gdy potrzebujesz bezpośredniej kontroli.

foura_auto

Podaj URL, jeśli chcesz, aby FourA wybrało metodę żądania. Wykonuje ono ograniczoną liczbę prób przy użyciu dostępnych ścieżek HTTP, proxy i przeglądarkowych. Przekaż parametr validate dla chronionych celów, aby odpowiedź musiała zawierać treść identyfikującą właściwą stronę. Jeśli żadna próba nie spełni warunków walidacji, narzędzie zwróci błąd zamiast prezentować stronę weryfikacji CAPTCHA/challenge jako sukces.

Odpowiedź zawiera szczegóły wykonania w meta oraz domyślnie obiekt session wielokrotnego użytku z proxy, cookies i userAgent. W przypadku zwykłego kolejnego żądania wywołaj foura_single z session.proxy jako proxy, zserializuj pliki cookie jako nagłówek Cookie i wyślij session.userAgent jako nagłówek User-Agent. Do renderowania JavaScriptu przekaż wartości sesji do pasujących pól foura_browser.

foura_single

Jedno żądanie HTTP, jedna odpowiedź zwrotna. Odpowiada POST /api/single/ w relacji jeden do jednego.

Używaj dla stron statycznych, interfejsów JSON API, kodu HTML renderowanego po stronie serwera.

Wybór prezentowanej przeglądarki

Żądanie domyślnie przedstawia się jako najnowszy Google Chrome. Gdy cel akceptuje jedną przeglądarkę, a odrzuca inną, ustaw browser (Chrome, Edge, Safari, Firefox lub Tor), os (Windows, macOS, Android lub iOS) albo version, lub przekaż dokładny identyfikator profile:

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

Najnowsza wersja ma pierwszeństwo, gdy pasuje kilka profili. Kombinacja, która nie istnieje, zwraca błąd z listą dostępnych opcji, więc request nigdy nie zostanie wysłany jako przeglądarka, której nie wybrano. Wybór wymaga unblocker, co jest domyślnie włączone. Katalog jest opublikowany pod adresem GET /api/profiles i nie wymaga klucza API.

Te same cztery pola znajdują się w obiekcie request w foura_proxy.

foura_proxy

Kieruj pojedynczy request HTTP przez rotujące proxy z automatycznym ponawianiem. Użyj tego, gdy foura_single jest zablokowany lub cel wymaga określonego kraju wyjściowego.

Ustaw exitCountries na ścisłą listę dozwolonych dwuliterowych kodów krajów widocznych dla celu, dostarczoną przez użytkownika lub wymaganą przez cel:

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

Wartości są przycinane, zamieniane na wielkie litery i deduplikowane. Węzły proxy z nieznanym krajem wyjściowym są wykluczane, a request nigdy nie przełącza się na niezażądany kraj. Wybór opiera się na najnowszych dostępnych metadanych kraju widocznego dla celu, aktualizowanych zwykle w ciągu dziesięciu minut; nie jest to geolokalizacja w czasie rzeczywistym podczas wykonywania requestu. Nie należy wnioskować o kraju obsługującym na podstawie adresu hosta proxy.

Sukces z określonym zakresem zwraca exitCountry oraz identyfikator proxy do ponownego użycia. Sprawdź, czy exitCountry należy do żądanej allowlisty. Jeśli w bieżącej puli nie ma dopasowania, narzędzie zwraca code: "no_eligible_proxy" ze znormalizowanym zakresem w details.exitCountries. Zachowaj ten zakres i ponów próbę później. Zmień go lub rozszerz tylko wtedy, gdy użytkownik wyraźnie zmieni wymagania. Określanie zakresu kraju jest dostępne od planu Startup wzwyż. W planie bez tej funkcji wywołanie wysyłające exitCountries jest odrzucane z kodem 403 i X-FourA-Limit: plan_limit_feature.

Jeśli wybrana strona wymaga później JavaScriptu, przekaż zwrócony identyfikator proxy do foura_browser.proxy, aby przeglądarka użyła tego samego węzła wyjściowego.

Ustaw exitClass: "premium" dla celu, do którego standardowa pula nie może dotrzeć niezależnie od liczby wypróbowanych węzłów wyjściowych. Jest to zezwolenie, a nie polecenie: standardowa pula nadal konkuruje o odpowiedź i zwykle wygrywa, a request obsłużony przez nią przed wypróbowaniem jakiegokolwiek węzła premium nie zużywa transferu premium. Próba premium zlicza przesłany transfer nawet w przypadku niepowodzenia. Response zwraca exitClass, premium lub standard, dzięki czemu widzisz dla każdego requestu, która klasa go obsłużyła. standard jest również odpowiedzią po wyczerpaniu transferu premium zawartego w planie i jest to normalny wynik, a nie błąd. exitClass: "standard" całkowicie zabrania eskalacji. exitClass: "premium" w planie bez węzłów wyjściowych premium jest odrzucane z błędem code: "plan_limit_premium". Zobacz exitClass.

Gdy rotacja musiała przełączyć się na inną rodzinę przeglądarek, aby uzyskać odpowiedź, udany response zawiera profile z rodziną, na której się zatrzymała. Użyj jej ponownie, inaczej kolejne wywołanie powtórzy wersję, która zakończyła się niepowodzeniem.

Nieudana rotacja zwraca attemptReport obok błędu: jedno zdanie w summary oraz liczniki rozróżniające węzły wyjściowe, które nigdy nie odpowiedziały (noResponse), węzły wyjściowe odrzucone przez weryfikację botów (defense, wraz z dostawcami w vendors), strony, które dotarły i zostały odrzucone wyłącznie przez Twoją własną regułę validate.data (contentRejected), statusRejected oraz other. profilesTried wymienia przeglądarki wysłane przez zadanie w kolejności pierwszego użycia, gdzie default oznacza, że request wyszedł dokładnie w postaci zapisanej. Wysoka wartość contentRejected oznacza, że FourA dostarczyło prawdziwe strony, a Twoja własna reguła je odrzuciła. Zobacz Dlaczego wyczerpały się próby requestu proxy.

foura_browser

Pełna sesja przeglądarki. JavaScript się wykonuje, DOM jest renderowany, cookies są zwracane. Odzwierciedla POST /api/browser/.

Używaj do aplikacji single-page (SPA), treści ładowanych leniwie (lazy loading) lub stron z weryfikacją wymagającą prawdziwej przeglądarki do ukończenia.

Formaty danych wejściowych, wartości domyślne i reguły walidacji dla każdego narzędzia opisano w dokumentacji endpointów REST. Schematy narzędzi odpowiadają polom REST API jeden do jednego, plus opcjonalne pole offload_large dostępne wyłącznie w MCP (patrz poniżej).

Gdy cel uruchamia weryfikację antybotową

foura_single oraz foura_proxy zwracają defense, gdy cel uruchomił weryfikację antybotową przed zwróceniem body. defense.solved: true oznacza, że weryfikacja zakończyła się sukcesem, a data to właściwa strona; false oznacza, że body może zawierać stronę challenge. Ponów próbę z inną przeglądarką, systemem operacyjnym lub wersją, albo przejdź do foura_proxy lub foura_browser, zamiast traktować stronę challenge jako treść właściwą.

Typowane odpowiedzi

Każda odpowiedź narzędzia zawiera zarówno content (czytelne dla człowieka podsumowanie tekstowe), jak i structuredContent (typowany JSON zweryfikowany z outputSchema narzędzia). Każde narzędzie ma własną, unikalną strukturę:

  • foura_auto: pojedyncza struktura { status, headers, data } oraz meta ({ rung, solved, attempts, credits }, zawsze obecne, gdzie rung przyjmuje wartość cache, probe, proxy, browser, warmup, fail) oraz domyślnie session ({ proxy, cookies, userAgent }) do ponownego użycia w narzędziach niższego poziomu. Brak total_time.
  • foura_single: { status, headers, data, total_time, ... } (headers jest tablicą, z jednym wpisem na każdy przeskok przekierowania)
  • foura_proxy: tak samo jak single plus { proxy, total }; sukces ze zdefiniowanym zakresem zawiera również exitCountry, request wskazujący klasę zawiera exitClass, rotacja zmieniająca rodzinę przeglądarek zawiera profile, a niepowodzenie zawiera attemptReport
  • foura_browser: odrębna struktura { status, headers: object, body, cookies, userAgent } (uwaga: body może być ciągiem znaków lub obiektem w zależności od content-type)

Każde narzędzie zwraca również koszt wywołania i dane do jego śledzenia, odczytane z nagłówków odpowiedzi API:

  • credits, kredyty wykorzystane przez to wywołanie. Pole obecne również przy błędach, ponieważ praca została wykonana. Opłata jest naliczana tylko za udane wywołanie, więc błąd wyświetla zużyte kredyty w tym polu, ale nie generuje kosztów.
  • request_id, identyfikator wywołania w FourA. Podaj go w zgłoszeniu do pomocy technicznej.
  • exitClass, premium, gdy wywołanie zostało obsłużone przez węzeł wyjściowy premium. W przypadku foura_single i foura_browser ma to miejsce, gdy proxy ponownie wykorzystuje węzeł wyjściowy znaleziony przez foura_proxy.

Pola te są pomijane, jeśli API nic nie zwróciło, dzięki czemu klient napisany dla wcześniejszej wersji działa bez zmian. Te same wartości są opisane w sekcji Nagłówki odpowiedzi.

Klienci obsługujący structuredContent mogą przekazywać typowany obiekt bezpośrednio do LLM, bez konieczności parsowania formatu JSON z tekstu.

Nagłówki odpowiedzi z wieloma wartościami

Nagłówki występujące wielokrotnie (Set-Cookie, Link, WWW-Authenticate) są zwracane jako tablice:

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

Ma to znaczenie w przypadku witryn, które ustawiają pliki cookie sesji, śledzenia i zgody w jednej odpowiedzi (większość e-commerce).

Duże odpowiedzi: offload_large (domyślnie: inline)

Domyślnie (od wersji v0.2.0) pełne treści odpowiedzi są zwracane inline w structuredContent bez względu na rozmiar. Działa to domyślnie w każdym kliencie MCP.

Jeśli Twój klient obsługuje MCP resources/read ORAZ chcesz zaoszczędzić tokeny na dużych stronach, przekaż offload_large: true w wywołaniu narzędzia. Odpowiedzi >= 50 KB są wtedy zapisywane na dysku, zwracane jako resource_link, a Twój klient pobiera treść tylko wtedy, gdy rzeczywiście jej potrzebuje. Na hostowanym serwerze buforowane payloady wygasają po 1 godzinie. Na Twojej własnej instancji nic nie usuwa zapisanych payloadów: usuwaj pliki starsze niż godzina z katalogu payload we własnym zakresie.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Klient offload_large: true
Claude Desktop jeszcze nie, pozostaw domyślne false
Claude Code, Cursor, Windsurf obsługiwane
Rozszerzenie VS Code MCP obsługiwane

Izolacja tenantów: każdy klucz API otrzymuje własną przestrzeń nazw (sha256(apiKey)[:16]). Tylko klucz, który zapisał payload, może go odczytać. Odczyty między tenantami zwracają Payload not found bez ujawniania istnienia danych.

Wbudowane Prompty

Sześć szablonów workflow jest dostępnych pod /prompts w każdym kliencie MCP. Każdy przyjmuje nazwane argumenty i zwraca szablonową wiadomość użytkownika orkiestrującą jedno lub więcej narzędzi.

Prompt Argumenty Działanie
smart_fetch url, opcjonalnie must_contain, extract Automatyczne pobieranie (wybiera metodę, obsługuje ochronę przed botami), a następnie zwraca lub ekstrahuje zawartość
scrape_product_page url Pobieranie przez przeglądarkę, a następnie ekstrakcja tytułu produktu, ceny, zdjęcia, stanu magazynowego, SKU jako JSON
extract_article url Pojedyncze żądanie z fallbackiem do proxy, następnie usunięcie nawigacji/reklam i zwrócenie czystego JSON artykułu
monitor_pricing url, opcjonalnie target_price Pobieranie przez proxy, ekstrakcja aktualnej ceny, porównanie z wartością docelową
check_endpoint_health url, opcjonalnie expected_text Pojedyncze żądanie ze ścisłą walidacją, zwraca dostępność i czasy odpowiedzi
bulk_fetch_urls urls (rozdzielone przecinkami) Równoległe pojedyncze żądania, automatyczny fallback do proxy dla każdego URL, zwraca tylko metadane

Prompty zużywają zero tokenów w stanie bezczynności. Tylko wywołane prompty trafiają do kontekstu LLM.

Pełny tekst oraz ręczne prompty fallback: MCP Recipes.

Koperta błędu (Error envelope)

Każdy błąd (isError: true) zawiera kopertę structuredContent. Minimalne pola dla każdego błędu:

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

W przypadku błędów upstream ze statusem HTTP obecne jest również pole status. W przypadku błędów rate-limit i limitów pojemności envelope upstream dodaje retryAfter, current.{concurrency, rpm} oraz limits.{maxConcurrency, maxRpm}. Zobacz Błędy API, aby poznać bazową strukturę REST.

Stabilne wartości code:

Kod HTTP Znaczenie Bezpieczny retry?
ssrf_blocked n/d Cel to adres prywatny lub zastrzeżony (RFC 5735, 6598, zastrzeżone IPv6), URL nie używa http(s) lub jego nazwa hosta nie została rozwiązana Nie, sprawdź URL. Chwilowy błąd rozpoznawania nazwy można ponowić
upstream_non_json różne Upstream zwrócił nieprawidłowo sformatowane body Być może, zweryfikuj
output_validation_failed n/d outputSchema serwera MCP odrzucił odpowiedź upstream lub narzędzie w ogóle nie mogło dokończyć wywołania (brak skonfigurowanego klucza API, API nieosiągalne) Być może: sprawdź konfigurację, a następnie zgłoś
bad_request 400 Odrzucona struktura danych wejściowych Nie, popraw argumenty
auth_failed 401 Klucz brakujący, nieprawidłowy lub dezaktywowany Nie, popraw klucz
forbidden 403 Cel odpowiedział 403, a Twoje validate go odrzuciło (weryfikacja witryny, ograniczenie regionalne) Nie lub przełącz na foura_proxy
not_found 404 Brak celu lub endpointu Nie
rate_limited 429 Osiągnięto limit RPM Tak, odczekaj retryAfter
at_capacity 503 Osiągnięto limit współbieżności Tak, odczekaj retryAfter
service_disabled 503 Usługa jest wyłączona z powodu prac konserwacyjnych. Narzędzie nieobjęte Twoim planem zwraca plan_limit_feature Skontaktuj się ze wsparciem
service_unavailable 503 Ogólny błąd 503 Tak, krótki backoff
upstream_error 500+ lub 0 Cel odpowiedział błędem serwera, lub przy foura_proxy, foura_browser i foura_auto w ogóle nie odpowiedziały Tak, wykładniczy backoff
upstream_client_error 4xx Inny 4xx Zwykle nie
upstream_unknown inne Żądanie zostało wykonane, ale nie dało zaakceptowanej odpowiedzi: przy foura_single cel w ogóle nie odpowiedział (timeout, odrzucone połączenie), a przy dowolnym narzędziu Twoje validate odrzuciło odpowiedź 2xx lub 3xx. Sprawdź status i error Zweryfikuj
no_eligible_proxy n/d Żadne proxy nie pasuje do ścisłego zakresu exitCountries Ponów później; zmieniaj zakres wyłącznie jawnie
plan_limit_* 403 lub 429 Jeden z limitów Twojego planu odrzucił wywołanie: plan_limit_, a następnie feature, premium, concurrency, rate, browser_daily, credits lub bandwidth. Zobacz Błędy serwera MCP Odczekaj retryAfter, jeśli jest obecne; w przeciwnym razie dopiero po zresetowaniu limitu lub zmianie planu

Agenci LLM mogą odczytywać code bezpośrednio na potrzeby logiki retry, bez parsowania tekstu. Instrukcja uwierzytelniania: Uwierzytelnianie.

Limity

  • Domyślnie treść inline. Z offload_large: true odpowiedzi >= 50 KB trafiają na dysk + resource_link (per tenant, 1 godzina TTL).
  • Prywatne cele są odrzucane (RFC 5735, RFC 6598, zarezerwowane bloki IPv6) na warstwie MCP. Przekazywane są tylko publiczne hosty.
  • Limit wielkości treści requestu wynosi 256 KB dla przychodzących żądań /mcp (rzeczywiste ładunki MCP to < 4 KB).
  • Rate limity są wymuszane przez FourA API dla każdej usługi. Zobacz Rate Limits.

Self-Hosting

Pełny kod źródłowy serwera jest publicznie dostępny w serwisie GitHub na licencji @fouradata/mcp. Sklonuj repozytorium, npm install, npm run build i uruchom node dist/http.js, aby postawić własną instancję. Działa bezstanowo w pojedynczym kontenerze za dowolnym load balancerem.

Konfigurowalne środowisko:

Variable Domyślnie Zastosowanie
PORT 3076 Port nasłuchiwania HTTP
FOURA_API_BASE https://api.foura.ai/api Bazowy adres URL upstream FourA REST
FOURA_MCP_PAYLOADS_DIR katalog foura-mcp-payloads w systemowym folderze temp (dołączony plik Docker Compose ustawia /data/payloads) Miejsce buforowania odpowiedzi >= 50 KB na dysku (z offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Biała lista nazw hostów dla nagłówka Host (ochrona przed DNS-rebinding)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Biała lista Origin dla wywołań z przeglądarki

Oficjalny kontener działa jako uid 1001 (non-root). Punkt montowania hosta /data/payloads musi mieć uprawnienia do zapisu dla tego uid.

Skaluj horyzontalnie za dowolnym load balancerem. Klienci przekazują swój klucz przy każdym requeście, więc sesje sticky nie są wymagane.

Aktualizacja: 27 września 2026