Référence du serveur MCP

Sur cette page

EmDash expose un serveur Model Context Protocol (MCP) intégré à /_emdash/api/mcp. Les clients MCP l’utilisent pour lire et gérer le contenu, les bylines, les schémas, les médias, les taxonomies, les menus, les révisions et les paramètres, et pour exporter ou importer l’ensemble du site.

Authentification

Le point de terminaison MCP exige un jeton Bearer. EmDash prend en charge ces flux de jetons :

MéthodeUsage
OAuth 2.1 Authorization Code with Proof Key for Code Exchange (PKCE)Clients MCP interactifs. L’utilisateur approuve les scopes demandés dans le navigateur.
Personal access tokenAccès de longue durée pour un client ou une automatisation. Les jetons utilisent le préfixe ec_pat_ et sont créés dans l’admin.
OAuth 2.0 Device Authorization GrantClients en ligne de commande qui demandent à l’utilisateur d’approuver un code dans le navigateur. emdash login utilise ce flux.

Les cookies de session n’authentifient pas le point de terminaison MCP.

Scopes

Les jetons OAuth et d’accès personnel limitent les outils qu’un client peut appeler. Le rôle de l’utilisateur est vérifié séparément : un scope n’accorde jamais une permission que l’utilisateur n’a pas.

ScopeAccès
content:readLire et rechercher contenu, bylines, taxonomies, termes, menus et révisions. Le contenu de type brouillon exige aussi la permission content:read_drafts de l’utilisateur.
content:writeCréer et modifier contenu, bylines et révisions. Accorde aussi taxonomies:manage et menus:manage pour compatibilité avec les jetons existants.
media:readLire les enregistrements média.
media:writeTéléverser, enregistrer, mettre à jour et supprimer des médias.
schema:readLire collections et champs.
schema:writeCréer, mettre à jour et supprimer collections et champs.
taxonomies:manageCréer, mettre à jour et supprimer définitions de taxonomie et termes.
menus:manageCréer, mettre à jour et supprimer menus et éléments de menu.
settings:readLire les paramètres du site.
settings:manageMettre à jour les paramètres du site.
mcp:toolsAppeler les outils MCP exposés par tout plugin activé.
mcp:tools:<pluginId>Appeler les outils MCP exposés par un plugin activé.
transfer:exportExporter l’ensemble du site en paquet de site et le télécharger.
transfer:analyzeTéléverser un paquet de site et l’analyser pour import.
transfer:executeDémarrer, faire avancer, annuler et abandonner un import de site.
adminAppeler tous les outils core, y compris le transfert de site. Les outils plugin exigent toujours mcp:tools ou le scope spécifique au plugin.

Le scope admin inclut transfer:export, transfer:analyze et transfer:execute. Chaque scope de transfert n’accorde que ses propres actions et exige le rôle administrateur. Pour qu’un client, par exemple un agent, analyse un paquet sans exporter ni importer, accordez transfer:analyze plutôt que admin.

La page de consentement du code d’autorisation permet à l’utilisateur de retirer des scopes demandés. EmDash intersecte aussi la demande avec les scopes enregistrés du client et le rôle de l’utilisateur, et refuse une octroi vide.

Exigences de rôle

Le tableau suivant indique le rôle minimum pour la capacité large. Les vérifications de propriété peuvent exiger un rôle supérieur lorsqu’un utilisateur agit sur le contenu d’un autre.

CapacitéRôle minimum
Lire contenu publié, médias, taxonomies, termes et menusSubscriber
Lire brouillons, contenu planifié, corbeille, comparaisons et révisionsContributor
Créer du contenu ou téléverser des médiasContributor
Modifier ou publier son contenu et enregistrer des médiasAuthor
Gérer bylines, taxonomies, menus ou le contenu de tous les utilisateursEditor
Lire schémas ou paramètresEditor
Modifier schémas ou paramètres, supprimer définitivement du contenu ou réparer l’usage médiaAdmin
Exporter ou importer l’ensemble du siteAdmin

Voir rôles utilisateur pour les définitions complètes.

Transport

Le serveur utilise HTTP Streamable sans état. Chaque requête est indépendante ; le serveur ne conserve ni session MCP ni connexion Server-Sent Events.

MéthodePoint de terminaisonComportement
POST/_emdash/api/mcpAccepte initialisation JSON-RPC, listage d’outils et appels d’outils.
GET/_emdash/api/mcpRenvoie 405 Method Not Allowed.
DELETE/_emdash/api/mcpRenvoie 405 Method Not Allowed.

