Skip to main content
Glama
Eduardo-Orsi

yampi-mcp

by Eduardo-Orsi

MCP-сервер, который позволяет общаться с вашим магазином Yampi через Claude — просматривать заказы, создавать товары, корректировать остатки, создавать купоны и предложения.

Каждый продавец размещает собственную копию на Cloudflare. Это не сервис: никто, кроме вас, не держит ваши учётные данные. Неофициальный проект, не связан с Yampi.

Как это работает

Учётные данные Yampi принадлежат пользователю, а не магазину: если под одним логином работают четыре магазина, отображаются все четыре. Вы подключаетесь один раз и выбираете магазин в каждой команде.

Related MCP server: MCP Shopify

Настройка

Вам понадобится аккаунт Cloudflare (бесплатного тарифа достаточно) и установленный Node.

git clone https://github.com/Eduardo-Orsi/yampi-mcp && cd yampi-mcp
npm install
cp wrangler.example.jsonc wrangler.jsonc
npx wrangler kv namespace create OAUTH_KV   # paste the returned id into wrangler.jsonc
npx wrangler deploy

В вашем клиенте Claude (claude.ai, Desktop или Code) добавьте пользовательский коннектор, указав https://yampi-mcp.<ваш-поддомен>.workers.dev/mcp.

При подключении на экране появится запрос на ввод User-Token и User-Secret-Key. Вы найдёте их в панели Yampi в разделе Perfil › Credenciais de API (Профиль › Учётные данные API). Вот и всё — создавать пароль не нужно.

Использование

После подключения это просто разговор:

«Сколько оплаченных заказов получил магазин X с 1 по 15 июня?» «Создай товар Black T-Shirt, бренд Acme, SKU TS-BLACK-M, 79,90 R$, 20 в наличии.» «У SKU TS-BLACK-M неправильная цена — измени её на 89,90 R$ и уменьши остаток до 5.» «Какие корзины были брошены на этой неделе и на какую сумму?» «Создай купон на 15% со сроком действия до конца месяца, минимальная сумма 100 R$, 50 использований.»

Если в аккаунте несколько магазинов, укажите, какой именно — инструменты требуют этого явно, чтобы ничего не записалось не в тот магазин.

Что он умеет

Инструмент

Что делает

describe_store

Магазины, статусы заказов, категории и бренды — карта, чтобы модель перестала угадывать id

search_orders

Заказы с фильтром по статусу, периоду и свободному тексту

get_order

Один заказ с товарами, покупателем, платежами, адресом и историей

search_products

Каталог с SKU, ценами и изображениями

get_product

Один товар с вариациями, остатками, брендом и категориями

search_customers

Покупатели и адреса

customer_history

Покупатель и все его заказы

abandoned_carts

Корзины, которые так и не стали заказами

create_product

Создаёт товар с его SKU

update_product

Редактирует поля товара

manage_sku

Создаёт SKU или обновляет цену и остаток

create_coupon

Купон на скидку

advance_order_status ⚠️

Переводит заказ в другой статус

add_order_comment ⚠️

Внутренняя заметка на заказе

manage_offers

Кэшбэк, допродажа при заказе, апселл и бесплатный подарок

⚠️ Не проверено на живом API. Остальные тринадцать были прогнаны от начала до конца на реальном магазине — создание товара, изменение цены, запись остатка, выпуск купона — и названия полей были исправлены по итогам этого процесса. Этим двум нужен существующий заказ, а в тестовом магазине их не было. Эндпоинты верны; тело запроса взято из документации, которая, как выяснилось, пропускает как минимум одно обязательное поле в каждой из остальных пяти операций записи. Ожидайте 422 при первом вызове — в сообщении будет указано недостающее поле.

Что он намеренно не делает

Он не отменяет заказы, не возвращает платежи и не переключает платёжные шлюзы. Это не функция, спрятанная за переменной окружения: такого кода просто нет. Это необратимые операции в API, и ни Claude Desktop, ни claude.ai не поддерживают elicitation — то есть у сервера нет способа по-настоящему запросить подтверждение. Отсутствие — единственная гарантия, которая не зависит от чьего-то внимания.

