Profile
Back to NewsBack
GitHub Trending 6 min
Reader Mode
Vladimir-Human/ru-marketplace-mcp: MCP-серверы и agent skills для 12 площадок РФ и Китая: WB, Ozon, Яндекс Маркет, Авито. Сравнение цен.

Vladimir-Human/ru-marketplace-mcp: MCP-серверы и agent skills для 12 площадок РФ и Китая: WB, Ozon, Яндекс Маркет, Авито. Сравнение цен.

ru-marketplace-mcp

Русский · English

CI</a> PyPI</a> Python 3.12+</a> License: MIT</a> MCP</a>

MCP-серверы для российских и китайских маркетплейсов. Цены, наличие, рейтинги, отзывы и реквизиты продавцов с Wildberries, Ozon, Яндекс Маркета, Детского мира, Авито, AliExpress, Taobao, Мегамаркета, Lamoda, DNS и Ситилинка. Плюс недвижимость с Циана и сравнение цен по всем товарным источникам одним вызовом.

Только чтение. Ключи API, токены и регистрация не нужны — площадки с жёстким анти-ботом читаются через ваш собственный Chrome. Одно исключение по желанию: опциональный MPStats берёт платный токен (MPSTATS_MP_AUTH) — без него всё остальное работает как прежде.

compare_prices("кроссовки мужские"): предложения Wildberries и Яндекс Маркета по цене, дешевле всего wildberries 712 ₽

Пример вызова из раздела «Сравнение цен».

Быстрый старт

Нужны Python 3.12+ и uv.

Без checkout пакет ставится с PyPI и сам подключается к найденному клиенту (--dry-run покажет план и ничего не запишет):

uvx ru-marketplace-mcp setup

Или в один клик: Install in VS Code</a> Install in Cursor</a>

Для установки клиента, выбора источников и проверки первого предложения — пошаговый старт. Node нужен только для тестов разработчика. Публикация на PyPI (для владельца): DEPLOYMENT.md — PyPI.

Первый успешный запрос · Архитектура · Как добавить источник · Про анти-бот


Что внутри

| Сервер | Инструментов | Что нужно, чтобы читалось | Что умеет | | ----------------- | ------------ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | Wildberries | 8 | анонимный HTTP | Поиск, карточки, отзывы, вопросы о товаре, реквизиты продавца, каталог и товары категории | | Яндекс Маркет | 2 | анонимный HTTP | Цены разных продавцов, разбивка оценок по звёздам, отзывы | | Детский мир | 3 | анонимный HTTP | Детские товары, наличие в офлайн-магазинах, категории | | Ozon | 3 | ваш Chrome; с домашнего IP часто и без него | Поиск, карточки, отзывы | | Авито | 3 | ваш Chrome + российский домашний IP и запросы вразрядку — иначе блок по IP | Поиск объявлений, карточки, репутация продавца | | Taobao | 2 | ваш Chrome с активным входом в Taobao | Поиск и карточки, цены в юанях | | Мегамаркет | 2 | ваш Chrome с активным входом — анонимной сессии API отдаёт пусто | Поиск и карточки через мобильный API | | Lamoda | 2 | карточки: HTTP GraphQL → Chrome при отказе; поиск — Chrome | Поиск, карточки с размерами | | DNS | 2 | ваш Chrome (Qrator) | Поиск и карточки электроники | | Ситилинк | 2 | ваш Chrome (Qrator) | Поиск и карточки электроники | | AliExpress | 2 | ваш Chrome (x5sec) | Поиск и карточки, цены в рублях | | Циан | 2 | ваш Chrome (WAF по IP) | Недвижимость: поиск по фильтрам (продажа, аренда, посуточно) и карточка объявления | | Сравнение | 4 | опрашивает всё перечисленное | «Где дешевле?» одним вызовом | | MPStats | 2 | платный аккаунт MPStats, cookie mp_auth (опционально) | Продажи/остатки/графики за 30 дней по SKU Ozon/WB, остатки по складам (FBS/FBO) |

