MCP

Creer un serveur MCP en TypeScript pas a pas

Le Model Context Protocol (MCP) permet a vos outils IA de se connecter a des sources de donnees et des services externes. Les serveurs communautaires couvrent les cas generiques (GitHub, PostgreSQL, Slack), mais pour vos outils internes, vous devez creer votre propre serveur. Ce tutoriel vous guide pas a pas pour creer un serveur MCP en TypeScript, du setup initial jusqu'a l'integration avec Claude Code. Prerequis * Node.js 18+ et npm * TypeScript 5+ * Un outil compatible MCP (Claude Code

Jean-Michel Helem

Jean-Michel Helem

26 mars 2026 · 4 min de lecture

Creer un serveur MCP en TypeScript pas a pas

Le Model Context Protocol (MCP) permet a vos outils IA de se connecter a des sources de donnees et des services externes. Les serveurs communautaires couvrent les cas generiques (GitHub, PostgreSQL, Slack), mais pour vos outils internes, vous devez creer votre propre serveur.

Ce tutoriel vous guide pas a pas pour creer un serveur MCP en TypeScript, du setup initial jusqu'a l'integration avec Claude Code.

Prerequis

  • Node.js 18+ et npm
  • TypeScript 5+
  • Un outil compatible MCP (Claude Code, Cline) pour tester
  • Connaissances de base en TypeScript

Setup du projet

Initialisez un nouveau projet :

mkdir mon-serveur-mcp
cd mon-serveur-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod

Configurez TypeScript :

{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
"include": ["src/*/"]

Structure du serveur

Un serveur MCP expose trois types de primitives :

  • Tools : des actions que l'IA peut executer (equivalent d'une fonction)
  • Resources : des donnees que l'IA peut lire (equivalent d'un endpoint GET)
  • Prompts : des templates de conversation pre-definis

Creez le fichier principal src/index.ts :

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: "mon-serveur",
version: "1.0.0",
});
// On ajoutera les tools et resources ici
const transport = new StdioServerTransport();

Le serveur communique via stdio (entree/sortie standard), ce qui le rend compatible avec tous les clients MCP.

Ajouter un tool

Un tool est une action que l'IA peut executer. Exemple : un tool qui recherche dans votre documentation interne.

