MCP-Server-Referenz

Auf dieser Seite

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:

MethodeSo funktioniert es
OAuth 2.1 Authorization Code + PKCEStandardablauf für MCP-Clients. Der Benutzer genehmigt Berechtigungen im Browser.
Persönlicher Zugriffstoken (PAT)Langlebige ec_pat_*-Tokens, die im Admin-Panel erstellt werden.
Device FlowCLI-ähnlicher Ablauf, bei dem Sie einen Code im Browser bestätigen. Wird von emdash login verwendet.

Sitzungscookies (aus der Admin-Oberfläche) funktionieren ebenfalls, sind aber für externe MCP-Clients nicht praktikabel.

Berechtigungen (Scopes)

Tokens sind auf bestimmte Berechtigungen beschränkt, um die möglichen Operationen eines Clients einzugrenzen. Berechtigungen werden während der OAuth-Autorisierung angefordert und bei jedem Tool-Aufruf durchgesetzt.

ScopeGewährt Zugriff auf
content:readInhalte auflisten, abrufen, vergleichen und durchsuchen. Taxonomie-Begriffe und Menüs auflisten.
content:writeInhalte erstellen, aktualisieren, löschen, veröffentlichen, zurückziehen, planen, duplizieren und wiederherstellen. Taxonomie-Begriffe erstellen.
media:readMedienelemente auflisten und abrufen.
media:writeMetadaten von Medien aktualisieren und löschen.
schema:readSammlungen auflisten und Sammlungsschemata abrufen.
schema:writeSammlungen und Felder erstellen und löschen.
adminVollständiger Zugriff auf alle Operationen.

Der admin-Scope gewährt Zugriff auf alles. Sitzungsbasierte Authentifizierung (ohne Token) hat ebenfalls vollen Zugriff basierend auf der Rolle des Benutzers.

Rollenanforderungen

Zusätzlich zu den Berechtigungen erfordern einige Tools eine Mindest-RBAC-Rolle:

OperationMindestrolle
InhaltsoperationenKeine Mindestanforderung (Berechtigungen steuern den Zugriff)
Schema lesenRedakteur (40)
Schema schreibenAdministrator (50)

Siehe die Authentifizierungsanleitung für Rollendefinitionen.

Transport

Der Server verwendet den Streamable-HTTP-Transport im zustandslosen Modus. Jede Anfrage ist unabhängig — es gibt keine Sitzungen oder langlebige Verbindungen.

  • POST /_emdash/api/mcp — JSON-RPC-Tool-Aufrufe senden
  • GET /_emdash/api/mcp — Gibt 405 zurück (kein SSE im zustandslosen Modus)
  • DELETE /_emdash/api/mcp — Gibt 405 zurück (keine Sitzung zum Beenden)

Antworten folgen dem JSON-RPC 2.0-Format. Fehler verwenden Standard-JSON-RPC-Fehlercodes, mit MCP-spezifischen Codes für Berechtigungs- und Zugriffsfehler.

Tools

Der Server stellt 33 Tools in sieben Bereichen bereit. Jedes Tool gibt Ergebnisse als JSON-Textinhalt zurück oder eine Fehlermeldung mit isError: true bei einem Fehler.

Inhalts-Tools

content_list

Inhalte in einer Sammlung mit optionaler Filterung und Paginierung auflisten.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug (z. B. posts, pages)
statusstringNeinFilter: draft, published oder scheduled
limitintegerNeinMaximale Anzahl zurückgegebener Elemente (1–100, Standard 50)
cursorstringNeinPaginierungscursor aus einer vorherigen Antwort
orderBystringNeinFeld zum Sortieren (z. B. created_at, updated_at)
orderstringNeinSortierrichtung: asc oder desc (Standard desc)
localestringNeinNach Sprache filtern (z. B. en, fr). Nur relevant bei i18n.

Scope: content:read | Nur Lesen: Ja

content_get

Ein einzelnes Inhaltselement anhand seiner ID oder seines Slugs abrufen. Gibt alle Feldwerte, Metadaten und ein _rev-Token für optimistische Nebenläufigkeit zurück.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID (ULID) oder Slug
localestringNeinSprache für die Slug-Suche. IDs sind global eindeutig.

Scope: content:read | Nur Lesen: Ja

content_create