Читается анонимно, без браузера: Wildberries, Яндекс Маркет и Детский мир. Карточки Lamoda сначала читаются по HTTP GraphQL; при отказе нужен ваш Chrome (CDP) для запасного уровня. Остальным нужен ваш залогиненный Chrome (CDP). Taobao и Мегамаркет вдобавок требуют активного входа в саму площадку — без него Taobao упирается в стену логина, а Мегамаркет отдаёт пустой ответ. Авито ещё и блокирует по IP: с датацентрового адреса это глухой отказ, с российского домашнего — работает, если не частить запросами. Запросы к CDP-источникам идут вразрядку: очередь подряд без пауз роняет их (DNS и Taobao в проверке так и деградировали), поэтому коннекторы держат паузу между вызовами сами. Точное состояние из вашей сессии покажет marketplace-mcp doctor.

MPStats стоит особняком: это единственный платный источник. Без MPSTATS_MP_AUTH объединённый marketplace-mcp вообще не монтирует его инструменты — они всё равно отвечали бы auth_missing — поэтому он опционален и подключается по желанию, на остальные тринадцать серверов он не влияет никак. Отдельный mpstats-mcp запускается и без токена и на вызовы отвечает auth_missing.

Всего 39 инструментов в 14 серверах на общем рантайме mcp-core. Плюс объединённый marketplace-mcp, который монтирует всё разом — одна запись в конфиге клиента вместо четырнадцати. У него два своих инструмента: marketplace_sources (какие коннекторы поднялись, а какие отвалились и почему) и marketplace_health (жив ли Chrome, какие хосты остывают, какую страницу открыть человеку). С токеном MPStats в нём 41 инструмент, без токена — 39: те же смонтированные источники минус два mpstats_*, плюс эти два.

Проверка 2.7.0: 30 октября с одного адреса Wildberries при отказе API (HTTP 403) сам прочитал поиск через Chrome: 40 товаров, у всех цена. Код остальных источников с v2.6.0 не менялся; их проверял прогон v2.6.0 того же дня (12 из 13 источников, MPStats без токена). Подробности v2.7.0.

Подключение к MCP-клиенту

Каждый сервер — консольная команда, поэтому пути в конфиге не зашиваются.

Claude Desktop — claude_desktop_config.json

Windows: %APPDATA%\Claude\claude_desktop_config.json macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Самый короткий путь — marketplace-mcp setup: команда находит Claude Desktop, Cursor и Claude Code, пишет им конфиг (по умолчанию профиль compare), запускает scraping-Chrome, прогоняет doctor и предлагает unblock для источника, закрытого браузером. --dry-run только печатает шаги и файлы.

marketplace-mcp setup

Если клиент нетипичный или нужен один конкретный, тот же конфиг пишет install --write:

marketplace-mcp install claude --write

Команда допишет запись marketplace в конфиг Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json на Windows, ~/Library/Application Support/Claude/claude_desktop_config.json на macOS, ~/.config/Claude/claude_desktop_config.json на Linux). Путь к uv и к вашему checkout подставятся абсолютными (у десктопного клиента часто нет PATH терминала), чужие серверы и остальные настройки конфига останутся на месте, старый файл сохранится как claude_desktop_config.json.bak-<метка>. Остаётся перезапустить клиент. --dry-run показывает, что именно будет записано, и ничего не пишет; --per-source возвращает старую раскладку — по записи на источник — и с --profile не сочетается.

По умолчанию запись запускает compare-mcp — профиль compare: 4 инструмента сравнения цен, самый дешёвый в каждом запросе. --profile decision добавляет осмотр карточки из шортлиста (5 инструментов), --profile full берёт marketplace-mcp со всеми инструментами источников — в несколько раз дороже (замер по профилям — в docs/TOOLS.md). Меняется только консольная команда записи, имя marketplace остаётся прежним. Подробнее о выборе режима — dsh/README.md и docs/QUICKSTART.md.

Если конфиг удобнее править руками, начните с одной записи:

{
  "mcpServers": {
    "marketplace": {
      "command": "uv",
      "args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "compare-mcp"],
    },
  },
}

