Aller au contenu
Retour aux Articles

Construire des serveurs MCP personnalises : etendre les agents IA avec des outils specifiques au domaine

Byte Smith · · 16 min de lecture

La plupart des equipes utilisant des agents de codage IA commencent avec les outils disponibles directement. Cela vous emmene etonnamment loin : acces aux fichiers, commandes terminal, recherche web, consultation de documentation. Mais vous finissez par atteindre le mur. Vos agents ne peuvent pas interroger vos bases de donnees internes. Ils ne peuvent pas verifier votre systeme de tickets. Ils ne peuvent pas declencher votre pipeline de deploiement ou consulter le contexte client depuis votre API proprietaire.

C’est le vide que les serveurs MCP personnalises comblent. Au lieu d’attendre que quelqu’un d’autre construise une integration pour vos systemes internes, vous la construisez vous-meme. Vous definissez les outils, controlez les permissions, appliquez les frontieres de securite et donnez a vos agents exactement les capacites dont ils ont besoin pour etre utiles dans les workflows specifiques de votre organisation.

Ce n’est pas theorique. Les equipes qui connectent les agents a des outils internes constatent un changement qualitatif dans ce que ces agents peuvent accomplir. Un agent qui peut lire votre schema de base de donnees, interroger les deploiements recents et verifier le statut d’un ticket Jira est fondamentalement plus utile qu’un agent qui ne peut voir que les fichiers sur le disque. La valeur composee vient du fait de donner aux agents acces au meme contexte que vos ingenieurs utilisent pour prendre des decisions.

Si vous connaissez deja le fonctionnement de MCP a un niveau eleve grace a notre apercu des agents de codage IA et de MCP, ce guide va plus en profondeur. Il couvre les decisions d’architecture, les patterns de securite, les preoccupations de production et une implementation de reference que vous pouvez forker et adapter.

Rappel de l’architecture MCP

Avant de construire, il est utile d’avoir l’architecture claire. MCP suit un modele client-serveur avec trois couches :

  • Hote : l’application avec laquelle l’utilisateur interagit (un IDE comme VS Code, Claude Desktop ou un runner d’agent personnalise)
  • Client MCP : vit a l’interieur de l’hote, gere les connexions a un ou plusieurs serveurs MCP
  • Serveur MCP : expose des capacites au client, se connecte a vos systemes backend

Le serveur est l’endroit ou vit votre code. Il recoit des requetes du client, execute la logique contre vos outils et sources de donnees et retourne des resultats structures.

Options de transport

MCP supporte deux mecanismes de transport principaux :

  • stdio : le serveur s’execute comme un sous-processus de l’hote. Simple, pas de configuration reseau, ideal pour le developpement local et les configurations mono-utilisateur.
  • Streamable HTTP (anciennement HTTP/SSE) : le serveur s’execute comme un service HTTP autonome. Requis pour les deploiements multi-utilisateurs, l’acces distant et les environnements de production ou vous avez besoin d’une authentification et d’un equilibrage de charge adequats.

Pour le developpement local et les tests, stdio est le chemin le plus rapide. Pour tout ce que vous prevoyez de deployer a une equipe, vous voulez le transport HTTP avec une authentification correcte devant.

Primitives de base

Les serveurs MCP exposent trois types de capacites :

  • Outils : des fonctions que l’agent peut appeler (interroger une base de donnees, creer un ticket, executer un build). Ce sont la primitive la plus courante et la plus puissante.
  • Ressources : des donnees en lecture seule auxquelles l’agent peut acceder (schemas de base de donnees, fichiers de configuration, documentation). Pensez-y comme du contexte que l’agent peut recuperer avant de decider quoi faire.
  • Prompts : des modeles de prompt reutilisables qui guident l’agent vers des workflows specifiques.

Pour la plupart des projets de serveur personnalise, vous passerez 90 % de votre temps a definir des outils et les frontieres de securite autour d’eux.

Si vous voulez une experience pratique de connexion a des serveurs MCP existants avant de construire le votre, commencez par notre tutoriel sur la configuration d’agents de codage alimentes par MCP ou l’extension de GitHub Copilot avec des outils MCP.

Choisir votre pattern de serveur MCP

Tous les serveurs MCP n’ont pas besoin du meme niveau de complexite. Le bon pattern depend de ce que vous exposez et du profil de risque de ces operations.

Acces aux donnees en lecture seule