Les réponses utilisent JSON-RPC 2.0. Appelez tools/list pour obtenir les schémas d’entrée et annotations MCP actuels avant de construire une requête d’outil.

Inventaire des outils

L’inventaire suivant correspond aux outils statiques renvoyés par tools/list. Le titre enregistré est inclus car les clients peuvent l’afficher à la place du nom de l’outil.

Outils de contenu

ToolRegistered titleRequired scope
content_listList Contentcontent:read
content_getGet Contentcontent:read
content_createCreate Contentcontent:write
content_updateUpdate Contentcontent:write
content_deleteDelete Content (Trash)content:write
content_restoreRestore Contentcontent:write
content_permanent_deletePermanently Delete Contentcontent:write
content_publishPublish Contentcontent:write
content_unpublishUnpublish Contentcontent:write
content_scheduleSchedule Contentcontent:write
content_unscheduleCancel Scheduled Publicationcontent:write
content_compareCompare Live vs Draftcontent:read
content_discard_draftDiscard Draftcontent:write
content_list_trashedList Trashed Contentcontent:read
content_duplicateDuplicate Contentcontent:write
content_translationsGet Content Translationscontent:read

Outils byline

ToolRegistered titleRequired scope
byline_listList Bylinescontent:read
byline_getGet Bylinecontent:read
byline_createCreate Bylinecontent:write
byline_updateUpdate Bylinecontent:write
byline_deleteDelete Bylinecontent:write
byline_translationsList Byline Translationscontent:read

Outils de schéma

ToolRegistered titleRequired scope
schema_list_collectionsList Collectionsschema:read
schema_get_collectionGet Collection Schemaschema:read
schema_list_block_typesList Block Typesschema:read
schema_get_block_typeGet Block Typeschema:read
schema_create_block_typeCreate Block Typeschema:write
schema_update_block_typeUpdate Block Typeschema:write
schema_activate_block_type_versionActivate Block Type Versionschema:write
schema_create_collectionCreate Collectionschema:write
schema_delete_collectionDelete Collectionschema:write
schema_update_collectionUpdate Collectionschema:write
schema_create_fieldAdd Field to Collectionschema:write
schema_delete_fieldRemove Field from Collectionschema:write
schema_update_fieldUpdate Fieldschema:write

Outils média

ToolRegistered titleRequired scope
media_listList Mediamedia:read
media_createConfirm Signed Media Uploadmedia:write
media_uploadUpload Mediamedia:write
media_getGet Media Itemmedia:read
media_updateUpdate Media Metadatamedia:write
media_deleteDelete Mediamedia:write
media_usage_repairRepair Media Usage Indexadmin

Outil de recherche

ToolRegistered titleRequired scope
searchSearch Contentcontent:read

Outils de taxonomie

ToolRegistered titleRequired scope
taxonomy_listList Taxonomiescontent:read
taxonomy_getGet Taxonomy Definitioncontent:read
taxonomy_createCreate Taxonomy Definitiontaxonomies:manage
taxonomy_updateUpdate Taxonomy Definitiontaxonomies:manage
taxonomy_deleteDelete Taxonomy Definitiontaxonomies:manage
taxonomy_list_termsList Taxonomy Termscontent:read
taxonomy_create_termCreate Taxonomy Termtaxonomies:manage
taxonomy_update_termUpdate Taxonomy Termtaxonomies:manage
taxonomy_delete_termDelete Taxonomy Termtaxonomies:manage
taxonomy_term_translationsList Term Translationscontent:read

Outils de menu

ToolRegistered titleRequired scope
menu_listList Menuscontent:read
menu_getGet Menu with Itemscontent:read
menu_translationsList Menu Translationscontent:read
menu_createCreate Menumenus:manage
menu_updateUpdate Menumenus:manage
menu_deleteDelete Menumenus:manage
menu_set_itemsSet Menu Itemsmenus:manage

Outils de révision

ToolRegistered titleRequired scope
revision_listList Revisionscontent:read
revision_restoreRestore Revisioncontent:write

Outils de paramètres

ToolRegistered titleRequired scope
settings_getGet Site Settingssettings:read
settings_updateUpdate Site Settingssettings:manage

Outils de transfert de site

transfer:* désigne l’un de transfer:export, transfer:analyze ou transfer:execute. Le scope admin satisfait toute exigence de ce tableau.

