Ir al contenido

Referencia del Servidor MCP

EmDash incluye un servidor integrado de Model Context Protocol (MCP) en /_emdash/api/mcp que expone operaciones de gestión de contenido como herramientas para asistentes de IA.

Esta página cubre los detalles del protocolo: autenticación, transporte, especificaciones de herramientas, descubrimiento OAuth y manejo de errores.

El servidor MCP admite tres métodos de autenticación:

MétodoCómo funciona
Código de Autorización OAuth 2.1 + PKCEFlujo estándar para clientes MCP. El usuario aprueba los alcances en el navegador.
Token de Acceso Personal (PAT)Tokens de larga duración ec_pat_* creados en el panel de administración.
Flujo de DispositivoFlujo estilo CLI donde apruebas un código en el navegador. Utilizado por emdash login.

Las cookies de sesión (desde la interfaz de administración) también funcionan, pero no son prácticas para clientes MCP externos.

Los tokens tienen alcances para limitar las operaciones que un cliente puede realizar. Los alcances se solicitan durante la autorización OAuth y se aplican en cada llamada a herramienta.

AlcanceOtorga acceso a
content:readListar, obtener, comparar y buscar contenido. Listar términos de taxonomía y menús.
content:writeCrear, actualizar, eliminar, publicar, despublicar, programar, duplicar y restaurar contenido. Crear términos de taxonomía.
media:readListar y obtener elementos multimedia.
media:writeActualizar y eliminar metadatos de elementos multimedia.
schema:readListar colecciones y obtener esquemas de colección.
schema:writeCrear y eliminar colecciones y campos.
adminAcceso completo a todas las operaciones.

El alcance admin otorga acceso a todo. La autenticación basada en sesión (sin token) también tiene acceso completo según el rol del usuario.

Además de los alcances, algunas herramientas requieren un rol mínimo de RBAC:

OperaciónRol mínimo
Operaciones de contenidoSin mínimo (los alcances controlan el acceso)
Lectura de esquemaEditor (40)
Escritura de esquemaAdministrador (50)

Consulta la guía de Autenticación para las definiciones de roles.

El servidor utiliza el transporte HTTP Streamable en modo sin estado. Cada solicitud es independiente: no hay sesiones ni conexiones de larga duración.

  • POST /_emdash/api/mcp — Enviar llamadas JSON-RPC a herramientas
  • GET /_emdash/api/mcp — Devuelve 405 (no hay SSE en modo sin estado)
  • DELETE /_emdash/api/mcp — Devuelve 405 (no hay sesión que cerrar)

Las respuestas siguen el formato JSON-RPC 2.0. Los errores utilizan códigos de error estándar de JSON-RPC, con códigos específicos de MCP para fallos de alcance y permisos.

El servidor expone 33 herramientas en siete dominios. Cada herramienta devuelve resultados como contenido de texto JSON, o un mensaje de error con isError: true en caso de fallo.

Lista elementos de contenido en una colección con filtrado opcional y paginación.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección (ej. posts, pages)
statusstringNoFiltro: draft, published o scheduled
limitintegerNoMáximo de elementos a devolver (1-100, predeterminado 50)
cursorstringNoCursor de paginación de una respuesta anterior
orderBystringNoCampo por el que ordenar (ej. created_at, updated_at)
orderstringNoDirección de orden: asc o desc (predeterminado desc)
localestringNoFiltrar por localización (ej. en, fr). Solo relevante con i18n.

Alcance: content:read | Solo lectura: Sí

Obtiene un único elemento de contenido por ID o slug. Devuelve todos los valores de campo, metadatos y un token _rev para concurrencia optimista.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID del elemento de contenido (ULID) o slug
localestringNoLocalización para búsqueda por slug. Los IDs son globalmente únicos.

Alcance: content:read | Solo lectura: Sí

Crea un nuevo elemento de contenido. El objeto data debe contener valores de campo que coincidan con el esquema de la colección: usa schema_get_collection para verificar qué campos están disponibles. Los elementos se crean como draft por defecto.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
dataobjectSíValores de campo como pares clave-valor
slugstringNoSlug de URL (se genera automáticamente desde el título si se omite)
statusstringNoEstado inicial: draft o published (predeterminado draft)
localestringNoLocalización para este contenido (predeterminado al valor por defecto del sitio)
translationOfstringNoID del elemento del que es traducción

Alcance: content:write

Actualiza un elemento de contenido existente. Solo incluye los campos que quieres cambiar; los campos no especificados permanecen sin cambios.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID del elemento de contenido o slug
dataobjectNoValores de campo a actualizar
slugstringNoNuevo slug de URL
statusstringNoNuevo estado: draft o published
_revstringNoToken de revisión de content_get para detección de conflictos

Alcance: content:write