C’est le pattern le plus simple et le moins risque. Votre serveur expose des outils qui interrogent des bases de donnees, recuperent des reponses API ou recherchent de la documentation, mais ne modifient jamais rien.

Exemples :

  • interroger une replique en lecture seule de votre base de donnees de production
  • rechercher dans la documentation interne ou les bases de connaissances
  • recuperer le statut de deploiement depuis votre systeme CI/CD
  • consulter le contexte client depuis une API CRM

Les serveurs en lecture seule sont le meilleur point de depart. Ils apportent une valeur immediate avec un risque minimal, car le pire cas est que l’agent voit des donnees qu’il ne devrait pas, ce que vous controlez par l’autorisation et le filtrage des sorties.

Operations avec etat

Une fois que vous depassez les lectures, les enjeux augmentent. Les operations avec etat incluent la creation de tickets, la mise a jour d’enregistrements, le declenchement de deploiements ou la modification de configuration.

Celles-ci necessitent une conception soignee des permissions :

  • une liste blanche explicite des operations autorisees
  • des workflows de confirmation pour les actions destructives
  • une journalisation d’audit pour chaque operation d’ecriture
  • des capacites de rollback la ou c’est possible

Le principe cle est que votre serveur MCP devrait appliquer des frontieres plus strictes que celles prevues pour un utilisateur humain. Un agent peut faire des erreurs plus vite et en plus grand volume qu’une personne. Votre serveur est la couche d’application.

Composition multi-outils

Les serveurs MCP les plus utiles exposent un ensemble coherent d’outils connexes, generalement cinq a dix, qui fonctionnent ensemble comme une boite a outils. Un serveur de base de donnees peut exposer list_tables, get_schema, query_database et explain_query. Un serveur de gestion de projet peut exposer search_tickets, get_ticket, create_ticket, update_status et add_comment.

La composition compte car les agents raisonnent mieux quand les outils sont regroupes logiquement et bien documentes. Un serveur avec trois outils cibles est plus utile qu’un serveur avec trente outils vaguement lies.

Cadre de decision

Commencez en lecture seule. Prouvez la valeur. Puis ajoutez des operations d’ecriture une par une, chacune avec sa propre verification de permission et piste d’audit. Ce n’est pas par prudence pour elle-meme. C’est pour construire la confiance dans le systeme de maniere incrementale afin de pouvoir aller plus vite plus tard.

Architecture de securite pour les serveurs MCP

La securite n’est pas une preoccupation ajoutee apres coup pour les serveurs MCP. C’est la contrainte de conception centrale. Votre serveur MCP se situe entre un agent IA et vos systemes internes. Si le serveur est permissif, l’agent herite de cette permissivite, et le rayon d’explosion d’une erreur ou d’une attaque s’etend en consequence.

Authentification

Comment le serveur verifie qui fait une requete :

  • Cles API : l’option la plus simple. Bonne pour les outils internes, les configurations mono-locataire et le developpement. Stockez les cles dans des variables d’environnement, jamais dans le code. Faites tourner regulierement.
  • OAuth2 : le bon choix quand votre serveur MCP doit agir au nom d’utilisateurs specifiques avec leurs permissions. Plus complexe a implementer mais necessaire pour les deploiements de production multi-utilisateurs.
  • mTLS : TLS mutuel pour la communication service-a-service. Utilisez ceci quand votre serveur MCP est appele par d’autres services plutot que directement par des hotes d’agents.

Pour la plupart des equipes debutantes, l’authentification par cle API avec un perimetre de permission par cle est le bon equilibre entre securite et simplicite.

Autorisation

L’authentification vous dit qui appelle. L’autorisation vous dit ce qu’ils sont autorises a faire.

Une autorisation efficace de serveur MCP inclut :

  • Permissions par outil : tous les utilisateurs authentifies ne devraient pas avoir acces a tous les outils. Une cle API en lecture seule ne devrait pas pouvoir appeler des outils d’ecriture.
  • Acces base sur les roles : mappez les cles API ou tokens OAuth a des roles (lecteur, editeur, administrateur) et appliquez des verifications de role dans chaque gestionnaire d’outil.
  • Isolation des locataires : si votre serveur sert plusieurs equipes ou clients, assurez-vous que les requetes sont limitees aux donnees de l’appelant. Ne comptez jamais sur l’agent pour ajouter la bonne clause WHERE.

Validation des entrees

