Aller au contenu principal
Leçon 9 sur 14 · MCP — Sujets avancés

Le transport STDIO

Leçon 9 sur 14 Mis à jour le 5 novembre 2026 Avancé
Sur cette page
  1. Le transport STDIO
  2. Voir STDIO en action
  3. La séquence de connexion MCP
  4. Quatre scénarios de communication
  5. Une session STDIO réelle, message par message
  6. Pourquoi comprendre STDIO est important
  7. À vous de jouer
  8. Points clés à retenir

Les clients et serveurs MCP communiquent en échangeant des messages JSON, mais comment ces messages sont-ils réellement transmis ? Le canal de communication utilisé s’appelle un transport, et la spécification en définit deux : les entrées/sorties standard (stdio) et Streamable HTTP. À la fin de cette leçon, vous saurez comment fonctionne stdio, quelle poignée de main ouvre une connexion (avant 2026-07-28), et vous aurez vu un échange réel, message par message.

Comparaison des transports MCP : STDIO vs StreamableHTTP

Le transport STDIO

Quand vous développez un serveur ou client MCP pour la première fois, le transport le plus couramment utilisé est le transport STDIO (Standard Input/Output). Cette approche est simple : le client lance le serveur MCP comme un sous-processus et communique via les flux d’entrée/sortie standard.

Voici comment ça fonctionne :

Client → stdin du serveur   (envoi de messages)
Serveur → stdout            (envoi de réponses)

Caractéristiques clés :

  • L’un ou l’autre peut envoyer un message à n’importe quel moment
  • Fonctionne uniquement quand client et serveur tournent sur la même machine
  • Idéal pour le développement et les tests locaux

Voir STDIO en action

Vous pouvez tester un serveur MCP directement depuis votre terminal sans écrire de client séparé. Quand vous lancez un serveur avec uv run server.py, il écoute stdin et écrit les réponses vers stdout.

Cela signifie que vous pouvez coller des messages JSON directement dans votre terminal et voir immédiatement les réponses du serveur.

La séquence de connexion MCP

Toute connexion MCP doit commencer par un handshake spécifique en trois messages :

1. InitializeRequest     ← Le client envoie ceci en premier
2. InitializeResult      ← Le serveur répond avec ses capacités
3. InitializedNotification ← Le client confirme (aucune réponse attendue)

Seulement après ce handshake, vous pouvez envoyer d’autres requêtes comme des appels d’outils ou des listes de prompts.

Quatre scénarios de communication

Avec n’importe quel transport, vous devez gérer quatre patterns de communication différents :

DirectionMécanisme
Client → Serveur (requête)Le client écrit sur stdin
Serveur → Client (réponse)Le serveur écrit sur stdout
Serveur → Client (requête)Le serveur écrit sur stdout
Client → Serveur (réponse)Le client écrit sur stdin

La beauté du transport STDIO est sa simplicité : chaque partie peut initier la communication à tout moment en utilisant ces deux canaux.

Une session STDIO réelle, message par message

Nous avons lancé le serveur de documents du cours (SDK Python 1.30.0) comme sous-processus et lui avons écrit des lignes JSON sur son entrée standard, en lisant sa sortie standard. Voici l’échange exact, une ligne par message :

CLIENT → SERVEUR : {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "corsen-raw-client", "version": "1.0"}}}
SERVEUR → CLIENT : {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-11-25","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"DocumentMCP","version":"1.30.0"}}}
CLIENT → SERVEUR : {"jsonrpc": "2.0", "method": "notifications/initialized"}
CLIENT → SERVEUR : {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "read_doc_contents", "arguments": {"doc_id": "rapport.pdf"}}}
SERVEUR → CLIENT : {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"Ce rapport détaille l'état d'une tour de condensation de 20m."}],"isError":false}}

Tout y est : la poignée de main en trois messages (requête initialize avec son id, résultat qui annonce les capacités du serveur, notification notifications/initialized sans id), puis l’appel d’outil et son résultat, qui porte le contenu et isError. Une ligne, un message : c’est la seule règle de framing du transport stdio, et c’est pourquoi un serveur ne doit jamais écrire autre chose sur sa sortie standard (les logs vont sur stderr).

Pourquoi comprendre STDIO est important

Le transport STDIO représente le cas “idéal” où la communication bidirectionnelle est transparente. Quand nous passerons aux autres transports comme HTTP, nous rencontrerons des limitations où le serveur ne peut pas toujours initier des requêtes vers le client.

Le transport STDIO sert de référence pour comprendre à quoi ressemble une communication MCP complète, avant d’aborder les contraintes des autres méthodes de transport.

Pour le développement et les tests, STDIO est parfait. Pour les déploiements en production où client et serveur doivent tourner sur des machines différentes, vous devrez considérer d’autres options de transport. Notez que la version 2026-07-28 supprime la poignée de main : chaque requête porte alors sa version et ses capacités dans _meta, et un client peut interroger server/discover ; le transport stdio, lui, ne change pas.

À vous de jouer

  1. Reproduisez l’échange ci-dessus : lancez votre serveur avec uv run mcp_server.py et collez les trois premiers messages dans le terminal, un par ligne. Lisez les capacités annoncées.
  2. Envoyez une requête tools/list ({"jsonrpc":"2.0","id":5,"method":"tools/list"}) et comparez le schéma reçu à vos décorateurs.
  3. Ajoutez un print() dans un outil et observez ce que fait le client : vous venez de casser le framing. Remplacez-le par une écriture sur stderr.

Sources officielles : The STDIO transport (Claude Academy) · Transports (spécification 2026-07-28) · Aperçu de l’architecture

Points clés à retenir

  • Stdio : le client lance le serveur en sous-processus et lui écrit sur stdin ; le serveur répond sur stdout ; une ligne JSON par message, rien d’autre sur stdout.
  • Avant 2026-07-28, toute connexion commence par initialize, le résultat avec les capacités, puis notifications/initialized ; depuis, _meta et server/discover remplacent la poignée de main.
  • Les deux parties peuvent initier un message à tout moment : stdio est la référence de la communication bidirectionnelle.
  • Même machine seulement ; pour le distant, Streamable HTTP.