Elimina suavemente un elemento de contenido moviéndolo a la papelera. Usa content_restore para deshacer, o content_permanent_delete para eliminarlo permanentemente.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID del elemento de contenido o slug

Alcance: content:write | Destructivo: Sí

Restaurar un elemento de contenido eliminado temporalmente de la papelera.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:write

Eliminar de forma permanente e irreversible un elemento de contenido en la papelera. El elemento debe estar primero en la papelera.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:write | Destructivo: Sí

Publicar un elemento de contenido, haciéndolo visible en el sitio. Crea una revisión publicada a partir del borrador actual. Las ediciones posteriores crean un nuevo borrador sin afectar la versión en vivo hasta que se vuelva a publicar.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:write

Revertir un elemento publicado a estado de borrador. Ya no será visible en el sitio en vivo, pero se conserva su contenido.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:write

Programar un elemento de contenido para su publicación futura. Se publicará automáticamente en la fecha/hora especificada.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido
scheduledAtstringSíFecha y hora en formato ISO 8601 (ej. 2026-06-01T09:00:00Z)

Alcance: content:write

Comparar la versión publicada (en vivo) de un elemento de contenido con su borrador actual. Devuelve ambas versiones y un indicador de si hay cambios.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:read | Solo lectura: Sí

Descartar el borrador actual y revertir a la última versión publicada. Solo funciona en elementos que se han publicado al menos una vez.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:write | Destructivo: Sí

Listar elementos de contenido eliminados temporalmente en la papelera de una colección.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
limitintegerNoMáximo de elementos (1-100, predeterminado 50)
cursorstringNoCursor de paginación

Alcance: content:read | Solo lectura: Sí

Crear una copia de un elemento de contenido existente. El duplicado se crea como un borrador con “(Copia)” añadido al título y un slug generado automáticamente.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento a duplicar

Alcance: content:write

Obtener todas las variantes de localización de un elemento de contenido. Devuelve el grupo de traducción y un resumen de cada versión de localización. Solo es relevante cuando i18n está habilitado.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido

Alcance: content:read | Solo lectura: Sí

Listar todas las colecciones de contenido definidas en el CMS. Devuelve slug, etiqueta, características admitidas y marcas de tiempo.

Sin parámetros.

Alcance: schema:read | Rol mínimo: Editor | Solo lectura: Sí

Obtener información detallada sobre una colección, incluidas todas las definiciones de campos. Los campos describen el modelo de contenido: nombre, tipo, restricciones y reglas de validación. Úsalo para entender qué esperan content_create y content_update.

ParámetroTipoRequeridoDescripción
slugstringSíSlug de la colección (ej. posts)

Alcance: schema:read | Rol mínimo: Editor | Solo lectura: Sí

Crear una nueva colección de contenido. Esto crea una tabla de base de datos y una definición de esquema. El slug debe ser alfanumérico en minúsculas con guiones bajos, comenzando con una letra.

ParámetroTipoRequeridoDescripción
slugstringSíIdentificador único (/^[a-z][a-z0-9_]*$/)
labelstringSíNombre para mostrar (plural, ej. “Entradas de Blog”)
labelSingularstringNoNombre para mostrar en singular
descriptionstringNoDescripción de esta colección
iconstringNoNombre del icono para la interfaz de administración
supportsstring[]NoCaracterísticas: drafts, revisions, preview, scheduling, search (predeterminado: ['drafts', 'revisions'])

Alcance: schema:write | Rol mínimo: Administrador

Eliminar una colección y su tabla de base de datos. Esto es irreversible y elimina todo el contenido de la colección.

ParámetroTipoRequeridoDescripción
slugstringSíSlug de la colección a eliminar
forcebooleanNoForzar la eliminación incluso si la colección tiene contenido

Alcance: schema:write | Rol mínimo: Administrador | Destructivo: Sí

Agregar un nuevo campo al esquema de una colección. Esto añade una columna a la tabla de la base de datos.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
slugstringSíIdentificador del campo (/^[a-z][a-z0-9_]*$/)
labelstringSíNombre para mostrar
typestringSíTipo de dato (ver abajo)
requiredbooleanNoSi el campo es obligatorio
uniquebooleanNoSi los valores deben ser únicos
defaultValueanyNoValor por defecto para nuevos elementos
validationobjectNoRestricciones: min, max, minLength, maxLength, pattern, options
optionsobjectNoConfiguración del widget: collection (para referencias), rows (para textarea)
searchablebooleanNoIncluir en el índice de búsqueda de texto completo
translatablebooleanNoSi este campo es traducible (por defecto true)

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

Para los tipos select y multiSelect, proporciona los valores permitidos en validation.options.

Alcance: schema:write | Rol mínimo: Admin

Elimina un campo de una colección. Esto elimina la columna y borra todos los datos en ese campo. Irreversible.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
fieldSlugstringSíSlug del campo a eliminar

