Stand: 2026-08-20. Diese Seite ist die Quelle, nicht eine Kopie: Sie liegt als Artikel im CMS und wird dort gepflegt. Am ehesten altert die DNS-Notiz unter Stolperfallen. Der Werkzeugumfang altert hier nicht — maßgeblich ist list_tools, das die Liste aus der laufenden Registry erzeugt (Stand dieser Fassung: 38 Werkzeuge).

Zweck: Dieses Blatt brauchst Du, wenn Du über das generic-cms-MCP Artikel anlegst, bearbeitest oder veröffentlichst, Bilder hochlädst oder Diagramme einbettest. Es dokumentiert Besonderheiten und Stolperfallen — die vollständige, immer aktuelle Werkzeugliste lieferst Du Dir selbst per list_tools oder über die Schemas der mcp__*-Werkzeuge.

Registrierung

claude mcp add --transport http generic-cms https://<cms-host>/mcp \
  --header "Authorization: Bearer gcms_<dein-token>"
  • <cms-host> ist der Hostname Deiner CMS-Instanz — nicht der persönliche Login-Host.
  • Lokaler Scope (nur das aktuelle Projektverzeichnis). Für global: --scope user.
  • Werkzeuge erscheinen erst nach einem Neustart der Sitzung. Ein Connector in claude.ai holt seine Werkzeugliste beim Verbindungsaufbau — nach einer Server-Änderung hilft nur ein Reconnect, kein Warten.
  • claude mcp list muss ✓ Connected zeigen.

Unverhandelbar: Der Token wird nie ins Repo committet, nie in Memory oder CLAUDE.md abgelegt und nie in Artikeln zitiert. Er existiert ausschließlich im Header der Registrierung.

Warum so viele Werkzeuge?

38 sind mehr, als man einem Modell üblicherweise vorsetzt — die gängige Empfehlung lautet „wenige, mächtige Werkzeuge". Hier ist es bewusst andersherum: 37 der 38 Werkzeuge rufen genau eine REST-Route, keines ruft zwei, und keine Route wird von zwei Werkzeugen geteilt (list_tools ist das einzige rein lokale). Was das für Dich heißt:

  • Ein Fehlschlag ist eindeutig. Der Status kommt von genau einer Route — kein Sammelwerkzeug, das Teilfehler für Dich deutet.
  • Rechte sind sichtbar. Jedes Werkzeug trägt den Scope seiner Route. Fehlt Dir ein Recht, scheitert genau der eine Aufruf.
  • Der Shim erfindet nichts. Er reicht das CMS durch; Antworten sind roh, dafür verlässlich.
  • Suche die Werkzeuge, statt sie zu erraten. Der Preis dieser Bauweise ist ein langer Katalog. list_tools liefert ihn gruppiert mit Kurzbeschreibung — einmal am Sitzungsbeginn aufrufen ist billiger als jeder Rateversuch.

Werkzeugumfang

Quelle der Wahrheit ist list_tools. Die Gruppierung hier dient nur der ersten Orientierung.

BereichWerkzeuge
Struktur & Discoverylist_tools, list_sections, create_section, update_section, list_categories, describe_frontmatter, list_article_classes, recommend_renderer
Artikel-Lifecyclelist_articles, create_article, read_article, update_article, preview_article, validate_article, lint_site, move_article, set_draft, delete_article, reindex_article
Papierkorblist_trash, restore_article, purge_article
Medienupload_image, upload_file, list_images, prune_images, mermaid_titelbild, uml_titelbild, dot_titelbild, d2_titelbild, vegalite_titelbild
Suchesearch_articles (Meilisearch-Volltext; indexiert ist nur der Stand des letzten release_site)
Build & Betriebrelease_site, build_status, build_log, site_status, get_stats, audit_log

Lesbare statt roher Antworten: list_trash, list_images, search_articles, audit_log, list_categories und list_tools nehmen format="text" und liefern dieselben Daten als gesetzten Text statt als JSON — rund ein Drittel der Zeichen. Zum Weiterverarbeiten der Felder bleibt der Vorgabewert "json" richtig. Die Werkzeuge mit outputSchema (u. a. list_articles, site_status, lint_site) haben den Parameter bewusst nicht — sie liefern stattdessen strukturierte Inhalte.

Diagramme — fünf Sprachen, eine Empfehlung

Mermaid ist der Standard und der sichere Rückfall, aber nicht die einzige Sprache. Vier weitere werden am Build zu SVG gerendert und automatisch eingebettet — kein Extra-Werkzeugaufruf nötig, es genügt der richtige Fence:

FenceSpracheWofür
```mermaidMermaidStandard: Abläufe, Zeitachsen, Mindmaps. Clientseitig gerendert.
```uml / ```plantumlPlantUMLUML im engeren Sinn: Sequenz, Klasse, Zustand.
```dot / ```graphvizGraphvizDichte Graphen, viele Knoten, hierarchische Layouts.
```d2D2Node-Link mit Anspruch an Optik und Layout.
```vegalite / ```vega-liteVega-LiteEchte Datendiagramme aus gemessenen Zahlen (JSON-Spec).

Welche passt? Frag recommend_renderer(task="…"), statt zu raten. Das Werkzeug rendert und schreibt nichts: Es liest die Absicht aus dem Prosa-Auftrag, schätzt die Datenform (nodes, edges, data_points — explizit übergeben oder aus dem Text gelesen) und liefert eine begründete Rangliste. Empfohlen wird nur, was in dieser Installation auch rendert; fällt ein Sidecar aus, verschwinden genau dessen Sprachen aus der Empfehlung und eine Notiz sagt, was fehlt. Das Feld fence ist die Angabe, die Du dann tatsächlich schreibst.

Vega-Lite: Daten müssen inline stehen. Eine Spec, die auf eine entfernte URL zeigt (data: {url: …}), wird mit 422 abgewiesen — der Build holt beim Rendern nichts aus dem Netz, und ein Diagramm, dessen Zahlen woanders liegen, ist nicht reproduzierbar. Also data: {values: [ … ]}. Zweiter Stolperstein: Vega-Lite stellt die Beschriftungen einer diskreten X-Achse standardmäßig hochkant — "axis": {"labelAngle": 0} auf dem Kanal stellt sie waagerecht.

Jede der fünf Sprachen kann ihr Diagramm auch zum Titelbild machen: mermaid_titelbild, uml_titelbild, dot_titelbild, d2_titelbild, vegalite_titelbild. Alle rahmen in dieselbe 1200×630-Karte mit Artikeltitel und Marken-Fuß, sodass Hero-Bilder gleich aussehen, egal welcher Renderer gezeichnet hat. block_index="auto" wählt den Block, der die Karte am besten füllt; ein unveränderter Lauf antwortet mit skipped.

Artikelklassen

create_article akzeptiert optional article_class — eine Inhalts-Gattung mit eigenem Layout, Zusatzfeldern und Body-Gerüst (leerer body → Gerüst wird eingesetzt). Quelle der Wahrheit ist list_article_classes. Ohne Klasse entsteht ein normaler Artikel.

KlasseWofürZusatzfelder (via extra_frontmatter)
analyseBewertung mit Haltung: These, Befunde, Fazit-Box oben, Quellen-Fußfazit, quellen
tutorialNummerierte Schritte zum Ergebnis; erzeugt HowTo-JSON-LDschwierigkeit, dauer, voraussetzungen
notizKurztipp ohne Ballast — kein Hero, kein Inhaltsverzeichnis—
referenzVersioniertes Nachschlagewerk mit Gültigkeitsstand — auch für „Don’t"-Wissenversion, stand, geltungsbereich, quellen
projektlogChronologisches Projekt-Journal mit datierten Einträgenprojekt, status, zeitraum

Frontmatter bei create_article

FeldTypHinweis
sectionstr (Pflicht)Pfad aus list_sections, z. B. blog
titlestr (Pflicht)Reader-sichtbar
bodystr (Pflicht)Hugo-Markdown
slugstr?Optional — sonst aus dem Titel abgeleitet (Umlaut-Transliteration, Kleinschreibung, Bindestrich)
article_classstr?Inhalts-Gattung, siehe oben; setzt den Hugo-type
kategorienlist[str]?Tags/Kategorien
lesezeitint?Minuten — weggelassen schätzt das Theme selbst
titelbildstr?Hero-Bild: exakt die url aus der upload_image-Antwort einsetzen — den Pfad nie selbst konstruieren
extra_frontmatterdict?Beliebige zusätzliche YAML-Felder (draft, aliases, weight, Klassen-Zusatzfelder)

