EmDash enthält einen integrierten Model Context Protocol (MCP) Server unter /_emdash/api/mcp, der Content-Management-Operationen als Tools für KI-Assistenten bereitstellt.
Diese Seite behandelt die Protokolldetails: Authentifizierung, Transport, Toolspezifikationen, OAuth-Discovery und Fehlerbehandlung.
Authentifizierung
Der MCP-Server unterstützt drei Authentifizierungsmethoden:
| Methode | Funktionsweise |
|---|---|
| OAuth 2.1 Authorization Code + PKCE | Standard-Flow für MCP-Clients. Benutzer genehmigt Scopes im Browser. |
| Personal Access Token (PAT) | Langlebige ec_pat_* Tokens, die im Admin-Panel erstellt werden. |
| Device Flow | CLI-artiger Flow, bei dem Sie einen Code im Browser genehmigen. Wird von emdash login verwendet. |
Session-Cookies (aus der Admin-UI) funktionieren ebenfalls, sind aber für externe MCP-Clients nicht praktikabel.
Scopes
Tokens sind auf Scopes beschränkt, um zu begrenzen, welche Operationen ein Client ausführen kann. Scopes werden während der OAuth-Autorisierung angefordert und bei jedem Tool-Aufruf erzwungen.
| Scope | Gewährt Zugriff auf |
|---|---|
content:read | Listen, Abrufen, Vergleichen und Durchsuchen von Inhalten. Listen von Taxonomien, Taxonomie-Begriffen und Menüs. |
content:write | Erstellen, Aktualisieren, Löschen, Veröffentlichen, Zurückziehen, Planen, Entplanen, Duplizieren und Wiederherstellen von Inhalten. Gewährt implizit taxonomies:manage und menus:manage für Abwärtskompatibilität mit Tokens, die vor Existenz dieser Scopes ausgestellt wurden. |
media:read | Listen und Abrufen von Medien-Elementen. |
media:write | Registrieren (Erstellen), Aktualisieren und Löschen von Medien-Metadaten. |
schema:read | Listen von Collections und Abrufen von Collection-Schemas. |
schema:write | Erstellen und Löschen von Collections und Feldern. |
taxonomies:manage | Erstellen, Aktualisieren und Löschen von Taxonomie-Begriffen. |
menus:manage | Erstellen, Aktualisieren und Löschen von Navigationsmenüs und deren Elementen. |
settings:read | Lesen von seitenweiten Einstellungen. |
settings:manage | Aktualisieren von seitenweiten Einstellungen. |
admin | Vollzugriff auf alle Operationen. |
Der admin Scope gewährt Zugriff auf alles. Session-basierte Authentifizierung (ohne Token) hat ebenfalls vollen Zugriff basierend auf der Benutzerrolle.
content:write gewährt implizit taxonomies:manage und menus:manage, sodass Personal Access Tokens, die vor der Aufteilung dieser Scopes ausgestellt wurden, weiterhin ohne Neuausstellung funktionieren. Neue Tokens sollten die granularen Scopes anfordern.
Rollenanforderungen
Zusätzlich zu Scopes erfordern einige Tools eine minimale RBAC-Rolle. Beide müssen erfüllt sein — ein Token mit dem richtigen Scope schlägt dennoch fehl, wenn die Rolle des aufrufenden Benutzers zu niedrig ist.
| Operation | Minimale Rolle |
|---|---|
| Content lesen | Subscriber (10) für veröffentlichte Elemente; Contributor (20) für Entwürfe, Geplantes, Papierkorb und Revisionen |
| Content erstellen | Contributor (20) |
| Eigenen Content bearbeiten / eigenen Content löschen | Author (30) |
| Content veröffentlichen | Author (30) für eigene Elemente; Editor (40) für fremde Elemente |
| Schema lesen | Editor (40) |
| Schema schreiben | Admin (50) |
| Taxonomien verwalten | Editor (40) |
| Menüs verwalten | Editor (40) |
| Einstellungen lesen | Editor (40) |
| Einstellungen verwalten | Admin (50) |
Medien hochladen (media_create) | Author (30) |
Siehe die Authentifizierungsanleitung für Rollendefinitionen.
Transport
Der Server verwendet den Streamable HTTP-Transport im stateless mode. Jede Anfrage ist unabhängig — es gibt keine Sessions oder langlebige Verbindungen.
POST /_emdash/api/mcp— JSON-RPC Tool-Aufrufe sendenGET /_emdash/api/mcp— Gibt 405 zurück (kein SSE im stateless mode)DELETE /_emdash/api/mcp— Gibt 405 zurück (keine Session zum Schließen)
Antworten folgen dem JSON-RPC 2.0 Format. Fehler verwenden Standard-JSON-RPC-Fehlercodes, mit MCP-spezifischen Codes für Scope- und Berechtigungsfehler.
Tools
Der Server stellt 45 Tools über acht Domänen bereit: Content, Schema, Media, Search, Taxonomies, Menus, Revisions und Settings. Jedes Tool gibt Ergebnisse als JSON-Text-Inhalt zurück, oder eine Fehlermeldung mit isError: true bei Fehler.
Content Tools
content_list
Listen von Content-Elementen in einer Collection mit optionaler Filterung und Paginierung.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug (z.B. posts, pages) |
status | string | Nein | Filter: draft, published oder scheduled |
limit | integer | Nein | Max. Anzahl zurückzugebender Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungs-Cursor aus vorheriger Antwort |
orderBy | string | Nein | Sortierfeld (z.B. created_at, updated_at) |
order | string | Nein | Sortierrichtung: asc oder desc (Standard desc) |
locale | string | Nein | Nach Locale filtern (z.B. en, fr). Nur relevant mit i18n. |
Scope: content:read | Read-only: Ja
content_get
Ein einzelnes Content-Element nach ID oder Slug abrufen. Gibt alle Feldwerte, Metadaten und ein _rev Token für optimistische Nebenläufigkeit zurück.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID (ULID) oder Slug |
locale | string | Nein | Locale für Slug-Suche. IDs sind global eindeutig. |
Scope: content:read | Read-only: Ja
content_create
Ein neues Content-Element erstellen. Das data Objekt sollte Feldwerte enthalten, die dem Schema der Collection entsprechen — verwenden Sie schema_get_collection, um zu prüfen, welche Felder verfügbar sind. Elemente werden standardmäßig als draft erstellt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
data | object | Ja | Feldwerte als Schlüssel-Wert-Paare |
slug | string | Nein | URL-Slug (automatisch aus Titel generiert, wenn weggelassen) |
status | string | Nein | Anfangsstatus: draft oder published (Standard draft) |
locale | string | Nein | Locale für diesen Content (Standard: Site-Standard) |
translationOf | string | Nein | ID des Elements, dessen Übersetzung dies ist |
Scope: content:write
content_update
Ein bestehendes Content-Element aktualisieren. Schließen Sie nur Felder ein, die Sie ändern möchten — nicht angegebene Felder bleiben unverändert.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
data | object | Nein | Zu aktualisierende Feldwerte |
slug | string | Nein | Neuer URL-Slug |
status | string | Nein | Neuer Status: draft oder published |
_rev | string | Nein | Revisions-Token von content_get zur Konflikterkennung |
Scope: content:write
content_delete
Ein Content-Element durch Verschieben in den Papierkorb soft-löschen. Verwenden Sie content_restore zum Rückgängigmachen oder content_permanent_delete zum endgültigen Entfernen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write | Destructive: Ja
content_restore
Ein soft-gelöschtes Content-Element aus dem Papierkorb wiederherstellen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write
content_permanent_delete
Ein im Papierkorb befindliches Content-Element dauerhaft und unwiderruflich löschen. Das Element muss zuerst im Papierkorb sein.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write | Destructive: Ja
content_publish
Ein Content-Element veröffentlichen und auf der Website live schalten. Erstellt eine veröffentlichte Revision aus dem aktuellen Entwurf. Weitere Bearbeitungen erstellen einen neuen Entwurf ohne die Live-Version zu beeinflussen, bis erneut veröffentlicht wird.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write
content_unpublish
Ein veröffentlichtes Element auf Entwurfsstatus zurücksetzen. Es wird auf der Live-Website nicht mehr sichtbar sein, aber sein Inhalt bleibt erhalten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write
content_schedule
Ein Content-Element für zukünftige Veröffentlichung planen. Es wird automatisch zum angegebenen Datum/Uhrzeit veröffentlicht.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
scheduledAt | string | Ja | ISO 8601 Datum/Zeit (z.B. 2026-06-01T09:00:00Z) |
Scope: content:write
content_unschedule
Eine zuvor geplante Veröffentlichung abbrechen. Das Element behält seinen aktuellen Status; nur der scheduledAt Zeitstempel wird gelöscht. Idempotent — Aufruf auf einem nicht geplanten Element ist ein No-op.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write
content_compare
Die veröffentlichte (Live-)Version eines Content-Elements mit seinem aktuellen Entwurf vergleichen. Gibt beide Versionen und ein Flag zurück, das anzeigt, ob es Änderungen gibt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:read | Read-only: Ja
content_discard_draft
Den aktuellen Entwurf verwerfen und zur letzten veröffentlichten Version zurückkehren. Funktioniert nur bei Elementen, die mindestens einmal veröffentlicht wurden.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:write | Destructive: Ja
content_list_trashed
Soft-gelöschte Content-Elemente im Papierkorb einer Collection auflisten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
limit | integer | Nein | Max. Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungs-Cursor |
Scope: content:read | Read-only: Ja
content_duplicate
Eine Kopie eines bestehenden Content-Elements erstellen. Das Duplikat wird als Entwurf mit “(Copy)” an den Titel angehängt und einem automatisch generierten Slug erstellt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Zu duplizierende Content-Element-ID oder Slug |
Scope: content:write
content_translations
Alle Locale-Varianten eines Content-Elements abrufen. Gibt die Übersetzungsgruppe und eine Zusammenfassung jeder Locale-Version zurück. Nur relevant, wenn i18n aktiviert ist.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
Scope: content:read | Read-only: Ja
Schema Tools
schema_list_collections
Alle im CMS definierten Content-Collections auflisten. Gibt Slug, Label, unterstützte Funktionen und Zeitstempel zurück.
Keine Parameter.
Scope: schema:read | Minimale Rolle: Editor | Read-only: Ja
schema_get_collection
Detaillierte Informationen über eine Collection einschließlich aller Felddefinitionen abrufen. Felder beschreiben das Datenmodell: Name, Typ, Einschränkungen und Validierungsregeln. Verwenden Sie dies, um zu verstehen, was content_create und content_update erwarten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
slug | string | Ja | Collection-Slug (z.B. posts) |
Scope: schema:read | Minimale Rolle: Editor | Read-only: Ja
schema_create_collection
Eine neue Content-Collection erstellen. Dies erstellt eine Datenbanktabelle und Schema-Definition. Der Slug muss kleingeschrieben, alphanumerisch mit Unterstrichen sein und mit einem Buchstaben beginnen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
slug | string | Ja | Eindeutiger Bezeichner (/^[a-z][a-z0-9_]*$/) |
label | string | Ja | Anzeigename (Plural, z.B. “Blog Posts”) |
labelSingular | string | Nein | Singular-Anzeigename |
description | string | Nein | Beschreibung dieser Collection |
icon | string | Nein | Icon-Name für die Admin-UI |
supports | string[] | Nein | Funktionen: drafts, revisions, preview, scheduling, search (Standard: ['drafts', 'revisions']) |
Scope: schema:write | Minimale Rolle: Admin
schema_delete_collection
Eine Collection und ihre Datenbanktabelle löschen. Dies ist unwiderruflich und löscht alle Inhalte in der Collection.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
slug | string | Ja | Zu löschender Collection-Slug |
force | boolean | Nein | Löschung erzwingen, auch wenn die Collection Inhalt hat |
Scope: schema:write | Minimale Rolle: Admin | Destructive: Ja
schema_create_field
Ein neues Feld zum Schema einer Collection hinzufügen. Dies fügt eine Spalte zur Datenbanktabelle hinzu.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
slug | string | Ja | Feld-Bezeichner (/^[a-z][a-z0-9_]*$/) |
label | string | Ja | Anzeigename |
type | string | Ja | Datentyp (siehe unten) |
required | boolean | Nein | Ob das Feld erforderlich ist |
unique | boolean | Nein | Ob Werte eindeutig sein müssen |
defaultValue | any | Nein | Standardwert für neue Elemente |
validation | object | Nein | Einschränkungen: min, max, minLength, maxLength, pattern, options |
options | object | Nein | Widget-Konfiguration: collection (für Referenzen), rows (für textarea) |
searchable | boolean | Nein | In Volltextsuchindex aufnehmen |
translatable | boolean | Nein | Ob dieses Feld übersetzbar ist (Standard true) |
Feldtypen: string, text, number, integer, boolean, datetime, select, multiSelect, portableText, image, file, reference, json, slug.
Für select und multiSelect Typen geben Sie erlaubte Werte in validation.options an.
Scope: schema:write | Minimale Rolle: Admin
schema_delete_field
Ein Feld aus einer Collection entfernen. Dies löscht die Spalte und alle Daten in diesem Feld. Unwiderruflich.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
fieldSlug | string | Ja | Zu entfernender Feld-Slug |
Scope: schema:write | Minimale Rolle: Admin | Destructive: Ja
Media Tools
media_list
Hochgeladene Mediendateien mit optionaler MIME-Typ-Filterung und Paginierung auflisten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
mimeType | string | Nein | Nach MIME-Typ-Präfix filtern (z.B. image/, application/pdf) |
limit | integer | Nein | Max. Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungs-Cursor |
Scope: media:read | Read-only: Ja
media_create
Eine Mediendatei registrieren, die bereits in den Speicher hochgeladen wurde. Der Aufrufer ist dafür verantwortlich, die Datei bei storageKey zu platzieren (typischerweise mittels signierter Upload-URL aus der Admin-UI oder einer separaten API). Dieses Tool persistiert den Metadaten-Datensatz, sodass die Datei über media_list / media_get auffindbar ist und von Content referenziert werden kann.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
filename | string | Ja | Original-Dateiname (z.B. logo.png) |
mimeType | string | Ja | MIME-Typ (z.B. image/png) |
storageKey | string | Ja | Speicherpfad/-schlüssel, zu dem die Datei hochgeladen wurde |
size | integer | Nein | Dateigröße in Bytes |
width | integer | Nein | Bildbreite in Pixeln |
height | integer | Nein | Bildhöhe in Pixeln |
contentHash | string | Nein | Hash des Dateiinhalts (zur Deduplizierung) |
blurhash | string | Nein | Blurhash für Bild-Platzhalter |
dominantColor | string | Nein | Hex-Farbstring für die dominante Farbe des Bildes |
Scope: media:write | Minimale Rolle: Author
media_get
Details einer einzelnen Mediendatei nach ID abrufen. Gibt Metadaten einschließlich Dateiname, MIME-Typ, Größe, Abmessungen, Alt-Text und URL zurück.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medien-Element-ID |
Scope: media:read | Read-only: Ja
media_update
Metadaten einer hochgeladenen Mediendatei aktualisieren. Die Datei selbst kann nicht geändert werden.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medien-Element-ID |
alt | string | Nein | Alt-Text für Barrierefreiheit |
caption | string | Nein | Bildunterschrift |
width | integer | Nein | Bildbreite in Pixeln |
height | integer | Nein | Bildhöhe in Pixeln |
Scope: media:write
media_delete
Eine Mediendatei dauerhaft löschen. Entfernt den Datenbank-Datensatz und die Datei aus dem Speicher. Content, der diese Medien referenziert, hat fehlerhafte Referenzen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medien-Element-ID |
Scope: media:write | Destructive: Ja
Search Tool
search
Volltextsuche über Content-Collections. Collections müssen search in ihrer supports Liste haben und Felder müssen als searchable markiert sein.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
query | string | Ja | Suchanfrage-Text |
collections | string[] | Nein | Suche auf bestimmte Collection-Slugs beschränken |
locale | string | Nein | Ergebnisse nach Locale filtern |
limit | integer | Nein | Max. Ergebnisse (1-50, Standard 20) |
Scope: content:read | Read-only: Ja
Taxonomy Tools
taxonomy_list
Alle Taxonomie-Definitionen auflisten (z.B. Kategorien, Tags). Gibt Name, Label, ob hierarchisch und zugehörige Collections zurück.
Keine Parameter.
Scope: content:read | Read-only: Ja
taxonomy_list_terms
Begriffe in einer Taxonomie mit Paginierung auflisten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomie-Name (z.B. categories, tags) |
limit | integer | Nein | Max. Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungs-Cursor |
Scope: content:read | Read-only: Ja
taxonomy_create_term
Einen neuen Begriff in einer Taxonomie erstellen. Für hierarchische Taxonomien geben Sie eine parentId an, um einen untergeordneten Begriff zu erstellen. Die Vorfahrenkette des Elternteils darf 100 Ebenen nicht überschreiten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomie-Name |
slug | string | Ja | URL-sicherer Bezeichner |
label | string | Ja | Anzeigename |
parentId | string | Nein | Eltern-Begriff-ID (für hierarchische Taxonomien) |
description | string | Nein | Beschreibung des Begriffs |
Scope: taxonomies:manage | Minimale Rolle: Editor
taxonomy_update_term
Einen bestehenden Begriff in einer Taxonomie aktualisieren. Jedes Feld kann weggelassen werden, um es unverändert zu lassen. Das Umbenennen eines Slugs darf nicht mit einem anderen Begriff in derselben Taxonomie kollidieren. Setzen Sie parentId auf null, um von einem Elternteil zu trennen. Das neue Elternteil muss existieren, zur selben Taxonomie gehören und darf keinen Zyklus einführen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomie-Name |
termSlug | string | Ja | Aktueller Slug des zu aktualisierenden Begriffs |
slug | string | Nein | Neuer Slug (muss in der Taxonomie eindeutig sein) |
label | string | Nein | Neuer Anzeigename |
parentId | string | null | Nein | Neue Eltern-Begriff-ID; null zum Trennen |
description | string | Nein | Neue Beschreibung |
Scope: taxonomies:manage | Minimale Rolle: Editor
taxonomy_delete_term
Einen Begriff dauerhaft aus einer Taxonomie löschen. Jeglicher mit dem Begriff getaggte Content verliert die Zuordnung. Kann keinen Begriff löschen, der untergeordnete Elemente hat — löschen Sie zuerst die untergeordneten Elemente.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomie-Name |
termSlug | string | Ja | Slug des zu löschenden Begriffs |
Scope: taxonomies:manage | Minimale Rolle: Editor | Destructive: Ja
Menu Tools
menu_list
Navigationsmenüs auflisten. Menüs sind pro Locale: übergeben Sie locale, um nur die Zeilen eines Locale zurückzugeben, oder lassen Sie es weg, um jede Locale-Variante aufzulisten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
locale | string | Nein | Nach Locale filtern (weglassen für alle Locale-Varianten) |
Scope: content:read | Read-only: Ja
menu_get
Ein Menü nach Namen einschließlich aller seiner Elemente in Reihenfolge abrufen. Elemente haben ein Label, URL, Typ und optionales Elternteil für Verschachtelung. Wenn derselbe Menüname in mehreren Locales existiert, übergeben Sie locale, um die beabsichtigte Übersetzung aufzulösen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Menüname (z.B. main, footer) |
locale | string | Nein | Locale zur Auflösung des Menüs |
Scope: content:read | Read-only: Ja
menu_create
Ein neues Navigationsmenü erstellen. Der name ist der stabile Bezeichner, der von Site-Templates verwendet wird; label ist der menschenlesbare Name, der im Admin angezeigt wird. Menüs sind pro Locale, übergeben Sie also locale, wenn derselbe Menüname in mehreren Übersetzungen existiert. Fügen Sie Elemente danach mit menu_set_items hinzu. Wenn translationOf gesetzt ist, muss auch locale gesetzt sein.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Stabiler Bezeichner (/^[a-z][a-z0-9_]*$/) |
label | string | Ja | Anzeigename für den Admin |
locale | string | Nein | Locale für dieses Menü (z.B. fr-fr) |
translationOf | string | Nein | Bestehende Menü-ID, von der diese Locale-Variante erstellt wird |
Scope: menus:manage | Minimale Rolle: Editor
menu_update
Das Label eines Menüs aktualisieren. Der name (stabiler Bezeichner) kann nicht geändert werden. Bei Multi-Locale-Installationen übergeben Sie locale, damit die richtige Übersetzung aktualisiert wird.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Zu aktualisierender Menüname |
label | string | Ja | Neues Anzeige-Label |
locale | string | Nein | Locale des zu aktualisierenden Menüs |
Scope: menus:manage | Minimale Rolle: Editor
menu_delete
Ein Menü und alle seine Elemente löschen. Kann nicht rückgängig gemacht werden. Bei Multi-Locale-Installationen übergeben Sie locale, damit nur die beabsichtigte Übersetzung entfernt wird.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Zu löschender Menüname |
locale | string | Nein | Locale des zu löschenden Menüs |
Scope: menus:manage | Minimale Rolle: Editor | Destructive: Ja
menu_set_items
Die gesamte Elementliste eines Menüs in einem Aufruf ersetzen. Atomar: bestehende Elemente werden gelöscht und die neue Liste wird in der angegebenen Reihenfolge eingefügt. Verwenden Sie dies statt pro-Element-Add/Remove-Operationen, damit die resultierende Reihenfolge und Eltern-Links eindeutig sind. Bei Multi-Locale-Installationen übergeben Sie locale, damit nur die beabsichtigte Übersetzung neu geschrieben wird.
Elemente werden nach Array-Index positioniert. Verschachtelung wird über parentIndex ausgedrückt — ein Element mit parentIndex: 0 ist unter dem Element bei Index 0 verschachtelt. Das Elternteil muss früher in der Liste erscheinen. Elemente ohne parentIndex sind oberste Ebene.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Zu aktualisierender Menüname |
locale | string | Nein | Locale des neu zu schreibenden Menüs |
items | MenuItem[] | Ja | Geordnete Liste von Menü-Elementen (siehe unten) |
Jedes MenuItem hat:
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
label | string | Ja | Element-Anzeigetext |
type | string | Ja | Einer von custom, page, post, taxonomy, collection |
customUrl | string | Nein | URL für type: "custom" Elemente (sonst ignoriert) |
referenceCollection | string | Nein | Ziel-Collection-Slug für Content-Referenzen |
referenceId | string | Nein | Ziel-Content-/Begriff-ID für Referenzen |
titleAttr | string | Nein | HTML title Attribut |
target | string | Nein | HTML target Attribut (z.B. _blank) |
cssClasses | string | Nein | Leerzeichen-getrennte CSS-Klassen |
parentIndex | integer | Nein | Array-Index des Eltern-Elements. Weglassen für oberste Ebene. |
Scope: menus:manage | Minimale Rolle: Editor
Revision Tools
revision_list
Revisionsverlauf für ein Content-Element auflisten, neueste zuerst. Erfordert, dass die Collection revisions unterstützt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Collection-Slug |
id | string | Ja | Content-Element-ID oder Slug |
limit | integer | Nein | Max. Revisionen (1-50, Standard 20) |
Scope: content:read | Read-only: Ja
revision_restore
Ein Content-Element auf eine frühere Revision zurücksetzen. Ersetzt den aktuellen Entwurf durch die Daten der angegebenen Revision. Wird nicht automatisch veröffentlicht — verwenden Sie danach bei Bedarf content_publish.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
revisionId | string | Ja | Wiederherzustellende Revisions-ID |
Scope: content:write
Settings Tools
Seitenweite Einstellungen — Titel, Tagline, Logo, Favicon, kanonische URL, Standard-Seitengröße, Datums- und Zeitformatierung, Social-Handles und SEO-Standards.
settings_get
Alle seitenweiten Einstellungen abrufen. Medien-Referenzen (logo, favicon, seo.defaultOgImage) enthalten aufgelöste URLs neben der zugrunde liegenden mediaId. Nicht gesetzte Werte werden in der Antwort weggelassen.
Keine Parameter.
Scope: settings:read | Minimale Rolle: Editor | Read-only: Ja
settings_update
Eine oder mehrere seitenweite Einstellungen aktualisieren. Partielle Aktualisierung: nur die bereitgestellten Felder werden geändert; weggelassene Felder bleiben wie sie sind. Gibt das vollständige Settings-Objekt nach der Aktualisierung zurück.
Um eine Medien-Referenz (logo, favicon, seo.defaultOgImage) zu setzen, übergeben Sie ein Objekt mit mediaId (und optionalem alt). Das Medien-Element muss bereits existieren — verwenden Sie zuerst media_create.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
title | string | Nein | Site-Titel |
tagline | string | Nein | Kurze Beschreibung neben dem Titel |
logo | MediaRef | Nein | Logo-Medien-Referenz ({ mediaId, alt? }) |
favicon | MediaRef | Nein | Favicon-Medien-Referenz |
url | string | Nein | Kanonische Site-URL (http oder https). Leerer String löscht sie. |
postsPerPage | integer | Nein | Standard-Seitengröße für Content-Auflistungen (1-100) |
dateFormat | string | Nein | Datumsformat-Token-String |
timezone | string | Nein | IANA-Zeitzone-Bezeichner |
social | object | Nein | Social-Handles — twitter, github, facebook, instagram, linkedin, youtube |
seo | object | Nein | SEO-Standards (siehe unten) |
Das seo Objekt akzeptiert:
| Feld | Typ | Beschreibung |
|---|---|---|
titleSeparator | string | Trennzeichen zwischen Seitentitel und Site-Titel (z.B. " | " für senkrechten Strich) |
defaultOgImage | MediaRef | Standard-Open Graph-Bild, wenn Content keines hat |
robotsTxt | string | Benutzerdefinierter robots.txt Body. Weglassen für EmDash-Standard. |
googleVerification | string | Google Search Console Verifizierungs-Token |
bingVerification | string | Bing Webmaster Tools Verifizierungs-Token |
Scope: settings:manage | Minimale Rolle: Admin
OAuth Discovery
Die meisten MCP-Clients handhaben dies für Sie; dieser Abschnitt ist für den Bau eines MCP-Clients gegen EmDash direkt. Clients, die OAuth 2.1 unterstützen, erkennen, wie sie sich authentifizieren, aus zwei Metadaten-Dokumenten, die der Server veröffentlicht:
Protected Resource Metadata
Fordern Sie die Protected Resource Metadata an folgendem Endpunkt an:
GET /.well-known/oauth-protected-resource
Der Server antwortet mit der Ressourcen-Kennung, ihrem Authorization Server und unterstützten Scopes:
{
"resource": "https://example.com/_emdash/api/mcp",
"authorization_servers": ["https://example.com/_emdash"],
"scopes_supported": [
"content:read", "content:write",
"media:read", "media:write",
"schema:read", "schema:write",
"taxonomies:manage", "menus:manage",
"settings:read", "settings:manage",
"admin"
],
"bearer_methods_supported": ["header"]
}
Authorization Server Metadata
Fordern Sie die Authorization Server Metadata an folgendem Endpunkt an:
GET /.well-known/oauth-authorization-server/_emdash
Der Server antwortet mit den Endpunkten, Scopes und Grant-Typen, die er unterstützt:
{
"issuer": "https://example.com/_emdash",
"authorization_endpoint": "https://example.com/_emdash/oauth/authorize",
"token_endpoint": "https://example.com/_emdash/api/oauth/token",
"scopes_supported": ["content:read", "content:write", "..."],
"response_types_supported": ["code"],
"grant_types_supported": [
"authorization_code",
"refresh_token",
"urn:ietf:params:oauth:grant-type:device_code"
],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"],
"device_authorization_endpoint": "https://example.com/_emdash/api/oauth/device/code"
}
Wenn eine nicht authentifizierte Anfrage den MCP-Endpunkt trifft, gibt der Server zurück:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"
Dies löst den Standard-MCP-Client-Discovery-Flow aus.
Fehlerbehandlung
Tool-Fehler werden als Text-Inhalt mit isError: true zurückgegeben. Die Nachricht ist mit einem stabilen [CODE] präfixiert, und derselbe Code wird in _meta.code wiederholt:
{
"content": [{ "type": "text", "text": "[NOT_FOUND] Collection 'nonexistent' not found" }],
"isError": true,
"_meta": { "code": "NOT_FOUND" }
}
Scope- und Berechtigungsfehler verwenden dasselbe Tool-Fehler-Envelope:
{
"content": [
{ "type": "text", "text": "[INSUFFICIENT_SCOPE] Insufficient scope: requires content:write" }
],
"isError": true,
"_meta": { "code": "INSUFFICIENT_SCOPE" }
}
Transport-Level-Fehler (Server-Fehlkonfiguration, unbehandelte Ausnahmen) geben JSON-RPC-Fehlercode -32603 (Internal error) zurück, ohne Implementierungsdetails preiszugeben.