Chaque entree d’un agent devrait etre traitee comme non fiable. Les agents peuvent halluciner des parametres, et un prompt compromis peut tenter des attaques par injection.

import { z } from "zod";

const QueryToolSchema = z.object({
  table: z
    .string()
    .refine((t) => ALLOWED_TABLES.includes(t), {
      message: "Table not in allowlist",
    }),
  columns: z
    .array(z.string())
    .max(20, "Too many columns requested"),
  where: z
    .record(z.string(), z.union([z.string(), z.number()]))
    .optional(),
  limit: z
    .number()
    .int()
    .min(1)
    .max(100)
    .default(25),
});

Patterns de validation cles :

  • application de schema sur chaque entree d’outil en utilisant Zod ou une bibliotheque similaire
  • prevention de l’injection SQL par des requetes parametrees (jamais de concatenation de chaines)
  • assainissement des parametres pour supprimer ou rejeter les patterns dangereux
  • liste blanche de tables et colonnes pour empecher l’acces aux donnees sensibles

Filtrage des sorties

Ce qui revient de vos systemes backend peut contenir des donnees que l’agent ne devrait pas voir ou retourner a l’utilisateur.

  • Masquage des DCP : masquer les adresses e-mail, numeros de telephone, numeros de securite sociale et autres champs sensibles avant de retourner les resultats
  • Exclusion de colonnes sensibles : definir des colonnes qui ne sont jamais retournees quelle que soit la requete
  • Securite au niveau des lignes : filtrer les resultats en fonction des permissions de l’appelant

Cela compte car les reponses des outils MCP deviennent partie du contexte de l’agent, et ce contexte peut etre visible pour l’utilisateur final ou journalise de manieres que vous ne controlez pas entierement.

Limitation de debit

Les agents peuvent faire des requetes beaucoup plus vite que les humains. Sans limites de debit, un agent mal configure peut marteler votre base de donnees ou epuiser vos quotas API en minutes.

Implementez des limites de debit par utilisateur et par outil. Retournez des erreurs claires et structurees quand les limites sont atteintes pour que l’agent puisse reculer intelligemment au lieu de reessayer en boucle serree.

Pour un traitement plus approfondi des patterns de securite pour les systemes connectes aux agents, voir notre guide pour securiser les applications d’IA agentique et les bonnes pratiques de securite des API pour les applications integrees a l’IA.

Si votre serveur MCP est utilise dans des workflows d’agents de codage, voir aussi notre guide pour securiser les pipelines d’agents de codage IA, qui couvre la detection, les controles de politique et les portes de revue par niveau de risque au niveau CI/CD.

Preoccupations de production

Faire fonctionner un outil localement est la partie facile. Le rendre fiable, observable et maintenable en production est la ou le vrai travail d’ingenierie se fait.

Gestion des erreurs

Les agents ne peuvent pas lire les stack traces. Ils ont besoin de reponses d’erreur structurees qui decrivent ce qui n’a pas fonctionne et ce qui, le cas echeant, peut etre fait.

import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";

function handleToolError(error: unknown): never {
  if (error instanceof ValidationError) {
    throw new McpError(
      ErrorCode.InvalidParams,
      `Invalid input: ${error.message}. Check the tool schema for valid parameters.`
    );
  }

  if (error instanceof AuthorizationError) {
    throw new McpError(
      ErrorCode.InvalidRequest,
      `Permission denied: your API key does not have access to this operation.`
    );
  }

  if (error instanceof QueryTimeoutError) {
    throw new McpError(
      ErrorCode.InternalError,
      `Query timed out after ${error.timeoutMs}ms. Try a more specific query with fewer results.`
    );
  }

  // Never expose internal details
  throw new McpError(
    ErrorCode.InternalError,
    "An unexpected error occurred. Contact the platform team if this persists."
  );
}

Les messages d’erreur devraient aider l’agent a se corriger. “Invalid table name” est mieux que “Error.” “Table not in allowlist, valid tables are: users, projects, deployments” est encore mieux.

Journalisation et pistes d’audit

Chaque invocation d’outil MCP devrait produire une entree de log structuree qui capture :

  • horodatage
  • identite authentifiee (ID de cle API, utilisateur ou service)
  • nom de l’outil et parametres d’entree
  • resume de la reponse (succes/echec, nombre de lignes, duree)
  • tout echec de validation ou operation bloquee

