Skip to main content
Glama
asmydev

asmy-mcp-server

Official
by asmydev

asmy-mcp-server

Servidor MCP para Asmy Digital Store. Expone el catálogo de productos, los códigos promocionales y las estadísticas de la tienda como herramientas MCP, consumibles por un agente (Junior.so, Claude Desktop, o cualquier cliente MCP).

Backend de datos: Firestore. Dos transportes: stdio y HTTP (SSE + Streamable HTTP).

Requisitos previos

  • Node >= 18 (Bun recomendado, los scripts npm lo usan)

  • Un proyecto Firebase con Firestore activado

  • Una clave de cuenta de servicio Firebase

Related MCP server: shopify-mcp-server

Instalación

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

Configuración

Firebase

El servidor resuelve las credenciales en este orden (firebase-config.js):

  1. FIREBASE_SERVICE_ACCOUNT — el JSON completo, en una línea o en base64

  2. FIREBASE_SERVICE_ACCOUNT_FILE — ruta al archivo

  3. ./firebase-service-account.json — fallback, junto a index.js

Si FIREBASE_SERVICE_ACCOUNT está presente pero es inválido, se hace fallback al archivo con un warning en stderr, no un crash.

En local: el archivo. En producción: la variable de entorno (base64 evita los problemas de escape en private_key).

El archivo firebase-service-account.json ya está en .gitignore. No hay ninguna razón para sacarlo de ahí.

Variables de entorno

Variable

Defecto

Rol

PORT

3000

Puerto HTTP

HOST

0.0.0.0

Interfaz de escucha

ALLOWED_HOSTS

—

Hosts permitidos, separados por comas. Requerido cuando se hace bind en 0.0.0.0

FIREBASE_SERVICE_ACCOUNT

—

JSON de la cuenta de servicio (una línea o base64)

FIREBASE_SERVICE_ACCOUNT_FILE

—

Ruta alternativa al JSON

MCP_STDIO

—

1 fuerza el transporte stdio

OPENAI_API_KEY

—

Solo para clientes de prueba

OPENAI_MODEL

gpt-4o-mini

Solo para clientes de prueba

MCP_SERVER_URL

—

Solo para test-mcp-url.js

localhost, 127.0.0.1, [::1] y RAILWAY_PUBLIC_DOMAIN (inyectado por Railway) se añaden automáticamente a la lista de hosts permitidos.

Nota: env.js es un parser .env propio, sin dependencias. Gestiona valores JSON multilínea (llaves) — útil para pegar una cuenta de servicio en bruto en el archivo. No gestiona mucho más: sin interpolación, sin escapes exóticos.

Ejecutar

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

El servidor elige stdio si se pasa --stdio como argumento o si MCP_STDIO=1. Si no, HTTP.

Endpoints HTTP

Ruta

Método

Descripción

/

GET

Health check, devuelve el nombre del servidor y la lista de endpoints

/mcp

ALL

Streamable HTTP (spec 2025-11-25), sesiones mediante cabecera mcp-session-id

/sse

GET

SSE legacy (spec 2024-11-05) — es lo que consume Junior.so

/messages

POST

Canal de retorno del transporte SSE, sesión mediante ?sessionId=

Los dos transportes coexisten. Una sesión abierta en SSE no puede reanudarse en /mcp (devuelve -32000).

Las sesiones se almacenan en memoria en un objeto local. Consecuencia: una sola instancia. Sin escalado horizontal sin sticky sessions o store compartido.

Herramientas expuestas

16 herramientas, todas definidas en index.js.

Productos (colección products)

Herramienta

Descripción

list_products

Catálogo con estado, precio, stock

get_product

Detalle por slug o id de Firestore

create_product

Creación. autoFindImage=true dispara la búsqueda de icono

update_product

Actualización parcial

set_product_status

active / draft / featured

duplicate_product

Copia con nuevo nombre opcional

delete_product

Eliminación definitiva

find_product_image

Búsqueda de icono sola, sin escribir en base

Promociones (colección promotions)

Herramienta

Descripción

list_promos

Todos los códigos

get_promo

Búsqueda por código

create_promo

Rechaza los duplicados de código

update_promo

Código, descuento o expiración

delete_promo

Eliminación

Varios

Herramienta

Descripción

get_stats

