MCP Server Reference

In questa pagina

EmDash include un server Model Context Protocol (MCP) integrato all’indirizzo /_emdash/api/mcp che espone le operazioni di gestione dei contenuti come strumenti per gli assistenti AI.

Questa pagina copre i dettagli del protocollo: autenticazione, trasporto, specifiche degli strumenti, discovery OAuth e gestione degli errori.

Autenticazione

Il server MCP supporta tre metodi di autenticazione:

MetodoCome funziona
OAuth 2.1 Authorization Code + PKCEFlusso standard per i client MCP. L’utente approva gli scope nel browser.
Personal Access Token (PAT)Token ec_pat_* a lunga durata creati nel pannello admin.
Device FlowFlusso in stile CLI dove approvi un codice nel browser. Usato da emdash login.

Anche i cookie di sessione (dall’interfaccia admin) funzionano, ma non sono pratici per client MCP esterni.

Scope

I token sono limitati da scope per controllare quali operazioni un client può eseguire. Gli scope vengono richiesti durante l’autorizzazione OAuth e applicati a ogni chiamata di strumento.

ScopeConcede accesso a
content:readElencare, ottenere, confrontare e cercare contenuti. Elencare termini di tassonomia e menu.
content:writeCreare, aggiornare, eliminare, pubblicare, depubblicare, pianificare, duplicare e ripristinare contenuti. Creare termini di tassonomia.
media:readElencare e ottenere elementi media.
media:writeAggiornare ed eliminare metadati dei media.
schema:readElencare le collezioni e ottenere gli schemi delle collezioni.
schema:writeCreare ed eliminare collezioni e campi.
adminAccesso completo a tutte le operazioni.

Lo scope admin concede accesso a tutto. L’autenticazione basata su sessione (senza token) ha anche accesso completo in base al ruolo dell’utente.

Requisiti di ruolo

Oltre agli scope, alcuni strumenti richiedono un ruolo RBAC minimo:

OperazioneRuolo minimo
Operazioni sui contenutiNessun minimo (gli scope controllano l’accesso)
Lettura schemaEditor (40)
Scrittura schemaAdmin (50)

Vedi la guida all’autenticazione per le definizioni dei ruoli.

Trasporto

Il server utilizza il trasporto Streamable HTTP in modalità stateless. Ogni richiesta è indipendente — non ci sono sessioni o connessioni persistenti.

  • POST /_emdash/api/mcp — Invia chiamate di strumenti JSON-RPC
  • GET /_emdash/api/mcp — Restituisce 405 (nessun SSE in modalità stateless)
  • DELETE /_emdash/api/mcp — Restituisce 405 (nessuna sessione da chiudere)

Le risposte seguono il formato JSON-RPC 2.0. Gli errori usano codici di errore JSON-RPC standard, con codici specifici MCP per errori di scope e permessi.

Strumenti

Il server espone 33 strumenti in sette domini. Ogni strumento restituisce risultati come contenuto di testo JSON, o un messaggio di errore con isError: true in caso di fallimento.

Strumenti per i contenuti

content_list

Elenca gli elementi di contenuto in una collezione con filtraggio e paginazione opzionali.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione (es. posts, pages)
statusstringNoFiltro: draft, published o scheduled
limitintegerNoNumero massimo di elementi (1-100, predefinito 50)
cursorstringNoCursore di paginazione da una risposta precedente
orderBystringNoCampo per l’ordinamento (es. created_at, updated_at)
orderstringNoDirezione ordinamento: asc o desc (predefinito desc)
localestringNoFiltra per locale (es. en, fr). Rilevante solo con i18n.

Scope: content:read | Sola lettura:

content_get

Ottieni un singolo elemento di contenuto per ID o slug. Restituisce tutti i valori dei campi, i metadati e un token _rev per la concorrenza ottimistica.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento (ULID) o slug
localestringNoLocale per la ricerca per slug. Gli ID sono globalmente univoci.

Scope: content:read | Sola lettura:

content_create

Crea un nuovo elemento di contenuto. L’oggetto data deve contenere valori dei campi corrispondenti allo schema della collezione — usa schema_get_collection per verificare quali campi sono disponibili. Gli elementi vengono creati come draft per impostazione predefinita.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
dataobjectValori dei campi come coppie chiave-valore
slugstringNoSlug URL (generato automaticamente dal titolo se omesso)
statusstringNoStato iniziale: draft o published (predefinito draft)
localestringNoLocale per questo contenuto (predefinito: default del sito)
translationOfstringNoID dell’elemento di cui questo è una traduzione

Scope: content:write

content_update

Aggiorna un elemento di contenuto esistente. Includi solo i campi che vuoi modificare — i campi non specificati rimangono invariati.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug
dataobjectNoValori dei campi da aggiornare
slugstringNoNuovo slug URL
statusstringNoNuovo stato: draft o published
_revstringNoToken di revisione da content_get per il rilevamento dei conflitti

Scope: content:write

content_delete

