DonnIA
Toutes les ressources
GuideClaude Skills & MCP18 min

Brancher Claude à tes outils avec le MCP

Exposer un premier outil en une trentaine de lignes, le tester, puis le brancher à Claude Code.


Un modèle de langage, seul, ne sait rien faire d'autre que produire du texte. Le MCP (Model Context Protocol) est la prise standard qui lui donne des mains : lire une base, appeler une API interne, écrire un fichier. Une fois le serveur branché, Claude voit tes outils comme s'ils faisaient partie de lui.

Ce guide monte un serveur minimal, le teste, puis le branche à Claude Code. Compte une vingtaine de minutes.

Ce que fait un serveur MCP

Un serveur MCP expose trois choses :

  • des outils, que le modèle peut appeler (chercher_client, créer_ticket) ;
  • des ressources, qu'il peut lire (un fichier, une table) ;
  • des prompts, des modèles de conversation prêts à l'emploi.

En pratique, 90 % des serveurs n'exposent que des outils. C'est ce qu'on fait ici.

Le MCP ne remplace pas une API

Le serveur MCP est une couche de traduction devant ce que tu as déjà. Si ton outil est une API REST, le serveur se contente de l'appeler et de mettre en forme la réponse pour le modèle.

Avant de commencer

  • Node.js 20 ou plus récent (node --version)
  • Claude Code installé et fonctionnel
  • Un dossier vide pour le projet

1Installer le SDK

mkdir mcp-meteo && cd mcp-meteo
npm init -y
npm install @modelcontextprotocol/server zod

Le paquet s'appelle @modelcontextprotocol/server depuis la version 2. Si tu tombes sur des exemples qui importent @modelcontextprotocol/sdk, ils datent de la v1 et utilisent server.tool(...) au lieu de server.registerTool(...).

2Écrire le serveur

Crée serveur.js. Un seul outil, qui renvoie la température d'une ville :

import { McpServer } from "@modelcontextprotocol/server";
import { serveStdio } from "@modelcontextprotocol/server/stdio";
import * as z from "zod/v4";

serveStdio(() => {
  const server = new McpServer({ name: "meteo", version: "1.0.0" });

  server.registerTool(
    "temperature_ville",
    {
      description:
        "Renvoie la temperature actuelle d'une ville, en degres Celsius.",
      inputSchema: z.object({
        ville: z.string().describe("Nom de la ville, par exemple Lyon"),
      }),
    },
    async ({ ville }) => {
      const geo = await fetch(
        `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(ville)}&count=1`
      ).then((r) => r.json());

      const lieu = geo.results?.[0];
      if (!lieu) {
        return {
          content: [{ type: "text", text: `Ville introuvable : ${ville}` }],
          isError: true,
        };
      }

      const meteo = await fetch(
        `https://api.open-meteo.com/v1/forecast?latitude=${lieu.latitude}&longitude=${lieu.longitude}&current=temperature_2m`
      ).then((r) => r.json());

      return {
        content: [
          {
            type: "text",
            text: `${lieu.name} : ${meteo.current.temperature_2m} degres`,
          },
        ],
      };
    }
  );

  return server;
});

Ajoute "type": "module" dans ton package.json, sinon Node refuse les import.

La description est la partie qui compte

Le modèle choisit un outil sur la seule foi de sa description. « Renvoie la température actuelle d'une ville » se déclenche au bon moment. « Outil météo » ne se déclenchera jamais, ou n'importe quand.

3Tester sans Claude

Un serveur stdio parle du JSON-RPC sur l'entrée standard. L'inspecteur officiel évite d'avoir à le faire à la main :

npx @modelcontextprotocol/inspector node serveur.js

Une interface s'ouvre dans le navigateur. Onglet Tools, tu vois temperature_ville, tu l'appelles avec {"ville": "Lyon"} et tu lis la réponse.

Tant que ça ne marche pas ici, inutile de brancher Claude : le problème est dans ton serveur, pas dans la connexion.

4Brancher à Claude Code

claude mcp add meteo -- node /chemin/absolu/vers/serveur.js

Relance Claude Code, puis vérifie :

claude mcp list

Ton serveur doit apparaître avec le statut connecté. Demande ensuite quelque chose qui a besoin de l'outil :

Quelle temperature fait-il a Lyon en ce moment ?

Claude appelle temperature_ville, te montre l'appel, et répond avec la vraie valeur.

Les erreurs qui coûtent une heure

SymptômeCause presque toujours
Le serveur n'apparaît pas dans claude mcp listChemin relatif au lieu d'absolu dans claude mcp add
« Unexpected token » au démarrage"type": "module" manquant dans package.json
L'outil existe mais Claude ne l'appelle jamaisDescription trop vague, ou qui ne dit pas quand s'en servir
Le serveur se coupe tout seulUn console.log dans le code : stdout est réservé au protocole, écris sur console.error

Le réflexe de débogage

Un serveur stdio ne doit rien écrire sur la sortie standard en dehors du protocole. Tous tes logs passent par console.error, qui part sur stderr et n'interfère pas.

Aller plus loin

Une fois ce squelette en place, la suite est mécanique : chaque nouvel outil est un registerTool de plus. Les questions qui deviennent intéressantes sont ailleurs.

  • Découper. Un serveur avec quarante outils sature le contexte du modèle. Mieux vaut plusieurs serveurs thématiques, activés selon le projet.
  • Renvoyer peu. Un outil qui renvoie 3 000 lignes de JSON coûte cher et noie la réponse. Filtre côté serveur, pas côté modèle.
  • Échouer clairement. isError: true avec un message explicite permet au modèle de se corriger. Une exception silencieuse le laisse deviner.

Tu as d’autres ressources comme ça ?

Ce que tu viens de lire est entièrement gratuit. Une nouvelle ressource part chaque semaine dans la newsletter : guides, modèles à copier et liens triés, sans compte à créer.

Cette page est en accès libre, n’hésite pas à la partager.