Referência do servidor MCP

Nesta página

O EmDash expõe um servidor Model Context Protocol (MCP) integrado em /_emdash/api/mcp. Os clientes MCP o usam para ler e gerenciar conteúdo, bylines, esquemas, mídia, taxonomias, menus, revisões e configurações, e para exportar ou importar o site inteiro.

Autenticação

O endpoint MCP exige um token Bearer. O EmDash oferece suporte a estes fluxos de token:

MétodoUso
OAuth 2.1 Authorization Code with Proof Key for Code Exchange (PKCE)Clientes MCP interativos. O usuário aprova no navegador os escopos solicitados.
Personal access tokenAcesso de longa duração para um cliente ou uma automação. Os tokens usam o prefixo ec_pat_ e são criados no admin.
OAuth 2.0 Device Authorization GrantClientes de linha de comando que pedem ao usuário que aprove um código no navegador. O emdash login usa esse fluxo.

Cookies de sessão não autenticam o endpoint MCP.

Escopos

Os tokens OAuth e os tokens de acesso pessoal limitam quais ferramentas um cliente pode chamar. O papel do usuário é verificado separadamente, então um escopo nunca concede uma permissão que o usuário não tem.

EscopoAcesso
content:readLer e pesquisar conteúdo, bylines, taxonomias, termos, menus e revisões. Conteúdo semelhante a rascunho também exige a permissão content:read_drafts do usuário.
content:writeCriar e alterar conteúdo, bylines e revisões. Também concede taxonomies:manage e menus:manage por compatibilidade com os tokens existentes.
media:readLer registros de mídia.
media:writeEnviar, registrar, atualizar e excluir mídia.
schema:readLer coleções e campos.
schema:writeCriar, atualizar e excluir coleções e campos.
taxonomies:manageCriar, atualizar e excluir definições de taxonomia e termos.
menus:manageCriar, atualizar e excluir menus e itens de menu.
settings:readLer as configurações do site.
settings:manageAtualizar as configurações do site.
mcp:toolsChamar as ferramentas MCP expostas por qualquer plugin habilitado.
mcp:tools:<pluginId>Chamar as ferramentas MCP expostas por um único plugin habilitado.
transfer:exportExportar o site inteiro como um pacote do site e baixá-lo.
transfer:analyzeEnviar um pacote do site e analisá-lo para importação.
transfer:executeIniciar, avançar, cancelar e abandonar uma importação do site.
adminChamar todas as ferramentas do núcleo, incluindo as de transferência de site. As ferramentas de plugins continuam exigindo mcp:tools ou o escopo específico do plugin.

O escopo admin inclui transfer:export, transfer:analyze e transfer:execute. Cada escopo de transferência concede apenas as próprias ações e exige o papel de administrador. Para permitir que um cliente, como um agente, analise um pacote do site sem exportar nem importar, conceda transfer:analyze em vez de admin.

A página de consentimento do código de autorização permite que o usuário remova escopos solicitados. O EmDash também cruza a requisição com os escopos registrados do cliente e com o papel do usuário, e recusa uma concessão vazia.

Requisitos de papel

A tabela a seguir mostra o papel mínimo para cada capacidade geral. As verificações de propriedade podem exigir um papel mais alto quando um usuário age sobre o conteúdo de outro usuário.

CapacidadePapel mínimo
Ler conteúdo publicado, mídia, taxonomias, termos e menusSubscriber
Ler rascunhos, conteúdo agendado, lixeira, comparações e revisõesContributor
Criar conteúdo ou enviar mídiaContributor
Editar ou publicar o próprio conteúdo e registrar mídiaAuthor
Gerenciar bylines, taxonomias, menus ou o conteúdo de todos os usuáriosEditor
Ler esquemas ou configuraçõesEditor
Alterar esquemas ou configurações, excluir conteúdo permanentemente ou reparar o uso de mídiaAdmin
Exportar ou importar o site inteiroAdmin

Consulte os papéis de usuário para ver as definições completas dos papéis.

Transporte

O servidor usa HTTP Streamable sem estado. Cada requisição é independente; o servidor não mantém uma sessão MCP nem uma conexão de Server-Sent Events.

MétodoEndpointComportamento
POST/_emdash/api/mcpAceita a inicialização do JSON-RPC, a listagem de ferramentas e as chamadas de ferramentas.
GET/_emdash/api/mcpRetorna 405 Method Not Allowed.
DELETE/_emdash/api/mcpRetorna 405 Method Not Allowed.

As respostas usam JSON-RPC 2.0. Chame tools/list para obter os esquemas de entrada e as anotações MCP atuais antes de montar uma requisição de ferramenta.