Elimina temporaneamente un elemento di contenuto spostandolo nel cestino. Usa content_restore per annullare, o content_permanent_delete per rimuoverlo definitivamente.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write | Distruttivo:

content_restore

Ripristina un elemento di contenuto eliminato temporaneamente dal cestino.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write

content_permanent_delete

Elimina permanentemente e irreversibilmente un elemento nel cestino. L’elemento deve essere prima nel cestino.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write | Distruttivo:

content_publish

Pubblica un elemento di contenuto, rendendolo visibile sul sito. Crea una revisione pubblicata dalla bozza corrente. Le modifiche successive creano una nuova bozza senza influire sulla versione live fino alla ripubblicazione.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write

content_unpublish

Riporta un elemento pubblicato allo stato di bozza. Non sarà più visibile sul sito live, ma il suo contenuto viene preservato.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write

content_schedule

Pianifica un elemento di contenuto per la pubblicazione futura. Verrà pubblicato automaticamente alla data/ora specificata.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug
scheduledAtstringData e ora ISO 8601 (es. 2026-06-01T09:00:00Z)

Scope: content:write

content_compare

Confronta la versione pubblicata (live) di un elemento di contenuto con la sua bozza corrente. Restituisce entrambe le versioni e un flag che indica se ci sono modifiche.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:read | Sola lettura:

content_discard_draft

Scarta la bozza corrente e ripristina l’ultima versione pubblicata. Funziona solo su elementi che sono stati pubblicati almeno una volta.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:write | Distruttivo:

content_list_trashed

Elenca gli elementi di contenuto eliminati temporaneamente nel cestino di una collezione.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
limitintegerNoNumero massimo (1-100, predefinito 50)
cursorstringNoCursore di paginazione

Scope: content:read | Sola lettura:

content_duplicate

Crea una copia di un elemento di contenuto esistente. Il duplicato viene creato come bozza con “(Copy)” aggiunto al titolo e uno slug generato automaticamente.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug da duplicare

Scope: content:write

content_translations

Ottieni tutte le varianti locali di un elemento di contenuto. Restituisce il gruppo di traduzione e un riepilogo di ogni versione locale. Rilevante solo quando l’i18n è abilitato.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug

Scope: content:read | Sola lettura:

Strumenti per lo schema

schema_list_collections

Elenca tutte le collezioni di contenuto definite nel CMS. Restituisce slug, etichetta, funzionalità supportate e timestamp.

Nessun parametro.

Scope: schema:read | Ruolo minimo: Editor | Sola lettura:

schema_get_collection

Ottieni informazioni dettagliate su una collezione, incluse tutte le definizioni dei campi. I campi descrivono il modello dati: nome, tipo, vincoli e regole di validazione. Usalo per capire cosa si aspettano content_create e content_update.

ParametroTipoObbligatorioDescrizione
slugstringSlug della collezione (es. posts)

Scope: schema:read | Ruolo minimo: Editor | Sola lettura:

schema_create_collection

Crea una nuova collezione di contenuto. Questo crea una tabella del database e una definizione dello schema. Lo slug deve essere alfanumerico minuscolo con underscore, che inizia con una lettera.

ParametroTipoObbligatorioDescrizione
slugstringIdentificatore univoco (/^[a-z][a-z0-9_]*$/)
labelstringNome visualizzato (plurale, es. “Blog Posts”)
labelSingularstringNoNome visualizzato singolare
descriptionstringNoDescrizione della collezione
iconstringNoNome icona per l’interfaccia admin
supportsstring[]NoFunzionalità: drafts, revisions, preview, scheduling, search (predefinito: ['drafts', 'revisions'])

Scope: schema:write | Ruolo minimo: Admin

schema_delete_collection

Elimina una collezione e la sua tabella del database. Questo è irreversibile e elimina tutti i contenuti nella collezione.

ParametroTipoObbligatorioDescrizione
slugstringSlug della collezione da eliminare
forcebooleanNoForza l’eliminazione anche se la collezione ha contenuti

Scope: schema:write | Ruolo minimo: Admin | Distruttivo:

schema_create_field

Aggiungi un nuovo campo allo schema di una collezione. Questo aggiunge una colonna alla tabella del database.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
slugstringIdentificatore del campo (/^[a-z][a-z0-9_]*$/)
labelstringNome visualizzato
typestringTipo di dato (vedi sotto)
requiredbooleanNoSe il campo è obbligatorio
uniquebooleanNoSe i valori devono essere univoci
defaultValueanyNoValore predefinito per i nuovi elementi
validationobjectNoVincoli: min, max, minLength, maxLength, pattern, options
optionsobjectNoConfigurazione widget: collection (per riferimenti), rows (per textarea)
searchablebooleanNoIncludi nell’indice di ricerca full-text
translatablebooleanNoSe questo campo è traducibile (predefinito true)

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

Per i tipi select e multiSelect, fornisci i valori consentiti in validation.options.

Scope: schema:write | Ruolo minimo: Admin

schema_delete_field

Rimuovi un campo da una collezione. Questo elimina la colonna e tutti i dati in quel campo. Irreversibile.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
fieldSlugstringSlug del campo da rimuovere