Alcance: schema:write | Rol mínimo: Admin | Destructivo: Sí

Lista archivos multimedia subidos con filtrado opcional por tipo MIME y paginación.

ParámetroTipoRequeridoDescripción
mimeTypestringNoFiltrar por prefijo de tipo MIME (ej. image/, application/pdf)
limitintegerNoMáximo de elementos (1-100, por defecto 50)
cursorstringNoCursor de paginación

Alcance: media:read | Solo lectura: Sí

Obtiene detalles de un solo archivo multimedia por ID. Devuelve metadatos incluyendo nombre de archivo, tipo MIME, tamaño, dimensiones, texto alternativo y URL.

ParámetroTipoRequeridoDescripción
idstringSíID del elemento multimedia

Alcance: media:read | Solo lectura: Sí

Actualiza los metadatos de un archivo multimedia subido. El archivo en sí no se puede cambiar.

ParámetroTipoRequeridoDescripción
idstringSíID del elemento multimedia
altstringNoTexto alternativo para accesibilidad
captionstringNoTexto del pie de foto
widthintegerNoAncho de la imagen en píxeles
heightintegerNoAltura de la imagen en píxeles

Alcance: media:write

Elimina permanentemente un archivo multimedia. Elimina el registro de la base de datos y el archivo del almacenamiento. El contenido que haga referencia a este medio tendrá referencias rotas.

ParámetroTipoRequeridoDescripción
idstringSíID del elemento multimedia

Alcance: media:write | Destructivo: Sí

Búsqueda de texto completo en colecciones de contenido. Las colecciones deben tener search en su lista de supports y los campos deben estar marcados como searchable.

ParámetroTipoRequeridoDescripción
querystringSíTexto de la consulta de búsqueda
collectionsstring[]NoLimitar la búsqueda a slugs de colección específicos
localestringNoFiltrar resultados por idioma
limitintegerNoMáximo de resultados (1-50, por defecto 20)

Alcance: content:read | Solo lectura: Sí

Lista todas las definiciones de taxonomía (ej. categorías, etiquetas). Devuelve nombre, etiqueta, si es jerárquica y las colecciones asociadas.

Sin parámetros.

Alcance: content:read | Solo lectura: Sí

Lista términos en una taxonomía con paginación.

ParámetroTipoRequeridoDescripción
taxonomystringSíNombre de la taxonomía (ej. categories, tags)
limitintegerNoMáximo de elementos (1-100, por defecto 50)
cursorstringNoCursor de paginación

Alcance: content:read | Solo lectura: Sí

Crea un nuevo término en una taxonomía. Para taxonomías jerárquicas, especifica un parentId para crear un término hijo.

ParámetroTipoRequeridoDescripción
taxonomystringSíNombre de la taxonomía
slugstringSíIdentificador seguro para URL
labelstringSíNombre para mostrar
parentIdstringNoID del término padre (para taxonomías jerárquicas)
descriptionstringNoDescripción del término

Alcance: content:write

Lista todos los menús de navegación. Devuelve nombre, etiqueta y marcas de tiempo.

Sin parámetros.

Alcance: content:read | Solo lectura: Sí

Obtiene un menú por nombre incluyendo todos sus elementos en orden. Los elementos tienen una etiqueta, URL, tipo y un padre opcional para anidamiento.

ParámetroTipoRequeridoDescripción
namestringSíNombre del menú (ej. main, footer)

Alcance: content:read | Solo lectura: Sí

Lista el historial de revisiones para un elemento de contenido, del más nuevo al más antiguo. Requiere que la colección admita revisions.

ParámetroTipoRequeridoDescripción
collectionstringSíSlug de la colección
idstringSíID o slug del elemento de contenido
limitintegerNoMáximo de revisiones (1-50, por defecto 20)

Alcance: content:read | Solo lectura: Sí

Restaura un elemento de contenido a una revisión anterior. Reemplaza el borrador actual con los datos de la revisión especificada. No se publica automáticamente; usa content_publish después si es necesario.

ParámetroTipoRequeridoDescripción
revisionIdstringSíID de la revisión a restaurar

Alcance: content:write

Los clientes MCP que admiten OAuth 2.1 pueden descubrir automáticamente cómo autenticarse. El servidor publica dos documentos de metadatos:

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

Cuando una solicitud no autenticada llega al endpoint MCP, el servidor devuelve:

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

Esto desencadena el flujo de descubrimiento estándar del cliente MCP.

Los errores de herramientas se devuelven como contenido de texto con isError: true:

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

Los errores de alcance y permisos lanzan errores del protocolo MCP:

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

Los errores a nivel de transporte (configuración incorrecta del servidor, excepciones no manejadas) devuelven el código de error JSON-RPC -32603 (Error interno) sin filtrar detalles de implementación.