Сервер MCP

MCP Server

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

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

Quick Start: локальный 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) и шесть промптов появятся в вашем списке инструментов.

Быстрый старт: хостинг (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 WWW-Authenticate: Bearer realm="foura-mcp"

Запрос 401 намеренно не содержит параметра RFC 9728 resource_metadata. Его указание заставляет клиенты с поддержкой OAuth запускать процесс, который данный сервер не реализует. Отправьте ваш ключ pk_live_ в качестве Bearer-токена, и ошибка 401 исчезнет.

Размещенный сервер не сохраняет состояние. Каждый запрос передает собственный ключ, который сервер перенаправляет в 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 для защищенных ресурсов, чтобы ответ обязательно содержал контент, идентифицирующий реальную страницу. Если ни одна попытка не удовлетворяет валидации, инструмент возвращает ошибку вместо того, чтобы считать страницу с проверкой успешным результатом.

Ответ включает детали выполнения в meta и, по умолчанию, повторно используемый объект session с полями proxy, cookies и userAgent. Для обычного последующего запроса вызовите foura_single с параметром session.proxy в виде proxy, сериализуйте cookie в заголовок 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:

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

При совпадении нескольких профилей выбирается самая новая версия. Если комбинация не существует, возвращается ошибка со списком доступных вариантов, поэтому request никогда не отправляется от имени браузера, который вы не выбирали. Для выбора требуется unblocker, включенный по умолчанию. Каталог опубликован по адресу GET /api/profiles и не требует API key.

Те же четыре поля находятся внутри объекта request в foura_proxy.

foura_proxy

Маршрутизация одного HTTP request через ротируемые proxy с автоматическим повтором. Используйте, когда foura_single заблокирован или целевой ресурс требует определенную страну выхода.

Установите exitCountries в строгий список разрешенных двухбуквенных кодов стран, видимых целевому ресурсу, переданных пользователем или требуемых ресурсом:

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

Значения очищаются от пробелов, переводятся в верхний регистр и дедуплицируются. Прокси с неизвестными точками выхода исключаются, а запрос никогда не переключается на незапрошенную страну. Для выбора используются последние доступные метаданные страны, видимые целевому ресурсу (обычно обновляются в течение десяти минут); это не динамический поиск геолокации во время запроса. Не определяйте обслуживающую страну по хост-адресу прокси.

Успешный ответ со скоупом возвращает exitCountry и переиспользуемый ID proxy. Убедитесь, что exitCountry входит в запрошенный список разрешений. Если в текущем пуле нет совпадений, инструмент возвращает code: "no_eligible_proxy" с нормализованным скоупом в details.exitCountries. Сохраните этот скоуп и повторите попытку позже. Изменяйте или расширяйте его только тогда, когда пользователь явно меняет требование. Выбор страны включен начиная с тарифа Startup. На тарифах без этой опции вызов с exitCountries отклоняется с 403 и X-FourA-Limit: plan_limit_feature.

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

Установите exitClass: "premium" для цели, которую стандартный пул не может открыть независимо от количества перепробованных точек выхода. Это разрешение, а не жесткая инструкция: стандартный пул по-прежнему конкурирует за ответ и обычно побеждает, а запрос, на который он ответил до попытки обращения к premium-выходу, не расходует premium-трафик. Попытка через premium учитывает переданный трафик, даже если она завершилась ошибкой. Ответ возвращает exitClass, premium или standard, позволяя увидеть для каждого запроса, какой класс его обслужил. standard также возвращается после того, как включенный в тариф premium-трафик израсходован; это штатный результат, а не ошибка. exitClass: "standard" полностью запрещает эскалацию. exitClass: "premium" на тарифе без 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 рендерится, cookie возвращаются. Повторяет POST /api/browser/.

Используйте для одностраничных приложений (SPA), ленивой загрузки контента или страниц с проверками, требующими полноценного браузера.

Форматы входных данных, значения по умолчанию и правила валидации для каждого инструмента приведены в REST endpoint reference. Схемы инструментов полностью совпадают с полями REST API, плюс доступна опция offload_large только для MCP (см. ниже).

Когда целевой ресурс запускает проверку на ботов

foura_single и foura_proxy возвращают defense, если целевой ресурс выполнял проверку на ботов перед отдачей тела ответа. defense.solved: true означает, что проверка пройдена и data содержит настоящую страницу; false означает, что тело ответа может содержать страницу с вызовом (challenge). Повторите попытку с другим браузером, ОС или версией, либо перейдите на foura_proxy или foura_browser, вместо того чтобы обрабатывать страницу проверки как контент.

Типизированные ответы

Каждый ответ инструмента содержит как 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 является массивом, по одной записи на каждый шаг редиректа)
  • foura_proxy: аналогично одиночному запросу плюс { proxy, total }; успешный ответ с ограничением области также включает exitCountry, запрос с указанием класса включает exitClass, ротация со сменой семейства браузера включает profile, а ошибка включает attemptReport
  • foura_browser: отдельная структура { status, headers: object, body, cookies, userAgent } (примечание: body может быть строкой или объектом в зависимости от content-type)

