Skip to main content
Glama
asmydev

asmy-mcp-server

Official
by asmydev

asmy-mcp-server

MCP-Server für Asmy Digital Store. Stellt den Produktkatalog, die Promo-Codes und die Shop-Statistiken als MCP-Tools bereit, die von einem Agenten (Junior.so, Claude Desktop oder einem beliebigen MCP-Client) konsumiert werden können.

Datenspeicher: Firestore. Zwei Transports: stdio und HTTP (SSE + Streamable HTTP).

Voraussetzungen

  • Node >= 18 (Bun empfohlen, die npm-Skripte verwenden es)

  • Ein Firebase-Projekt mit aktiviertem Firestore

  • Ein Firebase-Dienstkonto-Schlüssel

Related MCP server: shopify-mcp-server

Installation

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

Konfiguration

Firebase

Der Server löst die Anmeldedaten in dieser Reihenfolge auf (firebase-config.js):

  1. FIREBASE_SERVICE_ACCOUNT — das vollständige JSON, einzeilig oder als base64

  2. FIREBASE_SERVICE_ACCOUNT_FILE — Pfad zur Datei

  3. ./firebase-service-account.json — Fallback, neben index.js

Wenn FIREBASE_SERVICE_ACCOUNT vorhanden, aber ungültig ist, erfolgt ein Fallback auf die Datei mit einer Warnung auf stderr, kein Absturz.

Lokal: die Datei. In Produktion: die Umgebungsvariable (base64 vermeidet Probleme mit dem Escaping von private_key).

Die Datei firebase-service-account.json steht bereits in .gitignore. Es gibt keinen Grund, sie daraus zu entfernen.

Umgebungsvariablen

Variable

Standard

Rolle

PORT

3000

HTTP-Port

HOST

0.0.0.0

Abhörschnittstelle

ALLOWED_HOSTS

—

Erlaubte Hosts, durch Kommas getrennt. Erforderlich, wenn auf 0.0.0.0 gebunden wird

FIREBASE_SERVICE_ACCOUNT

—

JSON des Dienstkontos (einzeilig oder base64)

FIREBASE_SERVICE_ACCOUNT_FILE

—

Alternativer Pfad zum JSON

MCP_STDIO

—

1 erzwingt den stdio-Transport

OPENAI_API_KEY

—

Nur für Test-Clients

OPENAI_MODEL

gpt-4o-mini

Nur für Test-Clients

MCP_SERVER_URL

—

Nur für test-mcp-url.js

localhost, 127.0.0.1, [::1] und RAILWAY_PUBLIC_DOMAIN (von Railway injiziert) werden automatisch zur Liste der erlaubten Hosts hinzugefügt.

Hinweis: env.js ist ein eigener .env-Parser ohne Abhängigkeiten. Er verarbeitet mehrzeilige JSON-Werte (geschweifte Klammern) — nützlich, um ein rohes Dienstkonto in die Datei einzufügen. Viel mehr kann er nicht: keine Interpolation, keine exotischen Escape-Sequenzen.

Starten

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

Der Server wählt stdio, wenn --stdio als Argument übergeben wird oder MCP_STDIO=1 gesetzt ist. Andernfalls HTTP.

HTTP-Endpunkte

Route

Methode

Beschreibung

/

GET

Health-Check, gibt den Servernamen und die Liste der Endpunkte zurück

/mcp

ALL

Streamable HTTP (Spec 2025-11-25), Sitzungen über Header mcp-session-id

/sse

GET

SSE-Legacy (Spec 2024-11-05) — das nutzt Junior.so

/messages

POST

Rückkanal des SSE-Transports, Sitzung über ?sessionId=

Beide Transports koexistieren. Eine im SSE geöffnete Sitzung kann nicht auf /mcp fortgesetzt werden (Rückgabe -32000).

Die Sitzungen werden im Speicher in einem lokalen Objekt gehalten. Konsequenz: nur eine einzige Instanz. Keine horizontale Skalierung ohne Sticky Sessions oder gemeinsamen Speicher.

Verfügbare Tools

16 Tools, alle in index.js definiert.

Produkte (Sammlung products)

Tool

Beschreibung

list_products

Katalog mit Status, Preis, Lagerbestand

get_product

Details nach Slug oder Firestore-ID

create_product

Erstellung. autoFindImage=true löst die Symbolsuche aus

update_product

Teilweise Aktualisierung

set_product_status

active / draft / featured

duplicate_product

Kopie mit optionalem neuem Namen

delete_product

Endgültiges Löschen

find_product_image

Nur Symbolsuche, ohne in die Datenbank zu schreiben

Promotionen (Sammlung promotions)

Tool

Beschreibung

list_promos

Alle Codes

get_promo

Suche nach Code

create_promo

Lehnt doppelte Codes ab

update_promo

Code, Rabatt oder Ablaufdatum

delete_promo

Löschen

Sonstiges

Tool

Beschreibung

get_stats

Liest stats/overview

update_stats

Fügt einen Eintrag hinzu und berechnet die Monatssummen neu

get_current_date

