Le paysage de l'intelligence artificielle évolue rapidement des interfaces de chat isolées vers des systèmes intégrés et conscients du contexte. Au cœur de cette évolution se trouve le Model Context Protocol (MCP), une norme ouverte conçue pour standardiser la manière dont les applications fournissent du contexte aux grands modèles de langage (LLM). Bien que la consommation de clients MCP devienne de plus en plus courante, le véritable pouvoir de l'écosystème réside dans la construction de serveurs MCP robustes et performants. Ce guide propose une plongée technique dans la construction de ces serveurs, allant au-delà des tutoriels de base pour aborder les considérations architecturales, la définition des outils et la gestion des ressources.
Comprendre l'architecture du serveur
Avant d'écrire une seule ligne de code, il est crucial de comprendre le rôle du serveur MCP. Contrairement aux API REST ou GraphQL traditionnelles, un serveur MCP ne se contente pas de servir des données ; il sert des capacités. Il expose deux primitives principales au client : les Outils (Tools) et les Ressources.
Les outils sont des fonctions que le LLM peut exécuter, comme l'exécution d'une requête de base de données ou l'envoi d'un e-mail. Les ressources sont des sources de données statiques ou dynamiques, comme la lecture d'un fichier de configuration ou la récupération d'un cours boursier en direct. Un serveur MCP bien architecturé sépare strictement ces responsabilités tout en maintenant une couche de transport unifiée, généralement JSON-RPC sur stdio ou HTTP.
Définir les outils avec précision
La précision de l'utilisation des outils par un LLM dépend fortement de la manière dont vous définissez vos schémas. En TypeScript, en utilisant le @modelcontextprotocol/sdk officiel, vous définissez les outils à l'aide du validateur de schéma Zod pour assurer la sécurité des types et des descriptions claires.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const server = new McpServer({
name: "my-awesome-server",
version: "1.0.0"
});
// Définir un outil pour rechercher dans un index de documentation
server.tool(
"search_docs",
"Rechercher dans la documentation interne pour les requêtes techniques",
{
query: z.string().describe("La chaîne de requête de recherche"),
limit: z.number().default(5).describe("Nombre maximal de résultats à retourner")
},
async ({ query, limit }) => {
// Logique d'implémentation ici
const results = await myDocSearchEngine.search(query, limit);
return {
content: results.map(r => ({
type: "text",
text: JSON.stringify(r)
}))
};
}
);
Notez l'accent mis sur les champs description et description des paramètres. Ils ne servent pas uniquement à la documentation ; ce sont les signaux principaux que le LLM utilise pour déterminer quand et comment invoquer votre outil. L'ambiguïté ici conduit à des arguments hallucinés ou au refus d'utiliser l'outil.
Gérer les ressources et les invites
Au-delà des outils, les serveurs MCP peuvent exposer des ressources via des URI. Cela permet aux clients de demander des données dynamiquement. Par exemple, vous pourriez exposer une ressource à docs://config/latest qui retourne la configuration actuelle de l'application.
De plus, le MCP prend en charge les Invites (Prompts), qui sont des séquences d'instructions ou des modèles prédéfinis que les utilisateurs peuvent invoquer. Cela est distinct des outils car les invites génèrent du texte pour que l'utilisateur ou le LLM le lise, plutôt que d'exécuter du code. La mise en œuvre des invites nécessite d'enregistrer un gestionnaire d'invites qui retourne une liste de messages structurée.
server.prompt(
"summarize_code",
"Générer un résumé concis de l'extrait de code fourni",
{ filePath: z.string() },
async ({ filePath }) => {
const content = await fs.readFile(filePath, 'utf-8');
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Veuillez résumer ce code :\n\n${content}`
}
}
]
};
}
);
Bonnes pratiques pour la production
- Gestion des erreurs : Enveloppez toujours votre logique d'outil dans des blocs try-catch. Retournez des messages d'erreur structurés que le LLM peut comprendre, plutôt que des traces de pile brutes.
- Streaming : Pour les opérations de longue durée, implémentez des réponses en streaming. Cela améliore l'expérience utilisateur en fournissant des retours en temps réel.
- Sécurité : N'exposez jamais d'adresses réseau internes ou d'identifiants sensibles en tant que ressources. Validez rigoureusement toutes les entrées à l'aide de Zod pour prévenir les attaques par injection.
Conclusion
Construire des serveurs MCP ne consiste pas seulement à connecter une API à un LLM ; il s'agit de structurer les données et la logique de manière à maximiser l'utilité du modèle. En se concentrant sur des définitions d'outils claires, une gestion robuste des erreurs et une gestion sécurisée des ressources, vous pouvez créer des intégrations qui sont non seulement fonctionnelles, mais aussi fiables et évolutives. À mesure que l'écosystème MCP mûrit, attendez-vous à voir des serveurs plus sophistiqués qui exploitent ces primitives pour alimenter la prochaine génération d'applications pilotées par l'IA.