Skip to main content
Glama

Демонстрация Shopify MCP

Совершайте покупки в живом магазине Shopify изнутри ChatGPT или Claude и платите через Cashfree — каталог, корзина, вход по OTP, сохранённые адреса и оплата, не покидая разговор.

"show me shirts from the store"
      ↓  SearchProducts
  product grid  ⇄  product detail
        └────────┬───────┘
                 ↓
  cart  →  phone  →  OTP  →  address  →  payment
                                            ↓
                            Cashfree  →  order summary

Каждый путь оплаты заканчивается на одном и том же экране: что было куплено, с количеством и ценами, плюс идентификатор заказа и статус. Cashfree подтверждает, что деньги переместились, но он никогда не видел корзину Shopify и поэтому не может сказать, что в ней было.

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

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

Сервер выполняет три роли одновременно:

  • MCP-сервер для AI-хоста, предоставляющий один инструмент для модели (SearchProducts) плюс ресурс виджета

  • MCP-клиент для Shopify, общающийся через JSON-RPC к https://{SHOP_DOMAIN}/api/ucp/mcpбез аутентификации, домен магазина является всей конфигурацией

  • REST-клиент для Cashfree, для создания заказов, входа по OTP, сохранённых адресов и статуса заказа

React-виджет управляет всем процессом. Только поиск товаров доходит до модели; всё остальное — это взаимодействие виджета с сервером, что делает поток детерминированным.

Просмотр состоит из двух экранов. Сетка показывает одну карточку на товар с диапазоном цен и количеством опций; нажатие открывает детальный экран с описанием, выбором варианта и кнопкой «Добавить в корзину». Товар с одним вариантом можно добавить прямо с его карточки, а товар, уже находящийся в корзине, получает там степпер количества — так что обычные случаи требуют одного нажатия, и только действительно сложный выбор требует отдельного экрана. На обоих экранах отображается значок товаров, уже находящихся в корзине, и оба числа берутся из одной функции.

Related MCP server: Shopify Agentic MCP Gateway

Настройка

npm install
cp .env.example .env      # set SHOP_DOMAIN and the Cashfree keys
npm run build
npm start

Откройте доступ (ngrok http 8787), установите SERVER_URL в .env как публичный источник, перезапустите, затем добавьте <публичный-источник>/mcp как коннектор в вашем хосте.

Перезапуска достаточно — пересборка не требуется. Источник считывается при запуске и встраивается в HTML виджета каждый раз при обслуживании ресурса.

Переменная

Назначение

SHOP_DOMAIN

Магазин. Смените магазин, отредактировав эту строку и перезапустив.

UCP_AGENT_PROFILE

Требуется при каждом вызове UCP. Публичный пример профиля Shopify подходит для демонстрации.

CASHFREE_ENV

sandbox (по умолчанию) или production.

CASHFREE_CLIENT_ID / CASHFREE_CLIENT_SECRET

Панель управления → Разработчики → Ключи API.

CASHFREE_RETURN_URL

Куда Cashfree возвращает покупателя. По умолчанию — стабильная хостинговая страница.

SERVER_URL

Публичный источник при туннелировании.

PORT

По умолчанию 8787.

PAYMENT_ANNOTATIONS

honest (по умолчанию) или readonly. Измените в .env и перезапустите, чтобы протестировать оба пути отправки. readonly заставляет платёжные инструменты утверждать, что они только для чтения, чтобы хост их отправлял — только для диагностики, см. выше. Переменная оболочки переопределяет файл, так как --env-file не переопределяет уже установленную переменную окружения.

Чего ожидать при запуске

Оплата работает, кроме сохранённых карт. Хост ограничивает платёжные инструменты на основе их MCP-аннотаций. cashfree-here предоставляет честные — { readOnlyHint: false, destructiveHint: true } для инструмента, который списывает деньги с карты — и в ответ на них хост отказывается отправлять: модель формирует намерение, хост предварительно загружает шаблон виджета инструмента, и tools/call никогда не поступает.

Установка PAYMENT_ANNOTATIONS=readonly переопределяет их на { readOnlyHint: true, destructiveHint: false }, и четыре из пяти инструментов отправляются: UPI, интернет-банкинг, хостинговый чек, новая карта — и, как только приходит передача, сохранённая карта тоже.

