Guía para desarrolladores · Model Context Protocol
Crea un flujo de contenido automático con el servidor MCP de Endata
Endata expone todo su flujo editorial como herramientas MCP: preguntas, investigación, borradores, aprobaciones, publicación y difusión. Esta guía conecta un agente y arma un flujo que convierte la pregunta de un cliente en una respuesta publicada y con fuentes, con una persona que confirma el paso que se hace público.
Endata tiene dos servidores MCP. ¿Cuál necesitas?
| Servidor del espacio de trabajo | Servidor de la publicación | |
|---|---|---|
La mayor parte de esta guía trata del servidor del espacio de trabajo. El servidor de la publicación no requiere configuración alguna: existe desde el momento en que publicas y se anuncia en /.well-known/mcp.json.
Paso 1 2 minutos
Crea una clave de API con permisos acotados
En Configuración → Desarrollador → Claves API, crea una clave solo con los permisos que necesita el flujo.
Las claves pertenecen a un proyecto y empiezan con fsk_. Las crea un propietario y cada una lleva permisos. Las herramientas fuera de los permisos de una clave ni siquiera se le muestran al agente, así que una clave acotada también da una lista de herramientas más corta y clara.
| Permiso | Qué permite |
|---|---|
Para este flujo, otorga editorial:read, editorial:write y publishing:manage. Deja desactivados administration:manage y organization:manage, a menos que el agente realmente administre dominios, integraciones o miembros del equipo.
Paso 2 2 minutos
Conecta tu cliente MCP
Agrega el servidor a Claude Code, a Codex o a cualquier cliente que hable Streamable HTTP.
Claude Code
{
"mcpServers": {
"endata": {
"type": "http",
"url": "https://app.endata.com/mcp",
"headers": { "Authorization": "Bearer ${ENDATA_API_KEY}" }
}
}
}.mcp.json, en la raíz de tu proyecto. Define ENDATA_API_KEY en tu shell.Codex
[mcp_servers.endata]
url = "https://app.endata.com/mcp"
bearer_token_env_var = "ENDATA_API_KEY"~/.codex/config.toml.Tu propio código
El servidor es Streamable HTTP sin estado y solo acepta POST, así que el SDK oficial se conecta sin manejar sesiones. El pequeño asistente call de abajo se usa en todos los pasos siguientes.
// npm install @modelcontextprotocol/sdk
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from
"@modelcontextprotocol/sdk/client/streamableHttp.js";
const publicationId = process.env.ENDATA_PUBLICATION_ID;
const client = new Client({ name: "answer-pipeline", version: "1.0.0" });
await client.connect(new StreamableHTTPClientTransport(
new URL("https://app.endata.com/mcp"),
{ requestInit: { headers: {
Authorization: `Bearer ${process.env.ENDATA_API_KEY}`,
} } },
));
// Every tool takes { publicationId, input } and returns JSON as text.
async function call(name, input = {}, extra = {}) {
const result = await client.callTool({
name,
arguments: { publicationId, input, ...extra },
});
const value = JSON.parse(result.content[0].text);
if (result.isError) throw new Error(`${name}: ${value.message}`);
return value;
}Paso 3 1 minuto
Encuentra las preguntas que vale la pena responder
Llama a questions_list con el filtro to-answer, o agrega una pregunta con question_create.
Una pregunta es la unidad de trabajo: algo que pregunta un cliente y para lo cual el negocio debería tener la mejor respuesta. Las preguntas llegan de las sugerencias de Endata, de las brechas de tu informe de visibilidad en IA o de ti.
// Questions still waiting for an answer, highest priority first.
const { questions } = await call("questions_list", {
filter: "to-answer",
limit: 10,
});
// Or add one of your own: a gap from your AI Visibility report, say.
const added = await call("question_create", {
text: "How much cyber insurance does a 40-person firm need?",
customers: "Owners of professional services firms",
});questions_list devuelve questions, counts por estado y un summary. Los filtros incluyen to-answer, needs-update (respondida, pero las noticias cambiaron o la respuesta quedó desactualizada), open y all. discovery_read da una vista más amplia: qué porcentaje de las preguntas de los clientes has respondido y qué responder a continuación.
Paso 4 Unos minutos, sin supervisión
Investiga y redacta la respuesta
Llama a question_research para reunir evidencia y escribir un borrador con citas.
La investigación busca en los últimos 30 días de noticias y fuentes web para esa pregunta, conserva hasta ocho piezas de evidencia y escribe una respuesta que las cita. Se ejecuta en segundo plano y descuenta de la asignación mensual de respuestas investigadas del plan.
// Research the question and draft its answer. This runs in the
// background and counts against the plan's monthly answers.
const question = questions[0];
await call("question_research", { questionId: question.id });
// Optional: add what only the business knows, attributed to it.
await call("question_perspective", {
questionId: question.id,
text: "We size cover from the client's largest single contract, not headcount.",
});question_perspective es el paso que la mayoría de los flujos omite y no debería. Agrega la opinión propia del negocio, atribuida a un autor con nombre, que es lo que hace que la respuesta sea más que un resumen de páginas ajenas.
Paso 5 2 minutos
Lee el borrador y su evidencia
Llama a question_read y answer_read, y conserva el draftRevision que revisaste.
// When research is done ("question.researched" webhook, or poll),
// read the draft and the evidence behind it.
const detail = await call("question_read", { questionId: question.id });
const answer = await call("answer_read", { questionId: question.id });
console.log(answer.content); // the draft
console.log(answer.pending); // true: readers do not see it yet
console.log(answer.draftRevision); // the exact revision you reviewedAquí es donde un agente se gana su lugar. Pídele que compare el borrador con la evidencia que devuelve question_read, que marque cualquier afirmación sin fuente y que guarde un borrador mejorado con answer_update, que recibe el contenido y el expectedRevision en que se basó, para que dos editores no se sobrescriban entre sí. answer_preview devuelve la página tal como se publicaría.
Paso 6 1 minuto
Publica, con una persona en el circuito
Llama a prepare_action, muéstrale su resumen a una persona y luego llama a answer_publish con el token de confirmación.
Publicar, despublicar, compartir y los cambios administrativos se marcan como consecuentes. Endata no deja que una clave sin supervisión los realice por defecto. Hay dos caminos, y debes elegir con criterio:
Confirma cada acción
prepare_action devuelve un resumen y un token ligado a esa entrada exacta y al estado actual, válido por 10 minutos. Muéstrale el resumen a una persona; pasa el token cuando esté de acuerdo.
Otorga permisos sin supervisión
Un propietario puede permitir explícitamente que una clave actúe sin supervisión. Úsalo para un flujo en el que confías de principio a fin, y mantén acotados los permisos de la clave.
// Publishing is consequential. Prepare the exact action first:
const prepared = await client.callTool({
name: "prepare_action",
arguments: {
publicationId,
operation: "answer_publish",
input: { questionId: question.id, revisionId: answer.draftRevision },
},
});
const { confirmationToken } = JSON.parse(prepared.content[0].text);
// Show the summary to a person. Once they agree, within 10 minutes:
const live = await call(
"answer_publish",
{ questionId: question.id, revisionId: answer.draftRevision },
{ confirmationToken, requestKey: `publish-${answer.draftRevision}` },
);requestKey hace la llamada idempotente: un reintento con la misma clave y la misma entrada devuelve el primer resultado y no publica dos veces. La respuesta se publica al instante en /questions/<slug> de la publicación, y answer.url en el resultado es su dirección.
Paso 7 Opcional
Comparte artículos y escucha eventos
Usa article_share para publicar artículos en las redes conectadas, y webhooks para reaccionar cuando algo se publica.
Compartir funciona con los artículos, las notas de noticias que Endata escribe sobre tus temas, no con las respuestas. connections_list devuelve las cuentas conectadas; article_share recibe un articleId, un connectionId, tu commentary y cuándo enviarlo (now, at una hora, o cuando esté published). Es consecuente, así que se aplica la misma regla de confirmación.
Los webhooks cierran el ciclo. Hasta 10 endpoints HTTPS por proyecto reciben eventos firmados como question.answered, question.updated, article.approved y share.sent. La entrega es al menos una vez, con ocho intentos en unas 22 horas, así que haz el receptor idempotente y verifica la firma:
import { createHmac, timingSafeEqual } from "node:crypto";
// Pass the exact, unmodified UTF-8 request body and request headers.
function verifyWebhook(rawBody, headers, secret) {
const timestamp = headers.get("Webhook-Timestamp");
const signature = headers.get("Webhook-Signature");
if (!timestamp || !/^\d+$/.test(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (!/^v1=[a-f0-9]{64}$/.test(signature || "")) return false;
const expected = createHmac("sha256", secret)
.update(timestamp + "." + rawBody, "utf8")
.digest();
const received = Buffer.from(signature.slice(3), "hex");
return timingSafeEqual(expected, received);
}
// After verification, parse and validate the event.
// Atomically persist it with a unique constraint on Webhook-Id.
// Return 2xx after persistence; duplicate events should also return 2xx.
// Process asynchronously and reconcile current state through the API.Deja que otros agentes lean tus respuestas
Todo lo que publicas queda disponible de inmediato para cualquier agente, sin clave y sin trabajo de integración. Cada publicación sirve un servidor MCP de solo lectura con cuatro herramientas: search_answers, get_answer, list_questions y list_changes.
// No key. Any newsroom: yours, or one you want your agent to cite.
const newsroom = new Client({ name: "reader", version: "1.0.0" });
await newsroom.connect(new StreamableHTTPClientTransport(
new URL("https://news.example.com/mcp"),
));
const hits = await newsroom.callTool({
name: "search_answers",
arguments: { q: "cyber insurance for small firms" },
});El mismo contenido también se sirve como llms.txt, llms-full.txt, un JSON Feed en /answers.json y Markdown para cualquier respuesta, añadiendo .md a su dirección o enviando Accept: text/markdown. Este es el lado práctico de ser visible para la IA: un asistente que sale a buscar encuentra una respuesta limpia y con fuentes en el formato que mejor lee.
¿Prefieres REST? Las mismas operaciones están ahí
Las herramientas MCP y la API REST se generan desde un mismo registro, así que todo lo anterior se puede hacer con POST https://app.endata.com/api/v1/publications/:id/operations/:operationId. Las escrituras llevan el encabezado Idempotency-Key, y las confirmaciones se preparan en /publications/:id/confirmations.
GET /api/v1/operationslista cada operación con su JSON Schema, sin clave.GET /api/v1/openapi.jsones un documento OpenAPI 3.1 generado desde el mismo registro.- Límites: 120 solicitudes por minuto por clave, cuerpos JSON de 1 MB (14 MB para subidas de imágenes).
No hay un SDK de Endata que instalar y no hace falta: usa el SDK de MCP o un simple fetch. La referencia completa está en la página para desarrolladores.
Lo que el servidor MCP no hace
- No expone el informe de visibilidad en IA. No hay una herramienta para generar uno ni para leer sus posiciones. Incorpora las brechas como preguntas con
question_create. - No usa OAuth personal. Hoy solo se aceptan claves de API del proyecto.
- No está en Solo. La API, MCP y los webhooks forman parte de Business y Agency.
- No evita los límites del plan. La investigación y la redacción descuentan de la misma asignación mensual que la app.
Preguntas frecuentes
¿Cuál es la URL del servidor MCP de Endata?
https://app.endata.com/mcp. Es Streamable HTTP sin estado sobre POST, autenticado con una clave de API del proyecto enviada como Authorization: Bearer fsk_….
¿Qué clientes MCP funcionan con Endata?
Cualquier cliente que admita Streamable HTTP con un encabezado bearer, incluidos Claude Code, Codex y los SDK oficiales de Model Context Protocol.
¿Qué plan incluye MCP y la API?
Business ($199 al mes) y Agency. Solo no incluye la API, MCP ni webhooks. Mira los precios.
¿Puede un agente publicar sin una persona?
Solo si el propietario de un espacio de trabajo le otorgó a esa clave permisos sin supervisión. De lo contrario, las herramientas consecuentes requieren un token de confirmación de prepare_action, que tu cliente solo debería obtener después de que una persona esté de acuerdo.
¿Cuántas herramientas expone el servidor?
77 operaciones más prepare_action, que cubren contenido publicado, artículos, publicación, investigación, preguntas, respuestas, medios, configuración, webhooks, equipo y widgets. Una clave solo ve las herramientas que sus permisos permiten.
¿Puedo leer mi informe de visibilidad en IA por MCP o por la API?
Hoy no. Ninguna operación expone el informe. discovery_read y search_ai_read cubren el porcentaje de preguntas respondidas, las visitas de referencia desde IA y las solicitudes de recuperación.
¿Hay un servidor MCP público para el contenido publicado?
Sí. Cada publicación de Endata sirve un servidor MCP de solo lectura y sin clave en /mcp, con search_answers, get_answer, list_questions y list_changes, que se descubre en /.well-known/mcp.json.
¿Hay un SDK o una especificación OpenAPI?
No hay un SDK específico de Endata. Hay un documento OpenAPI 3.1 en vivo en https://app.endata.com/api/v1/openapi.json, y el catálogo de operaciones con JSON Schemas en /api/v1/operations.