Tutoriel

Connectez Claude Code à votre CMS headless via MCP

D'un clone tout neuf à Claude Code qui crée, modifie et publie une page affichée par votre propre application Next.js. Un jeton d'API, un fichier de configuration, aucun code de liaison.

É
Équipe Cmssy
9 min read

Connectez Claude Code à votre CMS headless via MCP

Lancez une application Next.js d'exemple, connectez Claude Code au même workspace cmssy via MCP et regardez les changements de contenu arriver sur votre propre site.

Ce que nous construisons

À la fin de ce guide, Claude Code créera une page, la remplira de contenu, la publiera puis la modifiera à nouveau, et une application Next.js tournant sur votre machine affichera chaque changement. Personne n'ouvre de panneau d'administration.

Trois éléments entrent en jeu, et il vaut mieux les distinguer :

  • Votre application Next.js affiche le site. Ici, il s'agit de simple-blog, issu du dépôt d'exemples cmssy. cmssy ne l'affiche ni ne l'héberge jamais.
  • Votre workspace cmssy stocke le contenu et le sert à l'application via l'API de diffusion.
  • @cmssy/mcp-server connecte Claude Code à ce workspace. Claude lit et écrit le contenu par son intermédiaire. Il ne touche pas à votre code : le serveur n'écrit aucun fichier et ne conserve aucun état local.

Prérequis

  • Node 22.13 ou plus récent, et pnpm (npm fonctionne aussi)
  • Claude Code installé
  • Un workspace cmssy. L'offre gratuite suffit pour ce guide.

Étape 1 : lancer l'application d'exemple

Clonez le dépôt d'exemples et démarrez simple-blog :

git clone https://github.com/cmssy-io/examples
cd examples/simple-blog
pnpm install
cp .env.example .env.local
pnpm dev

Ouvrez http://localhost:3000. La racine redirige vers /blog, qui affiche le contenu d'un workspace de démonstration public. Vous n'avez pas besoin de compte pour cette étape. Ensuite, pointez l'application vers votre propre workspace.

Étape 2 : créer un jeton d'API

Dans le tableau de bord cmssy, ouvrez API Tokens et cliquez sur Create Token. Donnez-lui un nom et, sous Workspace, choisissez le workspace utilisé par ce projet. Un jeton limité à un workspace ne peut ouvrir que celui-ci, ce qui suffit à un agent travaillant dans un seul dépôt.

Copiez la valeur cs_... dès qu'elle apparaît. Elle n'est affichée qu'une fois.

Un jeton n'a aucune permission propre. Il agit en votre nom, avec le rôle que vous détenez dans ce workspace : le jeton d'un éditeur peut modifier, celui d'un membre en lecture seule ne peut que lire.

Étape 3 : lier l'application à votre workspace

npx @cmssy/cli link --token cs_your_token

link récupère le slug de votre organisation, le slug du workspace et le secret de brouillon, puis les écrit dans .env.local. Si le workspace n'a pas encore de manifeste de blocs, la commande envoie aussi celui de l'application. Ce manifeste est la liste des types de blocs que l'application sait afficher, ici prose et blog-index. Redémarrez ensuite pnpm dev.

Le manifeste explique pourquoi Claude ne placera pas sur une page un bloc que votre site ne peut pas afficher : le serveur refuse les types de blocs absents du manifeste.

Étape 4 : trouver l'ID de votre workspace

Le serveur MCP attend un ID de workspace en plus du jeton. Ouvrez les Settings de votre workspace. L'ID se trouve sous Workspace Information.

Étape 5 : déclarer le serveur MCP

Ajoutez .mcp.json à la racine du projet. Il ne contient aucun secret, vous pouvez donc le commiter :

{
  "mcpServers": {
    "cmssy": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cmssy/mcp-server@latest"]
    }
  }
}

Gardez plutôt le jeton dans votre shell. Le serveur lit CMSSY_API_TOKEN et CMSSY_WORKSPACE_ID dans son environnement, et Claude Code le démarre avec le vôtre :

export CMSSY_API_TOKEN=cs_your_token
export CMSSY_WORKSPACE_ID=your_workspace_id
claude

La première fois que vous lancez claude dans le projet, Claude Code demande s'il doit faire confiance au serveur MCP déclaré dans .mcp.json. Acceptez, puis exécutez /mcp. Vous devriez voir cmssy connecté.

Le serveur accepte aussi les options --token et --workspace-id. Utilisez-les pour un test local rapide, mais gardez le jeton hors des fichiers commités.

Étape 6 : demander ce que le site sait afficher

Commencez par quelque chose en lecture seule :

Quels types de blocs mon site peut-il afficher, et quelles pages existent ?

