Développement MCP Server : construisez votre premier service MCP

Introduction : Quand vous codez dans Cursor, avez-vous déjà souhaité que l’IA vérifie directement la dernière version de vos dépendances ? Ou, en analysant des données dans Claude, vouloir qu’elle lise les infos de votre base de données ? Sans MCP, il faudrait écrire une couche d’adaptation pour chaque outil IA. Avec un MCP Server, vous ne codez qu’une fois — tous les clients compatibles MCP en profitent. Cet article vous guide from scratch pour écrire un MCP Server complet en TypeScript.
Qu’est-ce que MCP ? Comprendre les concepts en 3 minutes
L’histoire d’une interface USB
Ceux qui ont connu les gadgets numériques il y a quelques années se souviennent de cette époque gênante : souris en port rond, clavier en port carré, imprimante en port parallèle — chaque appareil exigeait sa prise. Puis USB est arrivé : une interface pour tout.
MCP (Model Context Protocol) devient le « standard USB » du monde des outils IA.
Sans MCP, pour qu’une IA accède à une source de données, vous écrivez une couche d’adaptation par outil : un plugin pour Claude, une extension pour Cursor, encore une pour Windsurf… La complexité est N × M (N sources × M outils IA).
Avec MCP, vous n’écrivez qu’un MCP Server ; tous les clients compatibles l’appellent directement. La complexité passe à N + M.
L’architecture à trois couches est simple :
+-------------+ +-------------+ +-------------+
| Host | -> | Client | -> | Server |
| (Claude) | | (client MCP)| | (votre svc) |
+-------------+ +-------------+ +-------------+
- Host : l’application IA elle-même, ex. Claude Desktop, Cursor
- Client : client MCP, communique avec le Host
- Server : votre service, fournit les fonctionnalités concrètes
Les trois capacités d’un MCP Server
Un MCP Server peut offrir trois types de fonctionnalités :
| Capacité | Usage | Exemple |
|---|---|---|
| Tools (outils) | Exécuter des actions | Météo, envoi de messages, lecture BDD |
| Resources (ressources) | Fournir des données | Contenu de fichiers, réponses API, config |
| Prompts (invites) | Modèles prédéfinis | Revue de code, génération de rapport quotidien |
Considérez Tools comme des « fonctions » — l’IA les appelle pour agir ; Resources comme des « sources de données » — l’IA lit leur contenu ; Prompts comme des « modèles » — ils aident l’IA à comprendre la tâche plus vite.
Différence avec d’autres articles : d’autres tutoriels MCP utilisent Python et FastMCP. Ici, le SDK TypeScript natif convient mieux aux développeurs frontend et full-stack. Les deux approches sont équivalentes — choisissez le langage que vous maîtrisez.
"https://modelcontextprotocol.io"
Préparation de l’environnement de développement
Prérequis
Cet article suppose que vous :
- avez installé Node.js 18+ ou Bun 1.0+
- connaissez TypeScript (
interface,async/await) - disposez de Claude Desktop ou d’un client MCP (Cursor, Windsurf, etc.)
Si vous n’avez jamais utilisé Bun, essayez-le — bien plus rapide que npm, avec TypeScript intégré, sans configurer ts-node.
Initialiser le projet
# Créer le répertoire du projet
mkdir mcp-weather-server && cd mcp-weather-server
# Initialiser (Bun ou npm)
bun init -y
# ou npm init -y
# Installer le SDK MCP TypeScript
bun add @modelcontextprotocol/sdk zod
# ou npm install @modelcontextprotocol/sdk zod
Deux dépendances :
@modelcontextprotocol/sdk: SDK TypeScript officiel MCPzod: validation de types à l’exécution, pour définir le schéma des paramètres d’outils
Points clés de la config TypeScript
Avec bun init, tsconfig.json est déjà prêt. En configuration manuelle, notez ces options :
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"strict": true
}
}
moduleResolution: "bundler" est important pour les modules ESM, sinon vous risquez l’erreur « xxx is not defined ».
Pratique : écrire un MCP Server météo
Ce tutoriel couvre un MCP Server complet qui :
- reçoit les appels de l’IA
- interroge l’API OpenWeatherMap pour la météo en temps réel
- renvoie un résultat formaté
Structure du projet
mcp-weather-server/
+-- src/
| +-- index.ts # Point d'entrée
| +-- weather.ts # Implémentation outil météo
| +-- resources.ts # Définition des ressources
+-- package.json
+-- tsconfig.json
Le code peut tout tenir dans index.ts (comme ici), mais le découpage en modules facilite la maintenance.
Étape 1 : créer le squelette du MCP Server
Commencez par un MCP Server qui démarre :
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Créer l'instance serveur
const server = new McpServer({
name: "weather-service",
version: "1.0.0",
});
// Enregistrer un outil (Tools)
server.tool(
"get_weather",
"Obtenir la météo actuelle d'une ville",
{
city: z.string().describe("Nom de la ville, ex. : Pékin, Shanghai"),
},
async ({ city }) => {
// Implémentation détaillée à l'étape suivante
return { content: [{ type: "text", text: `Requête météo pour ${city}...` }] };
}
);
// Démarrer le serveur
const transport = new StdioServerTransport();
await server.connect(transport);
McpServer est la classe centrale du SDK ; passez name et version. tool() enregistre un outil : nom, description, schéma des paramètres, fonction d’exécution.
Étape 2 : implémenter l’outil météo (code principal)
Rendons l’outil opérationnel avec l’API gratuite OpenWeatherMap :
// src/weather.ts
import { z } from "zod";
// Type de réponse API OpenWeatherMap
interface WeatherResponse {
name: string;
main: { temp: number; feels_like: number; humidity: number };
weather: [{ description: string }];
wind: { speed: number };
}
// Implémentation de l'outil météo
server.tool(
"get_weather",
"Obtenir la météo actuelle d'une ville",
{
city: z.string().describe("Nom de la ville, ex. : Pékin, Shanghai"),
},
async ({ city }) => {
const API_KEY = process.env.OPENWEATHER_API_KEY;
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric&lang=zh_cn`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Échec de la requête API : ${response.status}`);
}
const data: WeatherResponse = await response.json();
// Retour formaté
return {
content: [
{
type: "text",
text: JSON.stringify({
city: data.name,
temperature: `${data.main.temp}°C`,
feels_like: `${data.main.feels_like}°C`,
description: data.weather[0].description,
humidity: `${data.main.humidity}%`,
wind_speed: `${data.wind.speed} m/s`,
}, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Échec de la requête : ${error instanceof Error ? error.message : 'Erreur inconnue'}`,
},
],
isError: true,
};
}
}
);
Points importants :
- Clé API via variable d’environnement : ne jamais la coder en dur
- Gestion d’erreurs :
isError: truesignale l’échec au client - Typage : l’interface
WeatherResponsevalide la structure des données
Inscrivez-vous gratuitement sur OpenWeatherMap, récupérez votre clé API, puis :
export OPENWEATHER_API_KEY=your_api_key_here
Étape 3 : ajouter des Resources (optionnel mais recommandé)
Les Resources permettent des données en lecture seule. Exemple : état du serveur :
// src/resources.ts
// Informations d'état du serveur
server.resource(
"server-status",
"status://server",
async (uri) => ({
contents: [
{
uri: uri.href,
text: JSON.stringify({
name: "Weather Service",
version: "1.0.0",
status: "running",
timestamp: new Date().toISOString(),
}, null, 2),
},
],
})
);
// Documentation API
server.resource(
"api-docs",
"docs://api",
async (uri) => ({
contents: [
{
uri: uri.href,
text: `
# Weather MCP Server API
## Tools
- get_weather(city: string): météo d'une ville
## Resources
- status://server - État du serveur
- docs://api - Documentation API
`.trim(),
},
],
})
);
Les deux premiers paramètres de resource() sont le nom et l’URI ; le troisième est la fonction de lecture. L’URI peut utiliser n’importe quel schéma (status://, docs://), tant qu’ils sont distincts.
Étape 4 : ajouter des Prompts (fonction avancée)
Les Prompts sont des modèles de dialogue prédéfinis. Exemple : modèle « rapport météo » avec nom de ville prérempli :
// Modèle de rapport météo prédéfini
server.prompt(
"weather_report",
"Générer un rapport météo formaté",
{
city: z.string().describe("Nom de la ville"),
include_tips: z.boolean().optional().describe("Inclure des conseils vestimentaires"),
},
({ city, include_tips }) => ({
messages: [
{
role: "user",
content: {
type: "text",
text: `Générez un rapport météo pour ${city}.${include_tips ? " Incluez des conseils vestimentaires." : ""}`,
},
},
],
})
);
Le retour de prompt() est un tableau de messages avec role et content. L’IA reçoit ainsi un contexte prédéfini.
Étape 5 : finaliser le point d’entrée
Regroupez tout dans src/index.ts avec gestion d’erreurs :
// src/index.ts (version complète)
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: "weather-service",
version: "1.0.0",
});
// Enregistrer outils, ressources et prompts
// ... (code ci-dessus)
// Gestion d'erreurs
process.stdin.on("error", (err) => {
console.error("Erreur entrée standard :", err);
process.exit(1);
});
process.stdout.on("error", (err) => {
console.error("Erreur sortie standard :", err);
process.exit(1);
});
// Arrêt propre
process.on("SIGINT", async () => {
await server.close();
process.exit(0);
});
// Démarrer le serveur
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Weather Server démarré, en attente de connexion...");
StdioServerTransport communique via stdin/stdout — la gestion d’erreurs est essentielle. Le handler SIGINT permet un arrêt propre avec Ctrl+C.
Lancez avec bun run src/index.ts ; le message « démarré » confirme que tout fonctionne.
Configurer le client : connecter Claude à votre Server
Le Server est prêt ; configurons Claude Desktop ou Cursor.
Configuration Claude Desktop
Fichier de configuration :
- macOS :
~/Library/Application Support/Claude/claude_desktop_config.json - Windows :
%APPDATA%\Claude\claude_desktop_config.json
Ajoutez votre Server :
{
"mcpServers": {
"weather": {
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-weather-server/src/index.ts"],
"env": {
"OPENWEATHER_API_KEY": "votre clé API"
}
}
}
}
Attention : le chemin dans args doit être absolu. Un chemin relatif fait échouer le démarrage.
Configuration Cursor / Windsurf
Cursor et Windsurf suivent un schéma similaire : paramètres IDE → configuration MCP → ajouter une entrée serveur (même format).
Fichier Cursor habituel :
- macOS :
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb - ou dans l’IDE : Paramètres → IA → MCP → Ajouter un serveur
Tester votre Server
- Redémarrez Claude Desktop / Cursor
- Dans le chat : « Quel temps fait-il à Pékin ? »
- Claude devrait appeler automatiquement votre MCP Server
Sortie attendue en cas de succès :
{
"city": "北京",
"temperature": "18°C",
"feels_like": "16°C",
"description": "多云",
"humidity": "65%",
"wind_speed": "3.2 m/s"
}
Dépannage courant
| Problème | Cause probable | Solution |
|---|---|---|
| Server non connecté | Chemin incorrect | Vérifier le chemin absolu dans args |
| Clé API invalide | Variable d’env non transmise | Confirmer la config env |
| Pas de réponse | Erreur de compilation TypeScript | Compiler d’abord avec bun build ou tsc |
| Erreur de permissions | Droits du fichier de config | S’assurer que le fichier est lisible |
"https://github.com/modelcontextprotocol/typescript-sdk"
Extension et déploiement
Ajouter d’autres outils
La météo n’est qu’un début. Vous pouvez :
- Historique météo : API de données passées
- Comparaison multi-villes : plusieurs villes en une requête
- Alertes météo : vérifier les alertes de conditions extrêmes
Même enregistrement que get_weather, logique différente.
Comparaison des options de déploiement
Pour partager en équipe, le transport stdio local ne suffit plus :
| Mode | Cas d’usage | Avantages | Inconvénients |
|---|---|---|---|
| stdio local | Usage perso, dev/test | Simple, sécurisé | Non partageable |
| HTTP/SSE | Équipe, multi-utilisateurs | Accès distant | Authentification requise |
| Serverless | Production | Auto-scaling | Latence au cold start |
Points de production
Authentification : en HTTP, implémentez l’auth. MCP supporte OAuth 2.1 ; une clé API simple suffit aussi :
// Vérifier la clé API dans les en-têtes
const apiKey = request.headers.get("Authorization");
if (apiKey !== `Bearer ${process.env.API_KEY}`) {
return new Response("Unauthorized", { status: 401 });
}
Limitation de débit : évitez d’épuiser vos quotas API. Utilisez express-rate-limit ou le rate limiting Cloudflare Workers.
Logs : pino ou winston pour tracer les appels d’outils :
import pino from "pino";
const logger = pino();
server.tool("get_weather", /* ... */, async ({ city }) => {
logger.info({ city }, "Requête météo");
// ...
});
Monitoring : taux de succès et temps de réponse. Prometheus + Grafana est un duo courant.
Résumé
Cet article explique comment écrire un MCP Server en TypeScript from scratch :
- Comprendre MCP et son architecture à trois couches
- Créer un serveur avec le SDK MCP TypeScript
- Implémenter l’outil météo (Tools)
- Ajouter des ressources d’état serveur (Resources)
- Définir un modèle de rapport météo (Prompts)
- Configurer Claude Desktop / Cursor pour appeler le Server
Vous pouvez maintenant :
- Construire des wrappers MCP pour vos API (GitHub, Slack, Notion, etc.)
- Créer des interfaces MCP pour vos systèmes internes (CRM, bases de données)
- Explorer les serveurs MCP de la communauté
Ressources pour aller plus loin :
Pour approfondir le protocole MCP, consultez le guide des principes du protocole MCP.
FAQ
Quelles bases faut-il pour développer un MCP Server ?
Quelle différence entre MCP Server et FastMCP ?
Comment tester qu'un MCP Server fonctionne ?
Peut-on déployer un MCP Server sur un serveur distant ?
9 min de lecture · Publié le: 19 mars 2026 · Mis à jour le: 27 juil. 2026
Guide pratique MCP
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Outils IA incompatibles ? Le protocole MCP pour une intégration fluide (avec tutoriel pratique)
Analyse approfondie du protocole MCP pour résoudre les problèmes d'interopérabilité des outils IA, avec un cas pratique FastMCP pour un service météo. Code complet, guide de configuration et solutions aux problèmes courants pour démarrer en 5 minutes.
Partie 1 sur 4
Suivant
Tutoriel MCP : configurer Cursor pour interroger bases de données et API
Guide pas à pas pour configurer un MCP Server et laisser Cursor et Claude interroger SQLite/PostgreSQL et appeler des API. Exemples de code complets, dépannage et configuration en 15 minutes.
Partie 3 sur 4



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire