The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Seo Tools MCP listing page.
Русский | English
Восемь универсальных stdio MCP-серверов для SEO: доступ к SERP, Wordstat, Google Search Console, Google Analytics 4, Яндекс.Вебмастеру, Яндекс.Метрике и self-hosted A-Parser прямо из Claude Code (и любого MCP-клиента). Все инструменты read-only — ничего не публикуют и не меняют в твоих аккаунтах, вывод — строгий JSON. Машиночитаемо это заявлено аннотацией readOnlyHint; её намеренно нет у двадцати инструментов, каждый вызов которых тратит платный ресурс (запрос к XMLStock/XMLRiver, прокси-трафик A-Parser) — иначе клиент счёл бы их безобидными и перестал спрашивать подтверждение перед прогоном по большому пулу. К конкретному сайту не привязаны: дефолты (свойство GSC, свойство GA4, хост Вебмастера, счётчик Метрики) настраиваются на лету.
🛰 Эти серверы мы используем в продакшене в PBN Workers — инфраструктура поискового топа: семантика, PBN и сателлиты, автоматизация SEO. Нужен стабильный органический трафик — приходите.
| Сервер | Рабочие инструменты | Авторизация |
|---|---|---|
xmlstock | xmlstock_serp, xmlstock_images, xmlstock_news, xmlstock_video, xmlstock_wordstat, xmlstock_wordstat_dynamics, xmlstock_wordstat_regions, xmlstock_wordstat_regions_tree, xmlstock_balance | API-ключ |
xmlriver | xmlriver_serp, xmlriver_images, xmlriver_news, xmlriver_maps, xmlriver_check_index, xmlriver_suggest, xmlriver_related_questions, xmlriver_balance | API-ключ |
wordstat | wordstat_frequency, wordstat_dynamics, wordstat_regions, wordstat_regions_tree | Api-Key Yandex Cloud |
gsc | gsc_query, gsc_inspect_url, gsc_list_sites, gsc_get_site, gsc_list_sitemaps, gsc_get_sitemap | OAuth (все свойства аккаунта) / service account |
ga4 | ga4_list_properties, ga4_property_details, ga4_metadata, ga4_check_compatibility, ga4_report, ga4_bytime, ga4_traffic_sources, ga4_geo, ga4_devices, ga4_top_pages, ga4_events, ga4_funnel, ga4_annotations, ga4_realtime | OAuth (все свойства аккаунта) / service account |
ywm | ywm_hosts, ywm_summary, ywm_search_queries, ywm_queries_history, ywm_recommended_queries, ywm_popular, ywm_indexing_history, ywm_sqi_history, ywm_external_links, ywm_broken_links, ywm_diagnostics, ywm_important_urls, ywm_sitemaps | OAuth (авто-refresh) |
metrika | metrika_report, metrika_bytime, metrika_counters, metrika_goals, metrika_traffic_sources, metrika_geo, metrika_devices, metrika_landing_behavior, metrika_search_phrases, metrika_top_landings | OAuth (авто-refresh) |
aparser | aparser_ping, aparser_status, aparser_proxies, aparser_parsers, aparser_parser_fields, aparser_get_preset, aparser_serp_google, aparser_serp_yandex, aparser_suggest, aparser_request, aparser_bulk_request | self-hosted A-Parser (URL + пароль API) |
Где опубликовано: npm (восемь пакетов), официальный MCP Registry, GitHub MCP Registry (все восемь серверов), маркетплейс плагинов Claude Code (см. ниже) и .mcpb-бандлы в релизах.
У каждого сервера дополнительно есть auth-инструменты <server>_auth_status и <server>_set_credentials (см. Интерактивная авторизация).
xmlstock_serp — веб-выдача Google/Яндекса (органика + подсветки + SERP-фичи): регион, устройство, safe search, сортировка (Яндекс), период, рекламные блоки; третий движок yandex_xml — официальный Яндекс XML (groupby до 100 за 1 запрос, hlword на любых устройствах, статистика found/found-docs; тариф от 24 ₽/1000)xmlstock_images — поиск картинок Google (url страницы + url изображения + заголовок)xmlstock_news — новости Google (заголовок, источник, дата, сниппет)xmlstock_video — видео Google (url, заголовок, превью, хост, канал, длительность)xmlstock_wordstat — Яндекс Wordstat: топ + похожие запросы с частотностью (можно по региону), операторы Wordstatxmlstock_wordstat_dynamics — динамика частотности по времени (день/неделя/месяц)xmlstock_wordstat_regions — спрос по регионам (count, share, affinity index + имена регионов)xmlstock_wordstat_regions_tree — дерево регионов Wordstat (id + имя + путь)xmlstock_balance — баланс аккаунта / проверка ключа (бесплатно)Wordstat через XMLStock — тем же ключом
XMLSTOCK_*, что и SERP; не нужен Yandex Cloud (в отличие от отдельного сервераwordstat).
xmlriver_serp — органика Google/Яндекса (глубина добирается пагинацией: каждые 10 позиций = 1 платный запрос), флаг наличия AI Overview; опция includeAIOverview — полный текст Обзора от ИИ + цитируемые ссылки (платный ai=1, только Google); includeAdditional — доп. SERP-блоки Google из <addresults> (knowledge_graph, localresultsplace, rs и др.; наполнение зависит от платных опций кабинета XMLRiver, непришедшие блоки — в additional.unavailable); гео-таргетинг Google — location (город → loc, «Moscow»/«1011969») и country (ISO/числовой id, автовыводится из города); device — desktop/mobile/tablet, os (ios/android) отправляется только при device=mobilexmlriver_images — картинки Google (страница + url картинки + заголовок + источник + размеры); гео — location/countryxmlriver_news — новости Google (заголовок, источник, дата, сниппет), фильтр по времени; гео — location/countryxmlriver_maps — поиск заведений по Google Maps (setab=maps, обязательные zoom 1–15 и coords «широта,долгота», count 5–50): название, рейтинг, адрес, телефон, сервисы, координаты, place_id, число отзывов. ВАЖНО: формат по доке, лайвом не подтверждён (на тестовом аккаунте эндпоинт устойчиво отвечает кодом 500 — вероятно, нужна платная опция кабинета)xmlriver_check_index — проверка индексации URL в Google/Яндексе (inindex)xmlriver_suggest — поисковые подсказки Google (до 50 фраз за вызов, платно за каждую фразу); гео подсказок — location/countryxmlriver_related_questions — блок «Вопросы по теме» / People Also Ask Google (вопросы всегда; ответы — только при включённой платной опции «Related Questions с ответами» в кабинете)xmlriver_balance — баланс аккаунта / проверка ключа (бесплатно)wordstat_frequency — широкая и точная частотность, уточняющие запросы (related) и ассоциацииwordstat_dynamics — частотность по времени (день/неделя/месяц)wordstat_regions — распределение по регионам с индексом аффинити и именами регионовwordstat_regions_tree — полное дерево регионов Вордстата (id + имя)gsc_query — Search Analytics (клики/показы/CTR/позиция), авто-пагинация, dataState final/all, произвольные фильтры измерений (filters, AND-семантика) и aggregationType (auto/byProperty/byPage)gsc_inspect_url — URL Inspection: статус индексации, покрытие, canonical, последний обход, mobile usability, rich resultsgsc_list_sites — свойства, доступные авторизацииgsc_get_site — уровень доступа к свойствуgsc_list_sitemaps — отправленные sitemap со статусомgsc_get_sitemap — детали одного sitemapДаты Search Analytics — по Pacific Time (не МСК); история ~16 месяцев; финальные данные отстают на ~2-3 дня (свежие — dataState=all); ctr в ответе — доля 0..1.
ga4_list_properties — свойства GA4, доступные авторизации (отсюда берётся propertyId — это не Measurement ID G-XXXXXXX)ga4_metadata — какие измерения и метрики доступны в ЭТОМ свойстве, включая кастомные (customEvent:…); поиск подстрокой, blockedReasons (по такой метрике отчёт вернёт нули) и type (целое/дробное для metricFilters)ga4_check_compatibility — совместима ли связка измерений/метрик в этом свойстве, без тяжёлого отчёта; при несовместимости — какие поля убратьga4_report — произвольный отчёт: любые измерения × метрики, фильтры по измерениям, сортировка (полный Data API runReport)ga4_bytime — динамика метрик по времени (день/час/неделя/месяц)ga4_traffic_sources — источники трафика: группа каналов, source/medium, кампания; organicOnly — только органикаga4_geo — страна/регион/городga4_devices — тип устройства/ОС/браузерga4_top_pages — топ страниц по pagePath, странице входа или заголовку; фильтры organicOnly и pathContainsga4_events — события по eventName; keyEventsOnly — только ключевые события (бывшие конверсии)ga4_realtime — отчёт в реальном времени (последние 30 минут)ga4_funnel — воронка (runFunnelReport): сколько дошло до каждого шага и где отвалились; шаг = событие и/или условия по измерениям, разбивка по измерению. Внутри шагов действует схема Exploration API (pagePath там недоступен), корзина квоты отдельная и запрос дороже обычного отчётаga4_annotations — аннотации свойства: пометки на датах, включая созданные самой GA4 (systemGenerated) — частое объяснение необъяснимого скачка в динамикеga4_property_details — карточка свойства: таймзона отчётов, валюта, уровень сервиса (STANDARD/360) и потоки данных с их Measurement ID G-XXXXXXXВо всех отчётных инструментах есть includeQuota — сколько «токенов» Data API съел запрос и сколько осталось на час/сутки.
Единицы и даты: bounceRate/engagementRate GA4 отдаёт долей 0..1 (не процентами); даты считаются в таймзоне свойства — принимаются YYYY-MM-DD и ключевые слова GA4 (today, yesterday, 28daysAgo), фактическая таймзона возвращается в ответе. В ответах есть totalRows/truncated, а thresholded: true означает, что часть данных скрыта порогом конфиденциальности GA4.
ywm_hosts — id пользователя + подтверждённые сайтыywm_summary — ИКС, страниц в поиске, исключено, проблемы сайта по важностиywm_search_queries — аналитика запросов по URL (~2 недели по умолчанию; переопределяется dateFrom/dateTo)ywm_queries_history — суммарные показы/клики/позиции по времениywm_recommended_queries — приближённые рекомендованные запросы (спрос + недобор кликов)ywm_popular — популярные запросы хостаywm_indexing_history — страниц в поиске по времениywm_sqi_history — ИКС по времениywm_external_links — выборка внешних ссылок + общее числоywm_broken_links — битые внутренние/внешние ссылкиywm_diagnostics — проблемы сайтаywm_important_urls — отслеживаемые URL со статусом индексации/поискаywm_sitemaps — sitemap со статусомmetrika_report — произвольный отчёт: любые dimensions × metrics, фильтры, сортировка (полный Stat API)metrika_bytime — метрики по времени (день/неделя/месяц/час)metrika_traffic_sources — визиты/пользователи/отказы по источникам трафикаmetrika_geo — визиты по стране/региону/городуmetrika_devices — визиты по устройству/ОС/браузеруmetrika_goals — список целей (конверсий)metrika_counters — доступные счётчикиmetrika_landing_behavior — поведение на посадочных + достижения целейmetrika_search_phrases — поисковые фразы (органика)metrika_top_landings — топ органических посадочныхaparser_ping — проверка связи с инстансом и пароля APIaparser_status — вердикт готовности: версия, установленные парсеры, очередь, живые проксиaparser_proxies — живые прокси инстанса (можно по пачкам proxy checkers; креды прокси не выводятся)aparser_parsers — парсеры, установленные на инстансеaparser_parser_fields — поля результата, которые умеет вернуть парсер (flat + arrays)aparser_get_preset — опции config-пресета парсера (чувствительные значения маскируются)aparser_serp_google — органика Google (парсер SE::Google); прокси по умолчанию + preflight живых проксиaparser_serp_yandex — органика Яндекса (SE::Yandex); регион через lraparser_suggest — поисковые подсказки Google/Яндексаaparser_request — универсальный синхронный запрос к любому парсеру (oneRequest)aparser_bulk_request — пакетный запрос: один парсер, много запросов в N потоков (bulkRequest)Нужен свой запущенный инстанс A-Parser (лицензия + сервер): мост им управляет, но не хостит и не проксирует его. Прокси и прокси-чекеры (пачки) настраиваются один раз в GUI A-Parser — мост их читает, проверяет (preflight) и выбирает (
checkers), но не создаёт. v1 синхронный и read-only: очередь задач и большие асинхронные выгрузки не подключены.
Самый простой способ, ничего ставить руками не нужно: скачай нужный .mcpb со страницы релиза и открой двойным кликом — Claude Desktop поставит сервер сам и спросит ключи в диалоге установки.
xmlstock, xmlriver, wordstat, aparser) — ключи вводятся прямо в установщике.gsc, ga4, ywm, metrika) ничего не спрашивают: авторизация проходит в чате (<server>_oauth_start → <server>_oauth_finish).Бандлы самодостаточны (~0.2 МБ, зависимости внутри), Node.js 20+ нужен только для варианта с npx. Собрать самому: pnpm build:mcpb.
Аналог .mcpb, но для Claude Code: сервер, ключи и подсказки ставятся одной командой, ключи спрашиваются диалогом, секреты уходят в системное хранилище, а не в открытый файл.
Дальше — только те источники, которые нужны; каждый плагин тянет ровно один сервер:
Доступны xmlstock, xmlriver, wordstat, gsc, ga4, ywm, metrika, aparser — и seo-tools, который ставит все восемь сразу. Бандл удобен, но это ~100 инструментов в каждой сессии: если работаешь только с Вебмастером и Метрикой, ставь два плагина, а не бандл.
Ключи можно ввести сразу (--config KEY=VALUE) или потом через /plugin configure <плагин>@seo-tools-mcp:
Поля, помеченные как секретные (API-ключи, OAuth-секреты), Claude Code кладёт в системное хранилище; в settings.json они не попадают. Плагины на OAuth (gsc, ga4, ywm, metrika) при установке спрашивают только client_id/secret — сам вход проходит в чате через <сервер>_oauth_start → <сервер>_oauth_finish.
Вместе с сервером плагин приносит навыки — процедурные инструкции по своему источнику:
как не сжечь баланс на снятии позиций, почему freq_broad завышает трафик в разы, отчего
GA4 молча отдаёт нули, чем усреднённая позиция GSC отличается от снятой из выдачи. В контексте
они всегда занимают ~110 токенов на навык и разворачиваются, только когда действительно нужны.
Каждый сервер — самодостаточный npm-пакет seo-tools-mcp-<сервер>; ставится одной командой:
Серверы не связаны между собой: возьмите один пакет и игнорируйте остальные. Каждый самодостаточен — общий код @seo-tools/shared вшит в сборку, так что лишних зависимостей и «хвоста» монорепы не тянется. Достаточно установить нужный пакет с npm — там уже всё из коробки (npx -y скачает и запустит его сам):
| Пакет (npm) | Сервер |
|---|---|
seo-tools-mcp-xmlstock | SERP Google/Яндекс + Wordstat |
seo-tools-mcp-xmlriver | SERP Google/Яндекс + проверка индексации |
seo-tools-mcp-wordstat | частотности Яндекса (Yandex Cloud) |
seo-tools-mcp-gsc | Google Search Console |
seo-tools-mcp-ga4 | Google Analytics 4 |
seo-tools-mcp-ywm | Яндекс.Вебмастер |
seo-tools-mcp-metrika | Яндекс.Метрика |
seo-tools-mcp-aparser | мост к self-hosted A-Parser |
В любом MCP-клиенте (Claude Desktop, Cursor…) — прописывается один блок в mcpServers:
Прямая установка одного пакета по GitHub-ссылке (
npm i github:antohins/seo-tools-mcp) не поддерживается: это pnpm-монорепа, отдельный подпакет так не ставится. Для установки из исходников — вариант Б ниже (клонировать + собрать). Готовые пакеты живут на npm.
Дальше (любой вариант) — прямо в диалоге Claude Code: «настрой доступ к xmlstock» → агент вызовет xmlstock_auth_status, подскажет, какие ключи нужны и где их взять, примет их через xmlstock_set_credentials и сохранит. После этого спрашивайте данные обычным языком: «сними топ-10 Яндекса по запросу X», «частотность фраз …», «клики/показы из GSC за месяц». Ключи и OAuth настраиваются один раз (см. Получение доступов).
У каждого сервера есть auth-инструменты — ключи можно выдавать прямо в диалоге, без правки файлов и перезапуска:
<server>_auth_status — вызывается в начале работы: показывает, какие ключи заданы (маскированно), каких не хватает и как их получить (шаги регистрации).<server>_set_credentials — сохраняет переданные значения в ~/.config/seo-tools-mcp/.env (права 600) и применяет сразу.gsc_save_sa_json — принимает содержимое JSON-ключа сервис-аккаунта, кладёт его в конфиг-директорию и возвращает email, который нужно добавить в GSC.ywm_oauth_start / metrika_oauth_start → ссылка авторизации Яндекса; пользователь открывает, разрешает, копирует код → *_oauth_finish обменивает код на access+refresh токены. Дальше токен обновляется автоматически при протухании (code flow, не implicit).Типовой сценарий новой сессии: «настрой доступ к xmlstock» → агент вызывает xmlstock_auth_status → просит недостающие ключи → xmlstock_set_credentials → работает.
⚠ Ключи, переданные через чат, проходят через контекст модели. Для максимальной гигиены можно по-прежнему вписать их в ~/.config/seo-tools-mcp/.env руками — серверы подхватят файл сами.
Клиентские сайты раскиданы по разным аккаунтам Google/Яндекса — поддерживаются именованные профили:
account («clientX», «agency»...). Без него используется основной профиль — обратная совместимость полная.GSC_REFRESH_TOKEN__clientX, YANDEX_OAUTH_TOKEN__clientX, XMLSTOCK_KEY__clientX…gsc_oauth_start(account="clientX") → пользователь авторизуется под другим Google-аккаунтом → gsc_oauth_finish(account="clientX"). Аналогично ywm_oauth_start/finish(account=...) для Яндекса; API-ключи — <server>_set_credentials(account="clientX", ...).account="clientX" без настроенных ключей → ошибка со списком настроенных профилей (никаких тихих фолбэков в чужой аккаунт). Дефолты (GSC_SITE_URL__clientX, YWM_HOST_ID__clientX, METRIKA_COUNTER_ID__clientX) — тоже per-account.<server>_auth_status показывает все профили и их ключи (маскированно).SEO_TOOLS_MCP_ENV (при заданном пути домашний конфиг НЕ читается).Единый env-файл: ~/.config/seo-tools-mcp/.env (права 600). Все серверы читают его при старте, а *_set_credentials/*_oauth_finish пишут в него сами — ручная правка не обязательна. Шаблон — .env.example. Переменные из окружения процесса имеют приоритет над файлом. Альтернативный путь к файлу — SEO_TOOLS_MCP_ENV (так один хост может держать несколько независимых профилей: разные claude mcp add с разным SEO_TOOLS_MCP_ENV).
--scope user — доступно во всех сессиях/проектах. Для шаринга на команду — --scope project (создаст .mcp.json в репозитории; секреты подставлять только через ${VAR}).
Всё из этого раздела продублировано в ответах
<server>_auth_status— агент сам подскажет шаги. Ниже — для чтения человеком.
XMLSTOCK_USER, XMLSTOCK_KEY (или через xmlstock_set_credentials).xmlstock_balance.Нюансы (выяснено на живых ответах):
text_bolds) — параметр hlword=1, тег <hlword> вложенным XML (парсится через stopNodes, соседние слова склеиваются во фразы); PAA и related searches — related=1 (PAA только у Google);lr принимает id регионов Яндекса для обоих движков (XMLStock маппит на Google сам);<error code>: 20–25/101/110/111/500 ретраятся, 55 — rate-limit с паузой, 15 = пустая выдача (деньги списаны), 31/42 — фатальные (авторизация);Официальный Wordstat API v2 (в составе Yandex Cloud Search API) — бесплатный, без заявок и OAuth. Один раз в https://console.yandex.cloud:
WORDSTAT_FOLDER_ID.search-api.webSearch.user.yc.search-api.execute → WORDSTAT_API_KEY.wordstat_frequency по любой фразе.Нюансы: точная частотность = операторы "!слово !слово" (поддерживаются в topRequests/regions; в dynamics — только при period=daily); данные topRequests — за последние 30 дней; count приходит строками (парсится); квоты 10 rps / 100 запросов в час (429 ретраится, но для массового съёма закладывать троттлинг); associations максимум 20.
Два пути; рекомендуемый — OAuth: токен наследует доступ твоего Google-аккаунта и видит все его свойства GSC разом (включая будущие), добавлять пользователя в каждое свойство не нужно.
Путь A — OAuth (один раз):
gsc_oauth_start (передать clientId+secret) → открыть ссылку → разрешить → браузер редиректнется на localhost:8585, код подхватится автоматически → gsc_oauth_finish.gsc_list_sites — покажет все свойства аккаунта.Путь B — сервис-аккаунт (для headless-кронов): IAM → Service Accounts → JSON-ключ → gsc_save_sa_json (или путь в GSC_SA_JSON) → добавить email аккаунта в каждое нужное свойство GSC (Настройки → Пользователи и права, «Полный»).
Если заданы оба — приоритет у OAuth.
Авторизация та же, что у GSC, и OAuth-приложение общее (GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET переиспользуются). Но scope у GA4 свой, поэтому нужна отдельная авторизация — один раз.
ga4_oauth_start (если client ID/secret уже сохранены для GSC — без аргументов) → открыть ссылку → разрешить → браузер редиректнется на localhost:8586 (порт отличается от GSC, чтобы серверы не конфликтовали), код подхватится автоматически → ga4_oauth_finish.ga4_list_properties — покажет все свойства аккаунта и их propertyId.ga4_set_credentials → GA4_PROPERTY_ID (числовой id из п. 3), иначе передавать propertyId в каждом вызове.Путь B — сервис-аккаунт: JSON-ключ → ga4_save_sa_json → добавить email аккаунта в свойство GA4 (Администратор → Управление доступом к ресурсу, роль «Просмотр»).
https://oauth.yandex.ru/verification_code. Права (scope): Яндекс.Вебмастер — «Получение информации о сайтах» (webmaster:hostinfo) + «Управление сайтами» (webmaster:verify); Яндекс.Метрика — «Получение статистики» (metrika:read). Взять ClientID и Client secret.ywm_oauth_start (передать ClientID + secret, сохранятся) → открыть ссылку под аккаунтом-владельцем сайта/счётчика → скопировать код → ywm_oauth_finish. Получатся access+refresh токены, общие для ywm и metrika; обновляются автоматически.YWM_HOST_ID (список — ywm_hosts), METRIKA_COUNTER_ID (список — metrika_counters) — задать через *_set_credentials, либо передавать в каждом вызове.response_type=token) и сохранить в YANDEX_OAUTH_TOKEN — но без refresh он протухнет (Вебмастер ~6 мес, Метрика ~1 год).Ограничения API Яндекса (не баги серверов): фильтр по URL в Вебмастере есть только в query-analytics (данные ~2 недели); эндпоинта «рекомендованные запросы» в API v4 нет — ywm_recommended_queries аппроксимирует через спрос (DEMAND) + недобор кликов; поисковые фразы в Метрике в основном «Не определено» (шифрование).
APARSER_URL = http://<IP-инстанса>:<порт>/API (обязательно с путём /API), APARSER_PASSWORD = пароль оттуда же → aparser_set_credentials.aparser_ping, затем aparser_status (готовность инстанса + живые прокси).Нюансы: прокси и прокси-чекеры (пачки) настраиваются один раз в GUI — без живых прокси Google/Яндекс быстро банят, поэтому serp/suggest-инструменты делают preflight и предупреждают (use_proxy=false — на свой риск); пресеты и пачки по умолчанию задаются env (APARSER_GOOGLE_PRESET, APARSER_YANDEX_PRESET, APARSER_PROXY_CHECKERS, APARSER_USE_PROXY); v1 синхронный и read-only — очередь задач и мутирующие методы API не подключены.
Даты — YYYY-MM-DD (МСК). Регионы: имя из встроенного списка частых регионов («Москва», «спб», «Казахстан»…) или числовой id региона Яндекса (213, 225…) — числовой id работает всегда. Несколько регионов через запятую поддерживает только сервер wordstat; SERP-инструменты xmlstock_*/xmlriver_* принимают ОДИН регион. Полный справочник id — инструмент wordstat_regions_tree.
Серверы — обычные stdio-процессы без привязки к машине. Четыре сценария:
Зарегистрировать через claude mcp add --scope user (блок «Регистрация в Claude Code» выше) — доступно во всех проектах и сессиях.
В claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/):
Ключи подхватятся из ~/.config/seo-tools-mcp/.env автоматически.
claude.ai (web/mobile) умеет только remote MCP (Streamable HTTP по публичному HTTPS). Наши stdio-серверы выносятся на VPS через мост supergateway:
Дальше nginx: TLS + proxy_pass на 127.0.0.1:880X под секретным путём (например /mcp-<длинный-случайный-токен>/xmlstock/) — supergateway слушать только на localhost. Подключение:
claude mcp add --transport http xmlstock https://host/<секретный-путь>/xmlstock/mcp⚠ Секретный путь — минимальный гейт (custom connectors claude.ai не передают произвольные заголовки авторизации). За эндпоинтом — все ключи сервисов, поэтому: только HTTPS, длинный токен в пути, отдельный access-лог.
Альтернатива для Claude Code без HTTP-моста — stdio через ssh:
Юнит-тесты покрывают чистую логику: маскирование секретов, классификацию OAuth-ошибок, пагинацию Метрики/GSC (дедуп, truncated), фильтры, парсер SERP, регионы. Лайв-смоук поднимает каждый сервер и дёргает бесплатный инструмент (xmlstock_balance, xmlriver_balance, wordstat_frequency, gsc_list_sites, ywm_hosts, metrika_counters, aparser_ping) — проверка авторизации end-to-end.
Общий код (shared/): HTTP-клиент с ретраями на 429/5xx (3 попытки, экспоненциальный backoff, Retry-After), загрузчик env + персистентный конфиг, фабрика auth-инструментов, Яндекс-OAuth с авто-refresh, JSON-хелперы MCP, счётчик расхода платных вызовов. XMLStock дополнительно ретраит свои «временные» коды из тела XML, код 15 («ничего не найдено») трактуется как пустая выдача.
Сборка серверов — tsup: shared/ вбивается в единый dist/index.js каждого сервера (рантайм-зависимости остаются external), поэтому npm-пакет самодостаточен.
Каждый сервер публикуется как отдельный пакет seo-tools-mcp-<сервер>; shared/ приватный и в npm не уходит (вбит в серверы). Версии всех серверов держим синхронно.
pnpm publish сам подставляет реальные версии вместо workspace:* и не даст опубликовать при грязном рабочем дереве.
Бамп версии — только через корневой package.json: правишь версию там и запускаешь pnpm version:sync, который разносит её по всем 42 местам (package.json и server.json каждого сервера, литерал в new McpServer({ version }), манифесты плагинов). pnpm -r exec npm version patch для этого НЕ годится: он обновит только пакеты серверов, остальное останется на старой версии, и pnpm version:check в CI упадёт. Проверить без записи — pnpm version:check.
PR приветствуются — см. CONTRIBUTING.md. История изменений — CHANGELOG.md. Уязвимости — приватно через Security Advisories (детали — SECURITY.md).
MIT © antohins