Empfohlener Ablauf

  1. validate_article(body=…, title=…) — Lint vor dem Anlegen; fängt kaputte Diagramme, H1 im Body und Frontmatter-Fehler, bevor Leser sie sehen.
  2. create_article(…) — für Änderungen update_article (ändert nur die übergebenen Felder). Nie delete+create für ein Edit. Der Body muss nicht komplett neu gesendet werden:
    • find + replace ersetzt genau eine eindeutige Fundstelle. 0 Treffer → 400, >1 Treffer → 400, außer mit replace_all=true. Deckt auch das Einfügen an einem Anker ab: Anker finden, durch Anker + neuen Text ersetzen.
    • body mit mode = append / prepend (Vorgabe replace = Ganz-Body-Ersatz).
    • normalize=true räumt einen Paste auf: mehrfache Leerzeilen → eine, Leerzeichen am Zeilenende weg.
    • release=true stößt nach erfolgreichem Speichern direkt den Voll-Build an.
    • expected_updated schützt davor, die Änderung eines anderen zu überschreiben: den updated-Wert aus dem read_article mitgeben, auf dem die Bearbeitung beruht.
  3. release_site() → build_status(build_id=…, wait_seconds=120). Gestartet ist nicht fertig — nur status == "success" heißt, dass die Änderung auf der Website steht.
  4. Verifikation per read_article, nicht über die öffentliche URL (viele Instanzen stehen hinter einem Zugangsschutz).

Jede Antwort trägt ein site-Feld mit dem Hostnamen der antwortenden Instanz — prüfe vor Schreiboperationen, dass Du mit der richtigen sprichst. Das ist kein Schmuck: Wer mehrere Instanzen registriert hat, schreibt sonst irgendwann in die falsche.

Vollständiges Beispiel

// 1. Hero-Bild hochladen — die Antwort liefert die einzusetzende URL:
//    {"uploaded": [{"url": "/images/mcp-setup-claude-code.jpg"}], "errors": []}

// 2. Artikel anlegen:
create_article(
  section = "tipps",
  title   = "MCP-Setup für externe Claude-Sitzungen",
  slug    = "mcp-setup-claude-code",
  kategorien = ["mcp", "claude-code", "hugo"],
  lesezeit   = 4,
  titelbild  = "/images/mcp-setup-claude-code.jpg",
  extra_frontmatter = { "draft": false, "weight": 10 },
  body = """
Kurzfassung: Bearer-Token registrieren, einmal die Sitzung neu starten, fertig.

```mermaid
flowchart LR
    A[claude mcp add] --> B[Sitzung neu starten]
    B --> C[Werkzeuge sichtbar]
    C --> D[create_article]
    D --> E[release_site]
    E --> F[build_status abfragen]
```

## Schritte

1. Befehl ausführen.
2. Sitzung neu starten.
3. Werkzeuge über die Schemas erkunden.
"""
)

Zur Verschachtelung: Der innere ```mermaid-Fence steht bewusst innerhalb des dreifach gequoteten body-Strings. Beim Nachbauen die Fence-Ebenen nicht verwechseln.

Mermaid — Stolperfallen

Das Theme lädt mermaid@11 vom CDN — also die jeweils neueste 11.x, nicht eine feste Fassung. Der Renderer, der die Titelbilder zeichnet, pinnt dagegen eine konkrete Version. Beides ist Absicht, aber es heißt: ein Diagramm kann im Browser minimal anders aussehen als in seiner Hero-Karte. Der Parser von Mermaid 10+ ist deutlich strikter als 9.x; die folgenden Punkte sind die Quelle praktisch aller „Syntax error in text"-Fehler:

  • Zeilenumbrüche in Node-Labels: <br/> verwenden, nicht \n.
  • Spitze Klammern in Labels als &lt; / &gt; escapen. Einzige unescaped erlaubte Tags sind <br/> und <br>.
  • Datenbank-/Zylinderform: DB[("Text")] — eckige plus runde Klammern um ein gequotetes Label.
  • Subgraph-Titel mit Leerzeichen quoten: subgraph "Mein Titel".
  • Pipe | oder Quote " im Label erzwingen Quoting des ganzen Labels: A["|d| sm"].
  • Gantt: Tags gehören VOR die ID, nie dahinter. Also Gate :milestone, g1, 2028-06, 0d — nicht Gate :g1, milestone, 2028-06, 0d. Mermaid streift die Tags (milestone, crit, active, done, vert) nur am Anfang der Feldliste ab; steht die ID davor, bleiben vier Felder stehen, und Mermaid kennt nur ein bis drei. Der Haken: Gantt-Tasks werden erst im Renderer übersetzt, nicht im Parser — Validierung und Build bleiben grün, und der Leser bekommt das Bomben-Icon. Deshalb prüft der Lint das textuell (GANTT_TAG_ORDER, GANTT_TASK_FIELDS).
  • Der Code-Fence muss exakt ```mermaid heißen (kleingeschrieben, kein Leerzeichen dahinter).

Die häufigsten Modellfehler (Pipe-Labels, Subgraphs mit Leerzeichen, \n-Umbrüche, ungeschützte spitze Klammern) normalisiert das CMS beim Speichern automatisch. Semantische Fehlentscheidungen — Zylinder gegen Rechteck — erkennt der Sanitizer bewusst nicht.