Этот флаг — измерение, а не исправление. Он заставляет инструмент, перемещающий деньги, утверждать, что он ничего не делает, что является ложью для того самого контроля, который существует для её выявления. По умолчанию он выключен, выводит предупреждение при первом использовании и не должен поставляться в производство.

Когда инструмент заблокирован, виджет сообщает об этом и предлагает ссылку Cashfree, которая работает. Оплатите во вкладке, вернитесь, и виджет подтвердит заказ.

Передача происходит поздно, а не теряется — и «заблокировано» может быть неверным. Ранее в этом файле говорилось, что передача от виджета к модели терялась примерно в половине случаев. Одна записанная сессия говорит об обратном: CheckoutTool был объявлен заблокированным после двух попыток виджета (2 × 4 с), покупатель перешёл по ссылке Cashfree, а затем tools/call всё равно поступил — примерно через 2–4 с после клика, то есть где-то через 12–20 с от начала до конца. Сервер обработал его за 37 мс. Каждая миллисекунда этой задержки была на стороне вышестоящей системы.

sendFollowUpMessage не просит хост запустить инструмент. Он отправляет сообщение пользователя и завершается, как только это сообщение доставлено, поэтому окно подтверждения виджета начинается в момент постановки в очередь, а затем измеряет полный цикл вывода модели на инфраструктуре хоста — для которого тайм-аут в 4 с никогда не был откалиброван.

Последствие хуже, чем медленный экран: покупатель платил по внешней ссылке, в то время как виджет Cashfree для того же payment_session_id отображался позади него. Два активных платёжных интерфейса для одного заказа. DISPATCH_ATTEMPTS = 2 отправляет последующее сообщение дважды, так что возможно и два виджета.

Чтение «теряется в половине случаев» было нашей собственной ошибкой. Два экземпляра App открывались на одном канале postMessage, который предоставляет транспорт MCP Apps: useMcpApp создавал и подключал один для рендеринга, getClientPlatform() создавал и подключал другой для передачи платежа. Рукопожатия соревновались, и тот, который проигрывал, затем отвечал «Не подключено» на всё последующее — покупатель выбирал способ оплаты, и tools/call никогда не достигал сервера. Передача, подобная подбрасыванию монеты, это то, как выглядит двусторонняя гонка, а не ненадёжный хост. Теперь хук подписывается на общий клиент, connect() идемпотентен, и размонтирование больше не вызывает close() на синглтоне, который переживает дерево React.

После этого исправления все передачи срабатывают с первой попытки. attemptsFor() уже возвращает 1 на хостах MCP Apps, поэтому повтор применяется только к ChatGPT, который использует LegacyOpenAiClient и никогда не имел этой гонки — нет измерений, оправдывающих его удаление, поэтому он остаётся.

UPI не работает для сумм выше ₹1,00,000 с сообщением «способ оплаты не подходит для этого заказа» — лимит на транзакцию UPI, подтверждённый бисекцией при ₹99,600 (ок) / ₹100,800 (ошибка). Интернет-банкинг и хостинговый чек имеют более высокие лимиты. У корзины нет ограничения, поэтому несколько нажатий на + могут незаметно превысить его без предупреждения.

Перезагрузка окна хоста безопасна в обоих хостах. Корзина, этап оформления заказа, сохранённые адреса и экран оплаты восстанавливаются; содержимое корзины восстанавливается из сохранённого состояния, а не перезапрашивается, поэтому перезагрузка не требует вызовов Shopify вообще в Claude. ChatGPT не доставляет повторно результат инструмента, поэтому для восстановления сетки товаров требуется один вызов search_catalog и ничего больше. Измерено на четырёх потоках с перезагрузками на нескольких этапах: 18 вышестоящих вызовов, ни один из которых не является повторным.

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