Каждый инструмент также сообщает стоимость вызова и данные для его трассировки, полученные из заголовков ответа API:

  • credits: количество кредитов, потраченных на этот вызов. Присутствует и при ошибках, поскольку работа была выполнена в любом случае. Оплата взимается только за успешные вызовы, поэтому при ошибке кредиты отображаются здесь, но фактически не списываются.
  • request_id: идентификатор вызова в FourA. Указывайте его при обращении в поддержку.
  • exitClass: premium, если вызов обслуживался через премиум-выход. В 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=/"]
    }
  ]
}

Это важно для сайтов, которые устанавливают session, tracking и consent cookie в одном ответе (большая часть e-commerce).

Большие ответы: offload_large (по умолчанию: inline)

По умолчанию (начиная с v0.2.0) полные тела ответов возвращаются inline в structuredContent независимо от размера. Это работает во всех клиентах MCP из коробки.

Если ваш клиент поддерживает MCP resources/read И вы хотите экономить токены на больших страницах, передавайте offload_large: true в каждом вызове инструмента. В этом случае ответы размером >= 50 КБ записываются на диск, возвращаются как resource_link, и клиент запрашивает тело только тогда, когда оно действительно нужно. На хостинг-сервере кэшированные полезные нагрузки удаляются через 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 поддерживается

Изоляция клиентов: каждый API key получает собственное пространство имен (sha256(apiKey)[:16]). Только ключ, сохранивший полезную нагрузку, может прочитать ее обратно. Попытки межклиентского чтения возвращают Payload not found без утечки данных о существовании ресурса.

Встроенные промпты

Шесть шаблонов рабочих процессов доступны в /prompts в любом MCP клиенте. Каждый принимает именованные аргументы и возвращает шаблонное сообщение пользователя, координирующее один или несколько инструментов.

Промпт Аргументы Назначение
smart_fetch url, опционально must_contain, extract Автоматическая загрузка (выбирает метод, обходит защиту от ботов), затем возвращает или извлекает контент
scrape_product_page url Загрузка через браузер, затем извлечение названия товара, цены, изображения, наличия, SKU в формате JSON
extract_article url Одиночный запрос с переключением на proxy, затем очистка от навигации/рекламы и возврат чистого JSON статьи
monitor_pricing url, опционально target_price Загрузка через proxy, извлечение текущей цены, сравнение с целевой
check_endpoint_health url, опционально expected_text Одиночный запрос со строгой валидацией, возврат доступности и времени ответа
bulk_fetch_urls urls (через запятую) Параллельные одиночные запросы, автоматическое переключение на proxy для каждого URL, возврат только метаданных

Промпты не расходуют токены в режиме ожидания. Только вызванные промпты попадают в контекст LLM.

Полный текст и резервные промпты для ручной настройки: MCP Recipes.

Конверт ошибки

Каждая ошибка (isError: true) содержит конверт structuredContent. Минимальный набор полей для каждой ошибки:

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

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

Стабильные значения code:

Код HTTP Значение Безопасен повтор?
ssrf_blocked n/a Целевой адрес является приватным или зарезервированным (RFC 5735, 6598, IPv6 reserved), URL не http(s), или имя хоста не разрешилось Нет, проверьте URL. Кратковременную ошибку DNS lookup можно повторить
upstream_non_json различается Upstream вернул некорректное тело ответа Возможно, требуется анализ
output_validation_failed n/a outputSchema MCP-сервера отклонил upstream response, или инструмент не смог выполнить вызов (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 целевой ресурс не ответил (таймаут, сброс соединения), а в любом другом инструменте ваш validate отклонил ответ 2xx или 3xx. Проверьте status и error Требуется анализ
no_eligible_proxy n/a Нет proxy, соответствующего строгому scope exitCountries Повторите позже; меняйте scope только явно
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 КБ сохраняются на диск + resource_link (для каждого tenant, TTL 1 час).
  • Запросы к приватным адресам отклоняются (RFC 5735, RFC 6598, зарезервированные блоки IPv6) на уровне MCP. Перенаправляются только публичные хосты.
  • Лимит размера тела запроса 256 КБ для входящих запросов /mcp (реальные полезные нагрузки MCP составляют < 4 КБ).
  • Rate limits применяются FourA API для каждого сервиса. См. Rate Limits.

Self-Hosting

Полный исходный код сервера доступен публично на GitHub под лицензией @fouradata/mcp. Клонируйте репозиторий, выполните npm install, npm run build и запустите node dist/http.js, чтобы поднять собственный инстанс. Работает без сохранения состояния (stateless) в одном контейнере за любым балансировщиком нагрузки.

Переменные окружения:

Переменная По умолчанию Назначение
PORT 3076 Порт прослушивания HTTP
FOURA_API_BASE https://api.foura.ai/api Базовый URL upstream FourA REST
FOURA_MCP_PAYLOADS_DIR папка foura-mcp-payloads в системном временном каталоге (в комплекте Docker Compose задает /data/payloads) Место кэширования ответов >= 50 КБ на диске (с 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 для браузерных клиентов

Официальный контейнер запускается от имени uid 1001 (non-root). Bind mount хоста /data/payloads должен быть доступен для записи этому uid.

Масштабируйте горизонтально за любым балансировщиком нагрузки. Клиенты передают свой ключ в каждом запросе, поэтому привязка сессий (sticky sessions) не требуется.

Обновлено: 27 сентября 2026 г.