EmDash inclut un serveur Model Context Protocol (MCP) intégré à /_emdash/api/mcp qui expose les opérations de gestion de contenu comme outils pour les assistants IA.
Cette page couvre les détails du protocole : authentification, transport, spécifications des outils, découverte OAuth et gestion des erreurs.
Authentification
Le serveur MCP supporte trois méthodes d’authentification :
| Méthode | Fonctionnement |
|---|---|
| OAuth 2.1 Authorization Code + PKCE | Flux standard pour les clients MCP. L’utilisateur approuve les scopes dans le navigateur. |
| Personal Access Token (PAT) | Tokens ec_pat_* à longue durée de vie créés dans le panneau d’administration. |
| Device Flow | Flux de type CLI où vous approuvez un code dans le navigateur. Utilisé par emdash login. |
Les cookies de session (de l’UI d’administration) fonctionnent aussi mais ne sont pas pratiques pour les clients MCP externes.
Scopes
Les tokens ont une portée limitée pour restreindre les opérations qu’un client peut effectuer. Les scopes sont demandés lors de l’autorisation OAuth et appliqués à chaque appel d’outil. Sur la page de consentement du code d’autorisation, tous les scopes demandés sont sélectionnés par défaut ; l’utilisateur peut retirer des scopes avant approbation mais ne peut pas en ajouter que le client n’a pas demandés. L’octroi effectif est aussi restreint par les scopes enregistrés du client et le rôle de l’utilisateur, et EmDash rejette un octroi vide.
| Scope | Accorde l’accès à |
|---|---|
content:read | Lister, obtenir, comparer et rechercher du contenu. Lister les taxonomies, termes de taxonomie et menus. |
content:write | Créer, mettre à jour, supprimer, publier, dépublier, planifier, déplanifier, dupliquer et restaurer du contenu. Accorde implicitement taxonomies:manage et menus:manage pour la rétrocompatibilité. |
media:read | Lister et obtenir des éléments média. |
media:write | Enregistrer (créer), mettre à jour et supprimer les métadonnées média. |
schema:read | Lister les collections et obtenir les schémas de collection. |
schema:write | Créer et supprimer des collections et des champs. |
taxonomies:manage | Créer, mettre à jour et supprimer des termes de taxonomie. |
menus:manage | Créer, mettre à jour et supprimer des menus de navigation et leurs éléments. |
settings:read | Lire les paramètres du site. |
settings:manage | Mettre à jour les paramètres du site. |
mcp:tools | Invoquer des outils MCP explicitement activés de n’importe quel plugin. |
mcp:tools:<pluginId> | Invoquer des outils MCP explicitement activés d’un plugin. |
admin | Accès complet à toutes les opérations. |
Le scope admin accorde l’accès aux opérations principales, mais pas l’accès MCP des plugins. Les outils de plugins nécessitent toujours mcp:tools ou le scope spécifique au plugin correspondant.
content:write accorde implicitement taxonomies:manage et menus:manage pour que les tokens émis avant la séparation de ces scopes continuent de fonctionner. Les nouveaux tokens devraient demander les scopes granulaires.
Exigences de rôle
En plus des scopes, certains outils nécessitent un rôle RBAC minimum. Les deux doivent être satisfaits — un token avec le bon scope échoue quand même si le rôle de l’utilisateur appelant est trop bas.
Les outils de plugins utilisent la permission déclarée par leur route sous-jacente. Ils sont absents de tools/list tant qu’un administrateur n’a pas activé la surface MCP de ce plugin. Les noms d’outils utilisent la forme déterministe <pluginId>__<localName>, et les invocations sont enregistrées dans le journal d’audit.
| Opération | Rôle minimum |
|---|---|
| Lecture de contenu | Subscriber (10) pour les éléments publiés ; Contributor (20) pour les brouillons, planifiés, corbeille et révisions |
| Création de contenu | Contributor (20) |
| Éditer/supprimer le sien | Author (30) |
| Publier du contenu | Author (30) pour les siens ; Editor (40) pour agir sur ceux des autres |
| Lecture de schéma | Editor (40) |
| Écriture de schéma | Admin (50) |
| Gestion des taxonomies | Editor (40) |
| Gestion des menus | Editor (40) |
| Lecture des paramètres | Editor (40) |
| Gestion des paramètres | Admin (50) |
Upload média (media_upload) | Contributor (20) |
Enregistrement média (media_create) | Author (30) |
| Réparation d’usage média | Admin (50) |
Consultez le guide d’authentification pour les définitions de rôles.
Transport
Le serveur utilise le transport Streamable HTTP en mode sans état. Chaque requête est indépendante — il n’y a pas de sessions ni de connexions longue durée.
POST /_emdash/api/mcp— Envoyer des appels d’outils JSON-RPCGET /_emdash/api/mcp— Retourne 405 (pas de SSE en mode sans état)DELETE /_emdash/api/mcp— Retourne 405 (pas de session à fermer)
Les réponses suivent le format JSON-RPC 2.0. Les erreurs utilisent les codes d’erreur JSON-RPC standard, avec des codes spécifiques MCP pour les échecs de scope et permission.
Outils
Le serveur expose des outils dans huit domaines : contenu, schéma, média, recherche, taxonomies, menus, révisions et paramètres. Chaque outil retourne des résultats en contenu texte JSON, ou un message d’erreur avec isError: true en cas d’échec.
Outils de contenu
content_list
Liste les éléments de contenu d’une collection avec filtrage et pagination optionnels.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection (ex. posts, pages) |
status | string | Non | Filtre : draft, published ou scheduled |
limit | integer | Non | Max. éléments à retourner (1-100, défaut 50) |
cursor | string | Non | Curseur de pagination d’une réponse précédente |
orderBy | string | Non | Champ de tri (ex. created_at, updated_at) |
order | string | Non | Direction de tri : asc ou desc (défaut desc) |
locale | string | Non | Filtrer par locale (ex. en, fr). Pertinent uniquement avec i18n. |
Scope : content:read | Lecture seule : Oui
content_get
Obtient un élément de contenu unique par ID ou slug. Retourne toutes les valeurs de champs, métadonnées et un token _rev pour la concurrence optimiste.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément (ULID) ou slug |
locale | string | Non | Locale pour la recherche par slug. Les IDs sont globalement uniques. |
Scope : content:read | Lecture seule : Oui
content_create
Crée un nouvel élément de contenu. L’objet data doit contenir des valeurs de champs correspondant au schéma de la collection — utilisez schema_get_collection pour vérifier quels champs sont disponibles. Les éléments sont créés comme draft par défaut.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
data | object | Oui | Valeurs de champs en paires clé-valeur |
slug | string | Non | Slug URL (auto-généré du titre si omis) |
status | string | Non | Statut initial : draft ou published (défaut draft) |
locale | string | Non | Locale pour ce contenu (défaut : défaut du site) |
translationOf | string | Non | ID de l’élément dont c’est une traduction |
Scope : content:write
content_update
Met à jour un élément de contenu existant. N’incluez que les champs à modifier — les champs non spécifiés restent inchangés.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
data | object | Non | Valeurs de champs à mettre à jour |
slug | string | Non | Nouveau slug URL |
status | string | Non | Nouveau statut : draft ou published |
_rev | string | Non | Token de révision de content_get pour la détection de conflits |
Scope : content:write
content_delete
Supprime un élément de contenu de manière réversible en le déplaçant vers la corbeille. Utilisez content_restore pour annuler, ou content_permanent_delete pour le supprimer définitivement.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write | Destructif : Oui
content_restore
Restaure un élément supprimé de manière réversible depuis la corbeille.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write
content_permanent_delete
Supprime définitivement et irréversiblement un élément de la corbeille. L’élément doit d’abord être dans la corbeille.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write | Destructif : Oui
content_publish
Publie un élément de contenu, le rendant visible sur le site. Crée une révision publiée à partir du brouillon actuel. Les modifications ultérieures créent un nouveau brouillon sans affecter la version en ligne jusqu’à re-publication.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write
content_unpublish
Remet un élément publié en statut brouillon. Il ne sera plus visible sur le site en ligne mais son contenu est préservé.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write
content_schedule
Planifie un élément de contenu pour publication future. Il sera automatiquement publié à la date/heure spécifiée.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
scheduledAt | string | Oui | Date/heure ISO 8601 (ex. 2026-06-01T09:00:00Z) |
Scope : content:write
content_unschedule
Annule une publication précédemment planifiée. L’élément garde son statut actuel ; seul le timestamp scheduledAt est effacé. Idempotent — appeler sur un élément non planifié est un no-op.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write
content_compare
Compare la version publiée (en ligne) d’un élément avec son brouillon actuel. Retourne les deux versions et un indicateur de changements.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:read | Lecture seule : Oui
content_discard_draft
Abandonne le brouillon actuel et revient à la dernière version publiée. Ne fonctionne que sur des éléments publiés au moins une fois.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:write | Destructif : Oui
content_list_trashed
Liste les éléments supprimés de manière réversible dans la corbeille d’une collection.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
limit | integer | Non | Max. éléments (1-100, défaut 50) |
cursor | string | Non | Curseur de pagination |
Scope : content:read | Lecture seule : Oui
content_duplicate
Crée une copie d’un élément existant. Le doublon est créé comme brouillon avec « (Copie) » ajouté au titre et un slug auto-généré.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID ou slug de l’élément à dupliquer |
Scope : content:write
content_translations
Obtient toutes les variantes de locale d’un élément de contenu. Retourne le groupe de traduction et un résumé de chaque version de locale. Pertinent uniquement quand i18n est activé.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
Scope : content:read | Lecture seule : Oui
Outils de schéma
schema_list_collections
Liste toutes les collections de contenu définies dans le CMS.
Aucun paramètre.
Scope : schema:read | Rôle minimum : Editor | Lecture seule : Oui
schema_get_collection
Obtient des informations détaillées sur une collection y compris toutes les définitions de champs.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
slug | string | Oui | Slug de la collection (ex. posts) |
Scope : schema:read | Rôle minimum : Editor | Lecture seule : Oui
schema_create_collection
Crée une nouvelle collection de contenu. Crée une table de base de données et une définition de schéma.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
slug | string | Oui | Identifiant unique (/^[a-z][a-z0-9_]*$/) |
label | string | Oui | Nom d’affichage (pluriel) |
labelSingular | string | Non | Nom d’affichage singulier |
description | string | Non | Description de cette collection |
icon | string | Non | Nom d’icône pour l’UI d’admin |
supports | string[] | Non | Fonctionnalités : drafts, revisions, preview, scheduling, search (défaut : ['drafts', 'revisions']) |
Scope : schema:write | Rôle minimum : Admin
schema_delete_collection
Supprime une collection et sa table de base de données. Irréversible et supprime tout le contenu.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
slug | string | Oui | Slug de la collection à supprimer |
force | boolean | Non | Forcer la suppression même si la collection a du contenu |
Scope : schema:write | Rôle minimum : Admin | Destructif : Oui
schema_create_field
Ajoute un nouveau champ au schéma d’une collection.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
slug | string | Oui | Identifiant du champ (/^[a-z][a-z0-9_]*$/) |
label | string | Oui | Nom d’affichage |
type | string | Oui | Type de données (voir ci-dessous) |
required | boolean | Non | Si le champ est obligatoire |
unique | boolean | Non | Si les valeurs doivent être uniques |
defaultValue | any | Non | Valeur par défaut pour les nouveaux éléments |
validation | object | Non | Contraintes : min, max, minLength, maxLength, pattern, options |
options | object | Non | Config widget : collection (pour les références), rows (pour textarea) |
searchable | boolean | Non | Inclure dans l’index de recherche plein texte |
translatable | boolean | Non | Si ce champ est traduisible (défaut true) |
Types de champs : string, text, number, integer, boolean, datetime, select, multiSelect, portableText, image, file, reference, json, slug.
Scope : schema:write | Rôle minimum : Admin
schema_delete_field
Supprime un champ d’une collection. Supprime la colonne et toutes les données. Irréversible.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
fieldSlug | string | Oui | Slug du champ à supprimer |
Scope : schema:write | Rôle minimum : Admin | Destructif : Oui
Outils média
media_list
Liste les fichiers média uploadés avec filtrage optionnel par type MIME et pagination.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
mimeType | string | Non | Filtrer par préfixe de type MIME (ex. image/, application/pdf) |
limit | integer | Non | Max. éléments (1-100, défaut 50) |
cursor | string | Non | Curseur de pagination |
Scope : media:read | Lecture seule : Oui
media_upload
Upload un fichier média depuis des données encodées en base64 ou une URL externe et l’enregistre dans la bibliothèque de médias.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
filename | string | Oui | Nom de fichier avec extension (ex. cover.png) |
base64 | string | Un des deux base64 / url | Contenu du fichier encodé en base64 |
url | string | Un des deux base64 / url | URL http(s) publique pour récupérer le fichier |
contentType | string | Avec base64 | Type MIME (ex. image/png) |
alt | string | Non | Texte alternatif pour l’accessibilité |
Scope : media:write | Rôle minimum : Contributor
media_create
Enregistre un fichier média déjà uploadé dans le stockage.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
filename | string | Oui | Nom de fichier original |
mimeType | string | Oui | Type MIME |
storageKey | string | Oui | Chemin/clé de stockage |
size | integer | Non | Taille du fichier en octets |
width | integer | Non | Largeur de l’image en pixels |
height | integer | Non | Hauteur de l’image en pixels |
contentHash | string | Non | Hash du contenu du fichier |
blurhash | string | Non | Blurhash pour les placeholders d’image |
dominantColor | string | Non | Couleur dominante hexadécimale |
Scope : media:write | Rôle minimum : Author
media_get
Obtient les détails d’un fichier média par ID.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
id | string | Oui | ID de l’élément média |
Scope : media:read | Lecture seule : Oui
media_update
Met à jour les métadonnées d’un fichier média. Le fichier lui-même ne peut pas être changé.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
id | string | Oui | ID de l’élément média |
alt | string | Non | Texte alternatif |
caption | string | Non | Légende |
width | integer | Non | Largeur en pixels |
height | integer | Non | Hauteur en pixels |
Scope : media:write
media_delete
Supprime définitivement un fichier média.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
id | string | Oui | ID de l’élément média |
Scope : media:write | Destructif : Oui
media_usage_repair
Répare les index d’utilisation de médias dans le contenu pour une collection ou toutes les collections.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
scope | "collection" | "all" | Oui | Réparer une collection ou toutes |
collection | string | Pour le scope collection | Slug de la collection |
Scope : admin | Rôle minimum : Admin
Outil de recherche
search
Recherche plein texte dans les collections de contenu.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
query | string | Oui | Texte de recherche |
collections | string[] | Non | Limiter à des slugs de collection spécifiques |
locale | string | Non | Filtrer par locale |
limit | integer | Non | Max. résultats (1-50, défaut 20) |
Scope : content:read | Lecture seule : Oui
Outils de taxonomie
taxonomy_list
Liste toutes les définitions de taxonomie.
Aucun paramètre.
Scope : content:read | Lecture seule : Oui
taxonomy_list_terms
Liste les termes d’une taxonomie avec pagination.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
taxonomy | string | Oui | Nom de la taxonomie |
limit | integer | Non | Max. éléments (1-100, défaut 50) |
cursor | string | Non | Curseur de pagination |
Scope : content:read | Lecture seule : Oui
taxonomy_create_term
Crée un nouveau terme dans une taxonomie.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
taxonomy | string | Oui | Nom de la taxonomie |
slug | string | Oui | Identifiant URL-safe |
label | string | Oui | Nom d’affichage |
parentId | string | Non | ID du terme parent (pour les taxonomies hiérarchiques) |
description | string | Non | Description du terme |
Scope : taxonomies:manage | Rôle minimum : Editor
taxonomy_update_term
Met à jour un terme existant dans une taxonomie.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
taxonomy | string | Oui | Nom de la taxonomie |
termSlug | string | Oui | Slug actuel du terme |
slug | string | Non | Nouveau slug |
label | string | Non | Nouveau nom d’affichage |
parentId | string | null | Non | Nouvel ID parent ; null pour détacher |
description | string | Non | Nouvelle description |
Scope : taxonomies:manage | Rôle minimum : Editor
taxonomy_delete_term
Supprime définitivement un terme d’une taxonomie.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
taxonomy | string | Oui | Nom de la taxonomie |
termSlug | string | Oui | Slug du terme à supprimer |
Scope : taxonomies:manage | Rôle minimum : Editor | Destructif : Oui
Outils de menu
menu_list
Liste les menus de navigation.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
locale | string | Non | Filtrer par locale |
Scope : content:read | Lecture seule : Oui
menu_get
Obtient un menu par nom avec tous ses éléments dans l’ordre.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Nom du menu (ex. main, footer) |
locale | string | Non | Locale pour résoudre le menu |
Scope : content:read | Lecture seule : Oui
menu_create
Crée un nouveau menu de navigation.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Identifiant stable (/^[a-z][a-z0-9_]*$/) |
label | string | Oui | Nom d’affichage pour l’admin |
locale | string | Non | Locale pour ce menu |
translationOf | string | Non | ID de menu existant pour cette variante de locale |
Scope : menus:manage | Rôle minimum : Editor
menu_update
Met à jour le label d’un menu.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Nom du menu à mettre à jour |
label | string | Oui | Nouveau label d’affichage |
locale | string | Non | Locale du menu à mettre à jour |
Scope : menus:manage | Rôle minimum : Editor
menu_delete
Supprime un menu et tous ses éléments. Irréversible.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Nom du menu à supprimer |
locale | string | Non | Locale du menu à supprimer |
Scope : menus:manage | Rôle minimum : Editor | Destructif : Oui
menu_set_items
Remplace la liste complète des éléments d’un menu en un seul appel. Atomique.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | Oui | Nom du menu |
locale | string | Non | Locale du menu |
items | MenuItem[] | Oui | Liste ordonnée d’éléments de menu |
Chaque MenuItem a :
| Champ | Type | Requis | Description |
|---|---|---|---|
label | string | Oui | Texte d’affichage |
type | string | Oui | Un de custom, page, post, taxonomy, collection |
customUrl | string | Non | URL pour type: "custom" |
referenceCollection | string | Non | Slug de collection cible |
referenceId | string | Non | ID de contenu/terme cible |
titleAttr | string | Non | Attribut HTML title |
target | string | Non | Attribut HTML target |
cssClasses | string | Non | Classes CSS séparées par des espaces |
parentIndex | integer | Non | Index du parent dans le tableau |
Scope : menus:manage | Rôle minimum : Editor
Outils de révision
revision_list
Liste l’historique des révisions d’un élément, plus récente en premier.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
collection | string | Oui | Slug de la collection |
id | string | Oui | ID de l’élément ou slug |
limit | integer | Non | Max. révisions (1-50, défaut 20) |
Scope : content:read | Lecture seule : Oui
revision_restore
Restaure un élément à une révision précédente. N’est pas automatiquement publié — utilisez content_publish ensuite si nécessaire.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
revisionId | string | Oui | ID de la révision à restaurer |
Scope : content:write
Outils de paramètres
Paramètres du site — titre, slogan, logo, favicon, URL canonique, taille de page par défaut, formatage de date et heure, identifiants sociaux et valeurs SEO par défaut.
settings_get
Obtient tous les paramètres du site.
Aucun paramètre.
Scope : settings:read | Rôle minimum : Editor | Lecture seule : Oui
settings_update
Met à jour un ou plusieurs paramètres du site. Mise à jour partielle.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
title | string | Non | Titre du site |
tagline | string | Non | Description courte |
logo | MediaRef | Non | Référence média du logo ({ mediaId, alt? }) |
favicon | MediaRef | Non | Référence média du favicon |
url | string | Non | URL canonique du site. Chaîne vide pour effacer. |
postsPerPage | integer | Non | Taille de page par défaut (1-100) |
dateFormat | string | Non | Format de date |
timezone | string | Non | Identifiant de fuseau horaire IANA |
social | object | Non | Identifiants sociaux — twitter, github, facebook, instagram, linkedin, youtube |
seo | object | Non | Valeurs SEO par défaut |
L’objet seo accepte :
| Champ | Type | Description |
|---|---|---|
titleSeparator | string | Séparateur entre titre de page et titre du site |
defaultOgImage | MediaRef | Image Open Graph par défaut |
robotsTxt | string | Corps personnalisé de robots.txt |
googleVerification | string | Token de vérification Google Search Console |
bingVerification | string | Token de vérification Bing Webmaster Tools |
Scope : settings:manage | Rôle minimum : Admin
Découverte OAuth
La plupart des clients MCP gèrent cela automatiquement ; cette section est pour construire un client MCP directement contre EmDash.
Métadonnées de la ressource protégée
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",
"taxonomies:manage", "menus:manage",
"settings:read", "settings:manage",
"admin"
],
"bearer_methods_supported": ["header"]
}
Métadonnées du serveur d’autorisation
GET /.well-known/oauth-authorization-server/_emdash
{
"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"
}
Quand une requête non authentifiée atteint le point de terminaison MCP :
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"
Gestion des erreurs
Les erreurs d’outils sont retournées comme contenu texte avec isError: true. Le message est préfixé d’un [CODE] stable :
{
"content": [{ "type": "text", "text": "[NOT_FOUND] Collection 'nonexistent' not found" }],
"isError": true,
"_meta": { "code": "NOT_FOUND" }
}
Les erreurs de scope et de permission utilisent la même enveloppe :
{
"content": [
{ "type": "text", "text": "[INSUFFICIENT_SCOPE] Insufficient scope: requires content:write" }
],
"isError": true,
"_meta": { "code": "INSUFFICIENT_SCOPE" }
}
Les erreurs au niveau du transport retournent le code d’erreur JSON-RPC -32603 (Erreur interne) sans divulguer les détails d’implémentation.