Serveur Model Context Protocol (MCP) qui permet à un agent IA de lire et d'éditer des documents sur une instance la-suite Docs, avec édition fine au niveau du paragraphe et compatibilité temps réel avec les éditeurs humains connectés.
Le truc qui rend ce MCP particulier : l'agent et toi partagez le même état Yjs (CRDT) en temps réel, comme deux humains qui éditeraient le même Google Doc. Concrètement :
- Tu tapes dans BlockNote (le navigateur), l'agent voit ta modif au prochain
read_document. Pas de cache à invalider, pas de "synchroniser maintenant" à cliquer. - L'agent insère un paragraphe, il apparaît instantanément dans ton navigateur, sans recharger la page.
- Vous pouvez taper en même temps dans le même paragraphe : Yjs résout les conflits par construction (CRDT). Personne n'écrase personne.
Pas de polling à coder côté agent, pas de mécanisme custom : c'est la nature même du protocole Yjs/Hocuspocus que Docs utilise. Le serveur MCP est juste un client Yjs comme ton navigateur — tous les clients connectés au même doc reçoivent les updates des autres en background.
Cas d'usage typique : « Claude, rédige la section 2 pendant que j'écris l'intro » — chacun travaille dans son coin de la même page, l'agent suit ce que tu fais, tu vois ce qu'il pose, et au final c'est cohérent. Sans aucun copier-coller, sans git pull, sans rafraîchissement.
Note technique : le serveur MCP doit rester long-lived pour que la WebSocket reste chaude (donc Claude Desktop / Claude Code OK ; pas un script qui spawn
nodeà chaque appel). Le SessionManager garde la connexion ouverte 5 min après le dernier appel, puis la ferme par GC. Tout ça est transparent pour l'agent.
v0.5.0 — upload d'images : nouveau tool insert_image qui prend une image en base64, l'upload sur le storage S3 du document via attachment-upload, et l'insère comme bloc image BlockNote dans le Y.Doc. read_document retourne aussi les images existantes (type, url, name, caption). Hérite de v0.4.0 (persistance garantie via PATCH automatique, vérification immédiate des cookies, distinction 401/403, hydratation REST avant WS, instructions MCP) et v0.3.0 (markdown inline sur les opérations d'édition). 17 tools : lecture (avec arborescence et images), édition de contenu en markdown, upload d'images, gestion de l'arborescence, authentification.
Le serveur Hocuspocus de Docs n'a aucun mécanisme de persistance automatique : c'est le frontend BlockNote qui sauvegarde toutes les 60s côté navigateur. Pour que le MCP soit fiable en autonomie (sans humain connecté en parallèle), il fait lui-même un PATCH sur le document après chaque write Yjs.
- En mode authentifié (cookies posés via
set_session_credentials) : persistance garantie, écritures fiables même sans humain connecté. - En mode anonyme (sans cookies, doc public en
link_role: editor) : le PATCH est refusé par Django. La persistance dépend alors d'un humain qui a le doc ouvert dans son navigateur — sinon, l'écriture est perdue. Le MCP retourne un champwarningclair à l'agent dans ce cas.
| Tool | Usage |
|---|---|
list_documents |
Liste les docs publics de l'instance |
read_document |
Lit la liste structurée des paragraphes/headings |
get_document_metadata |
Récupère les métadonnées (titre, dates, accès) |
list_document_children |
Enfants directs d'un document (1 niveau) |
list_document_descendants |
Tous les descendants à plat (récursif, max_depth borné). Sans parent → tous les docs accessibles à l'utilisateur. |
| Tool | Usage |
|---|---|
insert_block |
Insère un paragraphe ou heading. Le text est interprété comme du markdown inline (gras, italique, code, strike, liens) |
update_block |
Modifie le texte d'un bloc existant. Idem : markdown inline supporté |
delete_block |
Supprime un bloc |
insert_image |
Upload une image (base64) sur le storage du doc et insère un bloc image. Formats supportés : PNG, JPEG, GIF, WebP, SVG. |
Format markdown supporté sur les paramètres text de insert_block et update_block :
| Markdown | Rendu BlockNote |
|---|---|
**gras** |
gras |
*italique* |
italique |
`code` |
code (police mono, fond gris) |
~~barré~~ |
|
[texte](url) |
texte (lien cliquable) |
\* \_ ``` etc. |
Caractères littéraux échappés |
read_document retourne le contenu en markdown : un agent peut lire un bloc, modifier la chaîne markdown, et la réinjecter via update_block sans perte (round-trip propre).
| Tool | Usage |
|---|---|
set_session_credentials |
Enregistre docs_sessionid + csrftoken en mémoire (optionnel : settle l'instance) |
clear_session_credentials |
Vide les credentials (conserve l'instance) |
| Tool | Usage |
|---|---|
create_document |
Crée un doc top-level ou un sous-doc (parent_id) |
delete_document |
Supprime un doc (cascade sur les sous-docs) |
move_document |
Déplace un doc dans l'arborescence |
duplicate_document |
Duplique un doc (optionnel : avec les accès) |
update_document_title |
Renomme un doc |
list_my_documents |
Liste les docs accessibles à l'utilisateur connecté |
Prérequis : Node.js ≥ 20 (le projet utilise ESM NodeNext et top-level await).
git clone https://github.com/CoopCodeCommun/lasuite-docs-mcp.git
cd lasuite-docs-mcp
npm install
npm run buildVérification rapide après build :
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/server.js | head -c 300Doit retourner un JSON-RPC listant les 16 tools.
Variables d'environnement :
| Variable | Défaut | Description |
|---|---|---|
DOCS_INSTANCE_URL |
— | URL HTTPS de l'instance Docs. Optionnelle en v0.2 : l'instance est détectée automatiquement depuis les liens doc_url passés aux tools. Utile pour forcer une instance dès le démarrage (compat v0.1). |
DOCS_SESSION_TTL_MS |
300000 |
TTL des sessions WebSocket en cache |
DOCS_SYNC_TIMEOUT_MS |
10000 |
Timeout du sync initial Yjs |
Voir .env.example.
Les tools de gestion de l'arborescence (create_document, delete_document, etc.) et list_my_documents nécessitent un cookie de session valide. Le flow est le suivant :
- L'agent tente une opération d'écriture.
- Le serveur retourne
{code: "AUTH_REQUIRED", ...}avec les instructions pour récupérer les cookies. - L'utilisateur ouvre les DevTools de son navigateur sur l'instance Docs cible :
- Chrome / Edge / Brave : F12 → onglet « Application » → « Cookies » → URL de l'instance → copier les valeurs de
docs_sessionidetcsrftoken. - Firefox : F12 → onglet « Stockage » → « Cookies » → URL de l'instance → copier les valeurs.
- Note :
docs_sessionidest marquéHttpOnly, il n'est visible que depuis les DevTools, pas depuis la console JavaScript.
- Chrome / Edge / Brave : F12 → onglet « Application » → « Cookies » → URL de l'instance → copier les valeurs de
- L'utilisateur appelle
set_session_credentials({docs_sessionid: "...", csrftoken: "..."}). - L'agent retente l'opération.
Les credentials expirent ~12h après la connexion. Ils sont stockés uniquement en mémoire (jamais écrits sur disque, jamais inclus dans les réponses des tools).
Remplace /chemin/absolu/vers/lasuite-docs-mcp par le chemin réel sur ta machine. DOCS_INSTANCE_URL est optionnelle (cf. section Configuration).
Le plus rapide, via la commande CLI :
# Disponible dans toutes tes sessions (recommandé pour un usage personnel)
claude mcp add --transport stdio --scope user lasuite-docs \
-- node /chemin/absolu/vers/lasuite-docs-mcp/dist/server.js
# Avec une instance par défaut
claude mcp add --transport stdio --scope user \
--env DOCS_INSTANCE_URL=https://notes.liiib.re \
lasuite-docs -- node /chemin/absolu/vers/lasuite-docs-mcp/dist/server.js
# Limité à un projet précis (créera .mcp.json à la racine du projet)
claude mcp add --transport stdio --scope project lasuite-docs \
-- node /chemin/absolu/vers/lasuite-docs-mcp/dist/server.jsOu directement en JSON dans ~/.claude.json (user) ou .mcp.json (project) :
{
"mcpServers": {
"lasuite-docs": {
"type": "stdio",
"command": "node",
"args": ["/chemin/absolu/vers/lasuite-docs-mcp/dist/server.js"],
"env": {
"DOCS_INSTANCE_URL": "https://notes.liiib.re"
}
}
}
}Dans ~/Library/Application Support/Claude/claude_desktop_config.json (macOS), %APPDATA%\Claude\claude_desktop_config.json (Windows), ou équivalent Linux :
{
"mcpServers": {
"lasuite-docs": {
"command": "node",
"args": ["/chemin/absolu/vers/lasuite-docs-mcp/dist/server.js"],
"env": {
"DOCS_INSTANCE_URL": "https://notes.liiib.re"
}
}
}
}Redémarre Claude Desktop pour que la modif soit prise en compte.
Dans ~/.config/opencode/opencode.json (user) ou ./opencode.json (project) :
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"lasuite-docs": {
"type": "local",
"command": ["node", "/chemin/absolu/vers/lasuite-docs-mcp/dist/server.js"],
"enabled": true,
"environment": {
"DOCS_INSTANCE_URL": "https://notes.liiib.re"
}
}
}
}Note : OpenCode utilise command comme tableau (pas command + args séparés) et environment (pas env).
Une fois l'installation faite et le client redémarré, tu peux demander à l'agent : « Lis le doc https://notes.liiib.re/docs/<UUID>/ et insère un paragraphe au milieu » — l'instance est extraite automatiquement du lien.
npm test # Tests unitaires (vitest)
npm run test:integration # Test e2e lecture (nécessite DOCS_INTEGRATION_DOC_ID)
npm run test:integration:auth # Test e2e écriture auth (nécessite DOCS_INSTANCE_URL, DOCS_INTEGRATION_SESSIONID, DOCS_INTEGRATION_CSRFTOKEN)
npm run typecheck # TypeScript checkdocs/architecture.md— guide architecture & développement : choix techniques, les 4 obstacles du WebSocket Hocuspocus, le piège Yjs_prelimAttrs, authentification v0.2. Lire en premier avant de modifier le code.docs/superpowers/specs/2026-05-08-docs-mcp-design.md— spec validée du design v0.1docs/superpowers/plans/2026-05-08-docs-mcp-implementation.md— plan d'implémentation v0.1docs/superpowers/plans/2026-05-08-docs-mcp-v0.2-implementation.md— plan d'implémentation v0.2A TESTER ET DOCUMENTER/— scénarios de test manuel par featureCHANGELOG.md— historique bilingue FR/EN
MIT — Coopérative Code Commun