Servidor MCP
El servidor MCP (Model Context Protocol) de SupDesk da a los asistentes de IA y a otras herramientas basadas en LLM acceso directo al centro de ayuda, el tablero de feedback, el changelog, los hilos de mensajes, los programas beta y la lista de espera de un proyecto.
Endpoint
https://mcp.supdesk.app/mcpAutenticación
Pasa una clave de API como token Bearer:
Authorization: Bearer sd_live_...Genera claves en la consola de SupDesk, en Ajustes del workspace → Claves de API.
La clave determina el proyecto, así que ninguna herramienta acepta un argumento project_id.
No hay nada que un modelo tenga que adivinar o pueda equivocar.
Qué obtienes
Qué herramientas aparecen depende del proyecto. Una función desactivada en Ajustes del
proyecto no expone sus herramientas en tools/list en absoluto, igual que la API REST
responde 404 en esas rutas.
| Grupo | Herramientas | Requiere |
|---|---|---|
| Centro de ayuda | 10 | Centro de ayuda activado |
| Tablero de feedback | 5 | Tablero de feedback activado |
| Changelog | 5 | Changelog activado |
| Mensajes | 5 | Mensajes privados activados |
| Pruebas beta | 8 | Beta activado |
| Lista de espera | 4 | Lista de espera activada |
| Resumen | 1 | Siempre disponible |
La lectura funciona en todos los planes. Escribir requiere un plan de pago — crear,
actualizar o borrar con una clave de solo lectura devuelve forbidden, mientras que las lecturas
con esa misma clave funcionan sin problema.
Centro de ayuda
list_articles— artículos, con la edición más reciente primero. Incluye borradores y archivados; filtra constatuspara ver lo que ven los clientes.get_article— un artículo por id, con su cuerpo en Markdown.search_articles— búsqueda de texto completo sobre artículos publicados, ordenada por relevancia y con fragmento.create_article— crea un borrador. Publicar es una llamada aparte, para que nada llegue a los clientes por accidente.update_article— modifica cualquier campo; ponstatusenpublishedoarchived.delete_article— permanente; archiva en su lugar si quieres conservar el artículo.list_article_categories,create_article_category,update_article_category,delete_article_category— borrar una categoría deja sus artículos en su sitio, sin categoría.
El cuerpo de los artículos es Markdown, no HTML. El portal los renderiza con un visor que nunca evalúa HTML, así que el HTML llega a los lectores como texto literal.
create_article falla con limit_reached en cuanto se agota el cupo de artículos del plan —
Free 5, Pro 50, Team ilimitados.
Tablero de feedback
list_feedback— posts, los más recientes primero. Cubre los tres tipos (bug,feature,feedback) salvo que lo acotes contype.get_feedback,create_feedback,update_feedback— conupdate_feedbackmueves un post porbacklog → open → planned → in_progress → done.delete_feedback— elimina el post, sus votos y sus comentarios.
Changelog, mensajes, beta y lista de espera
Paridad completa con la API REST, sobre las mismas consultas:
- Changelog —
list_changelog,get_changelog_entry,create_changelog_entry,update_changelog_entry,delete_changelog_entry. Las entradas nacen como borrador, porque publicar es lo que envía el email de anuncio a tus suscriptores. - Mensajes —
list_threads,get_thread(con el historial completo),create_thread,reply_to_thread,update_thread. - Pruebas beta —
list_beta_programs,get_beta_program,create_beta_program,update_beta_program,delete_beta_program,list_beta_testers,add_beta_tester,remove_beta_tester.add_beta_testeres idempotente por email y devuelve el token de aceptación; este servidor no envía emails, así que entregar la invitación te corresponde a ti. - Lista de espera —
list_waitlist,add_waitlist_signup(idempotente por email),update_waitlist_signup,remove_waitlist_signup.
Resumen
project_stats devuelve recuentos de todo el proyecto — posts de feedback por estado, hilos
abiertos, artículos publicados y en borrador, y los votos útil / no útil que han recibido esos
artículos — para que un agente responda «¿qué queda pendiente?» sin recorrer cuatro listas
paginadas.
Salida estructurada
Cada herramienta declara un outputSchema y devuelve tanto structuredContent (tipado y
validado) como un bloque de texto content con los mismos datos en JSON. Procesa el que soporte
tu cliente.
const result = await mcpClient.callTool("get_article", { id: "8f7a..." });
result.structuredContent.article.title; // tipado
JSON.parse(result.content[0].text); // los mismos datos, como alternativaAnotaciones
Cada herramienta lleva anotaciones para que un cliente sepa qué está invocando antes de invocarlo:
| Anotación | Presente en |
|---|---|
readOnlyHint: true | list_*, get_*, search_*, project_stats |
idempotentHint: true | lecturas y update_* |
destructiveHint: true | delete_*, remove_* |
Paginación
Las herramientas de listado aceptan un cursor opaco y devuelven un next_cursor — devuélvelo
para la siguiente página y detente cuando sea null.
let cursor;
do {
const page = await mcpClient.callTool("list_articles", { status: "published", cursor });
handle(page.structuredContent.data);
cursor = page.structuredContent.next_cursor;
} while (cursor);Un cursor es un token, no aritmética — trátalo como opaco. Uno malformado devuelve
invalid_request en lugar de reiniciar en silencio desde la primera página, lo que haría que un
recorrido paginado se repitiera para siempre.
Ten en cuenta que esto es una convención dentro del esquema de argumentos de cada herramienta. El cursor a nivel de protocolo en MCP se aplica a listados de herramientas y recursos, no a lo que devuelve una herramienta; el listado de recursos de abajo sí usa el mecanismo real.
Recursos
Para adjuntar contenido del proyecto como contexto, en lugar de llamar a una herramienta y pegar el resultado:
| URI | Contenido |
|---|---|
supdesk://articles/{slug} | Un artículo de ayuda publicado, en Markdown. |
supdesk://board | Los posts de feedback abiertos del proyecto, en JSON. |
El listado de artículos está paginado de verdad a nivel de protocolo y cubre solo artículos publicados — un recurso es contenido que un cliente puede mostrar literalmente, y un borrador está sin publicar por algo.
Prompts
Dos puntos de partida, conectados a los datos reales del proyecto:
draft_article_from_thread— convierte una conversación de soporte resuelta en un artículo del centro de ayuda, para que el siguiente cliente con esa pregunta encuentre la respuesta en lugar de abrir un hilo. Necesita el centro de ayuda y los mensajes privados activados.triage_feedback— evalúa un post y recomienda un estado, con el razonamiento. Consulta antessearch_articles, así que una respuesta existente sale a la luz en lugar de proponerse trabajo nuevo.
Ambos usan la capacidad de completado de MCP para sus argumentos: mientras escribes una categoría, el servidor responde con los slugs de categoría reales del proyecto en vez de hacerte adivinar.
Logging
Las escrituras de varios pasos envían notificaciones de progreso por el logging de MCP —
create_article comprueba el cupo del plan, busca un slug libre y luego inserta, y lo informa en
cada paso. Un cliente sin soporte de logging no se ve afectado; la escritura ocurre igual.
Ejemplos
Claude Desktop
Añade esto a ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"sup-desk": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.supdesk.app/mcp",
"--header",
"Authorization: Bearer sd_live_..."
]
}
}
}Responder una pregunta, o escribir la respuesta
// Comprobar si el centro de ayuda ya lo cubre.
const hits = await mcpClient.callTool("search_articles", {
query: "restablecer contraseña",
limit: 5
});
if (hits.structuredContent.data.length === 0) {
// Aún no hay nada — redáctalo. Se crea como borrador.
const created = await mcpClient.callTool("create_article", {
title: "¿Cómo restablezco mi contraseña?",
body: "Abre **Ajustes** y elige *Restablecer contraseña*.",
category_id: "3c2b..."
});
// Publicar es deliberado y va aparte.
await mcpClient.callTool("update_article", {
id: created.structuredContent.article.id,
status: "published"
});
}Triar el tablero
const open = await mcpClient.callTool("list_feedback", {
status: "open",
limit: 10
});
await mcpClient.callTool("update_feedback", {
id: open.structuredContent.data[0].id,
status: "planned"
});Todo lo pendiente, en una llamada
const stats = await mcpClient.callTool("project_stats", {});
// { posts_by_status: { open: 12, planned: 3, ... }, open_threads: 4,
// articles_published: 18, articles_draft: 2,
// article_helpful: 240, article_not_helpful: 11 }Límites de tasa
El servidor MCP comparte los límites de la API REST: 120 peticiones por 60 segundos y proyecto. Ver Límites de tasa y uso.
Errores
Una llamada fallida devuelve isError: true con el mismo vocabulario de errores que usa la API
REST:
{
"error": {
"code": "limit_reached",
"message": "Your plan allows 5 help-center articles."
}
}| Código | Significado |
|---|---|
unauthorized | Clave de API ausente, malformada, revocada o desconocida. |
forbidden | Clave válida, pero el plan no tiene acceso de escritura a la API. |
invalid_request | Argumentos incorrectos — incluido un cursor malformado. |
not_found | No existe ese id en este proyecto. |
limit_reached | Se ha agotado un cupo del plan (por ejemplo el de artículos). |
rate_limited | Demasiadas peticiones en la ventana actual. |
internal_error | Algo ha fallado de nuestro lado. Es seguro reintentar. |
La lista completa está documentada en Errores.