Ce n’est pas optionnel pour une utilisation en production. Quand quelque chose tourne mal, et ca arrivera, vous devez reconstruire exactement ce que l’agent a demande et ce que le serveur a retourne. Traitez les logs du serveur MCP avec la meme rigueur que vous appliquez aux logs de gateway API ou aux pistes d’audit de base de donnees.

Tests

Les serveurs MCP ont besoin de trois couches de tests :

  • Tests unitaires pour les gestionnaires d’outils individuels : pour ces entrees, le gestionnaire retourne-t-il la bonne sortie et applique-t-il les bonnes contraintes ?
  • Tests d’integration avec un client MCP simule : le cycle complet requete/reponse fonctionne-t-il correctement, y compris l’authentification, la validation et la gestion des erreurs ?
  • Tests de securite : le serveur rejette-t-il correctement les requetes non autorisees, bloque-t-il les tentatives d’injection SQL et masque-t-il les donnees sensibles ?

Le SDK MCP fournit des utilitaires pour creer des clients de test, ce qui rend les tests d’integration simples.

Deploiement

Conteneurisez votre serveur MCP des le depart. Un build Docker multi-etapes garde l’image petite, et Docker Compose vous permet d’executer le serveur avec ses dependances (base de donnees, cache, etc.) pour le developpement local.

Les deploiements de production devraient inclure :

  • des endpoints de health check
  • une gestion d’arret gracieux
  • une configuration basee sur l’environnement (pas de secrets codes en dur)
  • des limites de ressources (memoire, CPU)
  • un scaling horizontal pour les deploiements par transport HTTP

Versionnage

A mesure que votre serveur MCP evolue, vous ajouterez des outils, changerez des schemas et modifierez le comportement. Les agents qui dependent de votre serveur casseront si vous changez les schemas d’outils sans coordination.

Bonnes pratiques :

  • traitez les schemas d’outils comme un contrat d’API public
  • ajoutez de nouveaux outils plutot que de modifier ceux existants quand c’est possible
  • utilisez le versionnage semantique pour votre serveur
  • documentez les changements cassants et fournissez des conseils de migration
  • envisagez d’executer plusieurs versions du serveur en parallele pendant les transitions

L’implementation de reference mcp-enterprise-starter

Pour rendre tout cela concret, nous avons construit mcp-enterprise-starter, une implementation de reference qui demontre chaque pattern discute dans ce guide.

Architecture

Le depot est structure comme un serveur MCP TypeScript qui se connecte a PostgreSQL :

mcp-enterprise-starter/
  src/
    server.ts              # MCP server setup and transport config
    tools/
      query-database.ts    # Safe database query tool
      list-tables.ts       # Table listing tool
      get-schema.ts        # Schema inspection tool
    resources/
      schema.ts            # Database schema as MCP resource
    middleware/
      auth.ts              # API key authentication
      validation.ts        # Input validation and sanitization
      rate-limit.ts        # Per-user rate limiting
    utils/
      db.ts                # PostgreSQL connection pool
      sanitize.ts          # Query sanitization helpers
      errors.ts            # Structured error types
  tests/
  docker-compose.yml
  Dockerfile

Configuration du serveur

L’initialisation du serveur connecte le transport, l’authentification et l’enregistrement des outils :

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { requireAuth } from "./middleware/auth.js";
import { checkRateLimit } from "./middleware/rate-limit.js";

const server = new Server(
  { name: "mcp-enterprise-starter", version: "1.0.0" },
  { capabilities: { tools: {}, resources: {} } },
);

// Register tool listing
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [queryDatabaseTool, listTablesTool, getSchemaTool],
}));

