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+Qna 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 }orazmeta({ rung, solved, attempts, credits }, zawsze obecne, gdzierungprzyjmuje wartośćcache,probe,proxy,browser,warmup,fail) oraz domyślniesession({ proxy, cookies, userAgent }) do ponownego użycia w narzędziach niższego poziomu. Braktotal_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ę zawieraexitClass, rotacja zmieniająca rodzinę przeglądarek zawieraprofile, a niepowodzenie zawieraattemptReportfoura_browser: odrębna struktura{ status, headers: object, body, cookies, userAgent }(uwaga:bodymoż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 przypadkufoura_singleifoura_browserma to miejsce, gdyproxyponownie wykorzystuje węzeł wyjściowy znaleziony przezfoura_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: trueodpowiedzi >= 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.