Если нужны отдельные серверы, marketplace-mcp install claude --per-source напечатает готовый блок для вставки. Путь к вашему checkout там уже подставлен: заглушку /path/to/ru-marketplace-mcp править руками не придётся. При установке из wheel вместо путей печатаются консольные команды на PATH. Неизвестное имя клиента (допустимы claude, claude-code, cursor, dsh) команда отклоняет с пояснением и кодом возврата 2 — молча подставить блок для Claude она не может.

У браузерного уровня есть ещё команды: marketplace-mcp browser start (запустить scraping-Chrome; по умолчанию окно видно, --hidden — за экраном), marketplace-mcp browser status (достижим ли CDP-эндпоинт, какая версия Chrome, сколько вкладок и где окно) и marketplace-mcp browser show (окно scraping-Chrome на экран — на Windows автозапуск коннектора стартует за экраном, и без этого нельзя ни войти руками, ни пройти проверку сайта). Когда doctor показывает стену, marketplace-mcp unblock откроет нужную страницу в новой вкладке, подождёт, пока вы пройдёте проверку или войдёте, и перепроверит только этот источник. Ни одна из этих команд не ходит в сайты сама и не решает проверку за человека.

Минимальный вариант вручную:

{
  "mcpServers": {
    "wildberries": {
      "command": "uv",
      "args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "wb-mcp"],
    },
    "ozon": {
      "command": "uv",
      "args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "ozon-mcp"],
    },
    "compare-prices": {
      "command": "uv",
      "args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "compare-mcp"],
    },
  },
}

Путь пишите с прямыми слешами / или двойными обратными \\. Полный список команд — wb-mcp, ozon-mcp, yandex-mcp, detmir-mcp, avito-mcp, taobao-mcp, megamarket-mcp, lamoda-mcp, dns-mcp, citilink-mcp, compare-mcp, marketplace-mcp.

Только нужные площадки: MARKETPLACE_SOURCES

Объединённый сервер монтирует все источники, а описания их инструментов уходят в контекст в каждом запросе. Переменная MARKETPLACE_SOURCES оставляет только перечисленные:

{
  "mcpServers": {
    "marketplace": {
      "command": "uv",
      "args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "marketplace-mcp"],
      "env": {
        "MARKETPLACE_SOURCES": "wildberries,ozon,yandex_market,avito,aliexpress,dns,compare",
      },
    },
  },
}

Имена — канонические (wildberries, ozon, yandex_market, detsky_mir, avito, taobao, megamarket, lamoda, dns, citilink, aliexpress, cian, compare, mpstats); короткие псевдонимы wb, ym/yandex, detmir, ali тоже принимаются. Неизвестное имя отклоняется при запуске с перечнем поддерживаемых источников, чтобы опечатка не превратилась в частичный сервер. Переменная не задана или пуста — монтируется всё, как раньше. Отключённые источники видно в marketplace_sources: они попадают в skipped с пометкой, что их сняли, а не что они не импортировались. compare_prices опрашивает ровно тот же набор.

Claude Code

Установка плагина (15 навыков + MCP) одной командой:

/plugin install ru-marketplace-mcp --marketplace Vladimir-Human/ru-marketplace-mcp

Или подключение серверов вручную из локального клона:

claude mcp add wildberries -- uv run --directory /путь/к/ru-marketplace-mcp wb-mcp
claude mcp add yandex-market -- uv run --directory /путь/к/ru-marketplace-mcp yandex-mcp
claude mcp add detsky-mir -- uv run --directory /путь/к/ru-marketplace-mcp detmir-mcp
claude mcp add ozon -- uv run --directory /путь/к/ru-marketplace-mcp ozon-mcp
claude mcp add compare-prices -- uv run --directory /путь/к/ru-marketplace-mcp compare-mcp

Cursor — .cursor/mcp.json

{
  "mcpServers": {
    "compare-prices": {
      "command": "uv",
      "args": ["run", "--directory", "/путь/к/ru-marketplace-mcp", "compare-mcp"],
    },
  },
}

Другой stdio-клиент

Запустите uv run --directory /путь/к/репозиторию <команда>, где команда — одна из wb-mcp, ozon-mcp, yandex-mcp, detmir-mcp, aliexpress-mcp, cian-mcp, compare-mcp. Серверы говорят по JSON-RPC через stdin и stdout, диагностику пишут в stderr. Опциональный mpstats-mcp запускается так же, с MPSTATS_MP_AUTH в окружении.

