MCP Server

Gérez le contenu cmssy depuis des agents IA via MCP - connectez Claude au serveur hébergé en vous connectant, ou lancez `@cmssy/mcp-server` en stdio avec un token API.

9 octobre 2026

Aperçu

@cmssy/mcp-server est un serveur Model Context Protocol qui relie les agents IA (Claude Code, Claude Desktop, tout outil compatible MCP) à un workspace Cmssy. Une fois configuré, l'agent peut lister et modifier des pages, ajouter ou retirer des blocs, publier des brouillons, gérer des formulaires et plus encore — sans jamais quitter son éditeur.

Il fonctionne de deux façons : Claude se connecte au serveur hébergé https://api.cmssy.io/mcp en vous connectant à cmssy, et n'importe quel client MCP peut lancer le paquet npm en stdio avec un token API. Aucune des deux ne demande de faire tourner votre propre serveur permanent.

Ce qui le distingue de l'API HTTP

  • Limité au workspace — une seule paire token + ID de workspace, tout est appliqué côté serveur
  • Outils de haut niveau — add_block_to_page, publish_page, patch_block_content, pas de GraphQL brut
  • Isolation des tenants intégrée — chaque requête est filtrée par votre workspace ; impossible de toucher accidentellement un autre tenant

Connecter Claude (sans token)

Claude sur le web, Claude Desktop et Claude Code se connectent au serveur hébergé https://api.cmssy.io/mcp. Vous vous connectez à cmssy et choisissez les workspaces que Claude peut utiliser - aucun token à copier, rien à installer.

Claude sur le web ou sur desktop

  1. Ouvrez Settings → Connectors et choisissez Add custom connector.
  2. Collez https://api.cmssy.io/mcp et ajoutez-le.
  3. Cliquez sur Connect, connectez-vous à cmssy, cochez les workspaces pour Claude et choisissez Lecture seule ou Lecture et écriture.

Un connecteur ajouté sur claude.ai est aussi disponible dans Claude Desktop.

Claude Code

claude mcp add --transport http cmssy https://api.cmssy.io/mcp

Lancez ensuite /mcp dans Claude Code et authentifiez-vous : la même connexion et le même choix de workspaces s'ouvrent dans votre navigateur.

Dans l'admin, Compte → Applications connectées → Connecter à Claude affiche la même URL et la même commande avec des boutons de copie.

Ce que Claude peut faire

  • Votre rôle, par workspace - Claude agit en votre nom, avec le rôle que vous avez dans chaque workspace coché. La lecture seule le limite à la lecture même là où votre rôle permettrait d'écrire.
  • Plusieurs workspaces à la fois - chaque outil prend un argument workspace (org-slug/workspace-slug), et list_workspaces liste ceux que vous avez accordés. Un workspace rejoint plus tard n'est pas ajouté - reconnectez-vous pour l'inclure.
  • Les outils destructeurs demandent d'abord - Claude vous demande avant un outil qui supprime ou publie, et la confirmation côté serveur (ci-dessous) s'applique toujours.
  • Audité à votre nom - une modification faite par Claude est enregistrée dans le journal d'audit du workspace à votre nom, comme une modification faite dans l'admin.

Déconnexion

Compte → Applications connectées → Déconnecter coupe Claude de tous les workspaces d'un coup. Un admin de workspace peut retirer un workspace de l'application d'un membre dans Paramètres → Applications connectées ; les autres workspaces du membre continuent de fonctionner. Perdre l'accès à un workspace le retire de vos connexions.

Ce qui parvient à Claude

Seulement le contenu des workspaces cochés, et seulement ce qu'un appel d'outil renvoie. cmssy stocke la connexion elle-même (quelle application, quels workspaces, lecture ou écriture) et des tokens hachés - jamais une copie de la conversation.

Installation avec un token API (stdio)

Pour la CI, des scripts ou un agent sans navigateur, lancez plutôt le paquet npm avec un token API.

1. Créez un token API

Workspace Settings → API Tokens → Create token. Copiez la valeur cs_… immédiatement — les tokens ne sont affichés qu'une seule fois. Le scope ne couvre que l'authentification ; ce que le token peut faire dépend de votre rôle et du flag isSuperAdmin.

Pas de navigateur ? Un agent peut créer le compte, l'organisation, le workspace et le token par l'API - voir Créer un token sans navigateur.

2. Trouvez l'ID de votre workspace

Workspace Settings → General propose un bouton de copie à côté de l'ID. C'est le même workspace que celui lié à votre token API.

3. Ajoutez-le à la config MCP de votre éditeur

Pour Claude Code, éditez .mcp.json à la racine du projet (ou enregistrez-le pour tous vos projets avec claude mcp add --scope user) :

{
  "mcpServers": {
    "cmssy": {
      "command": "npx",
      "args": [
        "-y",
        "@cmssy/mcp-server@latest",
        "--token", "cs_your_token_here",
        "--workspace-id", "507f1f77bcf86cd799439011"
      ]
    }
  }
}