Запрет реализован в двух местах, оба покрыты тестами: на алиасе статуса (tools/write.ts) и на стыке, через который проходит каждый запрос (yampi.ts). Обоснование в docs/adr/0002.

Отслеживание заказов тоже исключено: Yampi ограничивает этот маршрут 3 запросами в час, что делает инструмент бесполезным на практике — два вызова, и агент застрял на 20 минут.

Ваши учётные данные

  • Хранятся в зашифрованном виде (AES-GCM) в свойствах OAuth-гранта, внутри вашего KV.

  • Ключ, шифрующий их, обёрнут ключом, производным от токена доступа, а в KV хранится только хэш токена. Утечка KV сама по себе не открывает учётные данные.

  • Claude их никогда не получает: он видит только непрозрачный токен.

  • Отзыв означает удаление гранта — остальные подключения продолжают работать.

/authorize публичен и проверяет учётные данные, что технически делает его оракулом для проверки украденных ключей. Отсюда ограничение в 5 попыток с одного IP в минуту.

Чтобы ограничить экземпляр конкретными магазинами:

npx wrangler secret put ALLOWED_STORES   # e.g. my-store,other-store

Лимиты API

Yampi ограничивает каждый маршрут в минуту: 30 запросов/мин по товарам и SKU, 120 по чтению заказов, 30 по записи, 60 в целом. Сервер использует include=, чтобы подтягивать связи одним вызовом вместо N+1, читает X-RateLimit-Remaining из каждого ответа и предупреждает модель, когда квота заканчивается — вместо того чтобы она узнала об этом через 429.

Когда что-то идёт не так

403 на всё, включая чтение. Магазин имеет active: false в панели Yampi. Неактивные магазины отклоняют все маршруты. Реактивируйте его, затем переподключите коннектор.

422 при записи. В сообщении указано точное поле, которое отклонил Yampi — сервер пересылает весь объект errors. Обычно Claude исправляется при следующей попытке.

«Grant without credential» (Грант без учётных данных). Грант потерял свои свойства. Удалите коннектор и добавьте его заново.

Смена учётных данных. Просто переподключитесь: новый грант заменяет старый. Чтобы отозвать доступ без переподключения, удалите пространство имён KV.

Магазин отсутствует в списке. Либо он неактивен, либо учётные данные до него не достают. Запустите describe_store, чтобы увидеть, что видит сервер.

Причуды API Yampi

Обнаружены при тестировании на живом API. Все они могут сжечь часы, и ни одна не очевидна из документации:

  • Фильтры требуют синтаксис массива. ?status_id=4 молча игнорируется и возвращает весь набор данных; ?status_id[]=4 фильтрует. То же самое с active[]. Фильтр, который не фильтрует, хуже, чем отсутствие фильтра: агент обобщает 55 000 заказов, полагая, что видел июльские.

  • Даты используют особый формат: ?date=created_at:2026-06-01|2026-06-30. Всё остальное возвращает 500 или игнорируется.

  • filters[...] не фильтрует. Он лишь переключает ответ на пагинацию через scroll_id.

  • /auth/me — это POST, а не GET, и возвращает все магазины по учётным данным — потому что учётные данные принадлежат пользователю, а не магазину.

  • У include для заказов закрытый перечень: items, customer, marketplace, status, statuses, shipping_address, promocode, transactions, comments, files, discounts, seller, labels. payments там нет.

  • GET-ответы кэшируются на 30 минут на стороне Yampi. В контексте агента это ложь: создайте товар, попросите прочитать его — и получите прежнее состояние. Этот сервер отправляет ?skipCache=true при каждом чтении.

  • Остаток — это не поле SKU. quantity у SKU всегда null — включая реальные SKU живого магазина. Остаток живёт в /logistics/stocks (складская позиция), присоединённый к SKU через /catalog/skus/{id}/stocks. А stock_id — это не id из /logistics/warehouses, это совершенно другой ресурс.

  • discount_type купона принимает только p или v, а не percentage/fixed.

  • Даты купона требуют формат Y-m-d H:i:s. Только дата возвращает 422.

  • PUT /catalog/skus/{id} требует product_id и price_cost даже для частичного обновления.

  • Создание товара требует simple, brand_id и skus.*.blocked_sale — ни одно из них не очевидно.

  • Магазин с active: false возвращает 403 на всё, включая чтение. Этот сервер отфильтровывает такие магазины при подключении, поэтому модель никогда не получает вариант, который может только провалиться.

  • Ответы 422 содержат объект errors, указывающий точное поле, которое не прошло. Его стоит пересылать модели вместо показа только кода статуса — именно это позволяет ей исправиться.

