Anatomie du protocole MCP
MCP n'est pas une API propriétaire : c'est une spécification ouverte construite sur JSON-RPC 2.0. Le client envoie des requêtes JSON structurées, le serveur répond avec des objets JSON conformes à la spec. Chaque échange suit le schéma { "jsonrpc": "2.0", "id": 1, "method": "...", "params": { ... } }.
JSON-RPC 2.0 et les 3 transports (stdio, SSE, HTTP)
stdio : le transport natif pour les serveurs locaux. Le client (Claude Desktop, Claude Code) lance le processus serveur via spawn() et communique sur stdin/stdout. Zéro configuration réseau, latence minimale, isolation par processus. C'est le mode par défaut pour tous les serveurs MCP installés localement sur la machine du développeur.
SSE (Server-Sent Events) : canal push unidirectionnel du serveur vers le client sur une connexion HTTP longue durée. Le client envoie ses requêtes en HTTP POST classique, le serveur répond via le flux SSE. Adapté aux serveurs distants qui doivent streamer des résultats progressifs (ex : exécution longue, streaming de tokens). Moins adapté derrière certains load balancers qui terminent les connexions longues.
HTTP streamable : introduit dans la version de spec 2025-03-26, ce transport remplace progressivement SSE pour les déploiements production. Il supporte un mode bidirectionnel complet sur HTTP standard, avec support des réponses streamées via Transfer-Encoding chunked. Plus compatible avec les reverse proxies modernes (nginx, Cloudflare, AWS ALB).
Le handshake initialize / capabilities
Toute session MCP commence par un handshake en deux phases. Le client envoie initialize avec sa version de protocole et ses capabilities. Le serveur répond avec initialized + la liste de ses capabilities réelles (quels tools il expose, si il supporte les resources et les prompts, les options de logging). Ce mécanisme permet la négociation de version et la découverte dynamique : un client peut interroger un serveur inconnu et adapter son comportement selon ce que le serveur déclare supporter.
// Requête initialize du client
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": { "roots": { "listChanged": true } },
"clientInfo": { "name": "claude-code", "version": "1.0.0" }
}
}
// Réponse du serveur
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": false },
"resources": { "subscribe": false, "listChanged": false }
},
"serverInfo": { "name": "azenflow-gmail-mcp", "version": "0.1.0" }
}
}
Les 3 primitives : tools, resources, prompts
La confusion entre les trois primitives est la première source d'erreurs d'architecture dans les implémentations MCP.
- tools : actions avec effets de bord, équivalents aux function calls. Le modèle demande l'exécution d'un tool, le client exécute et retourne le résultat. Exemples : envoyer un email, créer un ticket Jira, déclencher un webhook n8n. Chaque tool expose un schéma JSON Schema strict pour ses paramètres d'entrée.
- resources : données en lecture seule identifiées par une URI. Le modèle lit une resource pour enrichir son contexte. Exemples : contenu d'un fichier, résultat d'une requête SQL, page Notion. Une resource peut être statique (contenu fixe) ou dynamique (contenu calculé à la demande).
- prompts : gabarits de messages paramétrés que l'utilisateur peut invoquer. Ils permettent de préconfigurer des interactions complexes réutilisables (ex : "analyse ce code selon nos standards", "rédige un email de relance client"). Les prompts sont listés dans Claude Desktop via le menu slash.
La gestion des erreurs et des notifications
MCP suit la convention JSON-RPC pour les erreurs : code négatif dans l'objet error. Les codes standardisés par MCP vont de -32700 (parse error) à -32603 (internal error), plus une plage -32000 à -32099 réservée aux erreurs applicatives du serveur. En dehors des réponses aux requêtes, le serveur peut envoyer des notifications unidirectionnelles (sans id) pour signaler des changements d'état, par exemple notifications/tools/list_changed quand la liste des tools évolue dynamiquement.
Créer un serveur MCP minimal en TypeScript
Setup avec @modelcontextprotocol/sdk
Le SDK officiel prend en charge le handshake, la sérialisation JSON-RPC et les trois transports. Installation :
npm install @modelcontextprotocol/sdk zod
zod n'est pas une dépendance obligatoire du SDK, mais il simplifie la validation des paramètres d'entrée des tools. Le SDK accepte n'importe quel schéma JSON Schema valide.
Exposer un tool : exemple send_email
Voici un serveur MCP stdio complet qui expose un tool send_email via Gmail :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "azenflow-gmail-mcp",
version: "0.1.0",
});
// Déclaration du tool send_email
server.tool(
"send_email",
"Envoie un email via Gmail API. Retourne l'ID du message créé.",
{
to: z.string().email().describe("Destinataire principal"),
subject: z.string().min(1).max(200).describe("Objet de l'email"),
body: z.string().min(1).max(10000).describe("Corps en texte brut"),
cc: z.string().email().optional().describe("Copie carbone (optionnel)"),
},
async ({ to, subject, body, cc }) => {
// Validation métier : jamais de credentials en dur ici
const gmailToken = process.env.GMAIL_ACCESS_TOKEN;
if (!gmailToken) {
return {
content: [{ type: "text", text: "Erreur : GMAIL_ACCESS_TOKEN absent" }],
isError: true,
};
}
const response = await fetch(
"https://gmail.googleapis.com/gmail/v1/users/me/messages/send",
{
method: "POST",
headers: {
Authorization: `Bearer ${gmailToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
raw: Buffer.from(
`To: ${to}\r\nSubject: ${subject}\r\n${cc ? `Cc: ${cc}\r\n` : ""}\r\n${body}`
).toString("base64url"),
}),
}
);
if (!response.ok) {
const err = await response.text();
return { content: [{ type: "text", text: `Erreur Gmail : ${err}` }], isError: true };
}
const data = await response.json();
return {
content: [{ type: "text", text: `Email envoyé. ID : ${data.id}` }],
};
}
);
// Démarrage en mode stdio
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Serveur MCP azenflow-gmail-mcp démarré sur stdio");
Exposer une resource : exemple lecture Notion
Les resources suivent un pattern légèrement différent : elles sont enregistrées avec une URI template et le handler reçoit l'URI résolue. Exemple pour lire une page Notion :
server.resource(
"notion-page",
new ResourceTemplate("notion://pages/{pageId}", { list: undefined }),
async (uri, { pageId }) => {
const res = await fetch(`https://api.notion.com/v1/pages/${pageId}`, {
headers: { Authorization: `Bearer ${process.env.NOTION_TOKEN}`,
"Notion-Version": "2022-06-28" },
});
const page = await res.json();
const title = page.properties?.title?.title?.[0]?.plain_text ?? "(sans titre)";
return {
contents: [{
uri: uri.href,
mimeType: "text/plain",
text: `Titre : ${title}\nID : ${pageId}`,
}],
};
}
);
Tester avec MCP Inspector
MCP Inspector (npx @modelcontextprotocol/inspector) est l'outil de débogage officiel. Il lance votre serveur en stdio, affiche le handshake, liste les tools et resources déclarés, et permet d'invoquer chaque tool manuellement avec un formulaire auto-généré depuis le schéma JSON Schema. Indispensable avant de connecter le serveur à Claude Desktop.
Intégrer MCP dans un workflow n8n
Limites actuelles : pas de noeud officiel n8n MCP en 2026
En mai 2026, le catalogue officiel n8n ne contient pas de noeud natif MCP client. La raison est architecturale : n8n orchestre des flux événementiels, alors que MCP est un protocole de session stateful (handshake, puis échanges multiples). L'intégration directe nécessiterait de maintenir une session MCP entre les noeuds d'un même workflow, ce que le modèle d'exécution n8n ne supporte pas nativement. Pour l'intégration n8n MCP en production, deux workarounds ont émergé.
Workaround 1 : appel HTTP direct vers un serveur MCP
Si votre serveur MCP expose le transport HTTP streamable, le noeud natif HTTP Request de n8n peut envoyer directement un appel tools/call en JSON-RPC. Le payload est standard :
{
"jsonrpc": "2.0",
"id": "n8n-exec-{{ $runIndex }}",
"method": "tools/call",
"params": {
"name": "send_email",
"arguments": {
"to": "{{ $json.email }}",
"subject": "Votre devis AzenFlow",
"body": "{{ $json.emailBody }}"
}
}
}
Configurez le noeud HTTP Request avec la méthode POST, le header Content-Type: application/json et le header d'authentification de votre serveur. Cette approche fonctionne pour les appels ponctuels sans session stateful.
Workaround 2 : Claude Code en mode headless
Pour les scénarios complexes qui nécessitent une vraie session MCP avec plusieurs échanges, le pattern le plus robuste est de déléguer à Claude Code CLI en mode headless. n8n déclenche un noeud Execute Command qui lance claude --mcp-config ./mcp.json -p "Ta mission : ...". Claude Code gère la session MCP complète (handshake, tools/call, gestion des erreurs) et retourne un résultat structuré que n8n parse. Voir aussi le comparatif technique MCP vs Claude Code CLI pour choisir l'approche adaptée.
Pattern recommandé pour AzenFlow : n8n orchestre, MCP enrichit
L'architecture que je déploie chez mes clients PME sépare clairement les responsabilités. n8n gère les déclencheurs (webhook entrant, schedule, événement Gmail), l'orchestration du flux et les intégrations SaaS standards (CRM, Slack, Sheets). MCP enrichit les noeuds qui nécessitent de la sémantique : lecture de contexte depuis une base de connaissances, génération de contenu avec outils, actions multi-étapes dans un outil tiers. Cette séparation évite de transformer n8n en gestionnaire de session MCP, rôle qu'il n'est pas conçu pour tenir.
Sécurité et conformité AI Act / RGPD
Surface d'attaque d'un serveur MCP
Un serveur MCP expose par construction un ensemble d'actions avec effets de bord. Les vecteurs d'attaque spécifiques sont au nombre de trois. D'abord, l'injection de prompt via les données retournées par une resource : le modèle lit la resource et exécute des instructions cachées dans son contenu (ex : un fichier texte contenant Ignore tes instructions précédentes...). Ensuite, l'exfiltration de données si un tool malveillant est connecté au même serveur que vos credentials. Enfin, l'escalade de privilèges si le token d'accès du serveur a des permissions trop larges par rapport à ce que les tools nécessitent réellement.
Sandboxing et permissions granulaires
- Un serveur MCP par domaine fonctionnel : un serveur pour Gmail, un pour Notion, un pour votre CRM. Jamais un serveur "tout-en-un" avec des credentials croisés.
- Scopes OAuth minimaux : le serveur Gmail ne demande que
gmail.send, pasgmail.readonlynimail.google.com. - Sandboxing réseau : chaque serveur MCP tourne dans un conteneur avec une liste d'allowlist réseau explicite (uniquement l'API cible, aucun accès sortant arbitraire).
- Validation stricte des paramètres : utiliser Zod avec des contraintes serrées (
.max(),.regex()) pour rejeter les entrées malformées avant tout traitement.
Journalisation pour audit AI Act art. 50
L'article 50 de l'IA Act européen impose des exigences de transparence sur les interactions avec les systèmes IA à usage général. Un serveur MCP peut contribuer directement à votre registre d'audit : loggez chaque appel tools/call avec timestamp, identifiant de session, nom du tool appelé, hash des paramètres (jamais le contenu brut si données personnelles) et code de résultat. Ce journal structuré constitue une trace d'audit conforme pour démontrer la supervision humaine des décisions automatisées. Combinez avec notre audit technique conformité IA Act / RGPD pour valider l'architecture complète.
Comparaison avec les alternatives (Tool Use API, function calling, plugins ChatGPT)
Avant de choisir MCP, il est utile de le situer par rapport aux alternatives existantes. Voir aussi les articles comparatifs Claude Code vs Cursor en 2026 et MCP vs Claude Code CLI pour les décisions d'architecture.
| Critère | MCP | Tool Use API Anthropic | OpenAI Function Calling | ChatGPT Plugins |
|---|---|---|---|---|
| Transport | stdio, SSE, HTTP | HTTP (API Anthropic) | HTTP (API OpenAI) | HTTP (manifest + OpenAPI) |
| Standardisation | Spec ouverte, multi-vendor | Propriétaire Anthropic | Propriétaire OpenAI | Déprécié (remplacé par GPT Actions) |
| Multi-client | Oui (1 serveur, N clients) | Non (lié à l'API Anthropic) | Non (lié à l'API OpenAI) | Non (uniquement ChatGPT) |
| Sécurité hosting | Votre infrastructure, contrôle total | Côté client, credentials exposés possible | Côté client, credentials exposés possible | OpenAI héberge, plugin accessible |
| Resources / contexte | Oui (primitive native) | Non (à gérer manuellement) | Non (à gérer manuellement) | Non (retrieval séparé) |
| Courbe d'apprentissage | Moyenne (JSON-RPC + SDK) | Faible (JSON dans l'API) | Faible (JSON dans l'API) | Faible mais dépréciée |
| Maturité (mai 2026) | Croissante, adoption large | Stable, production | Stable, production | Déprécié, migration requise |
La différence fondamentale de MCP est l'indépendance du fournisseur. Une fois votre serveur MCP déployé, il est interrogeable par Claude Desktop, Claude Code, un client OpenAI compatible MCP et tout IDE qui implémente le protocole. Vous construisez une fois, vous déployez partout. La formation Claude Code que nous animons couvre l'intégration complète MCP + Claude Code + n8n.
Roadmap MCP 2026 : ce qui s'en vient
Authentification standardisée
La feuille de route officielle MCP prévoit une couche d'authentification standardisée OAuth 2.1 pour les transports réseau (SSE et HTTP). Aujourd'hui, chaque implémentation gère l'authentification de manière ad hoc (bearer token, API key en header, mTLS). La standardisation permettra aux clients MCP de gérer l'authentification automatiquement via un flux OAuth unifié, sans configuration manuelle par serveur.
Multi-tenant
Les premiers serveurs MCP sont mono-utilisateur par construction (stdio = un processus par utilisateur). La roadmap introduit des primitives pour les serveurs multi-tenant : isolation des sessions par identifiant d'utilisateur, rate limiting par tenant, audit log segmenté. Ces fonctionnalités sont critiques pour les déploiements enterprise où plusieurs utilisateurs partagent la même infrastructure de serveurs MCP.
Adoption par OpenAI et Google
OpenAI a annoncé en mars 2026 l'intégration du support client MCP dans ses SDK Python et TypeScript. Google Gemini progresse sur la compatibilité MCP côté client via son SDK Vertex AI. Cette adoption multi-vendor valide le pari architectural : MCP n'est plus uniquement l'écosystème Anthropic, c'est en passe de devenir la couche d'interopérabilité standard entre les LLM et leurs outils. Anticiper cette adoption en déployant vos serveurs MCP dès aujourd'hui vous positionne en avance sur l'intégration multi-modèle de demain.
RÉDIGÉ PAR
Matthias Marin
Fondateur AzenFlow, cabinet de stratégie IA. 40+ automatisations en production active chez des TPE et PME françaises (depuis février 2025). Intervenant MSc Finance & Data x Mines Paris PSL, module Workflow Automation à Albert School. Formateur Claude Code dans 5 organismes Qualiopi (Matchers, Alphorm, Senza, École Cube, PLB). Profil LinkedIn.
Article publié le