Les équivalents en variables d'environnement sont aussi pris en charge : CMSSY_API_TOKEN, CMSSY_WORKSPACE_ID, CMSSY_API_URL. Utile si vous ne voulez pas du token dans un fichier de config commité.

--api-url (ou CMSSY_API_URL) est l'origine de l'API, https://api.cmssy.io par défaut ; le serveur ajoute lui-même /graphql, ne l'incluez donc pas.

4. Redémarrez l'éditeur

Claude Code charge le serveur au prochain démarrage de session. Vous devriez voir une entrée MCP cmssy avec la liste des outils disponibles.

Outils disponibles

La liste complète, avec la permission requise par chaque outil, se trouve dans Outils MCP - le serveur la génère à chaque version, elle correspond donc toujours à ce que votre version expose. Les outils partagent une forme de nommage - list_* et get_* pour lire, create_* / update_* / delete_* pour écrire, plus des verbes pour les transitions d'état - et se répartissent en groupes :

  • Pages et blocs - l'arbre des pages, les blocs, les régions de layout, les types de page et la publication : get_page, add_block_to_page, patch_block_content, publish_page. Appelez list_block_types avant d'ajouter un bloc : il renvoie les types de blocs que votre site enregistre réellement.
  • Modèles et enregistrements - les schémas et leurs entrées, y compris l'import en masse import_records. delete_record refuse tant qu'un bloc utilise encore l'enregistrement et nomme les pages qui l'utilisent ; passez force: true pour supprimer quand même.
  • Médias - les uploads et les dossiers.
  • Formulaires - les formulaires et leurs soumissions.
  • Commerce - les produits, les commandes (commandes manuelles, paiements, factures, remboursements, expédition, le pipeline de commandes), les paniers, les remises et les clients.
  • Webhooks - les abonnements, les livraisons et les secrets de signature. list_webhook_event_types est la liste autorisée des événements auxquels s'abonner ; un secret de signature n'est renvoyé qu'une fois, à la création et à la rotation.
  • Workspace - get_workspace_info (plan, limites, usage), get_site_config, l'équipe et les rôles.

La recherche plein texte search_content n'est pas exposée par le serveur MCP ; elle est accessible depuis l'assistant de l'admin. Rien dans cet ensemble ne touche à votre code : aucun outil n'écrit de fichier, ne modifie de composant ni n'ouvre de pull request - l'IA modifie le contenu, et les schémas de blocs restent dans votre dépôt, sous revue.

Confirmation avant les actions destructrices

Les outils dont l'effet est le plus difficile à annuler - par exemple delete_page, publish_page, refund_order, bulk_delete_products - n'agissent pas au premier appel. Ils répondent avec needsConfirmation: true, un summary d'une ligne décrivant ce qui se passerait et un ref - et rien ne change. L'agent vous montre le résumé ; une fois que vous approuvez, il rappelle le même outil avec les mêmes arguments plus _confirm: "<ref>".

  • Un ref fonctionne une fois, pendant la durée indiquée par expiresInSeconds, et seulement avec les arguments pour lesquels il a été émis - changez un argument et le serveur redemande.
  • Un outil qui demande une confirmation a un paramètre _confirm dans son schéma d'entrée : un client peut donc les reconnaître depuis tools/list.
  • La même règle s'applique dans l'assistant IA de l'admin, où vous approuvez avec un bouton dans le chat.

Brouillons de développement : un bloc pas encore déployé

Chaque outil d'écriture accepte un target optionnel. "draft" (par défaut) modifie le brouillon partagé de la page ; "devDraft" modifie votre propre calque, par utilisateur, qui part de la page actuelle et ne change l'aperçu de personne d'autre.

C'est ce qui permet de composer une page autour d'un type de bloc qui n'existe encore que sur votre machine. Une fois le bloc déployé, promote_dev_draft bascule votre calque sur le brouillon partagé. get_page avec target: "devDraft" renvoie le calque à côté du brouillon partagé, ou null si vous n'en avez pas.

patch_block_content — éditions chirurgicales

Pour des modifications ciblées sur du contenu de plusieurs Ko (articles de docs, longs billets de blog), patch_block_content n'envoie que le diff — pas la chaîne complète. Il s'appuie sur MongoDB findOneAndUpdate avec $set + arrayFilters, limité au tenant, atomique. Typiquement ~10× moins cher en tokens que renvoyer tout le HTML via update_block_content.

Trois types d'opérations

insert_before / insert_after

Insérez du HTML juste avant/après un marqueur unique. Le marqueur DOIT correspondre à exactement un emplacement — zéro ou plusieurs occurrences rejettent l'opération avec BAD_USER_INPUT.

{
  "op": "insert_after",
  "marker": "<h2>Pricing</h2>",
  "html": "<p>Plans start at $0/month.</p>"
}

replace_section

Remplace tout depuis startMarker (inclus) jusqu'à endMarker (exclu). Les deux marqueurs doivent se résoudre de façon unique.

