MCP Server
MCP сървър
Използвайте FourA от всеки клиент за Model Context Protocol (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) като четири нативни инструмента и шест промпта за работни процеси. Без код за интеграция, без персонализиран HTTP клиент.
С отворен код в GitHub; в npm като @fouradata/mcp. Текуща версия: 0.5.0.
Бърз старт: локално 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 клиент. Не е необходима глобална инсталация.
| Клиент | Къде се намира конфигурацията |
|---|---|
| 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 разширение) | .vscode/mcp.json |
Рестартирайте клиента. Инструментите (foura_auto, foura_single, foura_proxy, foura_browser) и шест prompt-а се появяват във вашия списък с инструменти.
Бърз старт: хостван (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_..."]
}
}
}
Справка за хостван endpoint
| Свойство | Стойност |
|---|---|
| URL | https://mcp.foura.ai/mcp |
| Транспорт | Streamable HTTP (POST /mcp, SSE responses) |
| Удостоверяване | Authorization: Bearer pk_live_... за всеки request |
| 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", resource_metadata="https://foura.ai/docs/mcp/server#auth" |
Хостваният сървър е stateless. Всеки request носи собствен ключ, който сървърът препраща към FourA API като X-API-Key. Един ключ отваря и четирите инструмента.
За защита срещу DNS-rebinding (CVE-2025-66414) сървърът валидира Host header (трябва да бъде mcp.foura.ai или localhost) и Origin header, когато е наличен (разрешени: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Извикващите сървър-към-сървър (curl, MCP клиенти в режим stdio bridge) не изпращат Origin и преминават директно.
Инструменти
И четирите инструмента са анотирани с readOnlyHint: true и openWorldHint: true съгласно MCP 2025-06-18 spec. Клиентите, които автоматично одобряват доверени read-only инструменти, ги извикват без модален прозорец за потвърждение на всеки request.
foura_auto е интелигентната настройка по подразбиране: подайте му URL и той връща съдържанието, като избира метода за изтегляне вместо вас. Останалите три са примитиви от по-ниско ниво, които той оркестрира. Използвайте ги, когато искате явен контрол.
foura_auto
Подайте му URL, когато искате FourA да избере метода за request. Той прави ограничен брой опити през наличните HTTP, proxy и browser пътища. Подайте validate за защитени цели, така че response да съдържа съдържание, което идентифицира реалната страница. Ако нито един опит не премине валидацията, инструментът връща грешка вместо да представи challenge страница като успех.
Този response включва детайли за завършване в meta и по подразбиране преизползваема session с proxy, cookies и userAgent. За обикновено последващо действие извикайте foura_single с session.proxy като proxy, сериализирайте cookies като Cookie header и изпратете session.userAgent като User-Agent header. За JavaScript рендиране подайте стойностите на сесията към съответстващите foura_browser полета.
foura_single
Един HTTP request, response обратно. Отразява POST /api/single/ едно към едно.
Използвайте за статични страници, JSON APIs и сървърно рендиран HTML.
Избор на браузър, който представяте
Всеки request представя най-новия 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 никога не се изпраща като браузър, който не сте избрали. Изборът изисква unblocker, което е включено по подразбиране. Каталогът е публикуван на GET /api/profiles и не изисква API ключ.
Същите четири полета се намират в request обекта на foura_proxy.
foura_proxy
Пренасочете един HTTP request през ротиращи proxies с автоматичен повторен опит. Използвайте го, когато foura_single е блокиран или целта изисква конкретна изходна държава.
Задайте exitCountries към строг списък с разрешени двубуквени кодове на държави, видими за целта, предоставени от потребителя или от изискванията на целта:
{
"maxTries": 5,
"exitCountries": ["CZ", "GB"],
"request": {
"method": "GET",
"url": "https://example.com/pricing",
"browser": "Chrome",
"os": "Windows"
}
}
Стойностите се изрязват, преобразуват се в главни букви и се премахват дубликатите. Проксита с неизвестни изходи се изключват, а заявката никога не преминава към непоискана държава. Изборът използва най-новите налични метаданни за държавата, видими за целта, които обикновено се актуализират в рамките на десет минути; това не е търсене на геолокация в реално време по време на заявката. Не правете извод за обслужващата държава въз основа на host адреса на проксито.
Успехът в зададения обхват връща exitCountry и ID за многократна употреба proxy. Проверете дали exitCountry принадлежи към поискания списък с разрешени. Ако в текущия пул няма съвпадение, инструментът връща code: "no_eligible_proxy" с нормализирания обхват в details.exitCountries. Запазете този обхват и опитайте отново по-късно. Променяйте го или го разширявайте само когато потребителят изрично промени изискването.
Ако избраната страница по-късно се нуждае от JavaScript, подайте върнатия proxy ID на foura_browser.proxy, за да може браузърът да използва повторно същия изход.
foura_browser
Пълна сесия на браузъра. JavaScript се изпълнява, DOM се рендира, бисквитките (cookies) се връщат. Отразява POST /api/browser/.
Използвайте за приложения с една страница (single-page apps), мързеливо зареждано съдържание (lazy-loaded content) или страници зад анти-бот предизвикателства, които се нуждаят от реален браузър за преминаване.
За входни формати, стойности по подразбиране и правила за валидация на всеки инструмент, вижте справката за REST endpoint. Схемите на инструментите съвпадат с REST API поле по поле, плюс offload_large опцията само за MCP (вижте по-долу).
Когато целта изпълнява проверка за ботове
foura_single и foura_proxy връщат defense, когато целта е изпълнила проверка за бот по пътя към body. defense.solved: true означава, че проверката е премината и data е реалната страница; false означава, че body може да е страница с предизвикателство (challenge page). Опитайте отново с различен браузър, OS или версия, или преминете към foura_proxy или foura_browser, вместо да третирате страницата с предизвикателството като съдържание.
Типизирани отговори
Всеки отговор на инструмент включва както content (четимо от хора текстово резюме), така и structuredContent (типизиран JSON, валидиран спрямо outputSchema на инструмента). Всеки инструмент има своя собствена уникална структура:
foura_auto: единичен формат{ status, headers, data }плюсmeta({ rung, solved, attempts, credits }, винаги присъства, къдетоrungе едно отcache,probe,proxy,browser,fail) и, по подразбиране,session({ proxy, cookies, userAgent }) за повторно възпроизвеждане чрез инструментите от по-ниско ниво. Нямаtotal_time.foura_single:{ status, headers, data, total_time, ... }(headers е масив, по един запис за всяка стъпка на пренасочване)foura_proxy: същото като единичния плюс{ proxy, total }; успехът с обхват също включваexitCountryfoura_browser: различен формат{ status, headers: object, body, cookies, userAgent }(забележка:bodyможе да бъде низ или обект в зависимост от content-type)
Клиентите, които поддържат 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=/"]
}
]
}
Това е важно за сайтове, които задават session + tracking + consent cookies в един response (повечето сайтове за електронна търговия).
Големи responses: offload_large (по подразбиране: inline)
По подразбиране (от v0.2.0), пълните response тела се връщат inline в structuredContent независимо от размера. Това работи във всеки MCP клиент без допълнителни настройки.
Ако вашият клиент поддържа MCP resources/read И искате да спестите token при големи страници, подайте offload_large: true за всеки tool call. Responses >= 50 KB се записват на диска, връщат се като resource_link, а вашият клиент изтегля тялото само когато действително му е необходимо. Кешираните payloads изтичат след 1 час.
{
"method": "GET",
"url": "https://en.wikipedia.org/wiki/Web_scraping",
"offload_large": true
}
| Клиент | offload_large: true |
|---|---|
| Claude Desktop | все още не, оставете по подразбиране false |
| Claude Code, Cursor, Windsurf | поддържа се |
| VS Code MCP extension | поддържа се |
Изолирано по наемател: всеки API ключ получава свое собствено пространство от имена (sha256(apiKey)[:16]). Само ключът, който е съхранил данните, може да ги прочете обратно. Четенията между наематели връщат 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 обвивка. Минимални полета за всяка грешка:
{
"service": "auto | single | proxy | browser",
"code": "rate_limited",
"error": "Rate limit exceeded"
}
При грешки от сървъра (upstream) с HTTP статус, присъства и status. При грешки за ограничения на скоростта и капацитета, обвивката на сървъра добавя retryAfter, current.{concurrency, rpm} и limits.{maxConcurrency, maxRpm}. Вижте API Errors за основната REST структура.
Стабилни code стойности:
| Код | HTTP | Значение | Безопасно за повторен опит? |
|---|---|---|---|
ssrf_blocked |
n/a | Целеви IP адрес в частен или запазен диапазон (RFC 5735, 6598, IPv6 запазени) | Не, променете URL |
upstream_non_json |
варира | Сървърът върна неправилно форматирано тяло | Може би, проучете |
output_validation_failed |
n/a | outputSchema на MCP сървъра отхвърли отговора на сървъра (бъг в сървъра или неочаквана структура) |
Може би, докладвайте |
bad_request |
400 | Входната структура е отхвърлена | Не, поправете аргументите |
auth_failed |
401 | Ключът липсва, е невалиден или деактивиран | Не, поправете ключа |
forbidden |
403 | Удостоверен, но без разрешение | Не, или превключете на foura_proxy |
not_found |
404 | Целта или endpoint липсва | Не |
rate_limited |
429 | Достигнат лимит на RPM | Да, изчакайте retryAfter |
at_capacity |
503 | Достигнат лимит на едновременни заявки | Да, изчакайте retryAfter |
service_disabled |
503 | Прозорец за поддръжка или планът ви не включва този инструмент | Свържете се с поддръжката |
service_unavailable |
503 | Обща 503 грешка | Да, кратко изчакване |
upstream_error |
500+ | Upstream 5xx | Да, експоненциално изчакване |
upstream_client_error |
4xx | Друга 4xx | Обикновено не |
upstream_unknown |
друго | Дефанзивно, не би трябвало да се случва на практика | Проучете |
no_eligible_proxy |
n/a | Нито един proxy не отговаря на строгия exitCountries обхват |
Опитайте по-късно, променете обхвата само изрично |
LLM агентите могат да четат code директно за логика за повторни опити, без да анализират текст. Ръководство за удостоверяване: Authentication.
Лимити
- Тяло inline по подразбиране. С
offload_large: trueотговори >= 50 KB отиват на диск +resource_link(за всеки наемател, 1-час TTL). - Частните цели се отказват (RFC 5735, RFC 6598, IPv6 запазени блокове) на слоя MCP. Препращат се само публични хостове.
- Ограничение на тялото на заявката от 256 KB за входящи
/mcpзаявки (истинските MCP полезни товари са < 4 KB). - Ограниченията на скоростта се налагат от FourA API за всяка услуга. Вижте Rate Limits.
Самостоятелно хостване
Пълният изходен код на сървъра е публичен в GitHub под @fouradata/mcp. Клонирайте хранилището, npm install, npm run build и стартирайте node dist/http.js, за да вдигнете собствена инстанция. Работи stateless в един контейнер зад всеки load balancer.
Конфигурируема среда:
| Променлива | По подразбиране | Предназначение |
|---|---|---|
PORT |
3076 |
Порт за слушане на HTTP |
FOURA_API_BASE |
https://api.foura.ai/api |
Базов URL адрес за upstream FourA REST |
FOURA_MCP_PAYLOADS_DIR |
/data/payloads |
Къде се кешират на диска отговори >= 50 KB (с offload_large: true) |
FOURA_MCP_ALLOWED_HOSTS |
mcp.foura.ai,localhost,127.0.0.1,[::1] |
Списък с разрешени хостове за хедъра Host (защита от DNS-rebinding) |
FOURA_MCP_ALLOWED_ORIGINS |
https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com |
Списък с разрешени източници (Origin) за заявки от браузър |
FOURA_MCP_RESOURCE_METADATA_URL |
https://foura.ai/docs/mcp/server#auth |
URL, който се връща в WWW-Authenticate при 401 |
Официалният контейнер се изпълнява като uid 1001 (non-root). Хост bind mount-ът на /data/payloads трябва да позволява запис от този uid.
Мащабирайте хоризонтално зад всеки load balancer. Клиентите предоставят своя ключ при всяка заявка, така че няма sticky сесия.