Ein neues Inhaltselement erstellen. Das data-Objekt sollte Feldwerte enthalten, die dem Schema der Sammlung entsprechen — verwenden Sie schema_get_collection, um die verfügbaren Felder zu prüfen. Elemente werden standardmäßig als draft erstellt.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
dataobjectJaFeldwerte als Schlüssel-Wert-Paare
slugstringNeinURL-Slug (wird automatisch aus dem Titel generiert, wenn nicht angegeben)
statusstringNeinAnfangsstatus: draft oder published (Standard draft)
localestringNeinSprache für diesen Inhalt (Standard: Website-Standard)
translationOfstringNeinID des Elements, dessen Übersetzung dies ist

Scope: content:write

content_update

Ein bestehendes Inhaltselement aktualisieren. Geben Sie nur die Felder an, die Sie ändern möchten — nicht angegebene Felder bleiben unverändert.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug
dataobjectNeinZu aktualisierende Feldwerte
slugstringNeinNeuer URL-Slug
statusstringNeinNeuer Status: draft oder published
_revstringNeinRevisionstoken von content_get zur Konflikterkennung

Scope: content:write

content_delete

Ein Inhaltselement durch Verschieben in den Papierkorb vorläufig löschen. Verwenden Sie content_restore zum Rückgängigmachen oder content_permanent_delete zum endgültigen Entfernen.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write | Destruktiv: Ja

content_restore

Ein vorläufig gelöschtes Inhaltselement aus dem Papierkorb wiederherstellen.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write

content_permanent_delete

Ein Inhaltselement im Papierkorb dauerhaft und unwiderruflich löschen. Das Element muss sich zuvor im Papierkorb befinden.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write | Destruktiv: Ja

content_publish

Ein Inhaltselement veröffentlichen und auf der Website live schalten. Erstellt eine veröffentlichte Revision aus dem aktuellen Entwurf. Weitere Bearbeitungen erzeugen einen neuen Entwurf, ohne die Live-Version zu beeinflussen, bis erneut veröffentlicht wird.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write

content_unpublish

Ein veröffentlichtes Element in den Entwurfsstatus zurückversetzen. Es ist auf der Live-Website nicht mehr sichtbar, aber der Inhalt bleibt erhalten.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write

content_schedule

Ein Inhaltselement für eine zukünftige Veröffentlichung planen. Es wird automatisch zum angegebenen Datum/Zeitpunkt veröffentlicht.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug
scheduledAtstringJaISO 8601-Datum/Uhrzeit (z. B. 2026-06-01T09:00:00Z)

Scope: content:write

content_compare

Die veröffentlichte (Live-)Version eines Inhaltselements mit seinem aktuellen Entwurf vergleichen. Gibt beide Versionen und ein Flag zurück, das anzeigt, ob Änderungen vorliegen.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:read | Nur Lesen: 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.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:write | Destruktiv: Ja

content_list_trashed

Vorläufig gelöschte Inhaltselemente im Papierkorb einer Sammlung auflisten.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
limitintegerNeinMaximale Elemente (1–100, Standard 50)
cursorstringNeinPaginierungscursor

Scope: content:read | Nur Lesen: Ja

content_duplicate

Eine Kopie eines bestehenden Inhaltselements erstellen. Das Duplikat wird als Entwurf erstellt, mit „(Kopie)” am Titel angehängt und einem automatisch generierten Slug.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug zum Duplizieren

Scope: content:write

content_translations

Alle Sprachvarianten eines Inhaltselements abrufen. Gibt die Übersetzungsgruppe und eine Zusammenfassung jeder Sprachversion zurück. Nur relevant, wenn i18n aktiviert ist.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug

Scope: content:read | Nur Lesen: Ja

Schema-Tools

schema_list_collections

Alle im CMS definierten Inhaltssammlungen auflisten. Gibt Slug, Label, unterstützte Funktionen und Zeitstempel zurück.

Keine Parameter.

Scope: schema:read | Mindestrolle: Redakteur | Nur Lesen: Ja

schema_get_collection

Detaillierte Informationen über eine Sammlung 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.

ParameterTypErforderlichBeschreibung
slugstringJaSammlungs-Slug (z. B. posts)

Scope: schema:read | Mindestrolle: Redakteur | Nur Lesen: Ja

