Skip to main content
Glama
asmydev

asmy-mcp-server

Official
by asmydev

asmy-mcp-server

Сервер MCP для Asmy Digital Store. Предоставляет каталог продуктов, промокоды и статистику магазина в виде инструментов MCP, доступных для агента (Junior.so, Claude Desktop или любого MCP-клиента).

Бэкенд данных: Firestore. Два транспорта: stdio и HTTP (SSE + Streamable HTTP).

Предварительные требования

  • Node >= 18 (рекомендуется Bun, npm-скрипты его используют)

  • Проект Firebase с включённым Firestore

  • Ключ сервисного аккаунта Firebase

Related MCP server: shopify-mcp-server

Установка

bun install          # ou npm install
cp .env.example .env

Конфигурация

Firebase

Сервер разрешает учётные данные в следующем порядке (firebase-config.js):

  1. FIREBASE_SERVICE_ACCOUNT — полный JSON, в одну строку или в base64

  2. FIREBASE_SERVICE_ACCOUNT_FILE — путь к файлу

  3. ./firebase-service-account.json — запасной вариант, рядом с index.js

Если FIREBASE_SERVICE_ACCOUNT присутствует, но недействителен, происходит переход на файл с предупреждением в stderr, а не сбой.

Локально: файл. В продакшене: переменная окружения (base64 избегает проблем с экранированием private_key).

Файл firebase-service-account.json уже находится в .gitignore. Нет причин выносить его оттуда.

Переменные окружения

Переменная

По умолчанию

Роль

PORT

3000

HTTP-порт

HOST

0.0.0.0

Интерфейс прослушивания

ALLOWED_HOSTS

—

Разрешённые хосты, разделённые запятыми. Требуется при привязке к 0.0.0.0

FIREBASE_SERVICE_ACCOUNT

—

JSON сервисного аккаунта (одна строка или base64)

FIREBASE_SERVICE_ACCOUNT_FILE

—

Альтернативный путь к JSON

MCP_STDIO

—

1 принудительно включает транспорт stdio

OPENAI_API_KEY

—

Только для тестовых клиентов

OPENAI_MODEL

gpt-4o-mini

Только для тестовых клиентов

MCP_SERVER_URL

—

Только для test-mcp-url.js

localhost, 127.0.0.1, [::1] и RAILWAY_PUBLIC_DOMAIN (внедряется Railway) автоматически добавляются в список разрешённых хостов.

Примечание: env.js — это самодельный парсер .env без зависимостей. Он обрабатывает многострочные JSON-значения (фигурные скобки) — полезно для вставки сырого сервисного аккаунта в файл. Больше он почти ничего не умеет: без интерполяции, без экзотических экранирований.

Запуск

bun start          # HTTP sur $PORT
bun run dev        # HTTP + watch
bun run start:stdio  # transport stdio

Сервер выбирает stdio, если передан аргумент --stdio или установлен MCP_STDIO=1. В противном случае — HTTP.

HTTP-эндпоинты

Маршрут

Метод

Описание

/

GET

Проверка здоровья, возвращает имя сервера и список эндпоинтов

/mcp

ALL

Streamable HTTP (спецификация 2025-11-25), сессии через заголовок mcp-session-id

/sse

GET

SSE legacy (спецификация 2024-11-05) — именно это использует Junior.so

/messages

POST

Обратный канал транспорта SSE, сессия через ?sessionId=

Оба транспорта сосуществуют. Сессию, открытую через SSE, нельзя возобновить на /mcp (возвращается -32000).

Сессии хранятся в памяти в локальном объекте. Следствие: один экземпляр. Нет горизонтального масштабирования без sticky sessions или общего хранилища.

Предоставляемые инструменты

16 инструментов, все определены в index.js.

Продукты (коллекция products)

Инструмент

Описание

list_products

Каталог со статусом, ценой, остатком

get_product

Детали по slug или id Firestore

create_product

Создание. autoFindImage=true запускает поиск иконки

update_product

Частичное обновление

set_product_status

active / draft / featured

duplicate_product

Копия с новым необязательным именем

delete_product

Полное удаление

find_product_image

Поиск иконки отдельно, без записи в базу

Промоакции (коллекция promotions)

Инструмент

Описание

list_promos

Все коды

get_promo

Поиск по коду

create_promo

Отклоняет дубликаты кодов

update_promo

Код, скидка или срок действия

delete_promo

Удаление

Разное

Инструмент

Описание

get_stats

Читает stats/overview

update_stats

Добавляет запись и пересчитывает итоги месяца

get_current_date

Текущая дата в Africa/Douala (UTC+1)

get_current_date существует, потому что LLM ошибаются с датой и генерируют expiresAt в прошлом. Агент, создающий промокод, должен сначала вызвать его.