Inventário de ferramentas

O inventário a seguir corresponde às ferramentas estáticas retornadas por tools/list. O título registrado está incluído porque os clientes podem exibi-lo no lugar do nome da ferramenta.

Ferramentas de conteúdo

FerramentaTítulo registradoEscopo necessário
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

Ferramentas de byline

FerramentaTítulo registradoEscopo necessário
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

Ferramentas de esquema

FerramentaTítulo registradoEscopo necessário
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

Ferramentas de mídia

FerramentaTítulo registradoEscopo necessário
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

Ferramenta de busca

FerramentaTítulo registradoEscopo necessário
searchSearch Contentcontent:read

Ferramentas de taxonomia

FerramentaTítulo registradoEscopo necessário
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

Ferramentas de menu

FerramentaTítulo registradoEscopo necessário
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

Ferramentas de revisão

FerramentaTítulo registradoEscopo necessário
revision_listList Revisionscontent:read
revision_restoreRestore Revisioncontent:write

Ferramentas de configurações

FerramentaTítulo registradoEscopo necessário
settings_getGet Site Settingssettings:read
settings_updateUpdate Site Settingssettings:manage

Ferramentas de transferência de site

transfer:* significa qualquer um entre transfer:export, transfer:analyze ou transfer:execute. O escopo admin satisfaz todos os requisitos desta tabela.

FerramentaTítulo registradoEscopo necessário
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 e site_import_start também aceitam um token sem o escopo quando um administrador aprova a requisição. Para a operação que uma requisição aprovada inicia, site_export_status, site_import_status, site_import_resume e site_import_receipt passam então a aceitar o mesmo token sem o escopo.

Usar os esquemas das ferramentas

tools/list retorna a descrição, o esquema JSON de entrada e as anotações de cada ferramenta. Leia esses metadados antes de montar uma chamada, para que o seu cliente use os campos, os valores permitidos e os limites compatíveis com a versão do EmDash instalada.

Por exemplo, um cliente que atualiza um artigo chama primeiro content_get e guarda o _rev retornado. Depois, ele pode enviar esta requisição 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 é retornado como texto JSON no primeiro bloco de conteúdo. Uma ferramenta com um esquema de saída também pode retornar o mesmo valor em structuredContent.

Ciclo de vida do conteúdo e bylines

A referência do ciclo de vida do conteúdo define o comportamento de estados, revisões, permissões, conflitos e hooks compartilhado por MCP, REST, pela CLI e pelo painel de administração.

content_get retorna um valor _rev opaco. Passe-o para content_update, content_publish, content_unpublish, content_schedule ou content_discard_draft. Um valor desatualizado retorna um conflito, então leia o item novamente antes de tentar de novo.

content_update é uma atualização parcial: os campos omitidos mantêm os valores atuais. Atualizar um item publicado prepara um rascunho enquanto a versão ao vivo permanece inalterada. Use content_compare para revisar os valores ao vivo e os do rascunho e, em seguida, chame content_publish para publicar o rascunho ou content_discard_draft para removê-lo. content_delete move um item para a lixeira; somente content_permanent_delete remove permanentemente um item que está na lixeira.

Bylines são créditos reutilizáveis de autor ou colaborador. byline_create pode criar um crédito de convidado ou vincular uma byline a um usuário do CMS. Um usuário só pode ter uma byline por locale. Uma tradução criada com translationOf mantém o usuário da byline de origem, a menos que você passe userId; passe null para deixar a tradução sem vínculo. Passe o ID da byline retornado na entrada bylines aceita por content_create e content_update. Excluir uma byline remove esse crédito do conteúdo e a limpa como byline principal.

Enquanto outro usuário mantém o bloqueio de edição de uma entrada porque a abriu no admin, content_update, content_delete, content_publish, content_unpublish, content_schedule, content_unschedule, content_discard_draft e revision_restore falham com ENTRY_LOCKED, e o erro informa quem a mantém. Ler o item novamente não elimina a recusa. Passe overrideLock: true para gravar mesmo assim.

Traduções

As ferramentas de tradução de conteúdo, bylines, termos de taxonomia e menus retornam todas as variantes de locale do grupo de tradução em questão. Use a entrada translationOf da ferramenta de criação quando o esquema dela oferecer uma; tools/list é a fonte autoritativa para os campos obrigatórios.

content_translations aceita uma coleção e um ID ou slug de conteúdo. As ferramentas de tradução de bylines, termos de taxonomia e menus aceitam o ID de um registro ou o ID compartilhado do grupo de tradução. Um usuário sem acesso a rascunhos vê apenas as traduções de conteúdo publicado.

