MCP Server
Verwalte Cmssy-Workspace-Content aus KI-Agenten mit `@cmssy/mcp-server` — einer MCP-Bridge, die Tools für Seiten, Blöcke, Formulare und Medien über stdio bereitstellt.
Überblick
@cmssy/mcp-server ist ein Model-Context-Protocol-Server, der KI-Agenten (Claude Code, Claude Desktop, jedes MCP-fähige Tool) mit einem Cmssy-Workspace verbindet. Einmal konfiguriert, kann der Agent Seiten auflisten und bearbeiten, Blöcke hinzufügen oder entfernen, Entwürfe veröffentlichen, Formulare verwalten und mehr — ohne je den Editor zu verlassen.
Er wird über npm ausgeliefert und spricht stdio, du betreibst also keinen langlebigen Server: Der Agent startet ihn bei Bedarf über npx.
Was ihn vom HTTP-API unterscheidet
- Workspace-scoped — ein einziges Paar aus Token + Workspace-ID, alles serverseitig durchgesetzt
- High-Level-Tools —
add_block_to_page,publish_page,patch_block_content, kein rohes GraphQL - Tenant-Isolation eingebaut — jede Query wird nach deinem Workspace gefiltert; du kannst nicht versehentlich einen anderen Tenant anfassen
Setup
1. Erstelle ein API-Token
Workspace Settings → API Tokens → Create token. Kopiere den cs_…-Wert sofort — Tokens werden nur einmal angezeigt. Der Scope ist reine Authentifizierung; was das Token darf, bestimmen deine Rolle und das isSuperAdmin-Flag.
2. Finde deine Workspace-ID
Workspace Settings → General hat einen Kopier-Button neben der ID. Es ist derselbe Workspace, an den dein API-Token gebunden ist.
3. Trage ihn in die MCP-Config deines Editors ein
Für Claude Code bearbeite .mcp.json im Projekt-Root (oder ~/.claude/mcp.json für eine globale Installation):
{
"mcpServers": {
"cmssy": {
"command": "npx",
"args": [
"-y",
"@cmssy/mcp-server@latest",
"--token", "cs_your_token_here",
"--workspace-id", "507f1f77bcf86cd799439011",
"--api-url", "https://api.cmssy.io/graphql"
]
}
}
}Umgebungsvariablen-Äquivalente werden ebenfalls unterstützt: CMSSY_API_TOKEN, CMSSY_WORKSPACE_ID, CMSSY_API_URL. Nützlich, wenn du das Token nicht in einer committeten Config-Datei haben willst.
4. Editor neu starten
Claude Code lädt den Server beim nächsten Sessionstart. Du solltest einen cmssy-MCP-Eintrag mit den verfügbaren Tools sehen.
Verfügbare Tools
0.50.2 stellt 81 Tools bereit. Sie folgen einem Namensschema - list_* und get_* zum Lesen, create_* / update_* / delete_* zum Schreiben, dazu Verben für Zustandsübergänge - die Gruppe sagt also mehr als der einzelne Name.
Seiten und Blöcke
list_pages,get_page- der Seitenbaum und eine Seite mit allen Blöcken und Sprachen. Die Volltextsuchesearch_contentist im gemeinsamen Tool-Kern definiert, wird vom MCP-Server aber nicht gebunden; sie ist über den Assistenten im Admin erreichbar.create_page,update_page_settings,delete_page.update_page_settingshängt eine Seite überparentIdauch um, was den Slug des gesamten Teilbaums neu berechnet.publish_page,unpublish_page,revert_to_published.add_block_to_page,update_block_content,patch_block_content,remove_block_from_page,update_page_blocks,update_page_layout.list_block_types- die Blocktypen, die deine Site tatsächlich registriert, gelesen aus dem Manifest des Editor-Handshakes. Rufe es auf, bevor du einen Block einfügst: nur so weißt du, was das Frontend rendern kann.list_page_types,create_page_type.
Modelle und Records
list_models,get_model,create_model,update_model,delete_model- ein gelöschtes Modell nimmt alle seine Records mit.list_records,get_record,create_record,update_record,delete_record,import_records(bis 1000 pro Aufruf).
delete_record verweigert, solange ein Block den Record nutzt, und antwortet mit den Seiten, die ihn verwenden. Mit force: true löschst du trotzdem.
Medien
list_media,upload_media,move_media.list_media_folders,create_media_folder,update_media_folder,delete_media_folder.
Formulare
list_forms,get_form,create_form,update_form,delete_form.list_form_submissions,get_form_submission,update_form_submission_status,delete_form_submission.
Commerce
- Bestellungen -
list_orders,get_order,create_manual_order,edit_order,update_order_details,mark_order_paid,record_order_payment,record_order_invoice,refund_order,cancel_order,transition_order_fulfillment,get_order_pipeline,set_order_pipeline_stage. - Produkte -
list_products,bulk_update_products,bulk_delete_products,set_product_tiers. - Warenkörbe und Rabatte -
list_carts,update_cart_config,clear_cart_config,list_discounts,get_discount,create_discount,update_discount,set_discount_enabled.
Webhooks
list_webhooks,create_webhook,update_webhook,delete_webhook,rotate_webhook_secret,list_webhook_deliveries.list_webhook_event_types- die verbindliche Allowlist abonnierbarer Events. Lies sie, statt einen Eventnamen zu raten.
Ein Signing-Secret wird genau einmal zurückgegeben, beim Anlegen und beim Rotieren, danach nie wieder.
Workspace
get_workspace_info- Name, Plan, Limits und Nutzung.get_site_config- Sprachen, Navigation, aktivierte Features, Cart-Einstellungen.list_members,list_roles- nur lesend.
Nichts davon fasst deinen Code an. Kein Tool schreibt eine Datei, ändert eine Komponente oder öffnet einen Pull Request: KI bearbeitet Inhalte, Block-Schemas bleiben im Repo und im Review.
Dev-Drafts: ein Block, der noch nicht deployt ist
Jedes Write-Tool nimmt ein optionales target. "draft" (Standard) bearbeitet den gemeinsamen Seitenentwurf; "devDraft" bearbeitet dein eigenes Overlay pro Benutzer, das von der aktuellen Seite ausgeht und niemandes Vorschau verändert.
Genau das macht es sicher, eine Seite um einen Blocktyp herum zu bauen, den es bisher nur auf deinem Rechner gibt. Ist der Block ausgeliefert, schiebt promote_dev_draft dein Overlay auf den gemeinsamen Entwurf. get_page mit target: "devDraft" liefert das Overlay neben dem gemeinsamen Entwurf - oder null, wenn du keines hast.
patch_block_content — chirurgische Edits
Für gezielte Edits an Multi-KB-Content (Docs-Artikel, lange Blogposts) sendet patch_block_content nur den Diff — nicht den ganzen String. Dahinter steckt MongoDB findOneAndUpdate mit $set + arrayFilters, tenant-scoped, atomar. Typischerweise ~10× günstiger in Tokens, als das ganze HTML über update_block_content erneut zu senden.
Drei Operationstypen
insert_before / insert_after
Füge HTML direkt vor/nach einem eindeutigen Marker ein. Der Marker MUSS genau eine Stelle treffen — null oder mehrere Treffer lehnen die Operation mit BAD_USER_INPUT ab.
{
"op": "insert_after",
"marker": "<h2>Pricing</h2>",
"html": "<p>Plans start at $0/month.</p>"
}replace_section
Ersetze alles von startMarker (inklusive) bis endMarker (exklusive). Beide Marker müssen sich eindeutig auflösen lassen.
{
"op": "replace_section",
"startMarker": "<h2>Pricing</h2>",
"endMarker": "<h2>FAQ</h2>",
"html": "<h2>Pricing</h2><p>New plans here.</p>"
}Mehrere Ops in einem Aufruf
Operationen werden der Reihe nach auf das laufende Ergebnis angewendet. Jeder Fehler (fehlender Marker, mehrdeutig usw.) bricht den gesamten Patch ab — kein halb angewendeter Zustand.
{
"pageId": "...",
"blockId": "...",
"locale": "en",
"operations": [
{
"op": "insert_before",
"marker": "<h2>Appendix</h2>",
"html": "<h2>New Section</h2><p>…</p>"
},
{
"op": "replace_section",
"startMarker": "<h2>Pricing</h2>",
"endMarker": "<h2>FAQ</h2>",
"html": "<h2>Pricing</h2><p>Updated.</p>"
}
]
}Wenn eine Operation fehlschlägt
- 0 Treffer — Marker nicht gefunden. Prüfe auf exakte zeichengenaue Übereinstimmung; Whitespace und Attributreihenfolge zählen.
- 2+ Treffer — der Marker ist nicht eindeutig. Füge umgebendes HTML zur Disambiguierung hinzu. Überlappende Treffer zählen (
"aa"in"aaa"zählt als 2), vermeide also ultrakurze Marker. - Feld ist kein String — der anvisierte
fieldPathlöst zu einem Array oder Objekt auf. Nutzeupdate_block_contentfür strukturierte Felder. - Layout-Blöcke nicht unterstützt — Header/Footer und andere Layout-Blöcke laufen über
update_block_content.
patch_block_content vs update_block_content
patch_block_content | update_block_content | |
|---|---|---|
| Wann nutzen | Gezielte Edits an einem HTML-String | Vollständiger Content-Rewrite, beliebige Form |
| Token-Kosten | Proportional zum Diff | Proportional zum gesamten Content |
| Typische Ersparnis | ~10× bei Multi-KB-Content | – |
| Feldtypen | Nur Strings (über fieldPath) | Beliebig (Strings, Arrays, verschachtelte Objekte) |
| Teilweises Scheitern | Ganzer Patch bricht ab — kein halb angewendeter Zustand | Ganzer Write gelingt oder scheitert |
| Layout-Blöcke | Nicht unterstützt | Unterstützt |
Faustregel: Wenn du früher das gesamte HTML erneut geschickt hättest, um einen Absatz zu ändern, nimm patch_block_content. Sonst bleib bei update_block_content.
Troubleshooting
- „Workspace not found“ — die Person hinter dem Token ist kein Mitglied der angegebenen
--workspace-id, oder die ID stimmt nicht. Ein Token authentifiziert eine Person; was es darf, ergibt sich aus deren Rolle in diesem Workspace. Prüfe das Paar in den Workspace Settings. - „Not authenticated“ — Token abgelaufen oder widerrufen. Erstelle ein neues unter Workspace Settings → API Tokens.
- MCP-Server im Editor nicht sichtbar — starte den Editor nach Config-Änderungen neu. In Claude Code findest du unter Settings → MCP → cmssy die Startup-Logs.
- Rate-Limits / Plan-Limits — der MCP-Server respektiert die Plan-Limits des Workspace (max. Seiten, Storage, KI-Tokens).
get_workspace_infozeigt die aktuelle Nutzung vs. Limits.
Response-Modus
Seit 0.6.0 akzeptiert jedes Write-Tool einen optionalen Parameter response: "minimal" | "full" (Default "minimal"). Minimal gibt ein kleines Compact-JSON-Ack (~100-200 Bytes) zurück, nur mit den IDs und dem Zustand, den du zum Verketten des nächsten Aufrufs brauchst — nicht die volle mutierte Ressource.
Typische Bulk-Edit-Sessions (Agenten, die dieselbe Docs-Seite ~6-mal anfassen) verbrannten vor 0.6 ~170 kB an zurückgeschicktem HTML pro Seite. Der Minimal-Modus drückt das auf insgesamt ~1 kB — ~95 % weniger Response-Token-Kosten.
Minimal-Ack-Formen
- Seiten-Tools (
create_page,update_page_blocks,update_page_settings,publish_page,unpublish_page,revert_to_published,update_page_layout) —{id, slug, hasUnpublishedChanges, updatedAt}(+publishedbei publish/unpublish) - Block-on-Page-Tools (
add_block_to_page,update_block_content,remove_block_from_page) —{pageId, blockId, hasUnpublishedChanges, updatedAt} - Formular-Tools (
create_form,update_form) —{id, slug, status, updatedAt} - Modell-Tools (
create_model,update_model) —{id, slug, updatedAt} - Record-Tools (
create_record,update_record) —{id, status, updatedAt}
Wann du full wählen solltest
Übergib response: "full", wenn du die volle mutierte Ressource wirklich im selben Aufruf brauchst — z. B. um eine komplette Transformation zu verifizieren, ein servergeneriertes Feld zu lesen oder zu debuggen. Andernfalls hänge einen Lese-Tool-Aufruf an (get_page / get_form / get_model / get_record).
Tools ohne response
Geben bereits ein kompaktes Ack zurück und bleiben unverändert: patch_block_content, alle delete_*, update_form_submission_status, import_records.
Version
Diese Docs beschreiben @cmssy/mcp-server 0.50.2, das 81 Tools aus @cmssy/ai-tools 0.34.0 bindet. Orientierungspunkte: patch_block_content kam mit 0.5.0, minimale Responses mit 0.6.0, list_block_types mit 0.45.0, das Dev-Draft-target mit 0.48.0 - promote_dev_draft selbst wurde allerdings erst in 0.50.2 gebunden, sicheres Record-Löschen mit force in 0.48.0, die Medienordner-Tools in 0.49.2, clear_cart_config in 0.50.1. Pinne @cmssy/mcp-server@latest in .mcp.json, um immer die neuesten Tools zu bekommen.