Skip to Content
Serveur MCPServeur MCP

Serveur MCP

Le serveur MCP (Model Context Protocol) de SupDesk donne aux assistants IA et aux autres outils alimentés par des LLM un accès direct au centre d’aide, au tableau de feedback, au changelog, aux fils de messages, aux programmes bêta et à la liste d’attente d’un projet.

Point de terminaison

https://mcp.supdesk.app/mcp

Authentification

Passez une clé d’API en tant que token Bearer :

Authorization: Bearer sd_live_...

Générez des clés dans la console SupDesk, sous Réglages du workspace → Clés d’API.

La clé détermine le projet : aucun outil ne prend d’argument project_id. Il n’y a rien qu’un modèle doive deviner ou puisse se tromper.

Ce que vous obtenez

Les outils disponibles dépendent du projet. Une fonctionnalité désactivée dans les Réglages du projet voit ses outils totalement absents de tools/list, exactement comme l’API REST répond 404 sur ses routes.

GroupeOutilsNécessite
Centre d’aide10Centre d’aide activé
Tableau de feedback5Tableau de feedback activé
Changelog5Changelog activé
Messages5Messages privés activés
Tests bêta8Bêta activé
Liste d’attente4Liste d’attente activée
Vue d’ensemble1Toujours disponible

La lecture fonctionne sur toutes les formules. L’écriture exige une formule payante — créer, mettre à jour ou supprimer avec une clé en lecture seule renvoie forbidden, alors que les lectures avec cette même clé fonctionnent normalement.

Centre d’aide

  • list_articles — articles, la modification la plus récente d’abord. Inclut brouillons et archives ; filtrez avec status pour ce que les clients voient.
  • get_article — un article par id, avec son corps en Markdown.
  • search_articles — recherche plein texte sur les articles publiés, classée, avec extrait.
  • create_article — crée un brouillon. Publier est un appel distinct, pour que rien n’atteigne les clients par accident.
  • update_article — modifie n’importe quel champ ; passez status à published ou archived.
  • delete_article — définitif ; archivez plutôt si vous voulez conserver l’article.
  • list_article_categories, create_article_category, update_article_category, delete_article_category — supprimer une catégorie laisse ses articles en place, sans catégorie.

Le corps des articles est du Markdown, pas du HTML. Le portail les rend via une visionneuse qui n’évalue jamais le HTML : le HTML parvient donc aux lecteurs comme du texte littéral.

create_article échoue avec limit_reached dès que le quota d’articles de la formule est épuisé — Free 5, Pro 50, Team illimité.

Tableau de feedback

  • list_feedback — posts, les plus récents d’abord. Couvre les trois types (bug, feature, feedback) sauf si vous restreignez avec type.
  • get_feedback, create_feedback, update_feedbackupdate_feedback fait avancer un post dans backlog → open → planned → in_progress → done.
  • delete_feedback — supprime le post, ses votes et ses commentaires.

Changelog, messages, bêta et liste d’attente

Parité complète avec l’API REST, sur les mêmes requêtes :

  • Changeloglist_changelog, get_changelog_entry, create_changelog_entry, update_changelog_entry, delete_changelog_entry. Les entrées naissent en brouillon, car c’est la publication qui envoie l’e-mail d’annonce à vos abonnés.
  • Messageslist_threads, get_thread (avec l’historique complet), create_thread, reply_to_thread, update_thread.
  • Tests bêtalist_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_tester est idempotent sur l’e-mail et renvoie le token d’acceptation ; ce serveur n’envoie pas d’e-mail, la remise de l’invitation vous revient donc.
  • Liste d’attentelist_waitlist, add_waitlist_signup (idempotent sur l’e-mail), update_waitlist_signup, remove_waitlist_signup.

Vue d’ensemble

project_stats renvoie des décomptes sur tout le projet — posts de feedback par statut, fils ouverts, articles publiés et en brouillon, et les votes utile / pas utile reçus par ces articles — pour qu’un agent réponde à « qu’est-ce qui reste ? » sans parcourir quatre listes paginées.

Sortie structurée

Chaque outil déclare un outputSchema et renvoie à la fois structuredContent (typé et validé) et un bloc de texte content contenant les mêmes données en JSON. Traitez celui que votre client prend en charge.

const result = await mcpClient.callTool("get_article", { id: "8f7a..." }); result.structuredContent.article.title; // typé JSON.parse(result.content[0].text); // les mêmes données, en repli

Annotations

