MCP Server

MCP сървър

Използвайте FourA от всеки Model Context Protocol клиент (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) като четири вградени инструмента и шест работни prompt шаблона. Без код за интеграция, без персонализиран HTTP клиент.

Отворен код в GitHub; в npm като @fouradata/mcp. Текуща версия: 0.7.3.

Бърз старт: локален stdio (препоръчва се за Claude Desktop)

Вземете ключ от foura.ai/dashboard#api-keys (с един клик, показва се еднократно при създаване, формат pk_live_...). Добавете това в конфигурацията на вашия MCP клиент:

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

Особеност при Claude Desktop: затворете напълно Claude Desktop (Cmd+Q в macOS) преди редактирането на конфигурационния файл. Ако приложението все още работи, то ще презапише вашите промени с конфигурацията си от оперативната памет при изход.

Командата npx изтегля @fouradata/mcp при първото стартиране и я изпълнява като подпроцес на вашия MCP клиент. Не е необходима глобална инсталация.

Client Къде се намира конфигурацията
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 (първо задайте FOURA_API_KEY в env)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (MCP extension) .vscode/mcp.json

Рестартирайте клиента. Инструментите (foura_auto, foura_single, foura_proxy, foura_browser) и шестте prompt-а ще се появят във вашия списък с инструменти.

Бърз старт: hosted (Streamable HTTP)

За клиенти, които поддържат Streamable HTTP транспорт (Cursor, Windsurf, VS Code, Claude Code с --transport http), ги насочете към хоствания endpoint вместо да изпълнявате локален подпроцес:

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

За Claude Desktop използвайте горната конфигурация за stdio или свържете хоствания endpoint чрез mcp-remote:

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

Справочник за hosted endpoint