DeepSeek Harness (dsh) — плагин-бандл

В dsh это не запись mcpServers, а слой профиля. Бандл лежит в подкаталоге dsh/ и ставится штатным менеджером плагинов (pnpm нужен на PATH):

dsh plugin --profile web add ru-marketplace-mcp-dsh

или напрямую из GitHub:

dsh plugin --profile web add github:Vladimir-Human/ru-marketplace-mcp#path:/dsh

Сразу после установки появляются 15 навыков и ни одного MCP-инструмента: все три строки MCP выключены, пока не задана переменная RU_MARKETPLACE_MCP_DIR с путём к клону. Так сделано потому, что смонтированный сервер платится в каждом запросе: рекомендуемый режим сравнения цен стоит ≈1.7k токенов, режим с инспекцией карточки — ≈2.0k, полный набор — ≈13.4k (оценка по tools/list; подробности в docs/TOOLS.md). Включение и полный режим описаны в dsh/README.md.

После подключения перезапустите клиент и прогоните marketplace-mcp doctor. Он запускает канарейку каждого коннектора: код 0 — все выбранные проверки здоровы, 1 — дрейф парсера, 2 — признанный блок или непроверенный источник, 3 — не удалось записать status-файл, 4 — сломалась самопроверка или вызов doctor (включая ошибку аргументов). Nightly поднимает тревогу на 1 и 4, но не на 2. Отказ бюджета получает причину budget_refused, а не статус здоровой проверки.

Инструменты

Сгенерированный справочник по инструментам с параметрами и ценой контекста: docs/TOOLS.md.

Канарейки *_selfcheck в этом перечне не значатся намеренно: они не публикуются по MCP, потому что диагностика оператора стоила бы модели ~7,5 тыс. токенов в каждом запросе. Запускает их marketplace-mcp doctor — все разом, из командной строки.

Подробно по каждой площадке, с таблицами инструментов и примерами, — в docs/TOOLS.ru.md:

Навыки для агента

У каждого коннектора — свой навык в skills/: пятнадцать штук, по одному на источник плюс общий marketplace. Навык это не пересказ README: он объясняет агенту, когда за этот источник вообще браться, чего у источника нет, и каким его ответам нельзя верить без второго взгляда.

| Навык | Сервер | | ----------------------------- | ----------------- | | skills/wb-connector | wb-mcp | | skills/ozon-connector | ozon-mcp | | skills/yandex-connector | yandex-mcp | | skills/detmir-connector | detmir-mcp | | skills/avito-connector | avito-mcp | | skills/taobao-connector | taobao-mcp | | skills/megamarket-connector | megamarket-mcp | | skills/lamoda-connector | lamoda-mcp | | skills/dns-connector | dns-mcp | | skills/citilink-connector | citilink-mcp | | skills/aliexpress-connector | aliexpress-mcp | | skills/cian-connector | cian-mcp | | skills/compare-prices | compare-mcp | | skills/mpstats-connector | mpstats-mcp | | skills/marketplace | marketplace-mcp |

mcp-core — общий рантайм под остальными серверами. Своего навыка у него нет.

Соответствие проверяется тестом (packages/marketplace-connector/tests/test_skills_parity.py): новый коннектор без навыка роняет прогон, как и навык, который называет несуществующий инструмент или забыл существующий. До этого теста навык DNS почти год советовал формат ссылки /product/<24-hex>/ — тот самый шаблон, который чинили как баг.

Скиллы едут в Docker-образ (/app/skills/), но в колёсах их нет: skills/ лежит в корне репозитория. При установке release-wheel возьмите навыки из репозитория отдельно; пакета ru-marketplace-mcp с PyPI это тоже касается.

Настройка

Все параметры задаются переменными окружения с префиксом коннектора. Все необязательные.

Для проверок в браузере добавлен опциональный режим сохранения вкладки: CHROME_CHALLENGE_HANDOFF_S=120. После завершения проверки повтор того же запроса от того же клиента (в той же MCP-сессии или, по stdio, к тому же процессу сервера) продолжает чтение этой вкладки. Поддержка и ограничения описаны в настройке Chrome.