Lee stats/overview

update_stats

Añade una entrada y recalcula los totales del mes

get_current_date

Fecha actual en Africa/Douala (UTC+1)

get_current_date existe porque los LLM se equivocan de fecha y generan expiresAt en el pasado. Un agente que crea un código promocional debe llamarlo primero.

Convenciones

  • Los códigos promocionales se normalizan en mayúsculas, expiresAt en formato YYYY-MM-DD, discount entre 1 y 100.

  • El slug del producto se deriva del nombre (NFD, acentos eliminados, no alfanuméricos reemplazados por guiones).

  • Cada producto devuelto lleva una url construida sobre https://asmystore.shop/abonnements/{slug}.

  • update_stats hace push en history, luego recalcula monthTotal y monthOrders filtrando por el prefijo YYYY-MM. Escribir dos veces la misma entrada la cuenta dos veces — no hay deduplicación.

Búsqueda de imágenes

product-image.js resuelve un icono de producto en dos pasadas:

  1. Clearbit (logo.clearbit.com/{domaine}), con una tabla de correspondencia marca → dominio y un fallback {slug}.com / {slug}.io

  2. DuckDuckGo Images

Cada candidato se valida con un HEAD (y luego un GET con Range si el HEAD no devuelve nada aprovechable) para verificar que el content-type sea efectivamente una imagen.

Dos reservas a tener en cuenta: el endpoint i.js de DuckDuckGo no es una API pública — primero hay que hacer scraping de un token vqd, y puede romperse sin previo aviso. Y los logos obtenidos pertenecen a las marcas correspondientes; tú debes verificar qué tienes derecho a mostrar en la tienda.

En caso de fallo, la herramienta devuelve un error explícito y el producto se crea sin icono.

Pruebas

Dos clientes de prueba, ambos conectados a OpenAI para hacer tool calling en lenguaje natural. Se requiere 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 ?"

Sin argumentos, ambos entran en modo REPL. Máximo 10 turnos de llamadas a herramientas.

Despliegue (Railway)

  1. Haz push del repo (privado) a GitHub

  2. Railway → New Project → Deploy from GitHub

  3. Variables: FIREBASE_SERVICE_ACCOUNT (base64), PORT si es necesario

  4. RAILWAY_PUBLIC_DOMAIN se inyecta automáticamente y se añade a los hosts permitidos — si no, rellena ALLOWED_HOSTS manualmente

El servidor gestiona SIGINT / SIGTERM: los transportes abiertos se cierran antes del exit.

Conexión desde Junior.so

Dashboard → agente → Integrations → Create → Custom → MCP, y luego la URL SSE:

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

Junior habla la spec 2024-11-05, por lo tanto /sse y no /mcp. Las 16 herramientas se listan automáticamente tras la conexión.

Migración de promociones

migrate-promos.js es un script one-shot para repatriar los códigos promocionales del localStorage del front a Firestore.

  1. En asmystore.shop, consola de desarrollo: localStorage.getItem("asmy-admin-promos")

  2. Pega el JSON en la constante PROMOS_JSON del script

  3. bun migrate-promos.js

Atención: este script lee firebase-service-account.json en duro, no pasa por firebase-config.js. Las variables de entorno no funcionan aquí, se necesita el archivo. El script está pensado para ejecutarse una vez y luego olvidarse.

En el front, recuerda cambiar las lecturas/escrituras de promociones de localStorage a la colección promotions, si no las dos fuentes divergen.

Solución de problemas

Firebase no configurado al arrancar — no se ha encontrado ni FIREBASE_SERVICE_ACCOUNT, ni FIREBASE_SERVICE_ACCOUNT_FILE, ni el archivo por defecto.

JSON Firebase incompleto — el JSON se parsea pero falta type: "service_account" o private_key. Típicamente un copiar-pegar truncado o un base64 mal terminado.

Peticiones rechazadas en producción cuando funciona en local — protección contra DNS rebinding. El host no está en allowedHosts. Rellena ALLOWED_HOSTS.

Session not found en /messages — la sesión SSE ha expirado o el servidor se ha reiniciado. Las sesiones están en memoria, un redeploy las borra todas.

El cliente no ve ninguna herramienta — verifica que se está usando /sse (spec legacy) y no /mcp, y que GET / responde.

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