Claude appelle list_block_types et list_pages. Les types de blocs qu'il liste sont ceux du manifeste de votre application, avec leurs champs : Claude sait donc que prose a un champ de texte riche body avant d'écrire quoi que ce soit.

Étape 7 : construire et publier une page

Crée une page /blog avec un index de blog qui liste ses pages enfants.
En dessous, ajoute un article intitulé "Hello from Claude Code" avec deux
courts paragraphes dans un bloc prose. Remplis toutes les langues activées
dans le workspace, puis publie les deux pages.

Claude enchaîne get_site_config (pour connaître vos langues), create_page, add_block_to_page et publish_page. Claude Code demande confirmation avant d'exécuter chaque outil que vous n'avez pas encore autorisé, vous voyez donc chaque écriture avant qu'elle ait lieu.

Actualisez http://localhost:3000/blog. L'index liste le nouvel article, et l'article s'affiche via le composant prose de l'application.

Étape 8 : modifier, puis publier à nouveau

Réécris le premier paragraphe de "Hello from Claude Code" pour mentionner
MCP, et change son titre SEO. Puis publie-le.

Les modifications atterrissent d'abord dans le brouillon de la page. Votre site ne sert que la version publiée : rien ne change dans l'application tant que publish_page n'a pas été exécuté. Ensuite, actualisez et le nouveau texte est là : en développement, Next génère chaque requête à neuf.

Pour un seul paragraphe dans un long article, Claude peut utiliser patch_block_content, qui n'envoie que la partie modifiée au lieu de tout le HTML.

Décider ce que Claude peut faire sans demander

Claude Code demande confirmation avant chaque appel MCP que vous n'avez pas autorisé. Les lectures peuvent être autorisées sans risque. Laissez les écritures, et surtout publish_page et delete_page, soumises à confirmation. Dans .claude/settings.json :

{
  "permissions": {
    "allow": [
      "mcp__cmssy__list_block_types",
      "mcp__cmssy__list_pages",
      "mcp__cmssy__get_page",
      "mcp__cmssy__get_site_config"
    ]
  }
}

Le serveur étiquette ses outils pour le client : les outils de lecture comme étant en lecture seule, et ceux qui suppriment, publient ou enregistrent un remboursement comme destructifs.

Passer en production

En production, simple-blog met chaque page en cache jusqu'à une heure (revalidate = 3600), une publication apparaîtrait donc avec du retard. Activez les mises à jour immédiates avec une route de revalidation et un webhook :

import { createCmssyRevalidateRoute } from "@cmssy/next/server";

export const POST = createCmssyRevalidateRoute({
  secret: process.env.CMSSY_WEBHOOK_SECRET,
});

Placez ce code dans app/api/revalidate/route.ts, puis abonnez un webhook à content.changed pointant vers cette route. Claude peut créer le webhook avec create_webhook. Le secret de signature n'est renvoyé qu'une fois : placez-le directement dans CMSSY_WEBHOOK_SECRET sur votre hébergeur. La route vérifie la signature et invalide les tags de cache cmssy.

Pas de jeton ? Connectez-vous plutôt

Claude Code peut aussi utiliser le serveur MCP hébergé de cmssy, qui vous connecte via le navigateur au lieu d'utiliser un jeton :

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

Exécutez /mcp et authentifiez-vous. Vous choisissez les workspaces que Claude peut utiliser et s'il obtient la lecture seule ou la lecture et l'écriture. Les outils sont les mêmes, mais chacun prend le workspace sous la forme org/workspace, si bien qu'une seule connexion peut servir plusieurs workspaces. Utilisez la configuration par jeton pour la CI ou tout environnement sans navigateur.

Dépannage

  • Chaque appel renvoie "Not authorized" : le jeton est révoqué ou expiré, ou il ne peut pas ouvrir le workspace indiqué dans CMSSY_WORKSPACE_ID. Le serveur démarre même avec un mauvais jeton, donc l'état "connected" dans /mcp ne prouve pas que le jeton est valide.
  • Le serveur n'apparaît pas : les variables n'ont pas été exportées dans le shell qui a lancé claude. Sans jeton, le serveur s'arrête au démarrage.
  • Un outil attendu est absent : une ancienne version est peut-être en cache dans npx. Comparez npx -y @cmssy/mcp-server --version avec npm view @cmssy/mcp-server version.
  • Un bloc est refusé : son type n'est pas dans le manifeste du workspace. Demandez à Claude d'exécuter list_block_types et d'en utiliser un qui y figure.

La référence complète, avec chaque outil et la permission qu'il requiert, se trouve dans la documentation du serveur MCP. Les jetons sont décrits dans API tokens.