Fehler-Schnellreferenz

SymptomWahrscheinliche UrsacheErste Reaktion
409 bei release_siteBuild läuft bereitsbuild_status abfragen bis running: false, dann erneut auslösen
409 bei create_articleLive-Artikel mit diesem Slug existiert bereitsFür Änderungen update_article nutzen, sonst anderen Slug wählen
409 bei create_sectionSektion existiert bereits oder Name ist reserviertlist_sections prüfen, anderen Namen wählen
400 bei update_article (find/replace)find-Anker 0-mal oder >1-mal im BodyBei 0 Treffern den Anker per read_article gegen den echten Body prüfen; bei >1 mehr umgebenden Text — oder replace_all=true
404 direkt nach create_articleBuild noch nicht durch oder release_site vergessenrelease_site auslösen, build_status abwarten; mit read_article statt öffentlicher URL prüfen
404 bei read_article auf bekannten ArtikelFalscher Sektionspfad/Slug — oder Artikel liegt im Papierkorblist_articles bzw. search_articles nutzen; list_trash prüfen
401 konstantToken abgelaufen, falsch oder falscher HostRegistrierung prüfen: claude mcp list muss ✓ Connected zeigen
401/404 flackernd (mal ja, mal nein)Auflösungsproblem auf Betreiberseite, kein Fehler Deines AufrufsBeim Betreiber melden — von aussen nicht behebbar
payload_too_large bei upload_imageBase64-Inline-Upload über dem LimitFoto per curl -F file=@… https://<cms-host>/api/v1/images hochladen
302 auf einen Login beim Abruf einer öffentlichen URLDie Instanz steht hinter Zugangsschutz — kein FehlerVerifikation immer per read_article
last_status: "error" in build_statusBuild-Pipeline fehlgeschlagenbuild_log lesen — meldet den fehlgeschlagenen Schritt strukturiert
Artikel fehlt in search_articles, existiert aberSuchindex kennt nur den Stand des letzten BuildsErst release_site abschließen, dann suchen
Gantt-Diagramm zeigt ein Bomben-Icon, Build war grünFeldliste, die Mermaid erst im Renderer übersetztTag vor die ID setzen, höchstens drei Felder hinter dem :
422 beim Speichern eines ```vegalite-BlocksKein gültiges JSON — oder die Spec zeigt auf entfernte DatenZahlen inline setzen; die Meldung nennt die Fundstelle im Spec-Baum
Build bricht ab mit „D2-/Vega-Lite-/DOT-Diagramm(e) mit Fehler"Ein Block im Live-Inhalt lässt sich nicht rendern (im Papierkorb nicht blockierend)build_log nennt Datei und Zeile
Diagramm sieht im Titelbild anders aus als im ArtikelTheme lädt mermaid@11 ungepinnt, der Renderer pinntKein Fehler. Bei sichtbarem Unterschied das Titelbild mit force=true neu erzeugen

Besonderheiten und Stolperfallen

  • delete_article ist Soft-Delete in den Papierkorb mit Epoch-Präfix (1714398123_slug.md). Die Kette: list_trash zeigt, restore_article stellt wieder her, purge_article löscht endgültig — und verlangt dafür confirm="purge".
  • Echte Fotos nie als Base64 über das MCP-Werkzeug hochladen. Stattdessen curl -F file=@foto.jpg https://<cms-host>/api/v1/images. Das MCP-upload_image ist für kleine Grafiken gedacht; für generierte Diagramm-Titelbilder gibt es die fünf *_titelbild-Werkzeuge.
  • Sichtbarkeit unter https://<cms-host>/<sektion>/<slug>/ erst nach release_site und Build-Ende.
  • Viele Instanzen stehen hinter einem Zugangsschutz — ein direkter Abruf der öffentlichen URL läuft dann in eine Sackgasse. Für Verifikation ohne Zugangsdaten immer read_article nutzen.
  • Eine Unterrubrik ist keine URL-Ebene. Die Permalink-Regel ist auf die oberste Sektion gekeyt: ein Artikel in applebridge/atalkd erscheint unter /applebridge/<slug>/. Ein Artikel und eine gleichnamige Unterrubrik verdrängen sich deshalb; beides übereinander anzulegen wird mit 409 abgelehnt.

Quellen

  1. list_tools der laufenden Instanz (massgebliches Werkzeug-Inventar)
  2. generic-cms-Repo: mcp/server.py, cms/blueprints/api.py, cms/blueprints/build.py
  3. Vorgaengerfassung (ABGELOEST am 2026-08-20, nicht mehr gepflegt): sealog.de/mcp/mcp.html, Erstfassung 2026-05-01