schema_create_collection

Eine neue Inhaltssammlung erstellen. Dies erstellt eine Datenbanktabelle und Schemadefinition. Der Slug muss aus Kleinbuchstaben, Ziffern und Unterstrichen bestehen und mit einem Buchstaben beginnen.

ParameterTypErforderlichBeschreibung
slugstringJaEindeutiger Bezeichner (/^[a-z][a-z0-9_]*$/)
labelstringJaAnzeigename (Plural, z. B. „Blog-Beiträge”)
labelSingularstringNeinAnzeigename im Singular
descriptionstringNeinBeschreibung dieser Sammlung
iconstringNeinIcon-Name für die Admin-Oberfläche
supportsstring[]NeinFunktionen: drafts, revisions, preview, scheduling, search (Standard: ['drafts', 'revisions'])

Scope: schema:write | Mindestrolle: Administrator

schema_delete_collection

Eine Sammlung und ihre Datenbanktabelle löschen. Dies ist unwiderruflich und löscht alle Inhalte in der Sammlung.

ParameterTypErforderlichBeschreibung
slugstringJaZu löschender Sammlungs-Slug
forcebooleanNeinLöschung erzwingen, auch wenn die Sammlung Inhalte enthält

Scope: schema:write | Mindestrolle: Administrator | Destruktiv: Ja

schema_create_field

Ein neues Feld zum Schema einer Sammlung hinzufügen. Dies fügt der Datenbanktabelle eine Spalte hinzu.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
slugstringJaFeldbezeichner (/^[a-z][a-z0-9_]*$/)
labelstringJaAnzeigename
typestringJaDatentyp (siehe unten)
requiredbooleanNeinOb das Feld erforderlich ist
uniquebooleanNeinOb Werte eindeutig sein müssen
defaultValueanyNeinStandardwert für neue Elemente
validationobjectNeinEinschränkungen: min, max, minLength, maxLength, pattern, options
optionsobjectNeinWidget-Konfiguration: collection (für Referenzen), rows (für Textbereich)
searchablebooleanNeinIn den Volltextsuchindex aufnehmen
translatablebooleanNeinOb dieses Feld übersetzbar ist (Standard: true)

Feldtypen: string, text, number, integer, boolean, datetime, select, multiSelect, portableText, image, file, reference, json, slug.

Für die Typen select und multiSelect geben Sie die erlaubten Werte in validation.options an.

Scope: schema:write | Mindestrolle: Administrator

schema_delete_field

Ein Feld aus einer Sammlung entfernen. Dies entfernt die Spalte und löscht alle Daten in diesem Feld. Unwiderruflich.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
fieldSlugstringJaZu entfernender Feld-Slug

Scope: schema:write | Mindestrolle: Administrator | Destruktiv: Ja

Medien-Tools

media_list

Hochgeladene Mediendateien mit optionaler MIME-Typ-Filterung und Paginierung auflisten.

ParameterTypErforderlichBeschreibung
mimeTypestringNeinNach MIME-Typ-Präfix filtern (z. B. image/, application/pdf)
limitintegerNeinMaximale Elemente (1–100, Standard 50)
cursorstringNeinPaginierungscursor

Scope: media:read | Nur Lesen: Ja

media_get

Details einer einzelnen Mediendatei anhand der ID abrufen. Gibt Metadaten zurück, einschließlich Dateiname, MIME-Typ, Größe, Abmessungen, Alt-Text und URL.

ParameterTypErforderlichBeschreibung
idstringJaMedien-ID

Scope: media:read | Nur Lesen: Ja

media_update

Metadaten einer hochgeladenen Mediendatei aktualisieren. Die Datei selbst kann nicht geändert werden.

ParameterTypErforderlichBeschreibung
idstringJaMedien-ID
altstringNeinAlt-Text für Barrierefreiheit
captionstringNeinBildunterschrift
widthintegerNeinBildbreite in Pixeln
heightintegerNeinBildhöhe in Pixeln

Scope: media:write

media_delete

Eine Mediendatei dauerhaft löschen. Entfernt den Datenbankeintrag und die Datei aus dem Speicher. Inhalte, die auf dieses Medium verweisen, werden fehlerhafte Verweise haben.

ParameterTypErforderlichBeschreibung
idstringJaMedien-ID