// Handle tool calls with auth and rate limiting
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  const apiKey = process.env.MCP_API_KEY || process.env.API_KEYS?.split(",")[0];
  const authCtx = requireAuth(apiKey);
  checkRateLimit(authCtx.apiKey);

  switch (name) {
    case "query_database":
      return await handleQueryDatabase(args);
    case "list_tables":
      return await handleListTables();
    case "get_schema":
      return await handleGetSchema(args);
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

// Start with stdio transport for local dev
const transport = new StdioServerTransport();
await server.connect(transport);

Requetes de base de donnees securisees

L’outil query_database demontre comment donner a un agent un acces utile a la base de donnees sans lui donner une execution SQL illimitee :

  • les requetes sont des chaines SQL validees avec des valeurs parametrees, pas une execution brute non filtree
  • les noms de tables et de colonnes sont valides par rapport a une liste blanche
  • toutes les valeurs sont passees comme arguments de requete parametres
  • les resultats sont limites par defaut avec un maximum configurable
  • les colonnes sensibles sont masquees dans la sortie
  • les mots-cles destructifs (DROP, DELETE, UPDATE, ALTER) sont entierement bloques pour les cles en lecture seule

Middleware d’authentification

La couche d’authentification mappe les cles API a des ensembles de permissions :

import { McpToolError } from "../utils/errors.js";

export interface AuthContext {
  apiKey: string;
  permissions: "read" | "read-write";
}

function getApiKeys(): Map<string, AuthContext> {
  const keys = new Map<string, AuthContext>();
  const envKeys = process.env.API_KEYS || "";

  for (const key of envKeys.split(",").map((k) => k.trim()).filter(Boolean)) {
    keys.set(key, { apiKey: key, permissions: "read" });
  }
  return keys;
}

export function requireAuth(apiKey: string | undefined): AuthContext {
  if (!apiKey) {
    throw new McpToolError("auth_error", "Missing API key.", false);
  }
  const validKeys = getApiKeys();
  const context = validKeys.get(apiKey);
  if (!context) {
    throw new McpToolError("auth_error", "Invalid API key.", false);
  }
  return context;
}

Les cles API sont chargees depuis la variable d’environnement API_KEYS comme une liste separee par des virgules (par exemple dev-key-1,dev-key-2). Chaque cle mappe a un niveau de permission. Pour les systemes de production, vous etendriez cela avec des restrictions d’outils par cle, un acces base sur les roles ou le remplacement complet par OAuth2.

Comment l’utiliser

Le chemin le plus rapide du clonage au serveur fonctionnel :

  1. Clonez le depot et copiez .env.example vers .env
  2. Executez docker compose up pour demarrer PostgreSQL avec des donnees d’exemple et le serveur MCP
  3. Copiez le mcp-config.json fourni dans votre configuration MCP de Claude Desktop ou VS Code
  4. Commencez a poser des questions a votre agent : “Quelles tables sont disponibles ?”, “Montre-moi le schema de la table projects”, “Trouve tous les utilisateurs du departement ingenierie”

La base de donnees d’exemple inclut des tables realistes (users, departments, projects) avec suffisamment de donnees pour demontrer la construction de requetes, le filtrage et le masquage de colonnes sensibles.

Adapter a vos propres systemes

Le depot est concu pour etre forke et modifie. Pour le connecter a vos propres outils internes :

  1. Remplacez la connexion a la base de donnees par votre source de donnees
  2. Definissez de nouveaux outils dans src/tools/ en suivant les patterns existants
  3. Mettez a jour les listes blanches de tables et colonnes dans votre configuration
  4. Ajoutez vos propres cles API et portees de permission
  5. Ecrivez des tests pour votre logique d’outil specifique

Les patterns d’authentification, de validation, de gestion des erreurs et de journalisation se transferent quel que soit le backend que vous connectez. C’est le but de l’implementation de reference : elle vous donne un shell de qualite production que vous remplissez avec votre propre logique metier.

Quelle est la suite

Si vous voulez construire et deployer un serveur MCP personnalise etape par etape, suivez notre tutoriel compagnon : Construire, securiser et deployer un serveur MCP personnalise. Il parcourt chaque etape du scaffolding au deploiement conteneurise avec du code fonctionnel a chaque etape.

Si vous n’avez pas encore configure d’agents alimentes par MCP, commencez par les fondamentaux :

La trajectoire plus large pour MCP se dirige vers l’orchestration multi-serveurs, ou une seule session d’agent se connecte simultanement a plusieurs serveurs MCP, chacun fournissant un domaine de capacite different. Des registres de serveurs et des protocoles de decouverte emergent pour rendre cette coordination gerable. Les equipes qui construisent des serveurs MCP bien structures et securises maintenant seront dans la meilleure position a mesure que cet ecosysteme murira.

Le changement fondamental est simple : vos outils internes ne sont plus seulement pour les humains. Ils deviennent des capacites que les agents IA peuvent utiliser, sous votre controle, avec vos frontieres de securite, dans vos workflows. Construire un serveur MCP personnalise est la facon de rendre cela reel.

Obtenez le kit de demarrage MCP Enterprise →