Пересборка не достигает браузера, как и новый чат. URI виджета содержит идентификатор сборки, так что каждая сборка является отдельным ресурсом, и этого всё равно недостаточно: Claude обслуживал кэшированный виджет между пересборками и новыми разговорами, без единого resources/read в логе. Два раунда отладки ушли на инструментарий, который никогда не выполнялся. Единственный надёжный способ принудительно выполнить повторное чтение — отключить и снова подключить коннектор. Проверьте наличие POST /mcp (resources/read ui://widget/shopify-store-<build>.html) в логе, прежде чем доверять чему-либо, что вы видите.

Повторное подключение всё ещё не даёт полной картины: кэшированные метаданные инструментов хоста могут содержать URI из более ранней сборки, поэтому даже новый разговор может запрашивать идентификатор сборки, которого у этого сервера больше нет. Он отвечает за любую из них — см. «Версионирование URI виджета удаляет его старую версию» ниже — но идентификатор в строке resources/read принадлежит хосту, а не обязательно работающему серверу. window.__BUILD__ на экране оплаты говорит вам, какой пакет выполняется.

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

  • Ввод данных карты не отображается в Claude и не будет исправлен вышестоящей стороной. Cashfree Elements монтирует свои PCI-поля как вложенные кросс-доменные iframe. Claude применяет политику frame-src 'self' blob: data: и игнорирует frameDomains, объявленные ресурсом UI, поэтому поля загружаются как пустые, некликабельные блоки. Это политика, а не ошибка в транзите: инженер Anthropic заявил 09.04.2026 в claude-ai-mcp#40, что вложенные iframe не разрешены по соображениям безопасности, и два последующих вопроса «навсегда или временно?» остались без ответа. connectDomains и resourceDomains были исправлены в апреле и работают — заблокирован только фрейминг, поэтому fetch из виджета на этот сервер работает нормально.

    Stripe столкнулся с той же проблемой: их документация MCP Apps открывает размещенную страницу Checkout с помощью app.openLink(), а не встраивает поля карты. Это та же форма, что и CheckoutTool здесь, который работает сегодня и является рекомендуемым путем для карт в Claude.

    Сохранение ввода карты в диалоге возможно — обычные поля <input> (без iframe), отправляющие данные напрямую на этот сервер, что и было в cashfree-here до коммита 55da139, заменившего их на Elements. Это пропускает сырые PAN через наш сервер (территория SAQ-D), и 3DS все равно перенаправляет наружу, так что это дает форму, но не поток. Не реализовано; это продуктовое решение, а не техническое.

  • Оплата сохраненной картой не проходит внутри Cashfree. CardPaymentTool отправляет и отображает сохраненные карты корректно, но оплата одной из них возвращает HTTP 500 {"message":"Internal Server Error"} от /pg/orders/sessions/js. Изолировано на одном заказе: UPI и интернет-банкинг возвращают 200 с теми же payment_session_id и заголовками; только ветка payment_method.card.instrument_id выдает 500, с CVV или без. Общая ошибка 500 — это ошибка на стороне Cashfree — их ошибки валидации приходят как 400 с конкретными сообщениями. Нужно обращаться в Cashfree.

  • UPI предлагается сверх своего лимита в ₹1,00,000 и не отключается в выборе, а падает на стороне Cashfree.

  • cashfree-here пропатчен на месте. Два исправления находятся в соседнем checkout, а не в этом репозитории: useReconciliation.start() теперь очищает предыдущий таймер опроса, а уведомление об успешной оплате срабатывает один раз на заказ. Без них уведомление «Оплата прошла успешно» отправлялось в чат каждые несколько секунд бесконечно.

  • Выбранный адрес не привязан к заказу. Покупатель выбирает его, но Cashfree об этом не сообщается. Не решено; нужен ответ от команды OCC.

  • Заказ в Shopify не создается. Заказ существует только в Cashfree. Для создания требуется API-ключ Shopify Admin, которого этот проект намеренно избегает.

  • Хранилище сессий находится в памяти. Перезапуск сервера приводит к потере незавершенного оформления заказа.

  • Предложения и купоны отложены. Оба API проверены и задокументированы в docs/cashfree-occ-api.md; отсутствует только UI.

  • Только INR, соответствует демо-магазинам.

Заметки для тех, кто расширяет это

Выводы, на установление которых ушло реальное время. Каждый проверен, а не предположен.

Shopify

  • Цельтесь только в /api/ucp/mcp. Старый /api/mcp устарел после 31.08.2026, о чем сообщается в каждом ответе.

  • Опубликованная документация неверна в трех местах: в ней перепутано разделение конечных точек каталога/корзины, а строки корзины задокументированы как merchandise_id, когда UCP требует line_items[].item.id. Типы здесь взяты из захваченных полезных нагрузок в src/lib/ucp/__fixtures__/, а не из документации.

  • update_cart является декларативным — каждый раз отправляйте полный желаемый набор строк; удаление выражается пропуском строки.

  • Деньги указываются в младших единицах, валюта хранится один раз на уровне корзины. formatMoney берет количество десятичных знаков из Intl, поэтому валюты с нулевым десятичным знаком не делятся.

  • Магазин, защищенный паролем, все равно отображает ссылки на каталог, корзину и оформление заказа. Только просмотр витрины приводит на страницу ввода пароля.

  • search_catalog возвращает описания товаров в формате HTML, а варианты несут свои оси как options: [{ name, label }]. Описание преобразуется в обычный текст в normalise.ts до того, как попадет в React: это контент, управляемый магазином, отображаемый на том же экране, где собирается OTP, и никакое форматирование в нем не стоит поверхности для инъекций.

  • У товара с одним вариантом все равно есть одна опция — заполнитель Shopify { name: "Title", label: "Default Title" }. Его отображение показывает «1 название» под товаром, у которого нет выбора.

Cashfree

  • x-chxs-id это payment_session_id из Create Order. Это заставляет заказ существовать до входа в систему. Поддельный возвращает payment_session_id_invalid.

  • Вызовы OCC требуют ровно три заголовка. Никакие данные браузерной идентификации из захваченных запросов — идентификаторы устройств, токен Forter, куки, источник — не применяются.

  • Адреса требуют объединенной строки адреса длиной 10–185 символов. Более короткая строка возвращает 400 без каких-либо подсказок в UI, если вы специально это не проверите.

  • Ответ на создание адреса — это { shipping_address, billing_address }, а не список. При разборе как списка при успехе возвращается пустой массив.

  • /api/orders/:id проксирует сырое тело Cashfree, потому что сверка cashfree-here разбирает именно эту структуру.

Виджет

  • Карточка — это товар; строка корзины — это вариант, и они не совпадают. Объединение трех цветов одной футболки в одну карточку правильно для просмотра и неоднозначно для степпера — минус под карточкой, содержащей один Красный и один Синий, должен угадать, какой убрать. Карточка подсчитывает, сколько вариантов товара находится в корзине, и предлагает степпер только тогда, когда ответ ровно один; в противном случае она показывает общее количество значком и отправляет покупателя на экран деталей. Отказ дешевле, чем удаление того, что он не выбирал.

  • Экран деталей не хранит собственного состояния. Выбранный товар и вариант хранятся в состоянии виджета, потому что виджет перемонтируется при прокрутке покупателем (см. ниже), и локальный useState потерял бы выбор вместе с ним. Они очищаются при новом searchId, иначе товар из предыдущего поиска снова открылся бы поверх новых результатов.

Этот хост

  • Проверьте Access-Control-Allow-Headers прежде чем винить платформу.
    Ранее в этом файле утверждалось, что GET-запросы из iframe виджета никогда не достигают сервера. На самом деле они достигают. cashfree-here отправляет ngrok-skip-browser-warning в своем GET-запросе сверки, что делает запрос предварительным (preflighted); наш список разрешенных заголовков не содержал этого заголовка, поэтому браузер отклонил предварительный запрос, и GET так и не был отправлен. Затем сверка сообщала "Unable to verify payment status" и показывала Payment Failed для заказов, которые уже были ОПЛАЧЕНЫ.

    Два фактора создавали иллюзию блокировки платформой: ни один GET-запрос не появлялся в логе, а предварительные запросы отфильтровывались из лога как шум — поэтому отклоненный запрос и запрос, который никогда не был отправлен, были неразличимы. Теперь предварительные запросы на /api/* логируются.

    Эндпоинты, работающие только с POST (/api/pay/addresses/list, /api/orders/status), были созданы на основе этого ошибочного диагноза. Они работают, но не являются необходимыми.

  • Только вызов инструмента, инициированный моделью, заставляет хост отображать outputTemplate этого инструмента. callTool запускает обработчик, но ничего не отображает.

  • window.open блокируется в iframe виджета, а внешнее открытие хоста уводило навигацию и убивало MCP-соединение в середине платежа. Обычный <a target="_blank"> — единственное, что работает.

  • MCP-транспорт не имеет состояния (sessionIdGenerator: undefined). Выдача идентификаторов сессий при создании нового сервера для каждого запроса приводит к тому, что все после initialize завершается ошибкой "Server not initialized".

  • Состояние виджета переживает сам виджет, поэтому каждый результат инструмента должен быть датирован.
    Хост хранит состояние для всего диалога и восстанавливает каждый новый виджет из него. Поиск после оплаты, следовательно, просыпался с screen: "checkout" и отвечал на "покажи рубашки" предыдущим чеком — а следующий добавленный товар попадал в корзину, которую Shopify уже завершил. SearchProducts теперь добавляет searchId к каждому вызову, и виджет сбрасывается, если видит незнакомый идентификатор.

  • Тот, кто владеет состоянием, тот и должен его очищать. useCart и useCheckoutFlow инициализируются при монтировании и никогда не перечитывают переданные им значения, поэтому очистка только состояния виджета ничего не давала — они записывали свои устаревшие значения обратно уже в следующем рендере. Сессия теперь привязана к searchId, поэтому React отбрасывает их.

  • Сброс должен происходить во время рендера, а не в эффекте. Эффект сначала отображает старый экран; покупатель, запрашивающий брюки, видел "Оплата получена" от предыдущего заказа, а затем это сообщение заменялось.

  • Ничто не упорядочивает записи между активными виджетами. Все более ранние виджеты в диалоге продолжают работать и пишут в один общий ключ localStorage для всего источника. Счетчик revision предотвращает замену более свежего снимка устаревшим внутри одного экземпляра; он не упорядочивает записи между экземплярами, потому что каждый увеличивает свой собственный счетчик. Привязка состояния к конкретному диалогу решила бы проблему правильно.

  • Виджет перемонтируется гораздо чаще, чем кажется, и CORS-предварительный запрос — это способ это заметить. Claude уничтожает и пересоздает iframe виджета, когда покупатель прокручивает страницу, и отдает HTML из своего кэша — поэтому resources/read не появляется, и перемонтирование невидимо в логе. Выдает его OPTIONS /api/shop/cart: предварительный запрос кэшируется для каждого документа, поэтому новый предварительный запрос означает новый документ. Замерено в 22:48:29 и 22:52:25, когда ничего, кроме прокрутки, не происходило. Все защелки, ссылки и наблюдатели внутри виджета умирают вместе с ним, поэтому "загрузить это один раз при монтировании" — это не ограничение частоты, а частота на каждую прокрутку, на каждый виджет.

  • IntersectionObserver не сообщает, находится ли виджет на экране. Очевидное исправление выше — загружать данные только когда виджет видим. Это не работает: с нулевым корнем во вложенном контексте просмотра наблюдатель измеряет относительно вьюпорта этого iframe, а не вьюпорта страницы хоста. Каждый виджет, прокрученный далеко за пределы видимости, сообщает, что он полностью видим. Создано, протестировано, измерено, удалено — три виджета все равно загружались при каждой перезагрузке.

  • Кэшируйте то, что хост не вернет обратно. При частом перемонтировании, а не редком, все, что перезагружается при монтировании, перезагружается постоянно: три активных виджета означали три перезагрузки корзины при каждой перезагрузке хоста, и Shopify в итоге отвечал 429 Rate limit exceeded. Тело корзины теперь сохраняется вместе с идентификатором корзины и временной меткой и перезагружается только по истечении TTL. Сессия из трех потоков сократилась с 19–20 вызовов к вышестоящему сервису до 13, а две перезагрузки, которые раньше стоили шести вызовов, теперь не стоят ничего.

    Сначала TTL был 30 секунд, что ничего не предотвращало: замеры по трем потокам показали, что разрыв между последней загрузкой корзины и следующим монтированием составлял 32с, 41с, 41с, 42с, 53с, 80с и 143с — каждый из них превышал окно. Сейчас TTL составляет 10 минут. Тело корзины предназначено только для отображения; изменение количества перезагружает данные с сервера, а платеж оценивается на основе корзины Shopify, поэтому устаревшая цифра не может быть оплачена.

  • Версионирование URI виджета выводит его из эксплуатации, поэтому обслуживайте каждую сборку. URI содержит идентификатор сборки (см. ниже) для обхода кэширования хостом. Плата за это — пересборка делает недействительным идентификатор, с которым были созданы все виджеты, уже находящиеся в диалоге: хост перечитывает запомненный URI, сервер отвечает -32602 Resource not found, и эти виджеты отображают "магазин не загрузился". ResourceTemplate для ui://widget/shopify-store-{build}.html теперь отдает текущий пакет для устаревших идентификаторов, что обновляет их вместо того, чтобы ломать. Обратите внимание, что это проявляется и в новом диалоге — кэшированные метаданные инструмента хоста все еще содержат старый URI.

  • Предупреждение CSP может быть о том, что вы никогда не собирались поставлять. MCPJam сообщал о блокировке https://cdn.openai.com при каждом вызове инструмента. Двадцать ссылок были правилами @font-face в katex.min.css, подключенном через ./css из SDK приложений, для математики, которую этот виджет не отображает. Объявление домена сделало бы виджет Shopify и Cashfree зависимым от CDN OpenAI внутри Claude; импорт остальных шести таблиц стилей по пути вместо этого удалил ссылку и 21 КБ CSS. Также обратите внимание, что модель CSP MCP Apps не имеет scriptSrc — только connectDomains, resourceDomains и frameDomains — поэтому жалоба на источник скрипта — это не то, на что сервер может ответить.

  • Отклоняйте GET-часть потокового HTTP с кодом 405, а не 404. Транспорт не имеет состояния, поэтому нет потока от сервера к клиенту, который можно было бы открыть. MCPJam открывал эту часть 97 раз за одну сессию и получал 404, не прерываясь, так что это не то, что ломает его там; сообщается, что более строгие клиенты сдаются до initialize. 404 читается как "нет такого эндпоинта", что является другим и неверным ответом.

  • Стоимость перезагрузки различается в зависимости от хоста, и платит за это ChatGPT. В Claude перезагрузка теперь ничего не стоит: состояние и тело корзины восстанавливаются из хранилища. В ChatGPT каталог не доставляется повторно, поэтому useProducts запрашивает его у этого сервера — один search_catalog на каждую перезагрузку, и ничего больше.

Эндпоинты

Путь

Назначение

POST /mcp

MCP через HTTP для AI-хоста

POST /api/shop/cart

Создание/обновление корзины в Shopify

POST /api/shop/search

Восстановление каталога для хоста, перезагрузившегося без повторной доставки результата инструмента

POST /api/pay/order

Создание заказа Cashfree с оценкой стоимости из корзины Shopify

POST /api/pay/otp, /otp/verify

OTP-логин

POST /api/pay/addresses/list, /addresses

Сохраненные адреса: чтение и создание

POST /api/pay/dispatched

Действительно ли запускался обработчик платежного инструмента?

POST /api/orders/status

Статус заказа для нашего собственного экрана проверки

GET /api/orders/:id

Сырое тело заказа для сверки cashfree-here

Логи

Каждый запрос логирует метод, путь, статус и длительность; MCP-вызовы указывают метод и инструмент, а чтение ресурсов — URI — POST /mcp сам по себе нечитаем, когда каждый вызов хоста выглядит одинаково.

13:59:48.201 → POST /mcp (tools/call SearchProducts) 200 328ms
13:59:52.884 → POST /api/shop/cart 200 904ms
14:00:03.117 → POST /api/pay/order 200 1026ms
14:00:09.640 ✗ POST /api/pay/addresses 502 121ms

Временная метка нужна, потому что одни длительности не могут измерить промежуток между двумя запросами, а это единственный вопрос, который имеет значение, когда платежная отправка приходит с опозданием.

Тесты

npm test          # watch
npm run test:run
npm run type-check

Тесты находятся рядом с кодом, который они покрывают. Фикстуры в src/lib/ucp/__fixtures__/ — это реальные захваченные ответы Shopify, поэтому изменение формы приведет к провалу теста, а не демо. Фикстуры Cashfree написаны вручную и отредактированы — его токены сессии не должны попадать в репозиторий.

Документы

  • docs/cashfree-occ-api.md — контракт OCC, проверенный вживую. Нет в опубликованной документации Cashfree.

  • docs/spikes/2026-08-12-occ-spike.md — что измерил спайк.

  • docs/superpowers/specs/ — дизайн-спецификации для каждой вехи.

  • docs/superpowers/plans/ — пошаговые планы реализации, в которые они превратились.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Manage your Savanto store from your AI: catalog, content, prompts, and analytics, by chat.

  • Manage your NanoCart store from any AI agent: products, orders, coupons, subscribers, reports.

  • Amazon brand, seller, niche & buy-box intelligence inside your own Claude or ChatGPT.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/droiddevgeeks/shopify-mcp-demo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server