Aller au contenu principal
MCP

Protocole MCP avancé : transports et architecture

Spécification JSON-RPC 2.0, transports stdio/SSE/HTTP, capabilities negotiation, sécurité et debugging des MCP.

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é.

Pour qui ?

Ce contenu s'adresse aux développeurs qui veulent comprendre le protocole en profondeur, déployer des MCP distants (SSE, HTTP), ou diagnostiquer des problèmes complexes. Si vous débutez, commencez par les tutoriels TypeScript ou Python.

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éponse
  • method : la méthode appelée
  • params : 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éthodeDirectionDescription
initializeClient vers ServerInitialise la connexion, échange les capabilities
tools/listClient vers ServerListe tous les tools exposés par le serveur
tools/callClient vers ServerAppelle un tool avec des arguments
resources/listClient vers ServerListe toutes les resources disponibles
resources/readClient vers ServerLit le contenu d'une resource par URI
prompts/listClient vers ServerListe les prompts disponibles
prompts/getClient vers ServerRécupère un prompt avec ses arguments
notifications/cancelledClient vers ServerAnnule une requête en cours

Notifications vs Requêtes

Les notifications n'ont pas de champ id et n'attendent pas de réponse. Elles servent pour les événements unidirectionnels : changement de resource, mise à jour de progression, annulation.

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

CapabilityCôtéDescription
toolsServerLe serveur expose des outils
resourcesServerLe serveur expose des resources
resources.subscribeServerLe client peut s'abonner aux changements de resources
promptsServerLe serveur expose des prompts
samplingClientLe 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"
}
}
}
}

Sécurité obligatoire

Un MCP SSE est accessible sur le réseau. Protégez-le impérativement : authentification par token, HTTPS obligatoire, liste blanche d'IPs si possible. Un MCP exposé sans protection est une faille de sécurité critique.

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èreSSEStreamable HTTP
DirectionUnidirectionnel (serveur vers client)Bidirectionnel
ConnexionLongue durée (flux SSE persistant)Requêtes individuelles, streamées si besoin
RepriseReconnexion manuelleSupport natif de la reprise
ProxyCertains proxies coupent les SSECompatible avec tous les proxies HTTP

Configuration

{
"mcpServers": {
"remote-api": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer votre-token"
}
}
}
}

Adoption progressive

Le transport Streamable HTTP est plus récent que SSE. Vérifiez que le serveur MCP que vous ciblez le supporte. Le SDK officiel (TypeScript et Python) le supporte dans les versions récentes.

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 -----|                         |

Impact sur les coûts

Chaque requête de sampling consomme des tokens supplémentaires. Un MCP qui utilise le sampling de manière intensive peut augmenter vos coûts. Surveillez la consommation avec /cost dans Claude Code.

Performance et latence

Les MCP ajoutent de la latence à chaque interaction. Voici les sources principales et comment les optimiser.

Sources de latence

SourceLatence typiqueOptimisation
Démarrage du processus (stdio)500ms-2sGarder le processus actif
Découverte des tools (tools/list)10-50msMise en cache côté client
Appel d'un tool (tools/call)Variable selon le toolTimeouts appropriés
Appel API externe100ms-5sCache, retry, fallback
Transport réseau (SSE/HTTP)20-100msServeur 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 progression
server.tool(
"long-operation",
"Opération qui prend du temps",
{ input: z.string() },
async ({ input }, { sendProgress }) => {
await sendProgress(0, 100, "Démarrage...");
// ... opération longue
await sendProgress(50, 100, "Traitement en cours...");
// ... suite
await 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 tools
server.tool("my-tool", "Description", { param: z.string() }, async ({ param }) => {
console.error(`[AUDIT] tool=my-tool param=${param} time=${new Date().toISOString()}`);
// ... logique du tool
const 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 stdio
npx @modelcontextprotocol/inspector node dist/index.js
# Inspecter un serveur SSE
npx @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és
claude --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 statut
claude 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.js
node /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ômeCause probableDiagnostic
MCP "disconnected" au démarrageProcessus qui planteExécuter la commande manuellement
Tools non listésErreur dans initializeVérifier avec l'inspecteur MCP
Réponse vide ou timeoutHandler qui ne retourne rienAjouter des logs stderr
parse error JSON-RPCconsole.log() dans le codeRemplacer par console.error()
Token expiréCredentials périméesRégénérer le token et mettre à jour env

Prochaines étapes