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, Tool-Spezifikationen, 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. Der Benutzer genehmigt Scopes im Browser. |
| Personal Access Token (PAT) | Langlebige ec_pat_*-Token, 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
Token sind eingeschränkt, um zu begrenzen, welche Operationen ein Client ausführen kann. Scopes werden während der OAuth-Autorisierung angefordert und bei jedem Tool-Aufruf durchgesetzt. Auf der Zustimmungsseite des Authorization-Code-Flows sind alle angeforderten Scopes standardmäßig ausgewählt; der Benutzer kann Scopes vor der Genehmigung entfernen, aber keine hinzufügen, die der Client nicht angefordert hat. Die effektive Berechtigung wird auch durch die registrierten Scopes des Clients und die Rolle des Benutzers eingeschränkt, und EmDash lehnt eine leere Berechtigung ab.
| Scope | Gewährt Zugang zu |
|---|---|
content:read | Inhalte auflisten, abrufen, vergleichen und durchsuchen. Taxonomien, Taxonomie-Terme und Menüs auflisten. |
content:write | Inhalte erstellen, aktualisieren, löschen, veröffentlichen, zurückziehen, planen, Planung aufheben, duplizieren und wiederherstellen. Gewährt implizit taxonomies:manage und menus:manage für Abwärtskompatibilität mit Token, die vor diesen Scopes ausgestellt wurden. |
media:read | Medienelemente auflisten und abrufen. |
media:write | Medien-Metadaten registrieren (erstellen), aktualisieren und löschen. |
schema:read | Sammlungen auflisten und Sammlungsschemata abrufen. |
schema:write | Sammlungen und Felder erstellen und löschen. |
taxonomies:manage | Taxonomie-Terme erstellen, aktualisieren und löschen. |
menus:manage | Navigationsmenüs und deren Einträge erstellen, aktualisieren und löschen. |
settings:read | Seitenweite Einstellungen lesen. |
settings:manage | Seitenweite Einstellungen aktualisieren. |
mcp:tools | Explizit aktivierte MCP-Tools eines beliebigen Plugins aufrufen. |
mcp:tools:<pluginId> | Explizit aktivierte MCP-Tools eines bestimmten Plugins aufrufen. |
admin | Vollzugriff auf alle Operationen. |
Der admin-Scope gewährt Zugriff auf Kernoperationen, aber nicht auf Plugin-MCP-Zugriff. Plugin-Tools erfordern immer mcp:tools oder den passenden plugin-spezifischen Scope. Session-basierte Auth hat Zugriff basierend auf der Benutzerrolle und der expliziten Admin-Aktivierung des Plugins.
content:write gewährt implizit taxonomies:manage und menus:manage, damit Personal-Access-Token, die vor der Aufteilung dieser Scopes ausgestellt wurden, weiterhin ohne Neuausstellung funktionieren. Neue Token sollten die granularen Scopes anfordern.
Rollenanforderungen
Zusätzlich zu Scopes erfordern einige Tools eine Mindest-RBAC-Rolle. Beide müssen erfüllt sein — ein Token mit dem richtigen Scope schlägt trotzdem fehl, wenn die Rolle des aufrufenden Benutzers zu niedrig ist.
Plugin-Tools verwenden die Berechtigung, die von ihrer zugrunde liegenden Route deklariert wird. Sie fehlen in tools/list, bis ein Administrator die MCP-Oberfläche dieses Plugins aktiviert. Tool-Namen verwenden die deterministische Form <pluginId>__<localName>, und Aufrufe werden im Audit-Log mit Plugin-, Tool-, Routen- und Akteur-Provenienz aufgezeichnet.
| Operation | Mindestrolle |
|---|---|
| Inhalt lesen | Subscriber (10) für veröffentlichte Elemente; Contributor (20) für Entwürfe, geplante, Papierkorb und Revisionen |
| Inhalt erstellen | Contributor (20) |
| Eigene Inhalte bearbeiten / löschen | Author (30) |
| Inhalt veröffentlichen | Author (30) für eigene Elemente; Editor (40) um auf Elemente anderer zu agieren |
| 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_upload) | Contributor (20) |
Medien registrieren (media_create) | Author (30) |
| Mediennutzung reparieren | Admin (50) |
Siehe den Authentifizierungsleitfaden für Rollendefinitionen.
Transport
Der Server verwendet den Streamable-HTTP-Transport im zustandslosen Modus. Jede Anfrage ist unabhängig — es gibt keine Sessions oder langlebigen Verbindungen.
POST /_emdash/api/mcp— JSON-RPC-Tool-Aufrufe sendenGET /_emdash/api/mcp— Gibt 405 zurück (kein SSE im zustandslosen Modus)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 Tools in acht Domänen bereit: Inhalt, Schema, Medien, Suche, Taxonomien, Menüs, Revisionen und Einstellungen. Jedes Tool gibt Ergebnisse als JSON-Textinhalt zurück oder eine Fehlermeldung mit isError: true bei Fehlern.
Inhalts-Tools
content_list
Listet Inhaltselemente in einer Sammlung mit optionaler Filterung und Paginierung auf.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug (z.B. posts, pages) |
status | string | Nein | Filter: draft, published oder scheduled |
limit | integer | Nein | Max. zurückzugebende Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungscursor aus einer vorherigen 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 | Nur-Lesen: Ja
content_get
Ruft ein einzelnes Inhaltselement nach ID oder Slug ab. Gibt alle Feldwerte, Metadaten und ein _rev-Token für optimistische Nebenläufigkeit zurück.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID (ULID) oder Slug |
locale | string | Nein | Locale für Slug-Suche. IDs sind global eindeutig. |
Scope: content:read | Nur-Lesen: Ja
content_create
Erstellt ein neues Inhaltselement. Das data-Objekt sollte Feldwerte enthalten, die dem Schema der Sammlung 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 | Sammlungs-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 Inhalt (Standard: Site-Standard) |
translationOf | string | Nein | ID des Elements, von dem dies eine Übersetzung ist |
Scope: content:write
content_update
Aktualisiert ein bestehendes Inhaltselement. Nur Felder einschließen, die geändert werden sollen — nicht angegebene Felder bleiben unverändert.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-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 | Revisionstoken von content_get zur Konflikterkennung |
Scope: content:write
content_delete
Löscht ein Inhaltselement weich, indem es in den Papierkorb verschoben wird. Verwenden Sie content_restore zum Rückgängigmachen oder content_permanent_delete zum endgültigen Entfernen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write | Destruktiv: Ja
content_restore
Stellt ein weich gelöschtes Inhaltselement aus dem Papierkorb wieder her.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write
content_permanent_delete
Löscht ein im Papierkorb befindliches Inhaltselement dauerhaft und unwiderruflich. Das Element muss sich zuerst im Papierkorb befinden.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write | Destruktiv: Ja
content_publish
Veröffentlicht ein Inhaltselement und macht es auf der Site live. Erstellt eine veröffentlichte Revision aus dem aktuellen Entwurf. Weitere Bearbeitungen erstellen einen neuen Entwurf, ohne die Live-Version zu beeinflussen, bis sie erneut veröffentlicht wird.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write
content_unpublish
Setzt ein veröffentlichtes Element auf den Entwurfsstatus zurück. Es wird auf der Live-Site nicht mehr sichtbar sein, aber sein Inhalt bleibt erhalten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write
content_schedule
Plant ein Inhaltselement für zukünftige Veröffentlichung. Es wird automatisch zum angegebenen Datum/Zeitpunkt veröffentlicht.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
scheduledAt | string | Ja | ISO 8601 Datum/Uhrzeit (z.B. 2026-06-01T09:00:00Z) |
Scope: content:write
content_unschedule
Hebt eine zuvor geplante Veröffentlichung auf. Das Element behält seinen aktuellen Status; nur der scheduledAt-Zeitstempel wird gelöscht. Idempotent — der Aufruf bei einem nicht geplanten Element ist eine No-Op.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write
content_compare
Vergleicht die veröffentlichte (Live-)Version eines Inhaltselements mit seinem aktuellen Entwurf. Gibt beide Versionen und ein Flag zurück, das anzeigt, ob es Änderungen gibt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:read | Nur-Lesen: Ja
content_discard_draft
Verwirft den aktuellen Entwurf und kehrt zur letzten veröffentlichten Version zurück. Funktioniert nur bei Elementen, die mindestens einmal veröffentlicht wurden.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:write | Destruktiv: Ja
content_list_trashed
Listet weich gelöschte Inhaltselemente im Papierkorb einer Sammlung auf.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
limit | integer | Nein | Max. Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungscursor |
Scope: content:read | Nur-Lesen: Ja
content_duplicate
Erstellt eine Kopie eines bestehenden Inhaltselements. Das Duplikat wird als Entwurf erstellt mit „(Kopie)” am Titel angehängt und einem automatisch generierten Slug.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | ID oder Slug des zu duplizierenden Inhaltselements |
Scope: content:write
content_translations
Ruft alle Locale-Varianten eines Inhaltselements ab. Gibt die Übersetzungsgruppe und eine Zusammenfassung jeder Locale-Version zurück. Nur relevant, wenn i18n aktiviert ist.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
Scope: content:read | Nur-Lesen: Ja
Schema-Tools
schema_list_collections
Listet alle im CMS definierten Inhaltssammlungen auf. Gibt Slug, Label, unterstützte Features und Zeitstempel zurück.
Keine Parameter.
Scope: schema:read | Mindestrolle: Editor | Nur-Lesen: Ja
schema_get_collection
Ruft detaillierte Informationen über eine Sammlung ab, einschließlich aller Felddefinitionen. 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 | Sammlungs-Slug (z.B. posts) |
Scope: schema:read | Mindestrolle: Editor | Nur-Lesen: Ja
schema_create_collection
Erstellt eine neue Inhaltssammlung. Dies erstellt eine Datenbanktabelle und Schemadefinition. Der Slug muss aus Kleinbuchstaben, Ziffern und Unterstrichen bestehen 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-Beiträge”) |
labelSingular | string | Nein | Singular-Anzeigename |
description | string | Nein | Beschreibung dieser Sammlung |
icon | string | Nein | Icon-Name für die Admin-UI |
supports | string[] | Nein | Features: drafts, revisions, preview, scheduling, search (Standard: ['drafts', 'revisions']) |
Scope: schema:write | Mindestrolle: Admin
schema_delete_collection
Löscht eine Sammlung und ihre Datenbanktabelle. Dies ist unwiderruflich und löscht alle Inhalte in der Sammlung.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
slug | string | Ja | Zu löschender Sammlungs-Slug |
force | boolean | Nein | Löschung erzwingen, auch wenn die Sammlung Inhalte hat |
Scope: schema:write | Mindestrolle: Admin | Destruktiv: Ja
schema_create_field
Fügt einer Sammlung ein neues Feld hinzu. Dies fügt der Datenbanktabelle eine Spalte hinzu.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
slug | string | Ja | Feldbezeichner (/^[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 Textbereiche) |
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 | Mindestrolle: Admin
schema_delete_field
Entfernt ein Feld aus einer Sammlung. Dies löscht die Spalte und alle Daten in diesem Feld. Unwiderruflich.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
fieldSlug | string | Ja | Zu entfernender Feld-Slug |
Scope: schema:write | Mindestrolle: Admin | Destruktiv: Ja
Medien-Tools
media_list
Listet hochgeladene Mediendateien mit optionaler MIME-Typ-Filterung und Paginierung auf.
| 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 | Paginierungscursor |
Scope: media:read | Nur-Lesen: Ja
media_upload
Lädt eine Mediendatei aus base64-codierten Daten oder einer externen URL hoch und registriert sie in der Medienbibliothek. Gibt das Medienelement mit id, storageKey und url zurück — bereit zur Referenzierung aus Inhaltsfeldern (z.B. featured_image) über content_create / content_update.
Uploads werden nach Inhaltshash dedupliziert: Erneutes Hochladen identischer Bytes gibt das bestehende Element mit deduplicated: true zurück. Bild-Uploads werden automatisch mit Abmessungen, einem Blurhash-Platzhalter und der dominanten Farbe angereichert.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
filename | string | Ja | Dateiname einschließlich Erweiterung (z.B. cover.png) |
base64 | string | Eins von base64 / url | Base64-codierter Dateiinhalt |
url | string | Eins von base64 / url | Öffentliche http(s)-URL zum Abrufen der Datei |
contentType | string | Mit base64 | MIME-Typ (z.B. image/png). Bei url standardmäßig der Content-Type-Header der Antwort. |
alt | string | Nein | Alternativtext für Barrierefreiheit |
Scope: media:write | Mindestrolle: Contributor
media_create
Registriert eine Mediendatei, die bereits in den Speicher hochgeladen wurde. Der Aufrufer ist dafür verantwortlich, die Datei unter storageKey zu platzieren. Dieses Tool persistiert den Metadatensatz, damit die Datei über media_list / media_get auffindbar ist und von Inhalten referenziert werden kann.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
filename | string | Ja | Originaldateiname (z.B. logo.png) |
mimeType | string | Ja | MIME-Typ (z.B. image/png) |
storageKey | string | Ja | Speicherpfad/-schlüssel, unter 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-Farbwert der dominanten Bildfarbe |
Scope: media:write | Mindestrolle: Author
media_get
Ruft Details einer einzelnen Mediendatei nach ID ab. Gibt Metadaten einschließlich Dateiname, MIME-Typ, Größe, Abmessungen, Alternativtext und URL zurück.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medienelement-ID |
Scope: media:read | Nur-Lesen: Ja
media_update
Aktualisiert Metadaten einer hochgeladenen Mediendatei. Die Datei selbst kann nicht geändert werden.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medienelement-ID |
alt | string | Nein | Alternativtext für Barrierefreiheit |
caption | string | Nein | Beschriftungstext |
width | integer | Nein | Bildbreite in Pixeln |
height | integer | Nein | Bildhöhe in Pixeln |
Scope: media:write
media_delete
Löscht eine Mediendatei dauerhaft. Entfernt den Datenbankeintrag und die Datei aus dem Speicher. Inhalte, die auf dieses Medium verweisen, haben defekte Referenzen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Medienelement-ID |
Scope: media:write | Destruktiv: Ja
media_usage_repair
Repariert Inhalts-Mediennutzungsindizes für eine Sammlung oder alle Sammlungen. Die Reparatur läuft synchron und kann bei großen Sites langsam oder teuer sein; bevorzugen Sie den Sammlungsumfang wenn möglich.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
scope | "collection" | "all" | Ja | Ob eine Sammlung oder alle Sammlungen repariert werden |
collection | string | Für Sammlungsumfang | Sammlungs-Slug; weglassen wenn scope all ist |
Das Ergebnis hat einen strukturierten status von complete, partial, failed oder stale, plus aggregierte und pro-Sammlung-Quellenzählungen. Alle vier Status sind erfolgreiche MCP-Tool-Ergebnisse, daher müssen Aufrufer status prüfen anstatt sich auf isError zu verlassen. Authentifizierungs-, Validierungs- oder unerwartete Reparaturfehler geben isError: true zurück.
Scope: admin | Mindestrolle: Admin
Such-Tool
search
Volltextsuche über Inhaltssammlungen. Sammlungen müssen search in ihrer supports-Liste haben und Felder müssen als searchable markiert sein.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
query | string | Ja | Suchanfragetext |
collections | string[] | Nein | Suche auf bestimmte Sammlungs-Slugs beschränken |
locale | string | Nein | Ergebnisse nach Locale filtern |
limit | integer | Nein | Max. Ergebnisse (1-50, Standard 20) |
Scope: content:read | Nur-Lesen: Ja
Taxonomie-Tools
taxonomy_list
Listet alle Taxonomie-Definitionen auf (z.B. Kategorien, Tags). Gibt Name, Label, ob hierarchisch, und zugehörige Sammlungen zurück.
Keine Parameter.
Scope: content:read | Nur-Lesen: Ja
taxonomy_list_terms
Listet Terme in einer Taxonomie mit Paginierung auf.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomiename (z.B. categories, tags) |
limit | integer | Nein | Max. Elemente (1-100, Standard 50) |
cursor | string | Nein | Paginierungscursor |
Scope: content:read | Nur-Lesen: Ja
taxonomy_create_term
Erstellt einen neuen Term in einer Taxonomie. Für hierarchische Taxonomien geben Sie eine parentId an, um einen untergeordneten Term zu erstellen. Die Vorfahrenkette des übergeordneten Terms darf 100 Ebenen nicht überschreiten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomiename |
slug | string | Ja | URL-sicherer Bezeichner |
label | string | Ja | Anzeigename |
parentId | string | Nein | Übergeordnete Term-ID (für hierarchische Taxonomien) |
description | string | Nein | Beschreibung des Terms |
Scope: taxonomies:manage | Mindestrolle: Editor
taxonomy_update_term
Aktualisiert einen bestehenden Term in einer Taxonomie. Jedes Feld kann weggelassen werden, um es unverändert zu lassen. Das Umbenennen eines Slugs darf nicht mit einem anderen Term in derselben Taxonomie kollidieren. Setzen Sie parentId auf null, um vom übergeordneten Element zu lösen. Der neue übergeordnete Term muss existieren, zur selben Taxonomie gehören und keinen Zyklus erzeugen.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomiename |
termSlug | string | Ja | Aktueller Slug des zu aktualisierenden Terms |
slug | string | Nein | Neuer Slug (muss in der Taxonomie eindeutig sein) |
label | string | Nein | Neuer Anzeigename |
parentId | string | null | Nein | Neue übergeordnete Term-ID; null zum Lösen |
description | string | Nein | Neue Beschreibung |
Scope: taxonomies:manage | Mindestrolle: Editor
taxonomy_delete_term
Löscht einen Term dauerhaft aus einer Taxonomie. Alle mit dem Term getaggten Inhalte verlieren die Zuordnung. Kann keinen Term mit untergeordneten Termen löschen — löschen Sie zuerst die untergeordneten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
taxonomy | string | Ja | Taxonomiename |
termSlug | string | Ja | Slug des zu löschenden Terms |
Scope: taxonomies:manage | Mindestrolle: Editor | Destruktiv: Ja
Menü-Tools
menu_list
Listet Navigationsmenüs auf. Menüs sind pro Locale: Übergeben Sie locale, um nur die Zeilen eines Locales zurückzugeben, oder lassen Sie es weg, um alle Locale-Varianten aufzulisten.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
locale | string | Nein | Nach Locale filtern (weglassen für alle Locale-Varianten) |
Scope: content:read | Nur-Lesen: Ja
menu_get
Ruft ein Menü nach Name ab, einschließlich aller Einträge in Reihenfolge. Einträge haben ein Label, eine URL, einen Typ und optionalen Parent 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 zum Auflösen des Menüs |
Scope: content:read | Nur-Lesen: Ja
menu_create
Erstellt ein neues Navigationsmenü. 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 Einträge anschließend 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 | Mindestrolle: Editor
menu_update
Aktualisiert das Label eines Menüs. Der name (stabiler Bezeichner) kann nicht geändert werden. Bei mehrsprachigen 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 | Mindestrolle: Editor
menu_delete
Löscht ein Menü und alle seine Einträge. Kann nicht rückgängig gemacht werden. Bei mehrsprachigen 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 | Mindestrolle: Editor | Destruktiv: Ja
menu_set_items
Ersetzt die gesamte Eintragsliste eines Menüs in einem Aufruf. Atomar: Bestehende Einträge werden gelöscht und die neue Liste wird in der angegebenen Reihenfolge eingefügt. Verwenden Sie dies anstelle von einzelnen Hinzufügen-/Entfernen-Operationen, damit die resultierende Reihenfolge und Parent-Links eindeutig sind. Bei mehrsprachigen Installationen übergeben Sie locale, damit nur die beabsichtigte Übersetzung überschrieben wird.
Einträge werden nach Array-Index positioniert. Verschachtelung wird über parentIndex ausgedrückt — ein Eintrag mit parentIndex: 0 ist unter dem Eintrag an Index 0 verschachtelt. Der Parent muss früher in der Liste erscheinen. Einträge ohne parentIndex sind auf oberster Ebene.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Zu aktualisierender Menüname |
locale | string | Nein | Locale des zu überschreibenden Menüs |
items | MenuItem[] | Ja | Geordnete Liste von Menüeinträgen (siehe unten) |
Jedes MenuItem hat:
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
label | string | Ja | Anzeigetext des Eintrags |
type | string | Ja | Einer von custom, page, post, taxonomy, collection |
customUrl | string | Nein | URL für type: "custom" Einträge (sonst ignoriert) |
referenceCollection | string | Nein | Ziel-Sammlungs-Slug für Inhaltsreferenzen |
referenceId | string | Nein | Ziel-Inhalts-/Term-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 übergeordneten Eintrags. Weglassen für Einträge auf oberster Ebene. |
Scope: menus:manage | Mindestrolle: Editor
Revisions-Tools
revision_list
Listet die Revisionshistorie eines Inhaltselements auf, neueste zuerst. Erfordert, dass die Sammlung revisions unterstützt.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
collection | string | Ja | Sammlungs-Slug |
id | string | Ja | Inhaltselement-ID oder Slug |
limit | integer | Nein | Max. Revisionen (1-50, Standard 20) |
Scope: content:read | Nur-Lesen: Ja
revision_restore
Stellt ein Inhaltselement auf eine vorherige Revision wieder her. Ersetzt den aktuellen Entwurf durch die Daten der angegebenen Revision. Wird nicht automatisch veröffentlicht — verwenden Sie bei Bedarf anschließend content_publish.
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
revisionId | string | Ja | Wiederherzustellende Revisions-ID |
Scope: content:write
Einstellungs-Tools
Seitenweite Einstellungen — Titel, Untertitel, Logo, Favicon, kanonische URL, Standard-Seitengröße, Datums- und Zeitformatierung, Social-Media-Handles und SEO-Standards.
settings_get
Ruft alle seitenweiten Einstellungen ab. Medienreferenzen (logo, favicon, seo.defaultOgImage) enthalten aufgelöste URLs neben der zugrunde liegenden mediaId. Nicht gesetzte Werte werden aus der Antwort weggelassen.
Keine Parameter.
Scope: settings:read | Mindestrolle: Editor | Nur-Lesen: Ja
settings_update
Aktualisiert eine oder mehrere seitenweite Einstellungen. Teilaktualisierung: Nur die angegebenen Felder werden geändert; weggelassene Felder bleiben unverändert. Gibt das vollständige Einstellungsobjekt nach der Aktualisierung zurück.
Um eine Medienreferenz (logo, favicon, seo.defaultOgImage) zu setzen, übergeben Sie ein Objekt mit mediaId (und optionalem alt). Das Medienelement 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-Medienreferenz ({ mediaId, alt? }) |
favicon | MediaRef | Nein | Favicon-Medienreferenz |
url | string | Nein | Kanonische Site-URL (http oder https). Leerer String löscht sie. |
postsPerPage | integer | Nein | Standard-Seitengröße für Inhaltslisten (1-100) |
dateFormat | string | Nein | Datumsformat-Token-String |
timezone | string | Nein | IANA-Zeitzonen-Bezeichner |
social | object | Nein | Social-Media-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 einen vertikalen Strich) |
defaultOgImage | MediaRef | Standard-Open-Graph-Bild, wenn der Inhalt keins hat |
robotsTxt | string | Benutzerdefinierter robots.txt-Inhalt. Weglassen, um den EmDash-Standard zu verwenden. |
googleVerification | string | Google Search Console Verifizierungstoken |
bingVerification | string | Bing Webmaster Tools Verifizierungstoken |
Scope: settings:manage | Mindestrolle: Admin
OAuth-Discovery
Die meisten MCP-Clients handhaben dies automatisch; dieser Abschnitt ist für den direkten Aufbau eines MCP-Clients gegen EmDash. Clients, die OAuth 2.1 unterstützen, entdecken die Authentifizierungsmethode aus zwei Metadatendokumenten, die der Server veröffentlicht:
Metadaten der geschützten Ressource
Fordern Sie die Metadaten der geschützten Ressource am folgenden Endpunkt an:
GET /.well-known/oauth-protected-resource
Der Server antwortet mit dem Ressourcenbezeichner, seinem Autorisierungsserver 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"]
}
Autorisierungsserver-Metadaten
Fordern Sie die Autorisierungsserver-Metadaten am folgenden 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 erreicht, 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 Textinhalt mit isError: true zurückgegeben. Die Nachricht hat ein stabiles [CODE]-Präfix, 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 denselben Tool-Fehler-Umschlag:
{
"content": [
{ "type": "text", "text": "[INSUFFICIENT_SCOPE] Insufficient scope: requires content:write" }
],
"isError": true,
"_meta": { "code": "INSUFFICIENT_SCOPE" }
}
Transport-Level-Fehler (Serverkonfigurationsfehler, unbehandelte Ausnahmen) geben den JSON-RPC-Fehlercode -32603 (Interner Fehler) zurück, ohne Implementierungsdetails preiszugeben.