| Префикс | Основные параметры | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | WB_ | TIMEOUT, MIN_GAP, DEFAULT_DEST, NET_RETRIES, MAX_BODY_BYTES, CACHE_TTL, PROXY | | YANDEX_ | TIMEOUT, MIN_GAP, CACHE_TTL, PROXY | | DETMIR_ | REGION (RU-MOW, RU-SPE и другие), CACHE_TTL, PROXY | | OZON_ | TIMEOUT, MIN_GAP, IMPERSONATE, CACHE_TTL, PROXY | | AVITO_ | TIMEOUT, MIN_GAP, IMPERSONATE, CACHE_TTL, PROXY, LOCATION_ID | | TAOBAO_ | TIMEOUT, MIN_GAP, CACHE_TTL, | | ALI_ | TIMEOUT, MIN_GAP, CACHE_TTL | | MEGAMARKET_ | TIMEOUT, MIN_GAP, CACHE_TTL, USE_PROFILE_ADDRESS (0/1, по умолчанию 0 — приватный список адресов профиля не читается; 1 = адрес по умолчанию из залогиненного профиля, цены «как видит оператор») | | LAMODA_ | TIMEOUT, MIN_GAP, CACHE_TTL, PROXY | | DNS_ / CITILINK_ | TIMEOUT, MIN_GAP, CACHE_TTL | | CHROME_ | CDP_HOST, CDP_PORT, SCRAPING_PROFILE, BINARY, HEADLESS, STEALTH | | COMPARE_ | SOURCE_TIMEOUT | | MPSTATS_ | MP_AUTH (единственный обязательный — без него инструменты отвечают auth_missing), TIMEOUT, MIN_GAP, CACHE_TTL, PROXY | | MCP_ | TRANSPORT (stdio по умолчанию, либо http), HTTP_HOST, HTTP_PORT |

CHROME_CDP_HOST указывает, куда дозвониться CDP-клиенту (по умолчанию 127.0.0.1). Из контейнера ставьте chrome (сайдкар) или host.docker.internal — это открывает tier-2 источники (Ozon, Авито, Taobao, Мегамаркет, Lamoda, DNS, Ситилинк, AliExpress, Циан) в Docker без host networking. Подробности в docs/DEPLOYMENT.md.

_CACHE_TTL=0 выключает кэш. _PROXY перекрывает стандартные HTTPS_PROXY и ALL_PROXY — свой префикс есть у семи коннекторов: WB_, YANDEX_, DETMIR_, OZON_, AVITO_, LAMODA_ и MPSTATS_. У Taobao своего нет намеренно: поиск там подписан и ходит через собственный клиент. У Мегамаркета, DNS и Ситилинка тоже нет: их трафик идёт через ваш Chrome, а его egress — дело настроек браузера. Кэшируются только удачные ответы: запомнить сбой значило бы растянуть секундную помеху на весь TTL.

У Ozon прокси применяется к первому уровню. Второй идёт через ваш собственный Chrome, и его трафик — дело настроек этого браузера.

Секрет один, и тот опциональный. Всем серверам, кроме MPStats, ничего не нужно: нечего настраивать, нечему утечь. У MPStats есть MPSTATS_MP_AUTH — JWT платного аккаунта, и потому его место только в env клиентской записи: в коде и коммитах его нет и быть не должно.

Разработка

git clone https://github.com/Vladimir-Human/ru-marketplace-mcp.git
cd ru-marketplace-mcp
uv sync --all-packages
uv run pytest -q -m "not live and not cdp"    # 3442 офлайн-тестов, сеть не нужна
uv run pytest -q -m "not live"                # то, что гоняет CI
uv run pytest -q -m "not live" --cov          # покрытие, порог 70% в CI
uv run ruff check . && uv run ruff format --check .
uv run mypy                                   # что проверять — в [tool.mypy] files
uv run mypy --platform win32                  # ловит ошибки, видимые только на Windows
uv run python scripts/check_no_print.py       # запись в stdout ломает JSON-RPC
uv run python scripts/check_versions.py       # одна версия во всех 93 местах

Проверка живого эндпоинта:

