- MCP
- Advanced Protocol
Au-delà des bases
Vous savez créer un MCP, installer des tools et les utiliser dans Claude Code. Cette page va plus loin : le protocole JSON-RPC sous-jacent, les différents transports disponibles, la négociation de capabilities et les techniques de debugging avancé.
Spécification JSON-RPC 2.0
Le MCP repose sur JSON-RPC 2.0, un protocole léger de communication par messages JSON. Chaque échange suit un format strict : requête, réponse, ou notification.
Format d'une requête
{"jsonrpc": "2.0","id": 1,"method": "tools/call","params": {"name": "get-weather","arguments": { "city": "Paris" }}}
jsonrpc: toujours"2.0"id: identifiant unique pour corréler la réponsemethod: la méthode appeléeparams: les paramètres de l'appel
Format d'une réponse
{"jsonrpc": "2.0","id": 1,"result": {"content": [{"type": "text","text": "Météo à Paris : 18°C, Nuageux"}]}}
Les principales méthodes MCP
| Méthode | Direction | Description |
|---|---|---|
initialize | Client vers Server | Initialise la connexion, échange les capabilities |
tools/list | Client vers Server | Liste tous les tools exposés par le serveur |
tools/call | Client vers Server | Appelle un tool avec des arguments |
resources/list | Client vers Server | Liste toutes les resources disponibles |
resources/read | Client vers Server | Lit le contenu d'une resource par URI |
prompts/list | Client vers Server | Liste les prompts disponibles |
prompts/get | Client vers Server | Récupère un prompt avec ses arguments |
notifications/cancelled | Client vers Server | Annule une requête en cours |
Capabilities negotiation
Au démarrage, Claude Code et le MCP Server échangent leurs capabilities. C'est la première interaction après la connexion.
Requête d'initialisation
{"jsonrpc": "2.0","id": 1,"method": "initialize","params": {"protocolVersion": "2024-11-05","capabilities": {"sampling": {}},"clientInfo": {"name": "claude-code","version": "1.0.0"}}}
Réponse du serveur
{"jsonrpc": "2.0","id": 1,"result": {"protocolVersion": "2024-11-05","capabilities": {"tools": {},"resources": { "subscribe": true },"prompts": {}},"serverInfo": {"name": "mcp-weather","version": "1.0.0"}}}
Le client et le serveur s'accordent sur la version du protocole et annoncent ce qu'ils supportent. Un serveur qui ne déclare pas tools dans ses capabilities ne recevra pas d'appels tools/call.
Capabilities disponibles
| Capability | Côté | Description |
|---|---|---|
tools | Server | Le serveur expose des outils |
resources | Server | Le serveur expose des resources |
resources.subscribe | Server | Le client peut s'abonner aux changements de resources |
prompts | Server | Le serveur expose des prompts |
sampling | Client | Le client supporte le sampling (voir plus bas) |
Transport stdio : le mode par défaut
Le transport stdio (standard input/output) est le plus simple et le plus courant. Claude Code lance le processus MCP Server et communique via les flux stdin/stdout du processus.
Fonctionnement
Claude Code MCP Server (processus fils)
| |
|--- stdin: requête JSON-RPC ------->|
| |--- traitement
|<--- stdout: réponse JSON-RPC ------|
| |
|--- stdin: notification ----------->|
Chaque message est une ligne JSON terminée par \n. Les logs du serveur passent par stderr pour ne pas interférer avec le protocole.
Configuration
{"mcpServers": {"my-mcp": {"command": "node","args": ["dist/index.js"],"env": { "API_KEY": "..." }}}}
Avantages et limites
- Simple : pas de réseau, pas de ports, pas de configuration serveur
- Sécurisé : la communication est locale, pas de surface d'attaque réseau
- Limité : un processus par connexion, pas de partage entre plusieurs clients
- Local : le MCP doit tourner sur la même machine que Claude Code
Transport SSE : Server-Sent Events
Le transport SSE permet de connecter Claude Code à un MCP Server distant via HTTP. Le client envoie des requêtes POST et reçoit les réponses via un flux SSE (Server-Sent Events).
Quand l'utiliser
- Le MCP Server tourne sur un serveur distant (cloud, VPS, réseau interne)
- Plusieurs clients doivent se connecter au même MCP Server
- Vous voulez un MCP Server toujours disponible, sans le relancer à chaque session
Configuration
{"mcpServers": {"remote-db": {"url": "https://mcp.example.com/sse","headers": {"Authorization": "Bearer votre-token"}}}}
Flux de communication
Claude Code MCP Server (HTTP)
| |
|--- GET /sse (établir le flux SSE) --->|
|<--- SSE: endpoint URL ----------------|
| |
|--- POST /messages (requête) --------->|
|<--- SSE: réponse JSON-RPC ------------|
Transport Streamable HTTP : le nouveau standard
Le transport Streamable HTTP est le successeur du SSE pour les MCP distants. Il combine la simplicité du HTTP avec le streaming bidirectionnel.
Différences avec SSE
| Critère | SSE | Streamable HTTP |
|---|---|---|
| Direction | Unidirectionnel (serveur vers client) | Bidirectionnel |
| Connexion | Longue durée (flux SSE persistant) | Requêtes individuelles, streamées si besoin |
| Reprise | Reconnexion manuelle | Support natif de la reprise |
| Proxy | Certains proxies coupent les SSE | Compatible avec tous les proxies HTTP |
Configuration
{"mcpServers": {"remote-api": {"url": "https://mcp.example.com/mcp","headers": {"Authorization": "Bearer votre-token"}}}}
MCP Elicitation : demander une saisie en cours de tâche
L'Elicitation est une fonctionnalité introduite en 2026 qui permet à un MCP Server de demander une saisie structurée à l'utilisateur en cours d'exécution, via une boîte de dialogue interactive. Le tool n'a plus besoin de tout anticiper dans ses paramètres d'entrée.
Cas d'usage
- Un MCP de déploiement qui demande une confirmation avant de mettre en production
- Un MCP d'envoi d'email qui demande de choisir parmi plusieurs templates
- Un MCP de migration de base de données qui demande de valider les données transformées avant de les appliquer
Flux de communication
Claude Code MCP Server
| |
|--- tools/call --------->|
| |--- (besoin d'une décision utilisateur)
|<-- elicitation/request--|
| |
| [dialog dans le terminal]
| Utilisateur saisit une réponse
| |
|--- elicitation/response >|
| |--- (continue l'exécution)
|<-- résultat final -------|
Implémenter l'Elicitation dans votre MCP
import { Server } from "@modelcontextprotocol/sdk/server/index.js";import { ElicitRequest } from "@modelcontextprotocol/sdk/types.js";const server = new Server({ name: "deploy-mcp", version: "1.0.0" },{ capabilities: { tools: {}, elicitation: {} } } // Déclarer la capability);server.tool("deploy-to-production","Déploie l'application en production",{version: z.string(),environment: z.enum(["staging", "production"]),},async ({ version, environment }, { elicit }) => {// Demander une confirmation à l'utilisateur avant le déploiement critiqueif (environment === "production") {const confirmation = await elicit({message: `Confirmer le déploiement de la version ${version} en production ?`,requestedSchema: {type: "object",properties: {confirmed: {type: "boolean",title: "Confirmer",description: "Tapez true pour confirmer le déploiement",},rollbackPlan: {type: "string",title: "Plan de rollback",description: "Décrivez votre plan de rollback en cas de problème",},},required: ["confirmed"],},});if (!confirmation.confirmed) {return {content: [{ type: "text", text: "Déploiement annulé par l'utilisateur." }],};}}// Procéder au déploiementconst result = await doDeployment(version, environment);return {content: [{ type: "text", text: `Déployé : ${result.url}` }],};});
Ce que voit l'utilisateur dans Claude Code
Quand un MCP déclenche une Elicitation, Claude Code affiche une boîte de dialogue interactive dans le terminal :
╔══════════════════════════════════════════════════╗
║ MCP deploy-mcp — Confirmation requise ║
╠══════════════════════════════════════════════════╣
║ ║
║ Confirmer le déploiement de la version ║
║ v2.3.1 en production ? ║
║ ║
║ Confirmer [true/false]: _ ║
║ Plan de rollback (optionnel): _ ║
║ ║
╚══════════════════════════════════════════════════╝
Sampling : quand le MCP demande au LLM
Le sampling est une capability spéciale : elle permet au MCP Server de demander à Claude de compléter un prompt. C'est un flux inversé où le serveur devient temporairement "client" du LLM.
Cas d'usage
- Un tool de traduction qui demande à Claude de traduire un texte
- Un tool d'analyse qui demande à Claude de résumer des données
- Un outil de génération qui utilise Claude pour produire du contenu
Flux de communication
Claude Code MCP Server Claude (LLM)
| | |
|-- tools/call --->| |
| |--- sampling/request ---->|
| |<--- réponse LLM ---------|
|<-- résultat -----| |
Performance et latence
Les MCP ajoutent de la latence à chaque interaction. Voici les sources principales et comment les optimiser.
Sources de latence
| Source | Latence typique | Optimisation |
|---|---|---|
| Démarrage du processus (stdio) | 500ms-2s | Garder le processus actif |
Découverte des tools (tools/list) | 10-50ms | Mise en cache côté client |
Appel d'un tool (tools/call) | Variable selon le tool | Timeouts appropriés |
| Appel API externe | 100ms-5s | Cache, retry, fallback |
| Transport réseau (SSE/HTTP) | 20-100ms | Serveur proche géographiquement |
Gestion des timeouts
Claude Code impose un timeout par défaut sur les appels MCP. Si votre tool fait des opérations longues :
// Dans votre tool handler, envoyez des notifications de progressionserver.tool("long-operation","Opération qui prend du temps",{ input: z.string() },async ({ input }, { sendProgress }) => {await sendProgress(0, 100, "Démarrage...");// ... opération longueawait sendProgress(50, 100, "Traitement en cours...");// ... suiteawait sendProgress(100, 100, "Terminé");return {content: [{ type: "text" as const, text: "Résultat de l'opération" }],};});
Sécurité avancée
Sandboxing
Chaque MCP Server tourne dans son propre processus. Mais il a accès au système de fichiers et au réseau de la machine hôte. Pour limiter les risques :
- Exécutez les MCP dans un conteneur Docker avec des volumes restreints
- Utilisez des tokens avec scopes minimaux (lecture seule quand possible)
- Appliquez des règles réseau pour limiter les connexions sortantes
Audit logs
Pour tracer ce que fait un MCP :
// Wrapper de logging pour tous les appels de toolsserver.tool("my-tool", "Description", { param: z.string() }, async ({ param }) => {console.error(`[AUDIT] tool=my-tool param=${param} time=${new Date().toISOString()}`);// ... logique du toolconst result = "...";console.error(`[AUDIT] tool=my-tool result_length=${result.length}`);return { content: [{ type: "text" as const, text: result }] };});
Les logs sur stderr ne perturbent pas le protocole et peuvent être capturés par votre système de monitoring.
Token rotation
Pour les MCP qui utilisent des tokens d'API externe :
- Stockez les tokens dans des variables d'environnement, pas dans le code
- Mettez en place une rotation régulière des tokens (tous les 90 jours minimum)
- Utilisez un gestionnaire de secrets (Vault, AWS Secrets Manager) pour la production
- Révoquez immédiatement tout token potentiellement compromis
Debugging : diagnostiquer les problèmes
Inspection JSON-RPC
L'inspecteur MCP est votre meilleur outil pour débugger :
# Inspecter un serveur stdionpx @modelcontextprotocol/inspector node dist/index.js# Inspecter un serveur SSEnpx @modelcontextprotocol/inspector --url https://mcp.example.com/sse
L'inspecteur affiche chaque message JSON-RPC échangé, ce qui permet de voir exactement ce que le serveur reçoit et retourne.
Logging verbeux côté Claude Code
# Lancer Claude Code avec les logs MCP détaillésclaude --verbose
Le flag --verbose affiche les échanges JSON-RPC avec chaque MCP dans le terminal.
Vérifier la santé d'un MCP
# Lister les MCP configurés et leur statutclaude mcp list
Si un MCP apparaît comme "disconnected" ou "error" :
Vérifier que la commande fonctionne
Exécutez la commande du MCP directement dans votre terminal pour voir les erreurs :
# Exemple pour un MCP Node.jsnode /chemin/vers/mcp/dist/index.js
Si ça plante, le message d'erreur vous indiquera le problème (dépendance manquante, erreur de syntaxe, etc.).
Vérifier les variables d'environnement
Les tokens manquants sont la cause la plus fréquente. Vérifiez que toutes les variables env du .mcp.json sont correctes.
Tester avec l'inspecteur
npx @modelcontextprotocol/inspector node /chemin/vers/mcp/dist/index.js
Si l'inspecteur fonctionne mais pas Claude Code, le problème vient de la configuration Claude (chemin, arguments, permissions).
Erreurs fréquentes en debug
| Symptôme | Cause probable | Diagnostic |
|---|---|---|
| MCP "disconnected" au démarrage | Processus qui plante | Exécuter la commande manuellement |
| Tools non listés | Erreur dans initialize | Vérifier avec l'inspecteur MCP |
| Réponse vide ou timeout | Handler qui ne retourne rien | Ajouter des logs stderr |
parse error JSON-RPC | console.log() dans le code | Remplacer par console.error() |
| Token expiré | Credentials périmées | Régénérer le token et mettre à jour env |
Prochaines étapes
- Créer un MCP Server en TypeScript : tutoriel complet avec le SDK TypeScript
- Créer un MCP Server en Python : tutoriel avec le SDK Python et les décorateurs
- Sécurité des MCP : guide complet de sécurisation
- Comprendre les MCP : revenir aux fondamentaux du protocole