Déployer un serveur MCP pour connecter Claude à votre Notion.
MCP (Model Context Protocol) est l'API standard d'Anthropic pour donner à Claude accès à vos données. Voici comment câbler un serveur MCP sur Notion en moins d'une heure.
Pourquoi MCP plutôt qu'un connecteur custom
Avant MCP, chaque éditeur d'agent IA inventait son propre format de connecteur. Vous écriviez un wrapper pour ChatGPT, un autre pour Claude, un troisième pour Gemini. Lock-in, dette de maintenance, fragilité aux mises à jour de l'API du modèle.
MCP (Model Context Protocol) est un standard ouvert publié par Anthropic en novembre 2024. Un serveur MCP que vous écrivez aujourd'hui pour Claude marchera demain pour tout client qui parle MCP — y compris des éditeurs concurrents qui ont commencé à l'adopter. C'est le HTTP des agents IA : on parie sur un standard ouvert, on évite le piège du connecteur propriétaire.
Architecture d'un serveur MCP
Un serveur MCP expose trois primitives à Claude :
- Resources — des données lisibles (pages Notion, lignes de DB, fichiers Drive)
- Tools — des actions exécutables (créer une page, mettre à jour un bloc, supprimer une ligne)
- Prompts — des templates de prompt réutilisables côté serveur
Le serveur communique avec Claude via deux transports : stdio (process local, idéal pour Claude Desktop / Claude Code) ou sse (HTTP server-sent events, idéal pour serveurs partagés).
┌──────────────┐ MCP protocol ┌──────────────┐
│ Claude │ ◄──────────────────────────► │ MCP Server │
│ (host) │ stdio | sse transport │ (Notion) │
└──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Notion API │
└──────────────┘
Pré-requis
Avant de scaffolder, assurez-vous d'avoir :
- Node 22+ (le SDK MCP TypeScript exige les top-level await récents)
- Une intégration Notion avec une clé API et accès aux pages cibles (Settings → Integrations → New)
- Claude Desktop ou Claude Code en local (pour la phase de test)
Étape 1 : Scaffolding
Anthropic fournit un générateur officiel qui scaffolde la structure standard. Une commande, et vous avez un serveur MCP fonctionnel mais vide, prêt à être étendu.
npx @modelcontextprotocol/create-server notion-mcp
cd notion-mcp
npm install @notionhq/client
Vous obtenez l'arborescence suivante :
notion-mcp/
src/
index.ts ← entry point + setup transport
resources.ts ← pages Notion exposées
tools.ts ← actions Notion
package.json
tsconfig.json
Étape 2 : Définir les resources
Une resource MCP, c'est une donnée que Claude peut lire. Pour Notion, on expose chaque page de la workspace comme une resource avec un URI notion://page/{id}.
// src/resources.ts
import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_TOKEN });
export async function listResources() {
const response = await notion.search({
filter: { property: 'object', value: 'page' },
page_size: 100,
});
return response.results.map((page) => ({
uri: `notion://page/${page.id}`,
name: page.properties?.title?.title?.[0]?.plain_text ?? 'Untitled',
mimeType: 'text/markdown',
}));
}
export async function readResource(uri: string) {
const id = uri.replace('notion://page/', '');
const blocks = await notion.blocks.children.list({ block_id: id });
return {
contents: [{
uri,
mimeType: 'text/markdown',
text: blocksToMarkdown(blocks.results),
}],
};
}
Le serveur retourne le contenu en markdown, pas en JSON brut Notion. Claude comprend le markdown nativement, vous économisez des tokens et la lisibilité est immédiate.
Étape 3 : Définir les tools
Trois tools couvrent 90 % des usages : search pour retrouver une page par mot-clé, create_page pour en créer une nouvelle, update_block pour modifier un bloc existant.
// src/tools.ts
export const searchTool = {
name: 'search_notion',
description: 'Recherche dans toutes les pages Notion accessibles',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Texte à chercher' }
},
required: ['query']
},
handler: async ({ query }: { query: string }) => {
const results = await notion.search({ query, page_size: 10 });
return results.results.map((p) => ({
id: p.id,
title: p.properties?.title?.title?.[0]?.plain_text ?? 'Untitled',
url: p.url,
}));
},
};
export const createPageTool = {
name: 'create_notion_page',
description: 'Crée une nouvelle page Notion',
inputSchema: {
type: 'object',
properties: {
parent_id: { type: 'string' },
title: { type: 'string' },
content: { type: 'string', description: 'Contenu markdown' }
},
required: ['parent_id', 'title', 'content']
},
handler: async ({ parent_id, title, content }) => {
const page = await notion.pages.create({
parent: { page_id: parent_id },
properties: { title: { title: [{ text: { content: title } }] } },
children: markdownToBlocks(content),
});
return { id: page.id, url: page.url };
},
};
Notez la philosophie : chaque tool fait une chose, son input schema est strict, sa réponse est minimale. Claude est très bon pour orchestrer des tools simples — il est mauvais avec des tools « tout-en-un » à 12 paramètres optionnels.
Étape 4 : Test local + déploiement
Une fois le serveur compilé (npm run build), connectez-le à Claude Code en une commande :
claude mcp add notion-mcp \
--command "node /chemin/absolu/notion-mcp/dist/index.js" \
--env NOTION_TOKEN=secret_xxx
Vérifiez que la connexion fonctionne :
claude mcp list
# Doit afficher : notion-mcp [✓ connected]
claude
> List my recent Notion pages
# Claude appelle list_resources et retourne la liste
Pour un déploiement multi-utilisateur, basculez sur le transport SSE et hostez le serveur sur Vercel, Railway ou votre infra interne. Le code reste identique, seul le bootstrap change.
Sécurité et gouvernance
Un serveur MCP qui parle à Notion peut, mal configuré, exfiltrer toute votre base. Quatre règles :
- Scope minimal — l'intégration Notion ne doit avoir accès qu'aux pages réellement nécessaires. Pas d'accès workspace-wide par défaut.
- Audit log — logguer chaque appel de tool (
tool_name,input,output_size,duration_ms). Stocker 90 jours minimum. - MCP gate — pour les actions sensibles (suppression, modification de page partagée), ajouter une étape de confirmation explicite côté serveur, pas seulement côté UI Claude.
- Rotation des secrets — le
NOTION_TOKENdoit tourner tous les 90 jours. Stockez-le dans un gestionnaire de secrets (Vercel env, Doppler, AWS Secrets Manager), jamais en clair dans le repo.
MCP n'a pas inventé de nouveaux risques — il a juste rendu visible ce que les connecteurs custom cachaient. Traitez votre serveur MCP comme un service exposé : authentification, audit, scope, rotation. Le standard ne dispense pas de la rigueur.
Si vous voulez une bibliothèque de connecteurs MCP packagés pour votre stack (Notion, Drive, Slack, HubSpot, votre CRM maison), notre offre Conseil Claude Cowork couvre l'architecture, le code et la conformité sur 6 semaines.