ToolRegistered titleRequired scope
site_transfer_capabilitiesGet Site Transfer Capabilitiestransfer:*
site_export_startStart Site Exporttransfer:export
site_export_statusGet Site Export Statustransfer:export
site_import_analyzeAnalyze Site Importtransfer:analyze
site_import_startStart Site Importtransfer:execute
site_import_statusGet Site Import Statustransfer:*
site_import_resumeResume Site Importtransfer:execute
site_import_receiptGet Site Import Receipttransfer:*

site_export_start et site_import_start acceptent aussi un jeton sans le scope lorsqu’un admin approuve la demande. Pour l’opération qu’une demande approuvée démarre, site_export_status, site_import_status, site_import_resume et site_import_receipt acceptent le même jeton sans le scope.

Utiliser les schémas d’outils

tools/list renvoie pour chaque outil la description, le schéma d’entrée JSON et les annotations. Lisez ces métadonnées avant de construire un appel pour que votre client utilise les champs, valeurs autorisées et limites pris en charge par la version EmDash installée.

Par exemple, un client mettant à jour un article appelle d’abord content_get et conserve le _rev renvoyé. Il peut ensuite envoyer cette requête JSON-RPC :

{
	"jsonrpc": "2.0",
	"id": 2,
	"method": "tools/call",
	"params": {
		"name": "content_update",
		"arguments": {
			"collection": "articles",
			"id": "01JARTICLE0000000000000000",
			"data": { "title": "Updated title" },
			"_rev": "opaque-revision-token"
		}
	}
}

Le résultat est renvoyé en texte JSON dans le premier bloc de contenu. Un outil avec schéma de sortie peut aussi renvoyer la même valeur dans structuredContent.

Cycle de vie du contenu et bylines

La référence du cycle de vie du contenu définit l’état, la révision, les permissions, les conflits et le comportement des hooks partagés par MCP, REST, la CLI et le panneau d’admin.

content_get renvoie une valeur _rev opaque. Passez-la à content_update, content_publish, content_unpublish, content_schedule ou content_discard_draft. Une valeur obsolète provoque un conflit ; relisez l’élément avant de réessayer.

content_update est une mise à jour partielle : les champs omis conservent leurs valeurs actuelles. Mettre à jour un élément publié prépare un brouillon tandis que la version en ligne reste inchangée. Utilisez content_compare pour comparer les valeurs en ligne et brouillon, puis appelez content_publish pour publier le brouillon ou content_discard_draft pour le supprimer. content_delete déplace un élément vers la corbeille ; seul content_permanent_delete supprime définitivement un élément en corbeille.

Les bylines sont des crédits réutilisables d’auteur ou contributeur. byline_create peut créer un crédit invité ou lier une byline à un utilisateur CMS. Passez l’ID byline renvoyé dans l’entrée bylines acceptée par content_create et content_update. Supprimer une byline retire ce crédit du contenu et l’efface comme byline principale.

Les écritures MCP ne participent pas au verrou d’édition d’entrée de l’admin. La vérification _rev protège les opérations qui l’acceptent, mais d’autres outils d’écriture peuvent modifier une entrée pendant qu’un éditeur l’a ouverte.

Traductions

Les outils de traduction de contenu, byline, terme de taxonomie et menu renvoient chaque variante de locale du groupe de traduction concerné. Utilisez l’entrée translationOf de l’outil de création lorsque son schéma la fournit ; tools/list fait foi pour les champs requis.

content_translations accepte collection et ID ou slug de contenu. Les outils de traduction byline, terme et menu acceptent l’ID d’un enregistrement ou l’ID partagé du groupe de traduction. Un utilisateur sans accès aux brouillons ne voit que les traductions de contenu publié.

Schémas, médias, taxonomies et menus

Les outils de schéma modifient la structure de la base de données. Utilisez schema_get_collection avant de créer du contenu ou de modifier des champs ; il renvoie noms de champs, types, contraintes et règles de validation disponibles. La suppression de collections et champs retire le contenu stocké ou les valeurs de champ et est irréversible.

Utilisez media_upload pour envoyer des octets encodés en base64. Les téléversements sont soumis aux limites de taille et de type MIME configurées ; des octets identiques peuvent renvoyer un élément média existant avec deduplicated: true.

