README
ru-marketplace-mcp
MCP-серверы для российских и китайских маркетплейсов. Цены, наличие, рейтинги, отзывы и реквизиты продавцов с Wildberries, Ozon, Яндекс Маркета, Детского мира, Авито, AliExpress, Taobao, Мегамаркета, Lamoda, DNS и Ситилинка. Плюс сравнение цен по всем источникам одним вызовом.
Только чтение. Ключи API, токены и регистрация не нужны — площадки с жёстким
анти-ботом читаются через ваш собственный Chrome. Одно исключение по желанию:
опциональный MPStats берёт платный токен (MPSTATS_MP_AUTH) — без него всё
остальное работает как прежде.
English version below · Архитектура · Как добавить источник · Про анти-бот
Что внутри
| Сервер | Инструментов | Что нужно, чтобы читалось | Что умеет |
|---|---|---|---|
| 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 | карточки анонимно (GraphQL), поиск — ваш Chrome | Поиск, карточки с размерами |
| DNS | 2 | ваш Chrome (Qrator) | Поиск и карточки электроники |
| Ситилинк | 2 | ваш Chrome (Qrator) | Поиск и карточки электроники |
| AliExpress | 2 | ваш Chrome (x5sec) | Поиск и карточки, цены в рублях |
| Сравнение | 2 | опрашивает всё перечисленное | «Где дешевле?» одним вызовом |
| MPStats | 2 | платный аккаунт MPStats, cookie mp_auth (опционально) |
Продажи/остатки/графики за 30 дней по SKU Ozon/WB, остатки по складам (FBS/FBO) |
Читается анонимно, без браузера: Wildberries, Яндекс Маркет, Детский мир и
карточки Lamoda. Остальным нужен ваш залогиненный Chrome (CDP). Taobao и
Мегамаркет вдобавок требуют активного входа в саму площадку — без него Taobao
упирается в стену логина, а Мегамаркет отдаёт пустой ответ. Авито ещё и блокирует
по IP: с датацентрового адреса это глухой отказ, с российского домашнего — работает,
если не частить запросами. Запросы к CDP-источникам идут вразрядку: очередь
подряд без пауз роняет их (DNS и Taobao в проверке так и деградировали), поэтому
коннекторы держат паузу между вызовами сами. Точное состояние из вашей сессии
покажет marketplace-mcp doctor.
MPStats стоит особняком: это единственный платный источник. Без
MPSTATS_MP_AUTH сервер запускается, но инструменты отвечают auth_missing —
поэтому он опционален и подключается по желанию, на остальные двенадцать
серверов он не влияет никак.
Всего 35 инструментов в 13 серверах на общем рантайме mcp-core. Плюс объединённый
marketplace-mcp, который монтирует всё разом — одна запись в конфиге клиента
вместо тринадцати. Он добавляет свой инструмент marketplace_sources (какие коннекторы
поднялись, а какие отвалились и почему), так что в нём 36 инструментов: 35
смонтированных плюс этот.
Быстрый старт
Нужны Python 3.12+ и uv.
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" # 1208 офлайн-тестов, сеть не нужна
Проверка живого эндпоинта:
uv run python -c "
import asyncio
from wb_connector.server import wb_selfcheck
print(asyncio.run(wb_selfcheck()).status) # ждём success
"
Подключение к MCP-клиенту
Каждый сервер — консольная команда, поэтому пути в конфиге не зашиваются.
Claude Desktop — claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Проще всего подключить одну запись — объединённый сервер монтирует все
источники разом, а имена инструментов (wb_search, avito_seller, …) не
меняются:
{
"mcpServers": {
"marketplace": {
"command": "uv",
"args": ["run", "--directory", "C:/путь/к/ru-marketplace-mcp", "marketplace-mcp"],
},
},
}
Если нужны отдельные серверы, marketplace-mcp install claude напечатает
готовый блок для вставки. Путь к вашему checkout там уже подставлен: заглушку
/path/to/ru-marketplace-mcp править руками не придётся. При установке из wheel
вместо путей печатаются консольные команды на PATH. Неизвестное имя клиента
(допустимы claude, claude-code, cursor, dsh) команда отклоняет с пояснением и
кодом возврата 2 — молча подставить блок для Claude она не может. Минимальный
вариант вручную:
{
"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.
Claude Code
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, 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 github:Vladimir-Human/ru-marketplace-mcp#path:/dsh
Сразу после установки появляются 14 навыков и ни одного MCP-инструмента: обе
строки MCP выключены, пока не задана переменная RU_MARKETPLACE_MCP_DIR с путём к
клону. Так сделано потому, что смонтированный сервер платится в каждом запросе:
рекомендуемый режим сравнения цен стоит ~0,9 тыс. токенов, полный набор — ~13,6 тыс.
Включение и полный режим описаны в dsh/README.md.
После подключения перезапустите клиент и прогоните marketplace-mcp doctor. Он
запускает канарейку каждого коннектора и отвечает success, drift_detected или
inconclusive.
Инструменты
Канарейки *_selfcheck в этом перечне не значатся намеренно: они не публикуются
по MCP, потому что диагностика оператора стоила бы модели ~7,5 тыс. токенов в
каждом запросе. Запускает их marketplace-mcp doctor — все разом, из командной
строки.
Wildberries — wb_*
| Инструмент | Что делает |
|---|---|
wb_search(query, page) |
Поиск по тексту, до 100 товаров на страницу с ценами и остатками |
wb_card(nm_ids) |
Пакетный запрос до 100 известных SKU |
wb_root_info(nm_id) |
Находит imt_id (нужен для отзывов) и цветовые варианты |
wb_reviews(imt_id, limit, sort) |
Пул отзывов. Ключ — imt_id, а не nm_id |
wb_questions(imt_id, limit, skip, answered_only) |
Вопросы покупателей и ответы продавца. Тоже по imt_id |
wb_seller(supplier_id) |
Юрлицо, ИНН, КПП, ОГРН, юридический адрес |
wb_categories(root, max_depth) |
Дерево каталога с шардами и запросами самого WB |
wb_category_products(shard, query, page, sort, dest) |
Товары категории по shard и query из wb_categories |
wb_seller отвечает на вопрос, который карточка товара скрывает: кто на самом деле
продаёт? Возвращает зарегистрированное юрлицо и налоговые номера. Так отличают
официальный магазин бренда от перекупщика с похожим названием.
wb_questions закрывает другой пробел. Отзывы говорят, каково владеть товаром;
вопросы уточняют, что это вообще за товар — «10 или 16 ампер», «кабель в комплекте?».
Ответ продавца часто единственное публичное утверждение об этом. Пул общий для всех
вариантов товара, ключ — imt_id из wb_root_info.
wb_category_products замыкает связку с wb_categories: та отдаёт shard и query,
это — товары по ним. Формат элементов совпадает с wb_search, поэтому обход категорий
и текстовый поиск сравнимы напрямую. Часть крупных разделов WB помечает шардом
blackhole — у них нет своей выдачи, и инструмент честно об этом говорит вместо
пустого списка.
Яндекс Маркет — yandex_*
| Инструмент | Что делает |
|---|---|
yandex_search(query, page, limit) |
Поиск с обеими ценами, рейтингами, продавцами |
yandex_card(product_id, include_reviews) |
Карточка целиком: разбивка по звёздам и отзывы |
Две цены, всегда. price_rub платит любой покупатель. price_with_plus
требует подписку Яндекс Плюс и обычно на 25–30% ниже. Интерфейс Яндекса показывает
вторую крупным шрифтом, поэтому назвать её без оговорки — значит пообещать цену,
которую человек без подписки не получит.
rating_stars даёт распределение вида {1: 10, 2: 3, 3: 10, 4: 19, 5: 502}. Из
него видно, честная ли средняя 4.8 или за ней прячется кучка единиц.
Детский мир — detmir_*
| Инструмент | Что делает |
|---|---|
detmir_categories(parent, limit, region) |
Дерево каталога. Начинать отсюда |
detmir_category(alias, limit, offset, region) |
Товары категории с настоящим счётчиком |
detmir_card(product_id, region) |
Цена, рейтинг, наличие онлайн и в магазинах |
Регион задаётся на каждый вызов. Цены и особенно наличие в офлайн-магазинах
сильно зависят от города: один и тот же товар лежал в 152 магазинах Москвы, 37
Петербурга и 2 Хабаровска. Параметр region перекрывает DETMIR_REGION, так что
города можно сравнивать в одной сессии.
Текстового поиска здесь нет, и это намеренно. API Детского мира молча игнорирует любые текстовые фильтры и возвращает весь каталог на 300 тысяч позиций, а сайтовый роут поиска отдаёт 404 с промо-карусселью. Инструмент поиска возвращал бы уверенно неверные товары, поэтому навигация идёт через категории. Подробности в docs/ANTI_BOT.md.
Ozon — ozon_*
| Инструмент | Что делает |
|---|---|
ozon_search(query) |
Поиск по тексту |
ozon_card(sku_or_path) |
Карточка товара |
ozon_reviews(sku_or_path, limit, sort) |
Отзывы |
Ozon отклоняет датацентровый трафик, поэтому коннектор двухуровневый. Сначала TLS-имперсонация. Если Cloudflare выдаёт челлендж, запрос выполняется внутри вашего залогиненного Chrome через DevTools Protocol. Ничего не хранится: вход выполняете вы сами, в браузере, который контролируете. Настройка описана в docs/CDP_SETUP.md.
С российского домашнего IP первый уровень обычно работает, и браузер не нужен.
Авито — avito_*
| Инструмент | Что делает |
|---|---|
avito_search(query, page, location_id, category_id) |
Поиск объявлений через внутренний js/items API |
avito_card(item_id_or_url) |
Одно объявление: цена, описание, просмотры, продавец |
avito_seller(seller_id_or_url) |
Рейтинг продавца, число отзывов, активные объявления |
Авито — это объявления, а не каталог: пула отзывов на товар нет, репутация
продавца и есть сигнал доверия. Бесплатное/обменное объявление приходит с
price_rub: null — никогда не 0, чтобы не оказаться «самым дешёвым» в
сравнении. С датацентрового IP Авито отвечает 403-файрволом, поэтому коннектор
двухуровневый: TLS-имперсонация, дальше ваш Chrome (как у Ozon).
Taobao — taobao_*
| Инструмент | Что делает |
|---|---|
taobao_search(query, page) |
Поиск по каталогу Taobao |
taobao_card(item_id_or_url) |
Карточка товара |
Поиск Taobao — клиентское React-приложение с подписанным mtop API: каждый запрос
требует sign, вычисленный из cookie-токена, поэтому анонимного пути нет.
Все чтения идут внутри вашего Chrome, где сайт сам подписывает запросы. Цены в
юанях (CNY) и не конвертируются: зашитый курс молча устарел бы, так что
сравнение с рублёвыми источниками делайте явно.
Мегамаркет, Lamoda, DNS, Ситилинк
Эти четыре читаются через ваш Chrome (CDP). Мегамаркет (megamarket_*) — мобильный
JSON API из-за ServicePipe, и одного пройденного челленджа мало: анонимной сессии
API отдаёт пустой список, нужен активный вход в Мегамаркет. DNS (dns_*) и Ситилинк
(citilink_*) — отрисованный DOM из-за Qrator; у всех трёх анонимного пути нет вообще.
Lamoda (lamoda_*) наполовину: карточки берутся анонимно через GraphQL, а поиск —
через Chrome. Chrome с CDP (scripts/start_chrome_cdp.sh) нужен всем, кроме карточек
Lamoda.
Всего через CDP ходят восемь источников — эти плюс Taobao, AliExpress, Ozon и
Авито, где Chrome лишь
запасной уровень: их tier 1 обычно отвечает, а браузер включается, когда анонимный
уровень упёрся в челлендж. marketplace-mcp doctor из вашего браузера скажет, какие
эндпоинты подтверждены.
AliExpress — aliexpress_*
| Инструмент | Что делает |
|---|---|
aliexpress_search(query) |
Поиск: до 48 карточек с ценами в рублях |
aliexpress_card(item_id_or_url) |
Карточка: цена, рейтинг, число заказов |
Читается через ваш Chrome (CDP): x5sec ставит капчу анонимным клиентам, поэтому
коннектор садится на страницу поиска (её не челленджат) и открывает карточку
новой вкладкой из неё. Цены в рублях и участвуют в compare_prices. Карточка с
названием, но без цены — известное состояние: под нагрузкой x5sec перестаёт
отдавать ценовой модуль, коннектор пишет price_missing, а не выдумывает число.
Цена «N ₽ с купоном» в price_rub не публикуется: там обычная цена, про купон
коннектор честно предупреждает отдельно. Тексты отзывов не отдаются: только
рейтинг и число заказов. Как и у остальных CDP-источников, зелёный
aliexpress_selfcheck доказывает, что транспорт ответил, — не то, что цена
верна.
Сравнение цен — compare_*
| Инструмент | Что делает |
|---|---|
compare_prices(query, per_source_limit, sources) |
Все маркетплейсы сразу, с ранжированием |
compare_sources() |
Какие маркетплейсы доступны в этой установке |
compare_prices("кроссовки мужские")
wildberries 712 ₽ Кроссовки изи дышащие спортивные
wildberries 814 ₽ Зимние кроссовки теплые с мехом
yandex_market 2499 ₽ Кеды A-LOW
yandex_market 3480 ₽ Кеды
дешевле всего: wildberries 712 ₽, разброс 5858 ₽, complete: true
Маркетплейсы опрашиваются параллельно, и каждый отчитывается сам за себя. Если один
заблокирован, сравнение не рушится: complete: false вместе с source_outcomes
покажет, что именно вы видите. Подписочные цены в ранжировании не участвуют.
Совпадающие предложения по паре (источник, id товара) схлопываются, так что один
и тот же товар не занимает два места в ранжировании.
У каждого предложения есть currency (строчный ISO-код, по умолчанию rub) и
price_native — цена в этой валюте, как её показывает маркетплейс. Для российских
источников она совпадает с price_rub; у Taobao в ней лежит цена в юанях, которую
price_rub намеренно оставляет пустой. Раньше юаневую цену забирали и молча
выбрасывали, и строка Taobao приходила с пустой ценой без намёка, что цена вообще
есть. Теперь юань виден, но в рублёвом ранжировании по-прежнему не участвует: в
warnings появляется foreign_currency: … с числом исключённых предложений и
причиной. Конвертировать здесь значило бы зашить курс, который молча устареет, —
пересчёт за вами.
MPStats — mpstats_*
Аналитика продаж и остатков по SKU Ozon и Wildberries через плагин MPStats.
В отличие от всех остальных коннекторов, этот опционален и требует платный
аккаунт MPStats: авторизация — одна cookie mp_auth (JWT из залогиненной
сессии плагина на mpstats.io), задаётся переменной MPSTATS_MP_AUTH. Без неё
инструменты возвращают auth_missing, а сервер запускается как обычно — ни на
что другое это не влияет.
| Инструмент | Что делает |
|---|---|
mpstats_item(skus, place, oz_fbs=True) |
Аналитика за 30 дней по до 100 SKU: заказы, цена, остатки, графики по дням, продавец/бренд |
mpstats_warehouses(skus, place) |
Остатки по складам: FBS (склад продавца) и FBO (склад маркетплейса), last_update |
place — ozon или wildberries. Графики длиной 30, от старых к новым:
последняя ненулевая ячейка — текущая цена или остаток. Цена и остаток при
сплошь нулевом графике ведут себя намеренно по-разному: цена становится None
(ложный 0 выиграл бы любое сравнение «где дешевле»), а остаток — 0, потому
что «нулевой остаток» это осмысленное показание, а не отсутствие данных. Пустой
график даёт None в обоих случаях. Ноль в отдельной ячейке — «нет данных за тот
день», а не «значение было нулевым», поэтому сумму за окно считайте по графику. Отсутствие
токена и транспортные сбои selfcheck отчитывает как inconclusive, не drift:
гоняться за дрейфом схемы, которого не было, не нужно. Токен — секрет платного
аккаунта с квотой: не логируйте и не коммитьте его.
Навыки для агента
У каждого коннектора — свой навык в 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/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/
лежит в корне репозитория. Ставите с PyPI — возьмите навыки
из репозитория отдельно.
Настройка
Все параметры задаются переменными окружения с префиксом коннектора. Все необязательные.
更多「知识与研究」插件
mirage
作者 strukto-ai
全球首个面向 AI 智能体的统一虚拟文件系统。
graph-memory
作者 adoresever
Deepseek Harness、Openclaw知识图谱记忆插件。2026年4月受邀发布在清华大学讨论会。Knowledge Graph + Memory;Knowledge Graph Context Engine for OpenClaw — extracts structured triples from conversations, compresses context 75%, enables cross-session experience reuse
memtrace-public
作者 syncable-dev
面向编码智能体的结构化记忆,双时态图、MCP 原生、零 LLM 调用,支持多款主流编码工具。
anolisa
作者 alibaba
阿里巴巴开源的 Agentic OS,提供运行时、安全、可观测性,并通过无 Token 响应压缩降低用量与成本。