Соглашения

  • Промокоды нормализуются в верхний регистр, expiresAt в формате YYYY-MM-DD, discount от 1 до 100.

  • Slug продукта выводится из названия (NFD, удаление диакритики, неалфавитно- цифровые символы заменяются дефисами).

  • Каждый возвращаемый продукт содержит url, построенный на https://asmystore.shop/abonnements/{slug}.

  • update_stats добавляет запись в history, затем пересчитывает monthTotal и monthOrders, фильтруя по префиксу YYYY-MM. Запись одной и той же записи дважды учитывается дважды — дедупликации нет.

Поиск изображений

product-image.js находит иконку продукта в два прохода:

  1. Clearbit (logo.clearbit.com/{домен}), с таблицей соответствия бренд → домен и запасным вариантом {slug}.com / {slug}.io

  2. DuckDuckGo Images

Каждый кандидат проверяется через HEAD (а затем GET с Range, если HEAD не возвращает ничего полезного), чтобы убедиться, что content-type — это действительно изображение.

Два замечания, которые стоит иметь в виду: эндпоинт i.js DuckDuckGo не является публичным API — сначала нужно получить токен vqd, и это может сломаться без предупреждения. А полученные логотипы принадлежат соответствующим брендам; вам нужно проверить, что вы имеете право отображать их в магазине.

В случае неудачи инструмент возвращает явную ошибку, и продукт создаётся без иконки.

Тесты

Два тестовых клиента, оба подключены к OpenAI для вызова инструментов на естественном языке. Требуется OPENAI_API_KEY.

bun run test:mcp                          # spawn le serveur en stdio
bun run test:mcp "Liste les produits actifs"

MCP_SERVER_URL=https://xxx.up.railway.app bun run test:mcp:url
bun test-mcp-url.js https://xxx.up.railway.app "Quelle est la date ?"

Без аргументов оба входят в режим REPL. Максимум 10 раундов вызовов инструментов.

Развёртывание (Railway)

  1. Запушьте репозиторий (приватный) на GitHub

  2. Railway → New Project → Deploy from GitHub

  3. Переменные: FIREBASE_SERVICE_ACCOUNT (base64), PORT при необходимости

  4. RAILWAY_PUBLIC_DOMAIN внедряется автоматически и добавляется в разрешённые хосты — в противном случае укажите ALLOWED_HOSTS вручную

Сервер обрабатывает SIGINT / SIGTERM: открытые транспорты закрываются перед выходом.

Подключение из Junior.so

Dashboard → agent → Integrations → Create → Custom → MCP, затем URL SSE:

https://<ton-domaine>.up.railway.app/sse

Junior использует спецификацию 2024-11-05, поэтому /sse, а не /mcp. Все 16 инструментов автоматически перечисляются после подключения.

Миграция промоакций

migrate-promos.js — одноразовый скрипт для переноса промокодов из localStorage фронтенда в Firestore.

  1. На asmystore.shop, консоль разработчика: localStorage.getItem("asmy-admin-promos")

  2. Вставьте JSON в константу PROMOS_JSON скрипта

  3. bun migrate-promos.js

Внимание: этот скрипт жёстко читает firebase-service-account.json, он не использует firebase-config.js. Переменные окружения здесь не работают, нужен файл. Скрипт предназначен для однократного запуска, после чего о нём можно забыть.

На стороне фронтенда не забудьте переключить чтение/запись промоакций с localStorage на коллекцию promotions, иначе два источника разойдутся.

Устранение неполадок

Firebase не настроен при запуске — не найдены ни FIREBASE_SERVICE_ACCOUNT, ни FIREBASE_SERVICE_ACCOUNT_FILE, ни файл по умолчанию.

Неполный JSON Firebase — JSON распарсен, но отсутствует type: "service_account" или private_key. Обычно это обрезанное копирование или неправильно завершённый base64.

Запросы отклоняются в продакшене, хотя локально всё работает — защита от DNS rebinding. Хост не входит в allowedHosts. Укажите ALLOWED_HOSTS.

Session not found на /messages — сессия SSE истекла или сервер перезапустился. Сессии хранятся в памяти, повторное развёртывание стирает их все.

Клиент не видит ни одного инструмента — проверьте, что вы обращаетесь к /sse (legacy-спецификация), а не к /mcp, и что GET / отвечает.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    A production-grade MCP server and CLI tool that enables AI agents to manage Shopify stores through 49 built-in tools across products, orders, inventory, and analytics. It supports natural language workflows for tasks like inventory tracking, customer support, and sales reporting.
    78 npm
    18
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Exposes the Loyverse API as MCP tools to manage stores, products, inventory, customers, receipts, and more from AI assistants.
    54
    MIT