O EmDash expõe um servidor Model Context Protocol (MCP) integrado em /_emdash/api/mcp. Os clientes MCP usam-no para ler e gerir conteúdo, bylines, esquemas, media, taxonomias, menus, revisões e definições, e para exportar ou importar o site inteiro.
Autenticação
O endpoint MCP exige um token Bearer. O EmDash suporta estes fluxos de token:
| Método | Uso |
|---|---|
| OAuth 2.1 Authorization Code with Proof Key for Code Exchange (PKCE) | Clientes MCP interativos. O utilizador aprova os scopes pedidos no browser. |
| Personal access token | Acesso de longa duração para um cliente ou automação. Os tokens usam o prefixo ec_pat_ e são criados no admin. |
| OAuth 2.0 Device Authorization Grant | Clientes de linha de comandos que pedem ao utilizador para aprovar um código no browser. emdash login usa este fluxo. |
Cookies de sessão não autenticam o endpoint MCP.
Scopes
Tokens OAuth e de acesso pessoal limitam que ferramentas um cliente pode chamar. A função do utilizador é verificada separadamente, pelo que um scope nunca concede uma permissão que o utilizador não tem.
| Scope | Acesso |
|---|---|
content:read | Ler e pesquisar conteúdo, bylines, taxonomias, termos, menus e revisões. Conteúdo tipo rascunho também exige a permissão content:read_drafts do utilizador. |
content:write | Criar e alterar conteúdo, bylines e revisões. Também concede taxonomies:manage e menus:manage por compatibilidade com tokens existentes. |
media:read | Ler registos de media. |
media:write | Carregar, registar, atualizar e eliminar media. |
schema:read | Ler coleções e campos. |
schema:write | Criar, atualizar e eliminar coleções e campos. |
taxonomies:manage | Criar, atualizar e eliminar definições de taxonomia e termos. |
menus:manage | Criar, atualizar e eliminar menus e itens de menu. |
settings:read | Ler definições do site. |
settings:manage | Atualizar definições do site. |
mcp:tools | Chamar ferramentas MCP expostas por qualquer plugin ativado. |
mcp:tools:<pluginId> | Chamar ferramentas MCP expostas por um plugin ativado. |
transfer:export | Exportar o site inteiro como pacote de site e transferi-lo. |
transfer:analyze | Carregar um pacote de site e analisá-lo para importação. |
transfer:execute | Iniciar, avançar, cancelar e abandonar uma importação de site. |
admin | Chamar todas as ferramentas core, incluindo transferência de site. Ferramentas de plugins ainda exigem mcp:tools ou o scope específico do plugin. |
O scope admin inclui transfer:export, transfer:analyze e transfer:execute. Cada scope de transferência concede apenas as suas próprias ações e exige a função de administrador. Para um cliente, como um agente, analisar um pacote sem exportar ou importar, conceda transfer:analyze em vez de admin.
A página de consentimento do código de autorização permite ao utilizador remover scopes pedidos. O EmDash também intersecta o pedido com os scopes registados do cliente e a função do utilizador, e recusa uma concessão vazia.
Requisitos de função
A tabela seguinte mostra a função mínima para a capacidade ampla. Verificações de propriedade podem exigir função superior quando um utilizador age sobre conteúdo de outro.
| Capacidade | Função mínima |
|---|---|
| Ler conteúdo publicado, media, taxonomias, termos e menus | Subscriber |
| Ler rascunhos, conteúdo agendado, lixo, comparações e revisões | Contributor |
| Criar conteúdo ou carregar media | Contributor |
| Editar ou publicar conteúdo próprio e registar media | Author |
| Gerir bylines, taxonomias, menus ou conteúdo de todos os utilizadores | Editor |
| Ler esquemas ou definições | Editor |
| Alterar esquemas ou definições, eliminar conteúdo permanentemente ou reparar uso de media | Admin |
| Exportar ou importar o site inteiro | Admin |
Consulte funções de utilizador para definições completas.
Transporte
O servidor usa HTTP Streamable sem estado. Cada pedido é independente; o servidor não mantém sessão MCP nem ligação Server-Sent Events.
| Método | Endpoint | Comportamento |
|---|---|---|
POST | /_emdash/api/mcp | Aceita inicialização JSON-RPC, listagem de ferramentas e chamadas. |
GET | /_emdash/api/mcp | Devolve 405 Method Not Allowed. |
DELETE | /_emdash/api/mcp | Devolve 405 Method Not Allowed. |
As respostas usam JSON-RPC 2.0. Chame tools/list para obter os esquemas de entrada e anotações MCP atuais antes de construir um pedido de ferramenta.
Inventário de ferramentas
O inventário seguinte corresponde às ferramentas estáticas devolvidas por tools/list. O título registado está incluído porque os clientes podem exibi-lo em vez do nome da ferramenta.
Ferramentas de conteúdo
| Tool | Registered title | Required scope |
|---|---|---|
content_list | List Content | content:read |
content_get | Get Content | content:read |
content_create | Create Content | content:write |
content_update | Update Content | content:write |
content_delete | Delete Content (Trash) | content:write |
content_restore | Restore Content | content:write |
content_permanent_delete | Permanently Delete Content | content:write |
content_publish | Publish Content | content:write |
content_unpublish | Unpublish Content | content:write |
content_schedule | Schedule Content | content:write |
content_unschedule | Cancel Scheduled Publication | content:write |
content_compare | Compare Live vs Draft | content:read |
content_discard_draft | Discard Draft | content:write |
content_list_trashed | List Trashed Content | content:read |
content_duplicate | Duplicate Content | content:write |
content_translations | Get Content Translations | content:read |
Ferramentas de byline
| Tool | Registered title | Required scope |
|---|---|---|
byline_list | List Bylines | content:read |
byline_get | Get Byline | content:read |
byline_create | Create Byline | content:write |
byline_update | Update Byline | content:write |
byline_delete | Delete Byline | content:write |
byline_translations | List Byline Translations | content:read |
Ferramentas de esquema
| Tool | Registered title | Required scope |
|---|---|---|
schema_list_collections | List Collections | schema:read |
schema_get_collection | Get Collection Schema | schema:read |
schema_list_block_types | List Block Types | schema:read |
schema_get_block_type | Get Block Type | schema:read |
schema_create_block_type | Create Block Type | schema:write |
schema_update_block_type | Update Block Type | schema:write |
schema_activate_block_type_version | Activate Block Type Version | schema:write |
schema_create_collection | Create Collection | schema:write |
schema_delete_collection | Delete Collection | schema:write |
schema_update_collection | Update Collection | schema:write |
schema_create_field | Add Field to Collection | schema:write |
schema_delete_field | Remove Field from Collection | schema:write |
schema_update_field | Update Field | schema:write |
Ferramentas de media
| Tool | Registered title | Required scope |
|---|---|---|
media_list | List Media | media:read |
media_create | Confirm Signed Media Upload | media:write |
media_upload | Upload Media | media:write |
media_get | Get Media Item | media:read |
media_update | Update Media Metadata | media:write |
media_delete | Delete Media | media:write |
media_usage_repair | Repair Media Usage Index | admin |
Ferramenta de pesquisa
| Tool | Registered title | Required scope |
|---|---|---|
search | Search Content | content:read |
Ferramentas de taxonomia
| Tool | Registered title | Required scope |
|---|---|---|
taxonomy_list | List Taxonomies | content:read |
taxonomy_get | Get Taxonomy Definition | content:read |
taxonomy_create | Create Taxonomy Definition | taxonomies:manage |
taxonomy_update | Update Taxonomy Definition | taxonomies:manage |
taxonomy_delete | Delete Taxonomy Definition | taxonomies:manage |
taxonomy_list_terms | List Taxonomy Terms | content:read |
taxonomy_create_term | Create Taxonomy Term | taxonomies:manage |
taxonomy_update_term | Update Taxonomy Term | taxonomies:manage |
taxonomy_delete_term | Delete Taxonomy Term | taxonomies:manage |
taxonomy_term_translations | List Term Translations | content:read |
Ferramentas de menu
| Tool | Registered title | Required scope |
|---|---|---|
menu_list | List Menus | content:read |
menu_get | Get Menu with Items | content:read |
menu_translations | List Menu Translations | content:read |
menu_create | Create Menu | menus:manage |
menu_update | Update Menu | menus:manage |
menu_delete | Delete Menu | menus:manage |
menu_set_items | Set Menu Items | menus:manage |
Ferramentas de revisão
| Tool | Registered title | Required scope |
|---|---|---|
revision_list | List Revisions | content:read |
revision_restore | Restore Revision | content:write |
Ferramentas de definições
| Tool | Registered title | Required scope |
|---|---|---|
settings_get | Get Site Settings | settings:read |
settings_update | Update Site Settings | settings:manage |
Ferramentas de transferência de site
transfer:* significa qualquer um de transfer:export, transfer:analyze ou transfer:execute. O scope admin satisfaz todos os requisitos desta tabela.
| Tool | Registered title | Required scope |
|---|---|---|
site_transfer_capabilities | Get Site Transfer Capabilities | transfer:* |
site_export_start | Start Site Export | transfer:export |
site_export_status | Get Site Export Status | transfer:export |
site_import_analyze | Analyze Site Import | transfer:analyze |
site_import_start | Start Site Import | transfer:execute |
site_import_status | Get Site Import Status | transfer:* |
site_import_resume | Resume Site Import | transfer:execute |
site_import_receipt | Get Site Import Receipt | transfer:* |
site_export_start e site_import_start também aceitam um token sem o scope quando um administrador aprova o pedido. Para a operação que um pedido aprovado inicia, site_export_status, site_import_status, site_import_resume e site_import_receipt aceitam o mesmo token sem o scope.
Usar os esquemas das ferramentas
tools/list devolve a descrição, o esquema de entrada JSON e as anotações de cada ferramenta. Leia esses metadados antes de construir uma chamada para o cliente usar os campos, valores permitidos e limites suportados pela versão EmDash instalada.
Por exemplo, um cliente a atualizar um artigo chama primeiro content_get e mantém o _rev devolvido. Depois pode enviar este pedido 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"
}
}
}
O resultado é devolvido como texto JSON no primeiro bloco de conteúdo. Uma ferramenta com esquema de saída também pode devolver o mesmo valor em structuredContent.
Ciclo de vida do conteúdo e bylines
A referência do ciclo de vida do conteúdo define estado, revisão, permissões, conflitos e comportamento de hooks partilhados por MCP, REST, CLI e painel de admin.
content_get devolve um valor _rev opaco. Passe-o a content_update, content_publish, content_unpublish, content_schedule ou content_discard_draft. Um valor obsoleto devolve conflito; releia o item antes de repetir.
content_update é uma atualização parcial: campos omitidos mantêm os valores atuais. Atualizar um item publicado prepara um rascunho enquanto a versão live permanece inalterada. Use content_compare para rever valores live e rascunho, depois chame content_publish para publicar o rascunho ou content_discard_draft para o remover. content_delete move um item para o lixo; só content_permanent_delete remove permanentemente um item no lixo.
Bylines são créditos reutilizáveis de autor ou colaborador. byline_create pode criar crédito de convidado ou ligar uma byline a um utilizador CMS. Passe o ID de byline devolvido na entrada bylines aceite por content_create e content_update. Eliminar uma byline remove esse crédito do conteúdo e limpa-a como byline principal.
Escritas MCP não participam no bloqueio de edição de entrada do admin. A verificação _rev protege as operações que a aceitam, mas outras ferramentas de escrita podem alterar uma entrada enquanto um editor a tem aberta.
Traduções
Ferramentas de tradução de conteúdo, byline, termo de taxonomia e menu devolvem cada variante de locale no grupo de tradução relevante. Use a entrada translationOf da ferramenta de criação quando o esquema a fornecer; tools/list é autoritativo para os campos obrigatórios.
content_translations aceita coleção e ID ou slug de conteúdo. As ferramentas de tradução de byline, termo e menu aceitam o ID de um registo ou o ID partilhado do grupo de tradução. Um utilizador sem acesso a rascunhos vê apenas traduções de conteúdo publicado.
Esquemas, media, taxonomias e menus
Ferramentas de esquema alteram a estrutura da base de dados. Use schema_get_collection antes de criar conteúdo ou alterar campos; devolve nomes de campo, tipos, restrições e regras de validação disponíveis. Eliminar coleções e campos remove conteúdo armazenado ou valores de campo e não pode ser desfeito.
Use media_upload para enviar bytes codificados em base64. Carregamentos estão sujeitos aos limites de tamanho e tipo MIME configurados; bytes idênticos podem devolver um item de media existente com deduplicated: true.
media_create confirma um carregamento pendente criado via POST /_emdash/api/media/upload-url. Carregue o ficheiro com o URL assinado devolvido, depois chame media_create da mesma conta de utilizador com o storageKey devolvido. A ferramenta verifica que o ficheiro armazenado existe e corresponde ao tamanho indicado ao pedir o URL de carregamento antes de o disponibilizar na biblioteca de media.
Definições de taxonomia descrevem a classificação e as coleções a que se aplicam; termos são os valores individuais atribuídos ao conteúdo. Termos hierárquicos podem usar parentId, mas um pai deve pertencer à mesma taxonomia e não pode criar ciclo. Criar ou atualizar um termo com parentId numa taxonomia não hierárquica devolve VALIDATION_ERROR. Um termo com filhos deve tê-los removidos ou movidos antes da eliminação.
menu_set_items substitui a lista completa de itens de um menu numa operação atómica. A ordem do array torna-se a ordem do menu. O parentIndex de um item aninhado aponta para um item anterior no mesmo array; coloque cada pai antes dos filhos.
media_usage_repair pode processar uma coleção ou todas as coleções e pode demorar muito num site grande. Os estados complete, partial, failed e stale são respostas de ferramenta bem-sucedidas. Inspecione o estado e contagens devolvidos em vez de confiar em isError; falhas de autenticação, validação e execução inesperada definem isError: true.
Transferência de site
As ferramentas site_* exportam um site inteiro como pacote de site e importam um pacote para um site vazio. Iniciam e conduzem operações e devolvem resumos limitados. Nunca transportam bytes do pacote, media, conteúdos de registos, endereços de email de principals nem URLs de transferência. Transfira uma exportação e carregue um pacote para importação com a CLI ou a API REST, depois referencie a operação pelo ID.
Toda ferramenta de transferência exige a função Admin. A função é verificada antes do scope; um chamador não admin recebe INSUFFICIENT_PERMISSIONS e nenhum pedido de aprovação é criado.
Exportação
site_export_start aceita comments (predefinição true) e devolve a nova operação. site_export_status executa um passo de exportação limitado em cada chamada e reporta a operação e nextRequestInMs. Chame novamente após esse atraso até nextRequestInMs ser null. Passe advance: false para ler o estado sem executar um passo. Quando a exportação termina, o resultado também inclui totals: contagens de registos por tipo, contagem e bytes de media, e contagem e bytes de ficheiros do pacote.
Importação
Carregue o pacote primeiro. emdash site import <file> --analyze da CLI carrega, analisa e imprime o ID da operação.
site_import_analyze executa um passo de análise limitado por chamada. Repita até nextRequestInMs ser null; o resultado inclui então um resumo do plano com packageDigest, planDigest, executable, contagens, tamanhos, principals, decisões, transformações, avisos e bloqueadores. Cada transformação é listada como o seu code, o kind do registo quando existir, e um count, sem os IDs ou valores a que se aplica. Principals, avisos e bloqueadores listam no máximo 50 itens cada, com a contagem total em total. Principals são listados sem endereços de email, com IDs de utilizador alvo sugeridos e mapeados atualmente. Passe decisions para mapear principals a IDs de utilizador alvo (ou null) e escolher título e slogan do pacote ou alvo. Cada alteração produz um novo planDigest.
site_import_start recebe o ID da operação e os packageDigest e planDigest do plano mais recente. O plano não deve ter bloqueadores. A ferramenta tem destructiveHint: true: uma vez iniciada, a importação escreve no site e bloqueia outras escritas até concluir ou um administrador a abandonar. Mostre o plano ao utilizador e obtenha confirmação antes de chamar.
site_import_resume executa um passo de importação limitado e reporta a operação e nextRequestInMs. Chame até nextRequestInMs ser null; é seguro repetir após desligação. site_import_status reporta a operação e contagens de ficheiros carregados sem avançar a importação. site_import_receipt devolve o recibo completo, incluindo receiptDigest, quando a importação termina.
Enquanto uma importação executa, e após falhar ou ser cancelada até ser abandonada, toda outra ferramenta que possa escrever falha com TRANSFER_IMPORT_IN_PROGRESS. Isto inclui ferramentas de plugins. Ferramentas anotadas readOnlyHint: true e as oito ferramentas site_* continuam a funcionar, e initialize e tools/list nunca são bloqueados. Durante ativação de uso de media, ferramentas de escrita falham da mesma forma com MEDIA_USAGE_ACTIVATION_IN_PROGRESS.
Resumos de operação incluem id, kind, state, stage, progress, packageDigest, planDigest, error ({ code } ou null) e carimbos de data/hora. progress é { done, total } passos, mais records que uma exportação já escreveu, e bytesDone e bytesTotal quando conhecidos. As ferramentas MCP não podem cancelar nem abandonar uma importação; use a API REST.
Aprovações
Um token com admin ou o scope de transferência necessário nunca pede aprovação. Para um token sem nenhum, como um agente com apenas transfer:analyze, site_export_start e site_import_start executam quando um administrador aprova o pedido:
- A primeira chamada sem scope cria um pedido de aprovação pendente e falha com
TRANSFER_APPROVAL_REQUIRED. O texto da mensagem e_meta.detailstrazemapprovalIdeexpiresAt. Chamar de novo com os mesmos argumentos e semapprovalIddevolve o mesmo pedido aberto. - Um administrador aprova em Pedidos de aprovação em Definições → Transfer, ou com o endpoint de aprovação só de sessão da API REST. Tokens de API não podem aprovar pedidos.
- O cliente repete a chamada com os mesmos argumentos e o
approvalId. A aprovação é consumida quando essa chamada inicia a operação. Se a operação não arrancar, o cliente pode repetir com o mesmoapprovalIdaté expirar.
Um pedido está ligado ao utilizador, token, ação e argumentos exatos: opções de exportação, ou ID de operação de importação e ambos os digests. Um pedido pendente expira 15 minutos após criação, e um aprovado 15 minutos após aprovação. Uma chamada com argumentos diferentes ou outro token, ou com aprovação negada, expirada ou usada, falha com TRANSFER_APPROVAL_INVALID.
site_import_start verifica digests, estado da operação e bloqueadores do plano antes de criar um pedido, para um administrador só ser solicitado a aprovar uma importação executável. Uma aprovação precisa de ID de token; um chamador sem recebe INSUFFICIENT_SCOPE.
Após uma chamada aprovada iniciar uma operação, o mesmo utilizador e token podem chamar site_export_status, ou site_import_status, site_import_resume e site_import_receipt, para essa operação sem o scope.
Ferramentas de plugins
Um administrador deve ativar a superfície MCP de cada plugin. Ferramentas ativadas aparecem em tools/list como <pluginId>__<localName> e exigem mcp:tools ou mcp:tools:<pluginId> para chamadas autenticadas por token. O EmDash também verifica a permissão declarada pela rota do plugin e regista plugin, ferramenta, rota e ator no log de auditoria.
Como ferramentas de plugins dependem da instalação, não fazem parte do inventário estático acima.
Descoberta OAuth
Clientes MCP descobrem o servidor de autorização a partir dos metadados do recurso protegido:
GET /.well-known/oauth-protected-resource
A resposta identifica /_emdash/api/mcp como recurso protegido e liga ao servidor de autorização. Os clientes leem depois os metadados em:
GET /.well-known/oauth-authorization-server/_emdash
Esse documento fornece os endpoints atuais de autorização, token, registo e autorização de dispositivo, scopes suportados, tipos de grant e o método PKCE S256. Use os valores descobertos em vez de codificar rotas do protocolo OAuth.
Um pedido MCP não autenticado devolve 401 com o URL de descoberta:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"
Erros
Uma falha de ferramenta tem isError: true. O primeiro bloco de texto começa com um código estável, e _meta.code repete-o para clientes que leem metadados estruturados:
{
"content": [{ "type": "text", "text": "[NOT_FOUND] Collection 'articles' not found" }],
"isError": true,
"_meta": { "code": "NOT_FOUND" }
}
Falhas de autenticação usam códigos como INSUFFICIENT_SCOPE e INSUFFICIENT_PERMISSIONS. Falhas de transporte usam o código de erro interno JSON-RPC -32603 e não expõem a exceção subjacente.