server.tool(
"search-docs",
"Recherche dans la documentation interne du projet",
{
query: z.string().describe("Terme de recherche"),
limit: z.number().optional().default(5).describe("Nombre max de resultats"),
},
async ({ query, limit }) => {
// Ici, votre logique de recherche
const results = await searchInternalDocs(query, limit);
return {
content: [
{
type: "text",
text: JSON.stringify(results, null, 2),
},
],
};
}

Anatomie d'un tool

  • Nom : identifiant unique (search-docs)
  • Description : explique a l'IA quand utiliser ce tool
  • Schema : parametres valides avec Zod (l'IA envoie des parametres types)
  • Handler : fonction async qui execute l'action et retourne un resultat

La description est cruciale : c'est elle qui permet a l'IA de savoir quand utiliser votre tool. Soyez precis et concret.

Ajouter une resource

Une resource expose des donnees en lecture. Exemple : la configuration du projet.

server.resource(
"config://project",
"Configuration actuelle du projet (env, feature flags)",
async (uri) => {
const config = await loadProjectConfig();
return {
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(config, null, 2),
},
],
};
}

Les resources utilisent un schema d'URI pour l'identification. L'IA peut les lire mais pas les modifier.

Ajouter un prompt

Un prompt est un template de conversation pour un cas d'usage specifique :

server.prompt(
"debug-error",
"Analyse une erreur de production avec le contexte du projet",
{
errorId: z.string().describe("ID de l'erreur (ex: SENTRY-1234)"),
},
async ({ errorId }) => {
const error = await fetchError(errorId);
return {
messages: [
{
role: "user",
content: {
type: "text",
text: Analyse cette erreur de production et propose un fix :
Erreur: ${error.title}
Stack trace: ${error.stackTrace}
Occurrences: ${error.count} fois en ${error.timespan}
Derniere occurrence: ${error.lastSeen}
Contexte projet: API Spring Boot 3.4, PostgreSQL 17, deploye sur Kubernetes.,
},
},
],
};
}

Exemple complet : serveur pour une API interne

Voici un serveur MCP complet qui expose une API REST interne :

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const API_BASE = process.env.INTERNAL_API_URL || "http://localhost:3000";
const API_TOKEN = process.env.INTERNAL_API_TOKEN || "";
const server = new McpServer({
name: "internal-api",
version: "1.0.0",
});
// Tool : lister les utilisateurs
server.tool(
"list-users",
"Liste les utilisateurs de la plateforme avec filtrage",
{
role: z.enum(["admin", "user", "editor"]).optional(),
active: z.boolean().optional().default(true),
},
async ({ role, active }) => {
const params = new URLSearchParams();
if (role) params.set("role", role);
params.set("active", String(active));
const res = await fetch(${API_BASE}/api/users?${params}, {
headers: { Authorization: Bearer ${API_TOKEN} },
});
const data = await res.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// Tool : creer un ticket support
server.tool(
"create-ticket",
"Cree un ticket de support interne",
{
title: z.string().describe("Titre du ticket"),
description: z.string().describe("Description detaillee"),
priority: z.enum(["low", "medium", "high", "critical"]),
},
async ({ title, description, priority }) => {
const res = await fetch(${API_BASE}/api/tickets, {
method: "POST",
headers: {
Authorization: Bearer ${API_TOKEN},
"Content-Type": "application/json",
},
body: JSON.stringify({ title, description, priority }),
});
const ticket = await res.json();
return {
content: [
{
type: "text",
text: Ticket cree : #${ticket.id} - ${ticket.title},
},
],
};
}
);
// Resource : documentation API
server.resource(
"docs://api-endpoints",
"Liste de tous les endpoints de l'API interne",
async (uri) => {
const res = await fetch(${API_BASE}/api/docs/openapi.json, {
headers: { Authorization: Bearer ${API_TOKEN} },
});
const spec = await res.json();
return {
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(spec, null, 2),
},
],
};
}
);
const transport = new StdioServerTransport();

Tester votre serveur

Avec Claude Code

Ajoutez votre serveur dans la configuration :

{
"mcpServers": {
"internal-api": {
"command": "npx",
"args": ["tsx", "/chemin/vers/mon-serveur-mcp/src/index.ts"],
"env": {
"INTERNAL_API_URL": "http://localhost:3000",
"INTERNAL_API_TOKEN": "votre-token"
}
}
}

Lancez Claude Code et verifiez avec /mcp que votre serveur apparait avec ses tools.

Test manuel

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | npx tsx src/index.ts

Bonnes pratiques

Descriptions precises : la qualite des descriptions de vos tools determine si l'IA les utilisera correctement. "Liste les utilisateurs" est moins bon que "Liste les utilisateurs de la plateforme, filtrable par role et statut actif/inactif". Validation stricte : utilisez Zod pour valider tous les parametres. L'IA peut envoyer des valeurs inattendues. Gestion d'erreurs : retournez des messages d'erreur clairs que l'IA peut comprendre et transmettre a l'utilisateur. Principe du moindre privilege : un serveur MCP pour la documentation n'a pas besoin d'un acces en ecriture a la base de donnees. Logging : loguez les appels pour comprendre comment l'IA utilise vos tools et identifier les ameliorations possibles.

Pour aller plus loin

Articles similaires

MCP et bases de donnees : requetes IA en contexte
MCP

MCP et bases de donnees : requetes IA en contexte

Vos developpeurs passent des heures a ecrire des requetes SQL complexes, a dechiffrer des schemas de bases de donnees herites ou a debugger des performances. Et si un assistant IA pouvait interroger directement votre base de donnees, comprendre sa structure et generer les requetes adaptees en quelques secondes ? C'est exactement ce que permet le Model Context Protocol applique aux bases de donnees. Plus besoin de copier-coller des schemas ou de decrire manuellement vos tables : l'IA accede au co

Jean-Michel Helem · 30 avril 2026 · 7 min
Claude Code + MCP : integrer vos outils internes
Claude Code

Claude Code + MCP : integrer vos outils internes

Vous utilisez Claude Code au quotidien pour coder plus vite, mais il reste deconnecte de votre ecosysteme interne. Vos tickets Jira, votre documentation Confluence, vos bases de donnees PostgreSQL, vos API metier : autant de contexte critique que l'IA ne peut pas exploiter. Le Model Context Protocol (MCP) change la donne. Ce protocole ouvert permet a Claude Code d'interroger directement vos outils internes, transformant un assistant de code generique en un coequipier qui connait votre stack, vos

Jean-Michel Helem · 20 avril 2026 · 7 min
MCP en entreprise : securite et gouvernance
MCP

MCP en entreprise : securite et gouvernance

Le Model Context Protocol s'impose progressivement comme le standard d'interconnexion entre les modeles d'IA et les outils d'entreprise. Mais passer d'un prototype local a un deploiement en production dans une organisation de 500 ou 5 000 collaborateurs change radicalement la donne. Les donnees clients transitent par les serveurs MCP, les outils exposes peuvent modifier des bases de donnees critiques, et chaque appel non trace devient un angle mort pour la compliance. Ce guide detaille les mecan

Jean-Michel Helem · 15 avril 2026 · 9 min