
Les messages JSON-RPC de MCP doivent circuler par un canal. Ce canal s'appelle le transport, et MCP en propose trois : stdio pour le local, Streamable HTTP pour le réseau, et SSE, en voie de retrait. Le choix n'est pas anodin : il détermine si votre serveur tourne dans l'hôte ou à côté, s'il est partageable, et comment vous le déployez. Ce guide explique chaque transport et montre, lab à l'appui, qu'un même serveur se sert indifféremment sur stdio ou sur HTTP. Public visé : développeur ayant déjà écrit un serveur MCP.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre ce qu'est un transport MCP et pourquoi il y en a plusieurs.
- Distinguer stdio, Streamable HTTP et SSE.
- Servir un même serveur sur deux transports sans changer sa logique.
- Choisir le transport adapté à votre cas d'usage.
Prérequis
Section intitulée « Prérequis »Ce guide prolonge Créer son premier serveur MCP et l'anatomie du protocole. Vous avez besoin de Python 3.10+ et du SDK mcp installé.
Pourquoi plusieurs transports
Section intitulée « Pourquoi plusieurs transports »Le protocole MCP — les messages JSON-RPC, le cycle de vie — reste le même quel que soit le canal. Le transport ne change que la plomberie : par où les octets passent.
Cette séparation est volontaire. Un serveur MCP qui lit vos fichiers locaux n'a pas les mêmes besoins qu'un serveur partagé par toute une équipe. Le premier veut être simple et local ; le second veut être joignable sur le réseau. MCP laisse ce choix ouvert, sans toucher au reste.
stdio : le transport local
Section intitulée « stdio : le transport local »Le transport stdio (entrée/sortie standard) est le plus simple. Le serveur est un sous-processus de l'hôte : l'hôte le lance, et la communication passe par les flux stdin et stdout du processus.
Conséquences directes : aucun réseau, aucun port, aucune authentification réseau à gérer. Le serveur vit et meurt avec l'hôte qui l'a démarré. C'est le mode idéal pour un serveur qui accède à des ressources de la machine locale — fichiers, dépôt Git, base SQLite — et qui ne sert qu'un seul hôte.
C'est aussi le transport par défaut de FastMCP : mcp.run() sans argument démarre en stdio.
Streamable HTTP : le transport réseau
Section intitulée « Streamable HTTP : le transport réseau »Le transport Streamable HTTP fait du serveur un service HTTP indépendant. Le serveur tourne séparément, écoute sur une URL, et le client s'y connecte comme à n'importe quelle API web.
Tout change par rapport à stdio. Le serveur a une existence propre : on le lance une fois, il sert plusieurs clients, il peut tourner sur une autre machine. En contrepartie, il faut gérer ce qu'implique tout service réseau — un port, du TLS, une authentification, un éventuel reverse proxy.
C'est le standard recommandé pour tout serveur MCP destiné à être partagé ou déployé.
SSE : le transport en voie de retrait
Section intitulée « SSE : le transport en voie de retrait »Le transport SSE (Server-Sent Events) est l'ancien transport réseau de MCP. Il fonctionne, mais il est progressivement remplacé par Streamable HTTP, qui couvre les mêmes besoins de façon plus simple et plus robuste.
La règle est claire : pour un nouveau projet, choisissez Streamable HTTP. Vous ne croiserez SSE que sur des serveurs anciens pas encore migrés. Le connaître suffit ; l'adopter, non.
Le même serveur, deux transports
Section intitulée « Le même serveur, deux transports »La promesse de cette séparation, c'est qu'un serveur ne change pas quand on change de transport. Démontrons-le. Voici un serveur hello dont le transport est choisi en argument :
import sysfrom mcp.server.fastmcp import FastMCP
mcp = FastMCP("hello-server", host="127.0.0.1", port=8765)
@mcp.tool()def hello(name: str) -> str: """Renvoie un salut personnalisé.""" return f"Bonjour {name}, ici un serveur MCP."
if __name__ == "__main__": transport = sys.argv[1] if len(sys.argv) > 1 else "stdio" mcp.run(transport=transport)Le tool hello est identique dans les deux cas. Seul l'argument de mcp.run() diffère. Côté client, en revanche, la connexion change.
En stdio, le client lance lui-même le serveur et communique par ses flux standard.
from mcp import StdioServerParametersfrom mcp.client.stdio import stdio_client
params = StdioServerParameters(command=sys.executable, args=["server.py", "stdio"])async with stdio_client(params) as (read, write): ...En HTTP, le serveur doit déjà tourner (python server.py streamable-http). Le client se connecte à son URL.
from mcp.client.streamable_http import streamablehttp_client
async with streamablehttp_client("http://127.0.0.1:8765/mcp") as (read, write, _): ...Lancé sur les deux canaux, le serveur répond exactement pareil :
stdio -> Bonjour stdio, ici un serveur MCP.http -> Bonjour HTTP, ici un serveur MCP.La logique métier est écrite une fois. Le transport est un paramètre de déploiement, pas une réécriture.
Quand choisir lequel
Section intitulée « Quand choisir lequel »Le bon transport découle de qui doit joindre le serveur et où il tourne.
| Critère | stdio | Streamable HTTP |
|---|---|---|
| Cycle de vie du serveur | Lancé par l'hôte | Indépendant |
| Réseau | Aucun | Port, TLS, auth |
| Nombre de clients | Un seul | Plusieurs |
| Serveur distant | Non | Oui |
| Cas typique | Outils locaux (fichiers, Git) | Serveur partagé, déployé |
| Mise en place | Immédiate | Demande du durcissement réseau |
La règle pratique : stdio par défaut tant que le serveur est local et personnel ; Streamable HTTP dès qu'il doit être partagé ou déployé. SSE n'entre plus dans la décision pour un nouveau projet.
À retenir
Section intitulée « À retenir »- Le transport est le canal des messages MCP ; le protocole reste identique quel que soit le canal.
- stdio : serveur lancé par l'hôte, local, mono-client, sans réseau — le défaut.
- Streamable HTTP : serveur indépendant, joignable sur le réseau, multi-clients — le standard pour partager ou déployer.
- SSE : ancien transport réseau, en voie de retrait — à connaître, pas à adopter.
- Un même serveur se sert sur plusieurs transports sans changer sa logique : le transport est un paramètre de déploiement.
- Un transport HTTP impose de sécuriser : authentification, TLS, accès contrôlé.