{
  "op": "replace_section",
  "startMarker": "<h2>Pricing</h2>",
  "endMarker": "<h2>FAQ</h2>",
  "html": "<h2>Pricing</h2><p>New plans here.</p>"
}

Plusieurs opérations en un appel

Les opérations s'appliquent dans l'ordre sur le résultat courant. Tout échec (marqueur manquant, ambigu, etc.) annule le patch entier — pas d'état à moitié appliqué.

{
  "pageId": "...",
  "blockId": "...",
  "locale": "en",
  "operations": [
    {
      "op": "insert_before",
      "marker": "<h2>Appendix</h2>",
      "html": "<h2>New Section</h2><p>…</p>"
    },
    {
      "op": "replace_section",
      "startMarker": "<h2>Pricing</h2>",
      "endMarker": "<h2>FAQ</h2>",
      "html": "<h2>Pricing</h2><p>Updated.</p>"
    }
  ]
}

Quand une opération échoue

  • 0 correspondance — marqueur introuvable. Vérifiez la correspondance exacte au caractère près ; les espaces et l'ordre des attributs comptent.
  • 2+ correspondances — le marqueur n'est pas unique. Ajoutez du HTML environnant pour lever l'ambiguïté. Les correspondances qui se chevauchent comptent ("aa" dans "aaa" compte pour 2), évitez donc les marqueurs ultra-courts.
  • Le champ n'est pas une chaîne — le fieldPath ciblé résout vers un tableau ou un objet. Utilisez update_block_content pour les champs structurés.
  • Blocs de layout non pris en charge — header/footer et autres blocs de layout passent par update_block_content.

patch_block_content vs update_block_content

 patch_block_contentupdate_block_content
Quand l'utiliserÉditions ciblées sur une chaîne HTMLRéécriture complète du contenu, toute forme
Coût en tokensProportionnel au diffProportionnel au contenu complet
Gain typique~10× sur du contenu de plusieurs Ko–
Types de champsChaîne uniquement (via fieldPath)Tous (chaînes, tableaux, objets imbriqués)
Échec partielLe patch entier est annulé — pas d'état à moitié appliquéL'écriture entière réussit ou échoue
Blocs de layoutNon pris en chargePris en charge

Règle simple : si vous renvoyiez auparavant tout le HTML pour changer un seul paragraphe, utilisez patch_block_content. Sinon, restez sur update_block_content.

Dépannage

  • Chaque appel échoue en 404 - --api-url se termine par /graphql. Passez seulement l'origine (https://api.cmssy.io, la valeur par défaut) - le serveur ajoute le chemin lui-même.
  • « Workspace not found » — la personne derrière le token n'est pas membre du --workspace-id indiqué, ou l'identifiant est faux. Un token authentifie une personne ; ce qu'il permet vient du rôle de cette personne dans cet espace. Vérifiez la paire dans Workspace Settings.
  • « Not authenticated » — token expiré ou révoqué. Créez-en un nouveau depuis Workspace Settings → API Tokens.
  • Serveur MCP invisible dans l'éditeur — redémarrez l'éditeur après un changement de config. Dans Claude Code, consultez Settings → MCP → cmssy pour les logs de démarrage.
  • Limites de débit / de plan — le serveur MCP respecte les limites du plan du workspace (pages max, stockage, tokens IA). get_workspace_info montre l'utilisation actuelle vs les limites.

Mode de réponse

Chaque outil d'écriture accepte un paramètre optionnel response: "minimal" | "full" (défaut "minimal"). Minimal renvoie un petit ack JSON compact (~100-200 octets) avec juste les IDs et l'état nécessaires pour enchaîner l'appel suivant — pas la ressource mutée complète.

Formes d'ack minimal

  • Outils de pages (create_page, update_page_blocks, update_page_settings, publish_page, unpublish_page, revert_to_published, update_page_layout) — {id, slug, hasUnpublishedChanges, updatedAt} (+published pour publish/unpublish)
  • Outils bloc-sur-page (add_block_to_page, update_block_content, remove_block_from_page) — {pageId, blockId, hasUnpublishedChanges, updatedAt}
  • Outils de formulaires (create_form, update_form) — {id, slug, status, updatedAt}
  • Outils de modèles (create_model, update_model) — {id, slug, updatedAt}
  • Outils d'enregistrements (create_record, update_record) — {id, status, updatedAt}

Quand opter pour full

Passez response: "full" quand vous avez réellement besoin de la ressource mutée complète dans le même appel — p. ex. pour vérifier une transformation complète, lire un champ généré côté serveur ou déboguer. Sinon, enchaînez avec un outil de lecture (get_page / get_form / get_model / get_record).

Outils sans response

Ils renvoient déjà un ack compact et restent inchangés : patch_block_content, tous les delete_*, update_form_submission_status, import_records.

Version

Utilisez @cmssy/mcp-server@latest dans .mcp.json pour recevoir les nouveaux outils dès leur sortie ; npx @cmssy/mcp-server --version affiche la version que vous exécutez. Chaque version republie Outils MCP directement depuis le serveur : cette page correspond donc toujours à la version la plus récente.