Construire votre premier serveur MCP : guide pratique pour developpeurs
Engineering Team
Qu’est-ce que le Model Context Protocol (MCP) ?
Le Model Context Protocol (MCP) est un standard ouvert cree par Anthropic qui definit la maniere dont les applications AI communiquent avec les sources de donnees et les outils externes. Pensez au MCP comme a l’USB-C pour l’integration AI : tout comme l’USB-C fournit un connecteur universel unique pour la charge, le transfert de donnees et la sortie video, le MCP fournit un protocole universel unique pour connecter les modeles AI aux bases de donnees, API, systemes de fichiers et tout autre service. Le MCP elimine le besoin d’integrations personnalisees entre chaque application AI et chaque outil.
En 2026, le MCP est devenu le standard dominant pour la communication AI-outils. Gartner prevoit que 40 % des applications d’entreprise incluront des agents AI d’ici fin 2026, et le MCP est le protocole qui rend cela pratique a grande echelle. Avant le MCP, connecter un modele AI a N outils necessitait N integrations personnalisees. Avec M applications AI et N outils, il fallait M x N adaptateurs d’integration. Le MCP reduit cela a M + N : chaque application AI implemente un MCP client, chaque outil implemente un MCP server.
Architecture MCP : Host, Client, Server et Transport
Comprendre l’architecture MCP est essentiel avant d’ecrire du code. Le protocole definit quatre roles cles :
| Composant | Role | Exemple |
|---|---|---|
| Host | L’application AI avec laquelle l’utilisateur final interagit | Claude Desktop, Cursor, VS Code Copilot |
| Client | Le gestionnaire de protocole MCP a l’interieur du host | Integre dans l’application host |
| Server | Expose des tools, resources et prompts via MCP | Votre serveur personnalise (ce que nous allons construire) |
| Transport | La couche de communication entre client et server | stdio, HTTP+SSE, Streamable HTTP |
Le flux de communication fonctionne ainsi :
- Le Host demarre et initialise un MCP Client pour chaque serveur configure.
- Le Client se connecte au Server via un Transport (stdio pour le local, HTTP pour le distant).
- Le Client envoie une requete
initialize, negociant la version du protocole et les capacites. - Le Server repond avec ses tools, resources et prompts disponibles.
- Lorsque le modele AI a besoin de donnees ou d’actions externes, le Client appelle la methode serveur appropriee.
- Le Server execute l’operation et retourne les resultats via des messages JSON-RPC 2.0.
Tools vs Resources vs Prompts
Les MCP servers peuvent exposer trois types de capacites :
- Tools sont des fonctions que le modele AI peut appeler. Ils acceptent des entrees structurees et retournent des sorties structurees. Exemple :
query_database(sql: string)ousend_email(to: string, subject: string, body: string). - Resources sont des donnees que le modele AI peut lire. Elles sont identifiees par des URI et retournent du contenu. Exemple :
file:///path/to/document.mdoupostgres://localhost/mydb/users. - Prompts sont des modeles de prompts reutilisables fournis par le serveur. Ils aident a standardiser la facon dont l’AI interagit avec le domaine du serveur. Exemple : un modele
summarize_ticketpour un Jira MCP server.
Etape par etape : construire un serveur MCP en TypeScript
Construisons un serveur MCP pratique qui fournit un outil pour interroger une base de donnees SQLite. C’est un cas d’utilisation courant : donner a un modele AI un acces securise en lecture seule aux donnees de votre application.
Etape 1 : Initialiser le projet
mkdir mcp-sqlite-server && cd mcp-sqlite-server
npm init -y
npm install @modelcontextprotocol/sdk better-sqlite3
npm install -D typescript @types/node @types/better-sqlite3
npx tsc --init
Configurer tsconfig.json :
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"declaration": true
},
"include": ["src/**/*"]
}
Etape 2 : Implementer le serveur
Creer src/index.ts :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import Database from "better-sqlite3";
import { z } from "zod";
const db = new Database(process.env.DB_PATH || "./data.db", {
readonly: true,
});
const server = new McpServer({
name: "sqlite-query",
version: "1.0.0",
});
server.tool(
"query",
"Executer une requete SQL en lecture seule sur la base de donnees SQLite",
{
sql: z.string().describe("La requete SQL SELECT a executer"),
},
async ({ sql }) => {
const normalized = sql.trim().toUpperCase();
if (!normalized.startsWith("SELECT")) {
return {
content: [{ type: "text", text: "Erreur : seules les requetes SELECT sont autorisees." }],
isError: true,
};
}
try {
const rows = db.prepare(sql).all();
return {
content: [{ type: "text", text: JSON.stringify(rows, null, 2) }],
};
} catch (error) {
return {
content: [{ type: "text", text: `Erreur de requete : ${(error as Error).message}` }],
isError: true,
};
}
}
);
server.tool(
"list_tables",
"Lister toutes les tables de la base de donnees avec leurs schemas",
{},
async () => {
const tables = db
.prepare(
`SELECT name, sql FROM sqlite_master
WHERE type='table' AND name NOT LIKE 'sqlite_%'
ORDER BY name`
)
.all();
return {
content: [{ type: "text", text: JSON.stringify(tables, null, 2) }],
};
}
);
Etape 3 : Compiler et tester localement
npx tsc
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | node dist/index.js
Vous devriez voir une reponse JSON-RPC avec les capacites du serveur.
Etape 4 : Construire le meme serveur en Python
Pour les developpeurs Python, voici l’implementation equivalente utilisant le SDK Python MCP officiel :
import sqlite3
import json
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("sqlite-query")
DB_PATH = "data.db"
@mcp.tool()
def query(sql: str) -> str:
"""Executer une requete SQL en lecture seule sur la base de donnees SQLite."""
normalized = sql.strip().upper()
if not normalized.startswith("SELECT"):
raise ValueError("Seules les requetes SELECT sont autorisees.")
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
try:
cursor = conn.execute(sql)
rows = [dict(row) for row in cursor.fetchall()]
return json.dumps(rows, indent=2, default=str)
finally:
conn.close()
@mcp.tool()
def list_tables() -> str:
"""Lister toutes les tables de la base de donnees avec leurs schemas."""
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
try:
cursor = conn.execute(
"SELECT name, sql FROM sqlite_master "
"WHERE type='table' AND name NOT LIKE 'sqlite_%'"
)
tables = [dict(row) for row in cursor.fetchall()]
return json.dumps(tables, indent=2)
finally:
conn.close()
if __name__ == "__main__":
mcp.run(transport="stdio")
Connexion a Claude Desktop
Claude Desktop prend en charge nativement les serveurs MCP. Pour connecter votre serveur, editez le fichier de configuration de Claude Desktop :
macOS : ~/Library/Application Support/Claude/claude_desktop_config.json
Windows : %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sqlite-query": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": {
"DB_PATH": "/absolute/path/to/your/data.db"
}
}
}
}
Redemarrez Claude Desktop. Vous verrez une icone de marteau dans l’interface de chat indiquant les outils MCP disponibles. Vous pouvez maintenant poser des questions a Claude comme « Quelles tables existent dans la base de donnees ? » ou « Affiche les 10 premiers utilisateurs par date d’inscription » et Claude utilisera votre serveur MCP pour interroger la base de donnees directement.
Connexion a Cursor
Cursor prend egalement en charge les serveurs MCP. Ajoutez la configuration a .cursor/mcp.json dans la racine de votre projet :
{
"mcpServers": {
"sqlite-query": {
"command": "node",
"args": ["./dist/index.js"],
"env": {
"DB_PATH": "./data.db"
}
}
}
}
Apres avoir enregistre, redemarrez Cursor. Les outils MCP apparaissent dans le panneau de l’assistant AI et peuvent etre invoques pendant les sessions de generation de code et de debogage.
Test et debogage de votre serveur MCP
Utilisation du MCP Inspector
Le MCP Inspector est l’outil de debogage officiel. Il fournit une interface web pour interagir avec votre serveur :
npx @modelcontextprotocol/inspector node dist/index.js
Cela ouvre une interface navigateur a http://localhost:5173 ou vous pouvez :
- Visualiser tous les tools, resources et prompts enregistres
- Appeler des tools avec des entrees personnalisees et inspecter les reponses
- Surveiller le flux de messages JSON-RPC en temps reel
- Tester la gestion des erreurs en envoyant des requetes malformees
Problemes de debogage courants
| Probleme | Cause | Solution |
|---|---|---|
| Le serveur n’apparait pas dans Claude Desktop | Chemin de configuration ou erreur de syntaxe JSON | Valider le JSON, verifier les chemins absolus |
| Erreur « Tool not found » | Les tools ne sont pas enregistres avant la connexion | Enregistrer les tools avant d’appeler server.connect() |
| Timeout sur les appels d’outils | Operation longue sans notification de progression | Ajouter des notifications de progression via server.sendProgress() |
| La sortie stderr corrompt le protocole | console.log ecrit sur stdout (transport stdio) | Utiliser console.error() pour le logging avec stdio |
| Deconnexion apres inactivite | Timeout du transport | Implementer un heartbeat ou utiliser le transport HTTP |
Bonnes pratiques pour la production
-
Validation des entrees : Toujours valider et assainir les entrees des outils. Utilisez des schemas Zod (TypeScript) ou des modeles Pydantic (Python) pour une verification de type stricte.
-
Lecture seule par defaut : Commencez avec un acces en lecture seule. N’ajoutez des capacites d’ecriture que lorsque c’est reellement necessaire, et demandez toujours une confirmation pour les operations destructrices.
-
Gestion des erreurs : Retournez des messages d’erreur structures avec
isError: true. N’exposez jamais les traces de pile internes ou les chaines de connexion a la base de donnees. -
Journalisation : Enregistrez tous les appels d’outils avec horodatage, entrees et duree d’execution. Utilisez stderr pour la journalisation (pas stdout) avec le transport stdio.
-
Limitation de debit : Implementez des limites de debit par outil pour empecher les boucles AI non controlees de submerger vos services backend.
-
Timeout : Definissez des timeouts d’execution sur tous les handlers d’outils. Les modeles AI peuvent appeler des outils qui declenchent des requetes couteuses — protegez votre infrastructure.
-
Separation des environnements : Utilisez des variables d’environnement pour toute la configuration. Ne codez jamais en dur les URL de bases de donnees, les cles API ou les chemins de fichiers.
-
Gestion des versions : Utilisez le versionnage semantique pour votre serveur MCP. Le handshake
initializeinclut la negociation de version — les modifications incompatibles necessitent un bump de version majeure.
FAQ
Q : Quelle est la difference entre MCP et le function calling ? R : Le function calling (utilise par OpenAI, Anthropic et d’autres) definit les outils en ligne dans chaque requete API. Le MCP externalise les definitions d’outils vers des serveurs autonomes decouverts et utilises par les hosts compatibles MCP. Le function calling est par requete ; le MCP est un protocole persistant avec des sessions stateful.
Q : Puis-je utiliser MCP avec des modeles autres que Claude ? R : Oui. Le MCP est un protocole ouvert. OpenAI, Google DeepMind et Microsoft ont adopte le support MCP dans leurs plateformes depuis debut 2026. Toute application AI qui implemente un MCP client peut se connecter a n’importe quel MCP server.
Q : MCP est-il uniquement pour les outils locaux ? R : Non. Bien que le transport stdio soit concu pour les serveurs locaux, les transports HTTP+SSE et Streamable HTTP prennent en charge les serveurs MCP distants. Vous pouvez deployer un serveur MCP comme service cloud accessible via le reseau.
Q : Comment MCP gere-t-il l’authentification ? R : Le protocole prend en charge OAuth 2.0 pour les serveurs distants. Les serveurs stdio locaux heritent du contexte de securite du processus host. Pour les deployments enterprise, un MCP gateway peut centraliser l’authentification et l’autorisation.
Q : Quels langages peuvent etre utilises pour construire un serveur MCP ? R : Les SDK officiels sont disponibles pour TypeScript, Python, Java, Kotlin, C# et Swift. Les SDK communautaires incluent Rust, Go, Ruby et PHP. Le protocole est agnostique en termes de langage — tout langage capable de lire/ecrire du JSON-RPC via stdio ou HTTP peut implementer un serveur MCP.
Q : Comment mettre a jour un serveur MCP sans redemarrer le host ?
R : MCP prend en charge les notifications de changement de capacites. Lorsque les outils de votre serveur changent, le serveur peut envoyer un message notifications/tools/list_changed, invitant le client a recuperer la liste des outils. Pour les serveurs stdio, le host doit generalement etre redemarre. Les serveurs HTTP peuvent etre mis a jour sans redemarrer le host.