media_create confirme un téléversement en attente créé via POST /_emdash/api/media/upload-url. Téléversez le fichier avec l’URL signée renvoyée, puis appelez media_create depuis le même compte utilisateur avec le storageKey renvoyé. L’outil vérifie que le fichier stocké existe et correspond à la taille indiquée lors de la demande d’URL avant de le rendre disponible dans la bibliothèque média.

Les définitions de taxonomie décrivent la classification et les collections concernées ; les termes sont les valeurs individuelles assignées au contenu. Les termes hiérarchiques peuvent utiliser parentId, mais un parent doit appartenir à la même taxonomie et ne peut créer de cycle. Créer ou mettre à jour un terme avec parentId dans une taxonomie non hiérarchique renvoie VALIDATION_ERROR. Un terme avec des enfants doit les retirer ou les déplacer avant suppression.

menu_set_items remplace la liste complète des éléments d’un menu en une opération atomique. L’ordre du tableau devient l’ordre du menu. Le parentIndex d’un élément imbriqué pointe vers un élément antérieur du même tableau ; placez chaque parent avant ses enfants.

media_usage_repair peut traiter une collection ou toutes les collections et peut s’exécuter longtemps sur un grand site. Ses statuts complete, partial, failed et stale sont des réponses d’outil réussies. Inspectez le statut et les comptages renvoyés plutôt que de vous fier à isError ; authentification, validation et échecs d’exécution inattendus définissent isError: true.

Transfert de site

Les outils site_* exportent un site entier en paquet de site et importent un paquet dans un site vide. Ils démarrent et pilotent des opérations et renvoient des résumés bornés. Ils ne transportent jamais les octets du paquet, les médias, le contenu des enregistrements, les adresses e-mail des principals ni les URL de téléchargement. Téléchargez une exportation et téléversez un paquet pour import avec la CLI ou l’API REST, puis référencez l’opération par son ID.

Chaque outil de transfert exige le rôle Admin. Le rôle est vérifié avant le scope ; un appelant non admin reçoit INSUFFICIENT_PERMISSIONS et aucune demande d’approbation n’est créée.

Export

site_export_start accepte comments (par défaut true) et renvoie la nouvelle opération. site_export_status exécute une étape d’export bornée à chaque appel et signale l’opération et nextRequestInMs. Rappelez après ce délai jusqu’à ce que nextRequestInMs soit null. Passez advance: false pour lire le statut sans exécuter d’étape. Une fois l’export terminé, le résultat inclut aussi totals : comptages d’enregistrements par type, nombre et octets média, et nombre et octets de fichiers du paquet.

Import

Téléversez d’abord le paquet. emdash site import <file> --analyze de la CLI téléverse, analyse et affiche l’ID d’opération.

site_import_analyze exécute une étape d’analyse bornée par appel. Répétez jusqu’à ce que nextRequestInMs soit null ; le résultat inclut alors un résumé de plan avec packageDigest, planDigest, executable, comptages, tailles, principals, décisions, transformations, avertissements et bloqueurs. Chaque transformation est listée par son code, le kind d’enregistrement le cas échéant, et un count, sans les ID ou valeurs concernés. Principals, avertissements et bloqueurs listent au plus 50 éléments chacun, avec le total dans total. Les principals sont listés sans adresses e-mail, avec les ID utilisateur cible suggérés et mappés actuellement. Passez decisions pour mapper les principals aux ID utilisateur cible (ou null) et choisir titre et slogan du paquet ou de la cible. Chaque changement produit un nouveau planDigest.

site_import_start prend l’ID d’opération et les packageDigest et planDigest du plan le plus récent. Le plan ne doit avoir aucun bloqueur. L’outil a destructiveHint: true : une fois démarré, l’import écrit sur le site et bloque les autres écritures jusqu’à achèvement ou abandon par un administrateur. Montrez le plan à l’utilisateur et obtenez sa confirmation avant l’appel.

site_import_resume exécute une étape d’import bornée et signale l’opération et nextRequestInMs. Appelez jusqu’à ce que nextRequestInMs soit null ; la répétition après déconnexion est sûre. site_import_status signale l’opération et les comptages de fichiers téléversés sans faire avancer l’import. site_import_receipt renvoie le reçu complet, y compris receiptDigest, une fois l’import terminé.