Scope: schema:write | Ruolo minimo: Admin | Distruttivo:

Strumenti per i media

media_list

Elenca i file media caricati con filtraggio opzionale per tipo MIME e paginazione.

ParametroTipoObbligatorioDescrizione
mimeTypestringNoFiltra per prefisso tipo MIME (es. image/, application/pdf)
limitintegerNoNumero massimo (1-100, predefinito 50)
cursorstringNoCursore di paginazione

Scope: media:read | Sola lettura:

media_get

Ottieni i dettagli di un singolo file media per ID. Restituisce metadati inclusi nome file, tipo MIME, dimensione, dimensioni, testo alternativo e URL.

ParametroTipoObbligatorioDescrizione
idstringID dell’elemento media

Scope: media:read | Sola lettura:

media_update

Aggiorna i metadati di un file media caricato. Il file stesso non può essere modificato.

ParametroTipoObbligatorioDescrizione
idstringID dell’elemento media
altstringNoTesto alternativo per l’accessibilità
captionstringNoTesto didascalia
widthintegerNoLarghezza immagine in pixel
heightintegerNoAltezza immagine in pixel

Scope: media:write

media_delete

Elimina permanentemente un file media. Rimuove il record dal database e il file dallo storage. I contenuti che fanno riferimento a questo media avranno riferimenti interrotti.

ParametroTipoObbligatorioDescrizione
idstringID dell’elemento media

Scope: media:write | Distruttivo:

Strumento di ricerca

Ricerca full-text nelle collezioni di contenuto. Le collezioni devono avere search nella loro lista supports e i campi devono essere contrassegnati come searchable.

ParametroTipoObbligatorioDescrizione
querystringTesto della query di ricerca
collectionsstring[]NoLimita la ricerca a slug di collezioni specifiche
localestringNoFiltra i risultati per locale
limitintegerNoRisultati massimi (1-50, predefinito 20)

Scope: content:read | Sola lettura:

Strumenti per le tassonomie

taxonomy_list

Elenca tutte le definizioni delle tassonomie (es. categorie, tag). Restituisce nome, etichetta, se è gerarchica e le collezioni associate.

Nessun parametro.

Scope: content:read | Sola lettura:

taxonomy_list_terms

Elenca i termini di una tassonomia con paginazione.

ParametroTipoObbligatorioDescrizione
taxonomystringNome della tassonomia (es. categories, tags)
limitintegerNoNumero massimo (1-100, predefinito 50)
cursorstringNoCursore di paginazione

Scope: content:read | Sola lettura:

taxonomy_create_term

Crea un nuovo termine in una tassonomia. Per le tassonomie gerarchiche, specifica un parentId per creare un termine figlio.

ParametroTipoObbligatorioDescrizione
taxonomystringNome della tassonomia
slugstringIdentificatore URL-safe
labelstringNome visualizzato
parentIdstringNoID del termine genitore (per tassonomie gerarchiche)
descriptionstringNoDescrizione del termine

Scope: content:write

Strumenti per i menu

Elenca tutti i menu di navigazione. Restituisce nome, etichetta e timestamp.

Nessun parametro.

Scope: content:read | Sola lettura:

Ottieni un menu per nome, incluse tutte le sue voci in ordine. Le voci hanno un’etichetta, URL, tipo e genitore opzionale per l’annidamento.

ParametroTipoObbligatorioDescrizione
namestringNome del menu (es. main, footer)

Scope: content:read | Sola lettura:

Strumenti per le revisioni

revision_list

Elenca la cronologia delle revisioni per un elemento di contenuto, dalla più recente. Richiede che la collezione supporti revisions.

ParametroTipoObbligatorioDescrizione
collectionstringSlug della collezione
idstringID dell’elemento o slug
limitintegerNoRevisioni massime (1-50, predefinito 20)

Scope: content:read | Sola lettura:

revision_restore

Ripristina un elemento di contenuto a una revisione precedente. Sostituisce la bozza corrente con i dati della revisione specificata. Non viene pubblicato automaticamente — usa content_publish successivamente se necessario.

ParametroTipoObbligatorioDescrizione
revisionIdstringID della revisione da ripristinare

Scope: content:write

Discovery OAuth

I client MCP che supportano OAuth 2.1 possono scoprire automaticamente come autenticarsi. Il server pubblica due documenti di metadati:

Metadati della risorsa protetta

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"]
}

Metadati del server di autorizzazione

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"
}

Quando una richiesta non autenticata raggiunge l’endpoint MCP, il server restituisce:

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

Questo attiva il flusso standard di discovery del client MCP.

Gestione degli errori

Gli errori degli strumenti vengono restituiti come contenuto di testo con isError: true:

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

Gli errori di scope e permessi generano errori del protocollo MCP:

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

Gli errori a livello di trasporto (configurazione errata del server, eccezioni non gestite) restituiscono il codice di errore JSON-RPC -32603 (Internal error) senza divulgare dettagli implementativi.