Свойство Стойност
URL https://mcp.foura.ai/mcp
Транспорт Streamable HTTP (POST /mcp, SSE отговори)
Автентикация Authorization: Bearer pk_live_... за всяка заявка
MCP-Protocol-Version Според @modelcontextprotocol/sdk (в момента 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
401 challenge WWW-Authenticate: Bearer realm="foura-mcp"

Предизвикателството 401 умишлено не съдържа параметър RFC 9728 resource_metadata. Обявяването му кара клиент с поддръжка на OAuth да стартира процес, който този сървър не имплементира. Изпратете своя pk_live_ ключ като Bearer token и грешката 401 изчезва.

Хостваният сървър е stateless. Всяка заявка носи собствен ключ, който сървърът препраща към FourA API като X-API-Key. Един ключ отваря и четирите инструмента.

За защита срещу DNS-rebinding (CVE-2025-66414) сървърът валидира заглавката Host (трябва да бъде mcp.foura.ai или localhost) и заглавката Origin, когато е налична (в списъка с разрешени: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Извикванията между сървъри (curl, MCP клиенти в режим stdio bridge) не изпращат Origin и преминават директно.

Инструменти

И четирите инструмента са анотирани с readOnlyHint: true и openWorldHint: true според спецификацията на MCP от 2025-06-18. Клиенти, които автоматично одобряват надеждни инструменти само за четене, ги извикват без модален прозорец за потвърждение при всяка заявка.

foura_auto е интелигентният избор по подразбиране: подайте му URL и той връща съдържанието, като сам избира метода за извличане. Другите три са примитиви от по-ниско ниво, които той оркестрира. Използвайте ги, когато искате изричен контрол.

foura_auto

Подайте му URL, когато искате FourA да избере метода на заявка. Той прави ограничен брой опити през наличните HTTP, proxy и браузърни пътища. Подайте validate при защитени цели, така че отговорът да съдържа съдържание, което идентифицира реалната страница. Ако нито един опит не удовлетворява валидацията, инструментът връща грешка, вместо да представи challenge страница като успех.

Отговорът включва детайли за завършването в meta и по подразбиране преизползваем session с proxy, cookies и userAgent. За обикновена последваща заявка извикайте foura_single с session.proxy като proxy, сериализирайте бисквитките като заглавка Cookie и изпратете session.userAgent като заглавка User-Agent. За JavaScript рендиране предайте стойностите на сесията към съответните полета на foura_browser.

foura_single

Една HTTP заявка, получен отговор. Съответства едно към едно на POST /api/single/.

Използвайте за статични страници, JSON API и рендиран от сървъра HTML.

Избор на браузъра, който представяте

По подразбиране заявката представя най-новия Google Chrome. Когато дадена цел приема един браузър и отказва друг, задайте browser (Chrome, Edge, Safari, Firefox или Tor), os (Windows, macOS, Android или iOS) или version, или подайте точен profile id:

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

Най-новата версия има предимство, когато съвпадат няколко профила. Несъществуваща комбинация връща грешка с наличните опции, така че request никога не се изпраща като browser, който не сте избрали. Селекцията изисква unblocker, което е включено по подразбиране. Каталогът е публикуван на GET /api/profiles и не изисква API key.

Същите четири полета се намират в обекта request на foura_proxy.

foura_proxy

Рутирайте един HTTP request през ротиращи proxies с автоматичен retry. Използвайте го, когато foura_single е блокиран или целта изисква конкретна държава на изход.

Задайте exitCountries като стриктен allowlist от двубуквени кодове на държави, предоставени от потребителя или изискванията на целта:

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

Стойностите се изчистват от интервали, преобразуват се в главни букви и се дедупликират. Прокситата с неизвестни изходни точки се изключват, а заявката никога не преминава към незаявена държава. Изборът използва най-новите налични метаданни за държава, видима от целевия сайт, обикновено обновявани в рамките на десет минути; това не е геолокация в реално време по време на заявката. Не определяйте обслужващата държава от адреса на хоста на проксито.

Успехът с определен обхват връща exitCountry и идентификатора за многократна употреба proxy. Проверете дали exitCountry принадлежи към заявения списък с разрешени. Ако текущият пул няма съвпадение, инструментът връща code: "no_eligible_proxy" с нормализирания обхват в details.exitCountries. Запазете този обхват и опитайте отново по-късно. Променяйте или разширявайте го само когато потребителят изрично промени изискването. Ограничаването по държава е включено от план Startup нагоре. При план без тази функция, повикване, което изпраща exitCountries, се отхвърля с 403 и X-FourA-Limit: plan_limit_feature.

Ако избраната страница по-късно се нуждае от JavaScript, подайте върнатия proxy ID към foura_browser.proxy, за да може браузърът да използва повторно същата изходна точка.

Задайте exitClass: "premium" за цел, която стандартният пул не може да достигне, независимо колко изходни точки са опитани. Това е разрешение, а не инструкция: стандартният пул все още се състезава за отговора и обикновено печели, а заявка, на която той отговори преди опит с премиум изходна точка, не струва премиум трафик. Опитът с премиум отчита пренесения трафик дори при неуспех. Отговорът връща exitClass, premium или standard, така че можете да видите за всяка заявка кой клас ви е обслужил. standard е отговорът и след като премиум трафикът, включен във вашия план, бъде изчерпан, като това е нормален резултат, а не грешка. exitClass: "standard" забранява ескалацията напълно. exitClass: "premium" при план без премиум изходни точки се отхвърля с code: "plan_limit_premium". Вижте exitClass.

Когато ротацията е трябвало да премине към друго браузърно семейство, за да получи отговор, успешният отговор съдържа profile с избраното семейство. Изпълнете повторно с него, в противен случай следващото повикване ще повтори версията, която е била неуспешна.

Неуспешната ротация съдържа attemptReport до грешката: едно изречение summary, плюс броячи, които разделят изходните точки, които никога не са отговорили (noResponse), изходните точки, отхвърлени от проверка за ботове (defense, с доставчиците в vendors), страниците, които са получени и отхвърлени единствено от вашето собствено validate.data (contentRejected), statusRejected и other. profilesTried изброява браузърите, които задачата е изпратила, по ред на първо използване, като default означава, че заявката е изпратена точно както е написана. Висока стойност на contentRejected означава, че FourA е доставил реални страници, а вашето собствено правило ги е отхвърлило. Вижте Why a Proxy Request Ran Out of Tries.

foura_browser

Пълна браузърна сесия. JavaScript се изпълнява, DOM се рендира, бисквитките се връщат. Отразява POST /api/browser/.

Използвайте за едностранични приложения (SPA), съдържание с отложено зареждане или страници с проверка, изискваща реален браузър за завършване.

За структурите на входните данни, стойностите по подразбиране и правилата за валидация на всеки инструмент вижте справката за REST endpoint-и. Схемите на инструментите съответстват поле по поле на REST API, плюс специфичната само за MCP опция offload_large (вижте по-долу).

Когато целевият сайт изпълнява bot check

foura_single и foura_proxy връщат defense, когато целта е изпълнила bot check по пътя към тялото. defense.solved: true означава, че проверката е премината и data е реалната страница; false означава, че тялото може да е challenge страница. Опитайте отново с друг browser, os или version, или преминете към foura_proxy или foura_browser, вместо да третирате challenge страницата като съдържание.

Типизирани отговори

Всеки отговор от инструмент включва както content (четим за хора текстов обобщен вид), така и structuredContent (типизиран JSON, валидиран спрямо outputSchema на инструмента). Всеки инструмент има своя собствена уникална структура:

  • foura_auto: единична структура { status, headers, data } плюс meta ({ rung, solved, attempts, credits }, винаги налично, където rung е едно от cache, probe, proxy, browser, warmup, fail) и по подразбиране session ({ proxy, cookies, userAgent }) за повторно изпълнение през инструментите от по-ниско ниво. Без total_time.
  • foura_single: { status, headers, data, total_time, ... } (headers е масив, по един запис за всеки redirect hop)
  • foura_proxy: същото като единичния плюс { proxy, total }; успешен отговор с обхват включва и exitCountry, request с посочен клас включва exitClass, ротация с променена фамилия браузъри включва profile, а неуспехът включва attemptReport
  • foura_browser: отделна структура { status, headers: object, body, cookies, userAgent } (забележка: body може да бъде низ или обект в зависимост от content-type)

Всеки инструмент също така докладва каква е цената на извикването и как да бъде проследено, прочетено от response headers на API:

  • credits, кредити, изразходвани за това извикване. Налично е и при неуспех, тъй като работата е била извършена във всеки случай. Таксуват се само успешни извиквания, така че при грешка кредитите се показват тук, но не ви струват нищо.
  • request_id, идентификатор на FourA за извикването. Цитирайте го при заявка за поддръжка.
  • exitClass, premium, когато извикването е обслужено от premium exit. При foura_single и foura_browser това се случва, когато proxy преизползва изход, намерен от foura_proxy.

Всяко от тях липсва, когато API не е върнал нищо, така че клиент, написан за по-ранна версия, продължава да работи без промяна. Същите стойности са документирани в Response Headers.

Клиенти, които поддържат structuredContent, могат да подадат типизирания обект директно към LLM, вместо да изискват от него да парсва JSON от свободен текст.

Заглавки на отговора с множество стойности

Заглавки, които се появяват многократно (Set-Cookie, Link, WWW-Authenticate), се връщат като масиви:

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

Това е от значение за сайтове, които задават cookie за сесия + проследяване + съгласие в един response (по-голямата част от електронната търговия).

Големи responses: offload_large (по подразбиране: inline)

По подразбиране (от v0.2.0 насам), пълните response bodies се връщат inline в structuredContent независимо от размера. Това работи директно във всеки MCP клиент.

Ако вашият клиент поддържа MCP resources/read И искате да спестите token разходи при големи страници, подавайте offload_large: true при всяко извикване на tool. Responses >= 50 KB тогава се записват на диска, връщат се като resource_link, а вашият клиент изтегля body само когато действително му е необходимо. На хоствания сървър кешираните payloads изтичат след 1 час. На вашия собствен инстанс нищо не изтрива съхранените payloads: изчиствайте файловете, по-стари от един час, от директорията за payload сами.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Client offload_large: true
Claude Desktop все още не, оставете по подразбиране false
Claude Code, Cursor, Windsurf поддържа се
VS Code MCP extension поддържа се

Изолирано по tenant: всеки API key получава собствено именно пространство (sha256(apiKey)[:16]). Само ключът, съхранил даден payload, може да го прочете обратно. Четенията между различни tenants връщат Payload not found без изтичане на информация за съществуване.

Вградени Prompts

Шест шаблона за работни процеси са налични под /prompts във всеки MCP клиент. Всеки от тях приема именувани аргументи и връща шаблонизирано потребителско съобщение, оркестриращо един или повече инструменти.

Prompt Аргументи Какво прави
smart_fetch url, по избор must_contain, extract Автоматично извличане (избира метода, обработва защитата от ботове), след което връща или извлича съдържанието
scrape_product_page url Извличане през браузър, след което извлича заглавие на продукта, цена, изображение, наличност, SKU като JSON
extract_article url Единична заявка с proxy fallback, след което премахва навигация/реклами и връща изчистен JSON за статия
monitor_pricing url, по избор target_price Proxy извличане, извличане на текуща цена, сравнение с целевата
check_endpoint_health url, по избор expected_text Единична заявка със стриктна валидация, връщане на достъпност и време за изпълнение
bulk_fetch_urls urls (разделени със запетая) Паралелна единична заявка, автоматичен fallback към proxy за всеки URL, връщане само на метаданни

Prompts струват нула токени в покой. Само извиканите prompts влизат в контекста на LLM.

Пълен текст плюс ръчни fallback prompts: MCP Recipes.

Error envelope

Всяка грешка (isError: true) носи structuredContent envelope. Минимални полета при всяка грешка:

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

При грешки от upstream с HTTP статус е наличен и status. При грешки за rate limit и капацитет обвивката на upstream добавя retryAfter, current.{concurrency, rpm} и limits.{maxConcurrency, maxRpm}. Вижте API Errors за базовата REST структура.

Стабилни стойности за code:

Код HTTP Значение Безопасен ли е повторен опит?
ssrf_blocked n/a Целта е частен или резервиран адрес (RFC 5735, 6598, IPv6 reserved), URL адресът не е http(s), или неговият host name не се разреши Не, проверете URL адреса. Търсене, което е пропаднало временно, може да се опита отново
upstream_non_json варира Upstream върна невалидно тяло Може би, проверете
output_validation_failed n/a outputSchema на MCP сървъра отхвърли upstream отговора или инструментът не успя да завърши извикването изобщо (няма конфигуриран API ключ, API е недостъпен) Може би: проверете конфигурацията, след което докладвайте
bad_request 400 Форматът на входа е отхвърлен Не, коригирайте аргументите
auth_failed 401 Липсващ, невалиден или деактивиран ключ Не, коригирайте ключа
forbidden 403 Целта отговори с 403 и вашият validate го отхвърли (проверка на сайта, ограничение по държава) Не, или превключете към foura_proxy
not_found 404 Липсваща цел или endpoint Не
rate_limited 429 Достигнат RPM лимит Да, изчакайте retryAfter
at_capacity 503 Достигнат лимит за едновременност Да, изчакайте retryAfter
service_disabled 503 Услугата е изключена за поддръжка. Инструмент, който планът ви не включва, се връща като plan_limit_feature Свържете се с поддръжката
service_unavailable 503 Обща грешка 503 Да, кратък backoff
upstream_error 500+ или 0 Целта отговори със сървърна грешка или при foura_proxy, foura_browser и foura_auto така и не отговориха Да, експоненциален backoff
upstream_client_error 4xx Друга 4xx грешка Обикновено не
upstream_unknown друго Заявката се изпълни, но не върна приет отговор: при foura_single целта така и не отговори (timeout, отказана връзка), а при всеки инструмент вашият validate отхвърли 2xx или 3xx отговор. Прочетете status и error Проучете
no_eligible_proxy n/a Никое proxy не отговаря на строгия exitCountries обхват Опитайте отново по-късно; променете обхвата само изрично
plan_limit_* 403 или 429 Един от лимитите на вашия план отказа извикването: plan_limit_, последван от feature, premium, concurrency, rate, browser_daily, credits или bandwidth. Вижте MCP Server Errors Изчакайте retryAfter, когато е наличен; в противен случай изчакайте лимитът да се нулира или планът да се промени

LLM агентите могат да четат директно code за логика за повторен опит без парсване на текст. Ръководство за автентикация: Authentication.

Limits

  • Inline body по подразбиране. С offload_large: true, отговори >= 50 KB се записват на диск + resource_link (за отделен tenant, 1 час TTL).
  • Частни адреси се отхвърлят (RFC 5735, RFC 6598, IPv6 резервирани блокове) на MCP нивото. Препращат се само публични хостове.
  • Ограничение на request body до 256 KB за входящи /mcp заявки (реалните MCP payloads са < 4 KB).
  • Rate limits се налагат от FourA API за всяка услуга. Вижте Rate Limits.

Self-Hosting

Пълният сорс код на сървъра е публичен в GitHub под @fouradata/mcp. Клонирайте хранилището, npm install, npm run build, и изпълнете node dist/http.js, за да стартирате свой собствен инстанс. Работи stateless в единичен контейнер зад произволен load balancer.

Конфигурируема среда:

Променлива По подразбиране Предназначение
PORT 3076 HTTP listen порт
FOURA_API_BASE https://api.foura.ai/api Upstream FourA REST базов URL
FOURA_MCP_PAYLOADS_DIR папка foura-mcp-payloads в системната временна директория (включеният Docker Compose файл задава /data/payloads) Където се кешират на диск отговори >= 50 KB (с offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Hostname allowlist за Host хедър (защита срещу DNS-rebinding)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Origin allowlist за извиквания от браузър

Официалният контейнер се изпълнява като uid 1001 (non-root). /data/payloads host bind mount трябва да позволява запис от това uid.

Мащабирайте хоризонтално зад произволен load balancer. Клиентите подават своя ключ при всяка заявка, така че няма sticky session.

Обновено: 27 септември 2026 г.