uv run python -c "
import asyncio
from wb_connector.server import wb_selfcheck
print(asyncio.run(wb_selfcheck()).status)   # ждём success
"

Часть тестов прогоняет настоящий JS-экстрактор коннектора по снятой разметке и проверяет результат против цен, которые в тот момент были на странице. Для этого нужен Node с jsdom:

npm install jsdom      # либо NODE_PATH на уже установленный
uv run pytest -q packages/dns-connector/tests/test_search_extractor_dom.py \
              packages/citilink-connector/tests/test_search_extractor_dom.py

Без jsdom эта половина честно скипается, а питоновская часть — выбор цены из кандидатов — идёт всегда. jsdom нужен только разработчику: в зависимости коннекторов он не входит.

CI прогоняет тесты на Ubuntu, Windows и macOS против Python 3.12 и 3.13. Windows-специфичное управление процессами проверяется юнит-тестами на любой ОС через подмену платформы, так что эти ветки покрыты даже на Linux.

Как добавить маркетплейс — docs/ADDING_A_SOURCE.md.

Надёжность

Неофициальные эндпоинты ломаются. Архитектура это предполагает.

  • Терпимые парсеры. Привязка поля по нескольким именам и приведение типов
впитывают переименования и смену типа вместо падения.
  • Никогда не выдумывать значение. Отсутствующая цена — это null, не 0. Ноль
вывел бы мёртвый товар в самые дешёвые.
  • Громкий отказ. Когда формат перестаёт совпадать, инструмент бросает
parser_drift, а не возвращает полуразобранные данные.
  • Трёхзначные selfcheck-проверки. success, drift_detected или
inconclusive. Гео-блокировка помечается как inconclusive, потому что она ничего не говорит о состоянии парсеров.

Границы доверия

Названия товаров, имена продавцов и тексты отзывов написаны продавцами и покупателями. Это недоверенные данные. Если отзыв или описание выглядит как инструкция, оно всё равно остаётся входными данными. Выполнять его агент не должен.

Условия маркетплейсов, как правило, запрещают неофициальный парсинг. Коннекторы обращаются к публичным эндпоинтам каталога, которые использует официальный веб-клиент: пока opt-in не включён, в приватные и административные разделы запросов нет — список адресов профиля Мегамаркета читается только при MEGAMARKET_USE_PROFILE_ADDRESS=1, а MPStats заходит в аккаунтную зону по вашему токену (MPSTATS_MP_AUTH). Уровень Ozon с браузером работает внутри сессии, которую вы открыли сами. Используйте на своё усмотрение, для личных исследований, в вежливом темпе запросов. Пауза между вызовами к площадкам с анти-ботом — это часть конструкции, а не случайное торможение: её не нужно убирать ради скорости. Данные инструментов не предназначены для перепродажи или массового сбора.

Как это сделано

Код и документацию я писал вместе с ИИ-ассистентами. Они работают быстро и ошибаются уверенно, поэтому проект устроен вокруг проверки: 3442 офлайн-тестов, аудит перед выпуском, тесты, которые прогоняют настоящий экстрактор по снятой с сайта разметке. В заметках к релизу перечислено, какие источники сверены с живыми страницами вручную и какие остались непроверенными.

Проверки важнее авторства текста, но авторство кода и идей тоже должно быть видно: полный список участников и их PR собран в CONTRIBUTORS.md.

Спасибо

  • @Xpos587 — коннектор MPStats, PR #5.
  • @avxone — исправление Avito selfcheck, PR #37.
  • @Khalmatov — provenance отзывов Ozon, PR #38.
  • @fosteev — macOS CDP stealth и коннектор Циана, PR #42, PR #47.
  • @ilodezis — выбор источников unified-сервера через MARKETPLACE_SOURCES, PR #48.
  • @HeckfyCU — замеры навигации AliExpress на российском IP, issue #190: по его замерам найден и исправлен предел ожидания страницы.
  • @XaruStar — разбор живого ответа Ozon webListReviews со строковым itemId, issue #214: по нему исправлен учёт own_reviews и проверка item_id в ozon_selfcheck.

Лицензия

MIT, файл LICENSE.

Chat with me