Esquemas, mídia, taxonomias e menus

As ferramentas de esquema alteram a estrutura do banco de dados. Use schema_get_collection antes de criar conteúdo ou alterar campos; ela retorna os nomes de campo, os tipos, as restrições e as regras de validação disponíveis. Excluir coleções e campos remove o conteúdo ou os valores de campo armazenados e não pode ser desfeito.

Use media_upload para enviar bytes codificados em base64. Os envios estão sujeitos aos limites de tamanho e de tipo MIME configurados, e bytes idênticos podem retornar um item de mídia existente com deduplicated: true.

media_create confirma um envio pendente criado por meio de POST /_emdash/api/media/upload-url. Envie o arquivo com a URL assinada retornada e, depois, chame media_create a partir da mesma conta de usuário com o storageKey retornado. A ferramenta verifica se o arquivo armazenado existe e corresponde ao tamanho informado quando a URL de envio foi solicitada, antes de disponibilizá-lo na biblioteca de mídia.

As definições de taxonomia descrevem a classificação e as coleções às quais ela se aplica; os termos são os valores individuais atribuídos ao conteúdo. Termos hierárquicos podem usar parentId, mas o pai deve pertencer à mesma taxonomia e não pode criar um ciclo. Criar ou atualizar um termo com parentId em uma taxonomia não hierárquica retorna VALIDATION_ERROR. Um termo com filhos precisa ter esses filhos removidos ou movidos antes de ser excluído.

menu_set_items substitui a lista completa de itens de um menu em uma única operação atômica. A ordem do array passa a ser a ordem do menu. O parentIndex de um item aninhado aponta para um item anterior no mesmo array, então coloque cada pai antes dos seus filhos.

media_usage_repair pode processar uma coleção ou todas as coleções e pode levar muito tempo em um site grande. Os status complete, partial, failed e stale são respostas bem-sucedidas da ferramenta. Inspecione o status e as contagens retornados em vez de depender de isError; falhas de autenticação, de validação e de execução inesperadas definem isError: true.

Transferência de site

As ferramentas site_* exportam um site inteiro como um pacote do site e importam um pacote em um site vazio. Elas iniciam e conduzem as operações e retornam resumos limitados. Nunca transportam bytes do pacote, mídia, conteúdo de registros, endereços de e-mail dos principals nem URLs de download. Baixe uma exportação e envie um pacote para importação com a CLI ou a API REST e, depois, faça referência à operação pelo ID.

Toda ferramenta de transferência exige o papel Admin. O papel é verificado antes do escopo, então um chamador que não é administrador recebe INSUFFICIENT_PERMISSIONS e nenhuma requisição de aprovação é criada.

Exportação

site_export_start aceita comments (padrão true) e retorna a nova operação. site_export_status executa uma etapa de exportação limitada a cada chamada e informa a operação e nextRequestInMs. Chame-o novamente após esse intervalo até que nextRequestInMs seja null. Passe advance: false para ler o status sem executar uma etapa. Quando a exportação termina, o resultado também inclui totals: contagens de registros por tipo, número e bytes de mídia e número e bytes de arquivos do pacote.

Importação

Envie o pacote primeiro. O comando emdash site import <file> --analyze da CLI envia e analisa o pacote e imprime o ID da operação.

site_import_analyze executa uma etapa de análise limitada a cada chamada. Repita até que nextRequestInMs seja null; o resultado então inclui um resumo do plano com packageDigest, planDigest, executable, contagens, tamanhos, principals, decisões, transformações, avisos e bloqueios. Cada transformação é listada com o seu code, o kind do registro quando houver um e um count, sem os IDs ou valores aos quais se aplica. Principals, avisos e bloqueios listam no máximo 50 itens cada, com a contagem completa em total. Os principals são listados sem endereços de e-mail, com os IDs de usuário de destino sugeridos e os atualmente mapeados. Passe decisions para mapear principals para IDs de usuário de destino (ou null) e para escolher o título e o slogan do pacote ou do destino. Cada alteração produz um novo planDigest.

site_import_start recebe o ID da operação e o packageDigest e o planDigest do plano mais recente. O plano não pode ter bloqueios. A ferramenta tem destructiveHint: true: depois de iniciada, a importação grava no site e bloqueia as demais gravações até terminar ou até que um administrador a abandone. Mostre o plano ao usuário e obtenha a confirmação dele antes de chamá-la.