Scope: media:write | Destruktiv: Ja

Such-Tool

Volltextsuche über Inhaltssammlungen. Sammlungen müssen search in ihrer supports-Liste haben und Felder müssen als searchable markiert sein.

ParameterTypErforderlichBeschreibung
querystringJaSuchanfragetext
collectionsstring[]NeinSuche auf bestimmte Sammlungs-Slugs beschränken
localestringNeinErgebnisse nach Sprache filtern
limitintegerNeinMaximale Ergebnisse (1–50, Standard 20)

Scope: content:read | Nur Lesen: Ja

Taxonomie-Tools

taxonomy_list

Alle Taxonomie-Definitionen auflisten (z. B. Kategorien, Schlagwörter). Gibt Name, Label, ob hierarchisch, und zugehörige Sammlungen zurück.

Keine Parameter.

Scope: content:read | Nur Lesen: Ja

taxonomy_list_terms

Begriffe in einer Taxonomie mit Paginierung auflisten.

ParameterTypErforderlichBeschreibung
taxonomystringJaTaxonomie-Name (z. B. categories, tags)
limitintegerNeinMaximale Elemente (1–100, Standard 50)
cursorstringNeinPaginierungscursor

Scope: content:read | Nur Lesen: 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.

ParameterTypErforderlichBeschreibung
taxonomystringJaTaxonomie-Name
slugstringJaURL-sicherer Bezeichner
labelstringJaAnzeigename
parentIdstringNeinÜbergeordnete Begriff-ID (für hierarchische Taxonomien)
descriptionstringNeinBeschreibung des Begriffs

Scope: content:write

Menü-Tools

Alle Navigationsmenüs auflisten. Gibt Name, Label und Zeitstempel zurück.

Keine Parameter.

Scope: content:read | Nur Lesen: Ja

Ein Menü anhand des Namens einschließlich aller Einträge in Reihenfolge abrufen. Einträge haben ein Label, eine URL, einen Typ und optional einen übergeordneten Eintrag für Verschachtelung.

ParameterTypErforderlichBeschreibung
namestringJaMenüname (z. B. main, footer)

Scope: content:read | Nur Lesen: Ja

Revisions-Tools

revision_list

Revisionsverlauf für ein Inhaltselement auflisten, neueste zuerst. Die Sammlung muss revisions unterstützen.

ParameterTypErforderlichBeschreibung
collectionstringJaSammlungs-Slug
idstringJaInhaltselement-ID oder Slug
limitintegerNeinMaximale Revisionen (1–50, Standard 20)

Scope: content:read | Nur Lesen: Ja

revision_restore

Ein Inhaltselement auf eine frühere Revision zurücksetzen. Ersetzt den aktuellen Entwurf durch die Daten der angegebenen Revision. Wird nicht automatisch veröffentlicht — verwenden Sie anschließend content_publish, falls erforderlich.

ParameterTypErforderlichBeschreibung
revisionIdstringJaWiederherzustellende Revisions-ID

Scope: content:write

OAuth-Discovery

MCP-Clients, die OAuth 2.1 unterstützen, können automatisch erkennen, wie die Authentifizierung erfolgt. Der Server veröffentlicht zwei Metadaten-Dokumente:

Metadaten der geschützten Ressource

GET /.well-known/oauth-protected-resource
{
  "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",
    "admin"
  ],
  "bearer_methods_supported": ["header"]
}

Metadaten des Autorisierungsservers

GET /_emdash/.well-known/oauth-authorization-server
{
  "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 Folgendes zurück:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"

Dies löst den standardmäßigen MCP-Client-Discovery-Ablauf aus.

Fehlerbehandlung

Tool-Fehler werden als Textinhalt mit isError: true zurückgegeben:

{
  "content": [{ "type": "text", "text": "Collection 'nonexistent' not found" }],
  "isError": true
}

Berechtigungs- und Zugriffsfehler lösen MCP-Protokollfehler aus:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32600,
    "message": "Insufficient scope: requires content:write"
  },
  "id": 1
}

Transportebene-Fehler (Serverkonfigurationsfehler, unbehandelte Ausnahmen) geben den JSON-RPC-Fehlercode -32603 (Interner Fehler) zurück, ohne Implementierungsdetails preiszugeben.