Aktuelles Datum in Africa/Douala (UTC+1)

get_current_date existiert, weil LLMs sich beim Datum irren und expiresAt in der Vergangenheit erzeugen. Ein Agent, der einen Promo-Code erstellt, sollte es zuerst aufrufen.

Konventionen

  • Promo-Codes werden in Großbuchstaben normalisiert, expiresAt im Format YYYY-MM-DD, discount zwischen 1 und 100.

  • Der Produkt-Slug wird vom Namen abgeleitet (NFD, Akzente entfernt, Nicht-Alphanumerisches durch Bindestriche ersetzt).

  • Jedes zurückgegebene Produkt trägt eine url, die auf https://asmystore.shop/abonnements/{slug} aufbaut.

  • update_stats pusht in history und berechnet dann monthTotal und monthOrders neu, indem es auf das Präfix YYYY-MM filtert. Denselben Eintrag zweimal zu schreiben, zählt ihn doppelt — es gibt keine Deduplizierung.

Bildersuche

product-image.js löst ein Produktsymbol in zwei Durchgängen auf:

  1. Clearbit (logo.clearbit.com/{domaine}), mit einer Zuordnungstabelle Marke → Domain und einem Fallback {slug}.com / {slug}.io

  2. DuckDuckGo Images

Jeder Kandidat wird durch einen HEAD-Request validiert (und dann ein GET mit Range, wenn der HEAD nichts Brauchbares zurückgibt), um zu prüfen, ob der content-type wirklich ein Bild ist.

Zwei Vorbehalte sollte man im Hinterkopf behalten: Der i.js-Endpunkt von DuckDuckGo ist keine öffentliche API — man muss zuerst ein vqd-Token scrapen, und das kann ohne Vorwarnung brechen. Und die abgerufenen Logos gehören den jeweiligen Marken; du musst selbst prüfen, was du im Shop anzeigen darfst.

Im Fehlerfall gibt das Tool eine explizite Fehlermeldung zurück und das Produkt wird ohne Symbol erstellt.

Tests

Zwei Test-Clients, beide an OpenAI angebunden für Tool-Calling in natürlicher Sprache. OPENAI_API_KEY erforderlich.

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 ?"

Ohne Argument gehen beide in den REPL-Modus. Maximal 10 Runden Tool-Aufrufe.

Bereitstellung (Railway)

  1. Repo (privat) auf GitHub pushen

  2. Railway → New Project → Deploy from GitHub

  3. Variablen: FIREBASE_SERVICE_ACCOUNT (base64), PORT falls nötig

  4. RAILWAY_PUBLIC_DOMAIN wird automatisch injiziert und zu den erlaubten Hosts hinzugefügt — andernfalls ALLOWED_HOSTS manuell ausfüllen

Der Server behandelt SIGINT / SIGTERM: offene Transports werden vor dem Exit geschlossen.

Verbindung von Junior.so

Dashboard → Agent → Integrations → Create → Custom → MCP, dann die SSE-URL:

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

Junior spricht die Spec 2024-11-05, also /sse und nicht /mcp. Die 16 Tools werden nach der Verbindung automatisch aufgelistet.

Migration der Promos

migrate-promos.js ist ein Einmal-Skript, um die Promo-Codes aus dem localStorage des Frontends nach Firestore zu übernehmen.

  1. Auf asmystore.shop, Dev-Konsole: localStorage.getItem("asmy-admin-promos")

  2. Das JSON in die Konstante PROMOS_JSON des Skripts einfügen

  3. bun migrate-promos.js

Achtung: Dieses Skript liest firebase-service-account.json fest verdrahtet, es geht nicht über firebase-config.js. Umgebungsvariablen funktionieren hier nicht, es braucht die Datei. Das Skript ist dafür gedacht, einmal ausgeführt und dann vergessen zu werden.

Auf der Frontend-Seite daran denken, die Promo-Lese-/Schreibvorgänge von localStorage auf die Sammlung promotions umzustellen, sonst divergieren die beiden Quellen.

Fehlerbehebung

Firebase nicht konfiguriert beim Start — weder FIREBASE_SERVICE_ACCOUNT, noch FIREBASE_SERVICE_ACCOUNT_FILE, noch die Standarddatei wurden gefunden.

JSON Firebase unvollständig — das JSON wird geparst, aber es fehlt type: "service_account" oder private_key. Typischerweise ein abgeschnittenes Kopieren-Einfügen oder ein fehlerhaft beendetes base64.

Anfragen in Produktion abgelehnt, obwohl es lokal funktioniert — Schutz gegen DNS-Rebinding. Der Host ist nicht in allowedHosts. ALLOWED_HOSTS ausfüllen.

Session not found auf /messages — die SSE-Sitzung ist abgelaufen oder der Server wurde neu gestartet. Sitzungen sind im Speicher, ein erneutes Bereitstellen löscht sie alle.

Der Client sieht keine Tools — prüfen, ob wirklich /sse (Legacy-Spec) und nicht /mcp aufgerufen wird, und dass GET / antwortet.

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