site_import_resume executa uma etapa de importação limitada e informa a operação e nextRequestInMs. Chame-o até que nextRequestInMs seja null; é seguro repeti-lo após uma desconexão. site_import_status informa a operação e o número de arquivos enviados sem avançar a importação. site_import_receipt retorna o recibo completo, incluindo receiptDigest, quando a importação termina.

Enquanto uma importação está em execução, e depois que ela falha ou é cancelada até ser abandonada, toda outra ferramenta capaz de gravar falha com TRANSFER_IMPORT_IN_PROGRESS. Isso inclui as ferramentas de plugins. As ferramentas anotadas com readOnlyHint: true e as oito ferramentas site_* continuam funcionando, e initialize e tools/list nunca são bloqueadas. Durante a ativação do uso de mídia, as ferramentas de gravação falham da mesma forma com MEDIA_USAGE_ACTIVATION_IN_PROGRESS.

Os resumos de operação incluem id, kind, state, stage, progress, packageDigest, planDigest, error ({ code } ou null) e carimbos de data e hora. progress é { done, total } etapas, além de records, os registros que uma exportação gravou até o momento, 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 com o escopo de transferência necessário nunca pede aprovação. Para um token sem nenhum dos dois, como o de um agente que recebeu apenas transfer:analyze, site_export_start e site_import_start são executados quando um administrador aprova a requisição:

  1. A primeira chamada sem o escopo cria uma requisição de aprovação pendente e falha com TRANSFER_APPROVAL_REQUIRED. O texto da mensagem e _meta.details trazem o approvalId e o seu expiresAt. Chamar de novo com os mesmos argumentos e sem approvalId retorna a mesma requisição aberta.
  2. Um administrador aprova a requisição em Approval requests, dentro de Settings → Transfer, ou com o endpoint de aprovação exclusivo de sessão da API REST. Tokens de API não podem aprovar requisições.
  3. 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 falhar ao iniciar, o cliente pode tentar de novo com o mesmo approvalId até que ele expire.

Uma requisição fica vinculada ao usuário, ao token, à ação e aos argumentos exatos: as opções de exportação, ou o ID da operação de importação e os dois digests. Uma requisição pendente expira 15 minutos depois de feita, e uma aprovada, 15 minutos depois da aprovação. Uma chamada com argumentos diferentes ou outro token, ou com uma aprovação negada, expirada ou já usada, falha com TRANSFER_APPROVAL_INVALID.

site_import_start verifica os digests, o estado da operação e os bloqueios do plano antes de criar uma requisição, então só se pede a um administrador que aprove uma importação que pode ser executada. Uma aprovação precisa de um ID de token, então um chamador sem ele recebe INSUFFICIENT_SCOPE.

Depois que uma chamada aprovada inicia uma operação, o mesmo usuário e o mesmo token podem chamar site_export_status, ou site_import_status, site_import_resume e site_import_receipt, para essa operação sem o escopo.

Ferramentas de plugins

Um administrador deve habilitar a superfície MCP de cada plugin. As ferramentas habilitadas aparecem em tools/list como <pluginId>__<localName> e exigem mcp:tools ou mcp:tools:<pluginId> nas chamadas autenticadas por token. O EmDash também verifica a permissão declarada pela rota do plugin e registra o plugin, a ferramenta, a rota e o ator no log de auditoria.

Como as ferramentas de plugins dependem da instalação, elas não fazem parte do inventário estático acima.

Descoberta do OAuth

Os 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 o recurso protegido e aponta para o servidor de autorização. Em seguida, os clientes leem os metadados dele em:

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

Esse documento fornece os endpoints atuais de autorização, token, registro e autorização de dispositivo, os escopos e tipos de concessão compatíveis e o método PKCE S256. Use os valores descobertos em vez de fixar no código as rotas do protocolo OAuth.

Uma requisição MCP não autenticada retorna uma resposta 401 com a 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 o repete para os clientes que leem metadados estruturados:

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

Uma recusa causada pelo bloqueio de edição de uma entrada traz quem o mantém em _meta.details:

{
	"content": [{ "type": "text", "text": "[ENTRY_LOCKED] Ada is holding this entry" }],
	"isError": true,
	"_meta": {
		"code": "ENTRY_LOCKED",
		"details": {
			"userId": "01JB...",
			"userName": "Ada",
			"acquiredAt": "2026-05-01T09:12:04.117Z",
			"expiresAt": "2026-05-01T09:19:04.117Z"
		}
	}
}

As falhas de autenticação usam códigos como INSUFFICIENT_SCOPE e INSUFFICIENT_PERMISSIONS. As falhas de transporte usam o código de erro interno do JSON-RPC -32603 e não expõem a exceção subjacente.