Un serveur MCP est un petit programme qui expose vos outils et vos données internes aux assistants IA via le Model Context Protocol, un standard ouvert créé par Anthropic fin 2024. En TypeScript, le SDK officiel permet d'enregistrer des outils typés et de les servir en stdio ou en HTTP en moins de deux cents lignes. Construisez-en un quand plusieurs assistants ou équipes ont besoin des mêmes capacités ; une intégration en function calling suffit souvent pour un besoin ponctuel.
Qu'est-ce que le Model Context Protocol ?
MCP est un protocole ouvert qui standardise la façon dont les assistants IA appellent des outils externes et lisent des données externes. Anthropic l'a publié en novembre 2024, puis il s'est diffusé bien au-delà courant 2025 : la plupart des grands écosystèmes d'assistants savent désormais agir comme clients MCP. Un serveur écrit une fois les sert tous.
L'analogie consacrée est celle du port USB : avant, chaque intégration assistant-système était du code de liaison sur mesure ; avec MCP, le côté assistant implémente un client, vous implémentez un serveur, et le format d'échange (JSON-RPC 2.0) est fixé par la spécification. Conséquence : l'effort d'intégration passe de N assistants fois M systèmes à N plus M, et le serveur devient l'endroit unique où se décide ce qui est exposé.
Outils, ressources, prompts : quelles sont les trois primitives ?
MCP définit trois primitives. Les outils : des fonctions que le modèle peut appeler, décrites par nom, description et schéma d'entrée typé. Les ressources : des données en lecture seule, adressées par URI, chargées en contexte par le client. Les prompts : des gabarits réutilisables invoqués par l'utilisateur. La plupart des serveurs métier démarrent avec les seuls outils.
La distinction compte : le contrôle diffère. Le modèle choisit quand appeler un outil ; l'application ou l'utilisateur choisit les ressources à attacher et les prompts à lancer. Un outil create_support_ticket écrit donc dans vos systèmes à l'initiative du modèle, quand une ressource orders://recent ne fait qu'alimenter le contexte. Effets de bord dans les outils, données de référence dans les ressources, et des descriptions soignées comme une documentation d'API publique : c'est la seule chose que le modèle lit avant de décider.
Vous vous demandez quelles capacités internes méritent d'être exposées à un assistant ? Décrivez votre système : diagnostic d'une page sous 48 h.
Recevoir mon diagnostic →Comment s'articulent hôte, client et serveur ?
Trois rôles. L'hôte est l'application IA : un assistant de bureau, un IDE, un runtime d'agents. Dans l'hôte, un client MCP maintient une connexion avec état par serveur. Votre serveur MCP expose outils et ressources et dialogue avec les vrais systèmes derrière. Le modèle ne touche jamais vos API directement : chaque appel passe par cette chaîne.
Deux transports couvrent presque tous les cas. En local, stdio : l'hôte lance votre serveur comme sous-processus et échange du JSON-RPC sur stdin et stdout, sans surface réseau. À distance, le HTTP streamable : un endpoint unique derrière votre reverse proxy habituel, réponses en flux, authentification transportée (la spécification recommande OAuth 2.1 pour les serveurs distants). Commencez en stdio ; passez en HTTP quand plus d'une machine a besoin du serveur.
Comment construire le serveur en TypeScript ?
Installez @modelcontextprotocol/sdk et zod, puis enregistrez chaque capacité sur une instance McpServer. Le SDK prend en charge le cycle de vie du protocole, la négociation des capacités et le routage des messages ; vous n'écrivez que les handlers. Voici un serveur exposant la consultation d'une commande, avec l'amorçage stdio en dernière ligne :
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: "orders", version: "1.0.0" });
server.registerTool(
"get_order_status",
{
title: "Get order status",
description: "Look up one order by reference (format ORD-123456).",
inputSchema: {
orderRef: z.string().regex(/^ORD-\d{6}$/, "Expected format ORD-123456"),
},
},
async ({ orderRef }) => {
// Identifiants en lecture seule : cet outil ne peut jamais écrire
const order = await ordersDb.findByRef(orderRef);
if (!order) {
return { content: [{ type: "text", text: `No order ${orderRef}` }], isError: true };
}
return { content: [{ type: "text", text: JSON.stringify(order) }] };
},
);
// Amorçage stdio : l'hôte lance ce fichier et parle JSON-RPC sur stdin/stdout
await server.connect(new StdioServerTransport());
Un second outil, create_support_ticket, suit la même forme : un schéma zod (sujet, référence, sévérité en enum), un handler qui appelle votre API de ticketing avec un compte de service dédié, une réponse texte portant la référence du ticket. Ressources, prompts et transport HTTP sont documentés dans le dépôt du SDK TypeScript.
Pourquoi validation et moindre privilège comptent-ils autant ?
Parce que le modèle décide quand vous appeler, et avec quels arguments. Un appel d'outil MCP est une entrée générée par une machine, influencée par tout le contexte du modèle : messages utilisateur, documents récupérés, sorties d'autres outils. Traitez chaque appel comme non fiable, comme un endpoint public, même quand l'hôte tourne sur le poste d'un développeur.
Concrètement : des schémas zod stricts (motifs, enums, longueurs bornées) plutôt que des chaînes permissives ; des identifiants limités à ce que font les outils, lecture seule pour les consultations, un compte ticketing qui crée mais ne supprime pas ; et chaque appel journalisé avec arguments, résultat et durée. L'injection de prompt rend cela tangible : un document malveillant résumé par l'assistant peut tenter de pousser le modèle à appeler vos outils, le serveur doit donc borner ce qui est simplement possible. La même règle traverse notre article sur l'intégration d'IA dans un backend existant : le contrôle vit dans votre code, jamais dans le prompt.
Comment tester avec le MCP Inspector ?
Le MCP Inspector est l'interface officielle de développement : il se connecte à votre serveur, liste outils, ressources et prompts, et permet de déclencher des appels avec des arguments arbitraires avant tout assistant. Une commande npx suffit pour obtenir une interface navigateur :
npx @modelcontextprotocol/inspector node dist/server.js
Servez-vous-en pour trois vérifications. Les schémas : une référence invalide doit être rejetée avec un message lisible. Les descriptions : un modèle sans autre contexte doit comprendre quand chaque outil s'applique. Les chemins d'échec : à quoi ressemblent un timeout ou un résultat vide. Connectez ensuite un hôte réel et observez quand le modèle choisit réellement vos outils ; Anthropic documente ses connecteurs MCP sur docs.anthropic.com.
Quand ne pas construire de serveur MCP ?
Pas pour chaque intégration. Quand une application parle à un fournisseur de modèle pour un seul flux, le function calling sur votre API REST est plus simple : moins de pièces mobiles, pas de processus ni de protocole supplémentaires à opérer. MCP devient rentable quand les mêmes capacités doivent servir plusieurs assistants, équipes ou hôtes que vous ne contrôlez pas.
| Critère | Function calling classique | Serveur MCP |
|---|---|---|
| Réutilisation entre assistants | Redéclaré par application et fournisseur | Un serveur, tous les clients MCP |
| Découverte | Liste d'outils codée en dur | Listée par le client à la connexion |
| Transport | Votre API plus du code de liaison | stdio ou HTTP streamable standardisés |
| Authentification | Ce que votre application fait déjà | Spécifiée : OAuth 2.1 pour les serveurs distants |
| Quand ça gagne | Une application, un fournisseur, un flux | Capacités partagées, plusieurs hôtes ou équipes |
Notre règle simple : première intégration, function calling ; deuxième consommateur de la même capacité, promotion en serveur MCP. Ordonnancer cette migration et choisir les capacités à exposer fait partie de notre travail d'automatisation IA.
Checklist avant mise en service
- Entrées validées par des schémas zod stricts (enums, motifs, longueurs bornées)
- Identifiants limités par serveur : lecture seule quand la lecture suffit
- Descriptions d'outils relues comme de la documentation destinée au modèle
- Chaque appel journalisé avec arguments, résultat et durée
- Schémas et chemins d'échec exercés dans le MCP Inspector
- stdio en local ; HTTP streamable authentifié pour tout usage partagé