Pendant qu’un import s’exécute, et après échec ou annulation jusqu’à abandon, tout autre outil capable d’écrire échoue avec TRANSFER_IMPORT_IN_PROGRESS. Cela inclut les outils plugin. Les outils annotés readOnlyHint: true et les huit outils site_* continuent de fonctionner, et initialize et tools/list ne sont jamais bloqués. Pendant l’activation d’usage média, les outils d’écriture échouent de la même façon avec MEDIA_USAGE_ACTIVATION_IN_PROGRESS.

Les résumés d’opération incluent id, kind, state, stage, progress, packageDigest, planDigest, error ({ code } ou null) et horodatages. progress est { done, total } étapes, plus records écrits par une exportation jusqu’ici, et bytesDone et bytesTotal une fois connus. Les outils MCP ne peuvent pas annuler ni abandonner un import ; utilisez l’API REST.

Approbations

Un jeton avec admin ou le scope de transfert requis ne demande jamais d’approbation. Pour un jeton sans l’un ni l’autre, par exemple un agent avec seulement transfer:analyze, site_export_start et site_import_start s’exécutent lorsqu’un administrateur approuve la demande :

  1. Le premier appel sans scope crée une demande d’approbation en attente et échoue avec TRANSFER_APPROVAL_REQUIRED. Le texte du message et _meta.details portent approvalId et son expiresAt. Un nouvel appel avec les mêmes arguments et sans approvalId renvoie la même demande ouverte.
  2. Un administrateur approuve sous Demandes d’approbation dans Paramètres → Transfer, ou via le point de terminaison d’approbation réservé à la session de l’API REST. Les jetons API ne peuvent pas approuver.
  3. Le client répète l’appel avec les mêmes arguments et l’approvalId. L’approbation est consommée lorsque cet appel démarre l’opération. Si l’opération ne démarre pas, le client peut réessayer avec le même approvalId jusqu’à expiration.

Une demande est liée à l’utilisateur, au jeton, à l’action et aux arguments exacts : options d’export, ou ID d’opération d’import et les deux digests. Une demande en attente expire 15 minutes après création, une approuvée 15 minutes après approbation. Un appel avec d’autres arguments ou un autre jeton, ou avec approbation refusée, expirée ou utilisée, échoue avec TRANSFER_APPROVAL_INVALID.

site_import_start vérifie digests, état de l’opération et bloqueurs du plan avant de créer une demande, afin qu’un administrateur ne soit sollicité que pour un import exécutable. Une approbation exige un ID de jeton ; un appelant sans en reçoit INSUFFICIENT_SCOPE.

Après un appel approuvé qui démarre une opération, le même utilisateur et jeton peuvent appeler site_export_status, ou site_import_status, site_import_resume et site_import_receipt, pour cette opération sans le scope.

Outils plugin

Un administrateur doit activer la surface MCP de chaque plugin. Les outils activés apparaissent dans tools/list comme <pluginId>__<localName> et exigent mcp:tools ou mcp:tools:<pluginId> pour les appels authentifiés par jeton. EmDash vérifie aussi la permission déclarée par la route plugin et enregistre plugin, outil, route et acteur dans le journal d’audit.

Les outils plugin étant spécifiques à l’installation, ils ne font pas partie de l’inventaire statique ci-dessus.

Découverte OAuth

Les clients MCP découvrent le serveur d’autorisation via les métadonnées de ressource protégée :

GET /.well-known/oauth-protected-resource

La réponse identifie /_emdash/api/mcp comme ressource protégée et lie au serveur d’autorisation. Les clients lisent ensuite ses métadonnées à :

GET /.well-known/oauth-authorization-server/_emdash

Ce document fournit les points de terminaison actuels d’autorisation, de jeton, d’enregistrement et d’autorisation d’appareil, les scopes pris en charge, les types de grant et la méthode PKCE S256. Utilisez les valeurs découvertes plutôt que de coder en dur les routes du protocole OAuth.

Une requête MCP non authentifiée renvoie 401 avec l’URL de découverte :

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

Erreurs

Un échec d’outil a isError: true. Le premier bloc texte commence par un code stable, et _meta.code le répète pour les clients lisant les métadonnées structurées :

{
	"content": [{ "type": "text", "text": "[NOT_FOUND] Collection 'articles' not found" }],
	"isError": true,
	"_meta": { "code": "NOT_FOUND" }
}

Les échecs d’authentification utilisent des codes tels que INSUFFICIENT_SCOPE et INSUFFICIENT_PERMISSIONS. Les échecs de transport utilisent le code d’erreur interne JSON-RPC -32603 et n’exposent pas l’exception sous-jacente.