Разработка

npm test              # 32 unit tests, no network
npm run typecheck
npm run dev           # wrangler dev

Тестирование на собственном магазине

Модульный набор тестов использует фейковый fetch и доказывает логику сервера. Он не может заметить, что Yampi изменил эндпоинт, имя поля или синтаксис фильтра — а это происходило неоднократно при создании проекта. Вторую половину покрывает интеграционный набор тестов, который обращается к живому API, только на чтение, ничего не создавая и не меняя:

cp .env.example .env    # fill in the alias and credentials of YOUR store
npm run test:integration

Он проверяет, что обнаружение магазинов работает, что алиасы статусов существуют, что фильтрация по статусу действительно фильтрует, что формат даты принимается, что include разворачивает связи и что заголовки квоты приходят. Если один тест падает — API изменился, и сервер начнёт врать раньше, чем ломаться.

В архитектуре одно правило: ни один инструмент не говорит по HTTP. Всё проходит через src/yampi.ts. Именно это делает обещание «не обращается к запрещённым маршрутам» проверяемым — вся поверхность умещается в одном файле.

Словарь проекта в CONTEXT.md. Решения в docs/adr/.

Известные ограничения

  • Нет отслеживания заказов (лимит Yampi в 3 запроса/ч делает его непригодным).

  • Нет баннеров, правил бесплатной доставки, прогрессивных скидок или комбо.

  • advance_order_status и add_order_comment никогда не запускались на живом API.

  • Остаток записывается в первую зарегистрированную складскую позицию магазина. Тем, кто использует несколько позиций, нужно поправить defaultStockId() в src/tools/write.ts.

Участие в разработке

Pull request'ы приветствуются. Сделайте форк, откройте PR в main, и CI прогонит проверку типов и модульные тесты. Для чего-то большего, чем исправление бага, сначала откройте issue.

Одно не будет влито независимо от качества патча: всё, что отменяет заказ, возвращает платёж или переключает платёжный шлюз, включая косвенные пути. Это отсутствие и есть смысл проекта — обоснование в ADR 0002.

Подробности в CONTRIBUTING.md. Нашли проблему безопасности? Не открывайте публичный issue — см. SECURITY.md.

Лицензия

MIT — см. LICENSE.

Логотип Yampi в assets/ является товарным знаком Yampi и используется здесь только для идентификации платформы, с которой взаимодействует этот сервер. Он не подпадает под лицензию MIT, и данный проект не аффилирован с Yampi и не одобрен ею.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive MCP server for Shopify Admin API integration, enabling AI assistants to manage products, orders, customers, inventory, analytics, and more through natural language.
    20 npm
    19
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that integrates with the FacturaScripts ERP system, providing resources and tools to manage clients, products, invoices, accounting entries, and business analytics through natural language.
    10
    -
  • A
    license
    B
    quality
    A
    maintenance
    Servidor MCP para integrar la plataforma CLI MARKET con asistentes de IA. Permite gestionar productos, pedidos, clientes e inventario de tu tienda marketplace mediante lenguaje natural.
    32
    1
    MIT