Chaque outil porte des annotations, pour qu’un client sache ce qu’il invoque avant de l’invoquer :

AnnotationPrésente sur
readOnlyHint: truelist_*, get_*, search_*, project_stats
idempotentHint: trueles lectures et update_*
destructiveHint: truedelete_*, remove_*

Pagination

Les outils de listage acceptent un cursor opaque et renvoient un next_cursor — repassez-le pour la page suivante, et arrêtez-vous quand il vaut 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 curseur est un token, pas un calcul — traitez-le comme opaque. Un curseur malformé renvoie invalid_request plutôt que de repartir silencieusement de la première page, ce qui ferait boucler indéfiniment un parcours paginé.

Notez qu’il s’agit d’une convention dans le schéma d’arguments de chaque outil. Le curseur au niveau du protocole MCP s’applique aux listages d’outils et de ressources, pas à ce qu’un outil renvoie ; le listage de ressources ci-dessous utilise le mécanisme réel.

Ressources

Pour attacher du contenu du projet comme contexte, plutôt que d’appeler un outil et de coller le résultat :

URIContenu
supdesk://articles/{slug}Un article d’aide publié, en Markdown.
supdesk://boardLes posts de feedback ouverts du projet, en JSON.

Le listage d’articles est réellement paginé au niveau du protocole et couvre uniquement les articles publiés — une ressource est du contenu qu’un client peut afficher tel quel, et un brouillon n’est pas publié pour une raison.

Prompts

Deux points de départ, câblés aux données réelles du projet :

  • draft_article_from_thread — transforme une conversation de support résolue en article du centre d’aide, pour que le prochain client avec cette question trouve la réponse au lieu d’ouvrir un fil. Nécessite le centre d’aide et les messages privés.
  • triage_feedback — évalue un post et recommande un statut, avec le raisonnement. Il consulte d’abord search_articles, pour qu’une réponse existante ressorte plutôt que du travail nouveau soit proposé.

Tous deux utilisent la capacité de complétion de MCP pour leurs arguments : pendant que vous tapez une catégorie, le serveur répond avec les slugs de catégorie réels du projet, au lieu de vous laisser deviner.

Journalisation

Les écritures en plusieurs étapes envoient des notifications de progression via la journalisation MCP — create_article vérifie le quota de la formule, cherche un slug libre puis insère, et le signale à chaque étape. Un client sans support de journalisation n’est pas affecté ; l’écriture a lieu dans tous les cas.

Exemples

Claude Desktop

Ajoutez ceci à ~/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_..." ] } } }

Répondre à une question, ou écrire la réponse

// Vérifier si le centre d'aide le couvre déjà. const hits = await mcpClient.callTool("search_articles", { query: "réinitialiser mot de passe", limit: 5 }); if (hits.structuredContent.data.length === 0) { // Rien pour l'instant — rédigez-le. Il est créé en brouillon. const created = await mcpClient.callTool("create_article", { title: "Comment réinitialiser mon mot de passe ?", body: "Ouvrez **Réglages**, puis choisissez *Réinitialiser le mot de passe*.", category_id: "3c2b..." }); // Publier est délibéré et distinct. await mcpClient.callTool("update_article", { id: created.structuredContent.article.id, status: "published" }); }

Trier le tableau

const open = await mcpClient.callTool("list_feedback", { status: "open", limit: 10 }); await mcpClient.callTool("update_feedback", { id: open.structuredContent.data[0].id, status: "planned" });

Tout ce qui reste, en un appel

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 }

Limites de débit

Le serveur MCP partage les limites de l’API REST : 120 requêtes par 60 secondes et par projet. Voir Limites de débit et usage.

Erreurs

Un appel d’outil en échec renvoie isError: true, avec le même vocabulaire d’erreurs que l’API REST :

{ "error": { "code": "limit_reached", "message": "Your plan allows 5 help-center articles." } }
CodeSignification
unauthorizedClé d’API manquante, malformée, révoquée ou inconnue.
forbiddenClé valide, mais la formule n’a pas d’accès en écriture à l’API.
invalid_requestMauvais arguments — y compris un cursor malformé.
not_foundAucun id de ce genre dans ce projet.
limit_reachedUn quota de la formule est épuisé (par exemple le plafond d’articles).
rate_limitedTrop de requêtes dans la fenêtre courante.
internal_errorQuelque chose a échoué de notre côté. Réessayer est sans risque.

La liste complète est documentée sous Erreurs.

Last updated on