Nicolas Dabene
Retour au blog
04 December 2025 Nicolas Dabene 6 min

Comment l'IA découvre vos outils MCP?

Le Menu MCP : Comment l’IA Découvre et Utilise vos Outils

API IA SEO développement Tutoriel Intelligence Artificielle automatisation
Comment l'IA découvre vos outils MCP?

Le Menu MCP : Comment l’IA Découvre et Utilise vos Outils

Le Menu MCP : Comment l’IA Découvre et Utilise vos Outils

Vous avez créé votre premier outil readFile dans l’article précédent. Félicitations ! Mais imaginez que vous arriviez dans un restaurant sans menu. Comment sauriez-vous ce qui est disponible ? C’est exactement le problème que résout le système de découverte du MCP. Aujourd’hui, nous allons implémenter le “menu” complet qui permet à une IA de découvrir automatiquement tous vos outils et de les utiliser intelligemment.

Introduction

Dans mes 15 ans de développement d’API, j’ai vu beaucoup de systèmes d’intégration. Mais le MCP a quelque chose d’élégant : l’auto-découverte. Plutôt que de coder en dur chaque intégration, l’IA interroge votre serveur pour découvrir ce qu’il peut faire. C’est comme si votre API pouvait se présenter elle-même.

Cette approche change tout. Au lieu d’avoir des connecteurs spécifiques pour chaque IA, vous créez un standard que toutes les IA compatibles MCP peuvent comprendre. Une fois que vous maîtriserez ce système, vous pourrez exposer des dizaines d’outils sans jamais modifier le code de l’IA.

Rappel : Le Parcours Complet d’une Requête

Avant de coder, visualisons le parcours complet d’une interaction entre une IA et votre serveur MCP. C’est crucial pour comprendre où se situe le système de découverte.

Phase 1 : Découverte (ce que nous allons coder aujourd’hui)

Vous : “Claude, liste les fichiers de mon dossier projets”

Claude : “Je ne connais pas encore les outils de ce serveur. Laisse-moi les découvrir…”

Claude → Serveur : GET /mcp/tools

Serveur → Claude : Voici tous mes outils disponibles avec leurs descriptions

Claude : “Ah ! Il y a un outil listFiles. C’est exactement ce dont j’ai besoin.”

Phase 2 : Validation (gérée par l’application Claude)

Application Claude → Vous : “Autorisez-vous l’utilisation de l’outil listFiles sur le dossier /projets ?”

Vous : “Oui, autorisé”

Phase 3 : Exécution

Claude → Serveur : POST /mcp/execute avec {"tool": "listFiles", "params": {"chemin": "/projets"}}

Serveur → Claude : Résultat de l’exécution

Claude → Vous : “Voici les fichiers dans votre dossier projets : …”

Aujourd’hui, nous nous concentrons sur la Phase 1 : la découverte.

Le Format Standard de Découverte MCP

Le protocole MCP définit un format standard pour décrire vos outils. Voici la structure JSON que l’IA attend :

<span class="p">{</span><span class="w">
  </span><span class="nl">"protocol_version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"server_info"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mon Serveur MCP"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Serveur MCP pour accès aux fichiers locaux"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"tools"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"readFile"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Lit le contenu d'un fichier texte"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"input_schema"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"object"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"chemin_du_fichier"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Chemin vers le fichier à lire"</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"required"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"chemin_du_fichier"</span><span class="p">]</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span>

Cette structure contient trois informations clés :

protocol_version : Quelle version du MCP vous implémentez

server_info : Métadonnées sur votre serveur

tools : La liste complète de vos outils avec leur schéma d’entrée

Le input_schema utilise le standard JSON Schema. C’est comme une documentation auto-générée que l’IA peut lire et comprendre.

Créer le Gestionnaire de Protocole

Commençons par structurer notre implémentation du protocole MCP. Créez le fichier src/mcp/protocol.ts :

<span class="c1">// src/mcp/protocol.ts</span>

<span class="cm">/**
 * Version du protocole MCP implémenté
 */</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">MCP_PROTOCOL_VERSION</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">1.0</span><span class="dl">"</span><span class="p">;</span>

<span class="cm">/**
 * Informations sur le serveur
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">ServerInfo</span> <span class="p">{</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">version</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">description</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">author</span><span class="p">?:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">capabilities</span><span class="p">?:</span> <span class="kr">string</span><span class="p">[];</span>
<span class="p">}</span>

<span class="cm">/**
 * Schéma d'entrée pour un outil (JSON Schema)
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">InputSchema</span> <span class="p">{</span>
  <span class="nl">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">object</span><span class="dl">"</span><span class="p">;</span>
  <span class="nl">properties</span><span class="p">:</span> <span class="p">{</span>
    <span class="p">[</span><span class="na">paramName</span><span class="p">:</span> <span class="kr">string</span><span class="p">]:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
      <span class="nl">description</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
      <span class="nl">enum</span><span class="p">?:</span> <span class="kr">string</span><span class="p">[];</span>
      <span class="nl">default</span><span class="p">?:</span> <span class="kr">any</span><span class="p">;</span>
    <span class="p">};</span>
  <span class="p">};</span>
  <span class="nl">required</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
<span class="p">}</span>

<span class="cm">/**
 * Description complète d'un outil MCP
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">ToolDescription</span> <span class="p">{</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">description</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">input_schema</span><span class="p">:</span> <span class="nx">InputSchema</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/**
 * Réponse de découverte complète
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">DiscoveryResponse</span> <span class="p">{</span>
  <span class="nl">protocol_version</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">server_info</span><span class="p">:</span> <span class="nx">ServerInfo</span><span class="p">;</span>
  <span class="nl">tools</span><span class="p">:</span> <span class="nx">ToolDescription</span><span class="p">[];</span>
<span class="p">}</span>

<span class="cm">/**
 * Informations sur notre serveur
 */</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">SERVER_INFO</span><span class="p">:</span> <span class="nx">ServerInfo</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">MCP File Server</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">version</span><span class="p">:</span> <span class="dl">"</span><span class="s2">1.0.0</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Serveur MCP pour la gestion de fichiers locaux</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">author</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Nicolas Dabène</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">capabilities</span><span class="p">:</span> <span class="p">[</span>
    <span class="dl">"</span><span class="s2">file_reading</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">directory_listing</span><span class="dl">"</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">file_search</span><span class="dl">"</span>
  <span class="p">]</span>
<span class="p">};</span>

Ces types TypeScript nous donnent une structure solide. Chaque outil devra fournir une ToolDescription conforme à ce format.

Convertir nos Outils au Format MCP

Actuellement, nos outils ont une définition simple. Transformons-les au format MCP complet. Modifions src/tools/readFile.ts :

<span class="c1">// src/tools/readFile.ts</span>
<span class="k">import</span> <span class="nx">fs</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">fs/promises</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">path</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolResponse</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../types/mcp</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolDescription</span><span class="p">,</span> <span class="nx">InputSchema</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../mcp/protocol</span><span class="dl">'</span><span class="p">;</span>

<span class="k">export</span> <span class="kr">interface</span> <span class="nx">ReadFileParams</span> <span class="p">{</span>
  <span class="nl">chemin_du_fichier</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">encoding</span><span class="p">?:</span> <span class="dl">'</span><span class="s1">utf-8</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">ascii</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">base64</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nx">readFile</span><span class="p">(</span><span class="nx">params</span><span class="p">:</span> <span class="nx">ReadFileParams</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="nx">ToolResponse</span><span class="o">></span> <span class="p">{</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">params</span><span class="p">.</span><span class="nx">chemin_du_fichier</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Le paramètre 'chemin_du_fichier' est requis</span><span class="dl">"</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">absolutePath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">params</span><span class="p">.</span><span class="nx">chemin_du_fichier</span><span class="p">);</span>
    
    <span class="k">try</span> <span class="p">{</span>
      <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">access</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="s2">`Fichier introuvable : </span><span class="p">${</span><span class="nx">params</span><span class="p">.</span><span class="nx">chemin_du_fichier</span><span class="p">}</span><span class="s2">`</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">stats</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">);</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">stats</span><span class="p">.</span><span class="nx">isFile</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Le chemin spécifié n'est pas un fichier</span><span class="dl">"</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">MAX_FILE_SIZE</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">></span> <span class="nx">MAX_FILE_SIZE</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="s2">`Fichier trop volumineux (max </span><span class="p">${</span><span class="nx">MAX_FILE_SIZE</span> <span class="o">/</span> <span class="mi">1024</span> <span class="o">/</span> <span class="mi">1024</span><span class="p">}</span><span class="s2"> MB)`</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">encoding</span> <span class="o">=</span> <span class="nx">params</span><span class="p">.</span><span class="nx">encoding</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">utf-8</span><span class="dl">'</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">,</span> <span class="nx">encoding</span><span class="p">);</span>
    
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
      <span class="na">content</span><span class="p">:</span> <span class="nx">content</span><span class="p">,</span>
      <span class="na">metadata</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">path</span><span class="p">:</span> <span class="nx">absolutePath</span><span class="p">,</span>
        <span class="na">size</span><span class="p">:</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span><span class="p">,</span>
        <span class="na">encoding</span><span class="p">:</span> <span class="nx">encoding</span><span class="p">,</span>
        <span class="na">lastModified</span><span class="p">:</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">mtime</span>
      <span class="p">}</span>
    <span class="p">};</span>
    
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="na">error</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
      <span class="na">error</span><span class="p">:</span> <span class="s2">`Erreur lors de la lecture : </span><span class="p">${</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2">`</span>
    <span class="p">};</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Schéma d'entrée au format JSON Schema
 */</span>
<span class="kd">const</span> <span class="nx">readFileInputSchema</span><span class="p">:</span> <span class="nx">InputSchema</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">object</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">properties</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">chemin_du_fichier</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Chemin absolu ou relatif vers le fichier à lire</span><span class="dl">"</span>
    <span class="p">},</span>
    <span class="na">encoding</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Encodage du fichier</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">enum</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">utf-8</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">ascii</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">base64</span><span class="dl">"</span><span class="p">],</span>
      <span class="na">default</span><span class="p">:</span> <span class="dl">"</span><span class="s2">utf-8</span><span class="dl">"</span>
    <span class="p">}</span>
  <span class="p">},</span>
  <span class="na">required</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">chemin_du_fichier</span><span class="dl">"</span><span class="p">]</span>
<span class="p">};</span>

<span class="cm">/**
 * Description MCP complète de l'outil
 */</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">readFileDescription</span><span class="p">:</span> <span class="nx">ToolDescription</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">readFile</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Lit le contenu d'un fichier texte depuis le système de fichiers local. Supporte différents encodages (UTF-8, ASCII, Base64).</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">input_schema</span><span class="p">:</span> <span class="nx">readFileInputSchema</span>
<span class="p">};</span>

Vous voyez la différence ? Nous avons maintenant :

Un schéma JSON formel qui décrit exactement les paramètres attendus

Des métadonnées enrichies comme les valeurs par défaut et les énumérations

Une description détaillée qui aide l’IA à comprendre quand utiliser cet outil

Faisons de même pour listFiles. Modifiez src/tools/listFiles.ts :

<span class="c1">// src/tools/listFiles.ts</span>
<span class="k">import</span> <span class="nx">fs</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">fs/promises</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">path</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolResponse</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../types/mcp</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolDescription</span><span class="p">,</span> <span class="nx">InputSchema</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../mcp/protocol</span><span class="dl">'</span><span class="p">;</span>

<span class="k">export</span> <span class="kr">interface</span> <span class="nx">ListFilesParams</span> <span class="p">{</span>
  <span class="nl">chemin_du_dossier</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">include_hidden</span><span class="p">?:</span> <span class="nx">boolean</span><span class="p">;</span>
  <span class="nl">recursive</span><span class="p">?:</span> <span class="nx">boolean</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nx">listFiles</span><span class="p">(</span><span class="nx">params</span><span class="p">:</span> <span class="nx">ListFilesParams</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="nx">ToolResponse</span><span class="o">></span> <span class="p">{</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">params</span><span class="p">.</span><span class="nx">chemin_du_dossier</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Le paramètre 'chemin_du_dossier' est requis</span><span class="dl">"</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">absolutePath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">params</span><span class="p">.</span><span class="nx">chemin_du_dossier</span><span class="p">);</span>
    
    <span class="kd">const</span> <span class="nx">stats</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Le chemin spécifié n'est pas un dossier</span><span class="dl">"</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="c1">// Lire le contenu du dossier</span>
    <span class="kd">let</span> <span class="nx">files</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">);</span>
    
    <span class="c1">// Filtrer les fichiers cachés si nécessaire</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">params</span><span class="p">.</span><span class="nx">include_hidden</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">files</span> <span class="o">=</span> <span class="nx">files</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">file</span> <span class="o">=></span> <span class="o">!</span><span class="nx">file</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">));</span>
    <span class="p">}</span>
    
    <span class="c1">// Obtenir les détails de chaque fichier</span>
    <span class="kd">const</span> <span class="nx">filesWithDetails</span> <span class="o">=</span> <span class="k">await</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span>
      <span class="nx">files</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="k">async</span> <span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">filePath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">absolutePath</span><span class="p">,</span> <span class="nx">file</span><span class="p">);</span>
        <span class="kd">const</span> <span class="nx">fileStats</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span><span class="p">(</span><span class="nx">filePath</span><span class="p">);</span>
        
        <span class="k">return</span> <span class="p">{</span>
          <span class="na">name</span><span class="p">:</span> <span class="nx">file</span><span class="p">,</span>
          <span class="na">type</span><span class="p">:</span> <span class="nx">fileStats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">directory</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">file</span><span class="dl">'</span><span class="p">,</span>
          <span class="na">size</span><span class="p">:</span> <span class="nx">fileStats</span><span class="p">.</span><span class="nx">size</span><span class="p">,</span>
          <span class="na">lastModified</span><span class="p">:</span> <span class="nx">fileStats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">,</span>
          <span class="na">permissions</span><span class="p">:</span> <span class="nx">fileStats</span><span class="p">.</span><span class="nx">mode</span>
        <span class="p">};</span>
      <span class="p">})</span>
    <span class="p">);</span>
    
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
      <span class="na">content</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">filesWithDetails</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
      <span class="na">metadata</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">path</span><span class="p">:</span> <span class="nx">absolutePath</span><span class="p">,</span>
        <span class="na">count</span><span class="p">:</span> <span class="nx">filesWithDetails</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span>
        <span class="na">include_hidden</span><span class="p">:</span> <span class="nx">params</span><span class="p">.</span><span class="nx">include_hidden</span> <span class="o">||</span> <span class="kc">false</span>
      <span class="p">}</span>
    <span class="p">};</span>
    
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="na">error</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
      <span class="na">error</span><span class="p">:</span> <span class="s2">`Erreur lors de la lecture du dossier : </span><span class="p">${</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2">`</span>
    <span class="p">};</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">listFilesInputSchema</span><span class="p">:</span> <span class="nx">InputSchema</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">object</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">properties</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">chemin_du_dossier</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Chemin absolu ou relatif vers le dossier à lister</span><span class="dl">"</span>
    <span class="p">},</span>
    <span class="na">include_hidden</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">boolean</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Inclure les fichiers cachés (commençant par .)</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">default</span><span class="p">:</span> <span class="kc">false</span>
    <span class="p">},</span>
    <span class="na">recursive</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">boolean</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Lister récursivement les sous-dossiers</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">default</span><span class="p">:</span> <span class="kc">false</span>
    <span class="p">}</span>
  <span class="p">},</span>
  <span class="na">required</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">chemin_du_dossier</span><span class="dl">"</span><span class="p">]</span>
<span class="p">};</span>

<span class="k">export</span> <span class="kd">const</span> <span class="nx">listFilesDescription</span><span class="p">:</span> <span class="nx">ToolDescription</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">listFiles</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">description</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Liste les fichiers et dossiers dans un répertoire donné. Peut inclure les fichiers cachés et supporter la récursivité.</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">input_schema</span><span class="p">:</span> <span class="nx">listFilesInputSchema</span>
<span class="p">};</span>

Créer le Registre d’Outils Centralisé

Maintenant, créons un registre qui rassemble tous nos outils. Créez src/mcp/registry.ts :

<span class="c1">// src/mcp/registry.ts</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolDescription</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./protocol</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">ToolResponse</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../types/mcp</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">readFile</span><span class="p">,</span> <span class="nx">readFileDescription</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../tools/readFile</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">listFiles</span><span class="p">,</span> <span class="nx">listFilesDescription</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../tools/listFiles</span><span class="dl">'</span><span class="p">;</span>

<span class="cm">/**
 * Type pour une fonction outil
 */</span>
<span class="kd">type</span> <span class="nx">ToolFunction</span> <span class="o">=</span> <span class="p">(</span><span class="nx">params</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=></span> <span class="nb">Promise</span><span class="o"><</span><span class="nx">ToolResponse</span><span class="o">></span><span class="p">;</span>

<span class="cm">/**
 * Registre central de tous les outils disponibles
 */</span>
<span class="kd">class</span> <span class="nx">ToolRegistry</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">tools</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">ToolFunction</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
  <span class="k">private</span> <span class="nx">descriptions</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">ToolDescription</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>

  <span class="cm">/**
   * Enregistrer un nouvel outil
   */</span>
  <span class="nx">register</span><span class="p">(</span><span class="nx">description</span><span class="p">:</span> <span class="nx">ToolDescription</span><span class="p">,</span> <span class="nx">implementation</span><span class="p">:</span> <span class="nx">ToolFunction</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">description</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="nx">implementation</span><span class="p">);</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">descriptions</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">description</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`✅ Outil enregistré : </span><span class="p">${</span><span class="nx">description</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Obtenir tous les outils disponibles
   */</span>
  <span class="nx">getAllDescriptions</span><span class="p">():</span> <span class="nx">ToolDescription</span><span class="p">[]</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">descriptions</span><span class="p">.</span><span class="nx">values</span><span class="p">());</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Obtenir la description d'un outil spécifique
   */</span>
  <span class="nx">getDescription</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">ToolDescription</span> <span class="o">|</span> <span class="kc">undefined</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">descriptions</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Exécuter un outil
   */</span>
  <span class="k">async</span> <span class="nx">execute</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">params</span><span class="p">:</span> <span class="kr">any</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="nx">ToolResponse</span><span class="o">></span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">tool</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">tool</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="s2">`Outil '</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">' introuvable. Outils disponibles : </span><span class="p">${</span><span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">keys</span><span class="p">()).</span><span class="nx">join</span><span class="p">(</span><span class="dl">'</span><span class="s1">, </span><span class="dl">'</span><span class="p">)}</span><span class="s2">`</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="k">try</span> <span class="p">{</span>
      <span class="k">return</span> <span class="k">await</span> <span class="nx">tool</span><span class="p">(</span><span class="nx">params</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="na">error</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="s2">`Erreur lors de l'exécution de '</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">' : </span><span class="p">${</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2">`</span>
      <span class="p">};</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Vérifier si un outil existe
   */</span>
  <span class="nx">has</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Obtenir le nombre d'outils enregistrés
   */</span>
  <span class="nx">count</span><span class="p">():</span> <span class="kr">number</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Instance singleton du registre</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">toolRegistry</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ToolRegistry</span><span class="p">();</span>

<span class="c1">// Enregistrement de tous nos outils au démarrage</span>
<span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">readFileDescription</span><span class="p">,</span> <span class="nx">readFile</span><span class="p">);</span>
<span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">listFilesDescription</span><span class="p">,</span> <span class="nx">listFiles</span><span class="p">);</span>

Ce registre est le cœur de notre système. C’est lui qui :

Maintient la liste de tous les outils disponibles

Gère l’exécution des outils de manière unifiée

Fournit les descriptions pour la découverte

Gère les erreurs de manière centralisée

Implémenter les Endpoints MCP

Modifions maintenant notre serveur Express pour implémenter les endpoints MCP standards. Remplaçons src/index.ts :

<span class="c1">// src/index.ts</span>
<span class="k">import</span> <span class="nx">express</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">Response</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">MCP_PROTOCOL_VERSION</span><span class="p">,</span> <span class="nx">SERVER_INFO</span><span class="p">,</span> <span class="nx">DiscoveryResponse</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./mcp/protocol</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">toolRegistry</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./mcp/registry</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">PORT</span> <span class="o">=</span> <span class="mi">3000</span><span class="p">;</span>

<span class="c1">// Middleware</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">express</span><span class="p">.</span><span class="nx">json</span><span class="p">());</span>

<span class="c1">// Logging middleware</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">((</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`[</span><span class="p">${</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">()}</span><span class="s2">] </span><span class="p">${</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span><span class="p">}</span><span class="s2"> </span><span class="p">${</span><span class="nx">req</span><span class="p">.</span><span class="nx">path</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="nx">next</span><span class="p">();</span>
<span class="p">});</span>

<span class="c1">// ============================================</span>
<span class="c1">// ROUTES MCP STANDARD</span>
<span class="c1">// ============================================</span>

<span class="cm">/**
 * Endpoint racine - Informations sur le serveur
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span>
    <span class="na">message</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Serveur MCP File Server</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">version</span><span class="p">:</span> <span class="nx">SERVER_INFO</span><span class="p">.</span><span class="nx">version</span><span class="p">,</span>
    <span class="na">protocol_version</span><span class="p">:</span> <span class="nx">MCP_PROTOCOL_VERSION</span><span class="p">,</span>
    <span class="na">status</span><span class="p">:</span> <span class="dl">'</span><span class="s1">operational</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">endpoints</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">discovery</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/mcp/tools</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">execute</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/mcp/execute</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">health</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/health</span><span class="dl">'</span>
    <span class="p">}</span>
  <span class="p">});</span>
<span class="p">});</span>

<span class="cm">/**
 * Endpoint de découverte - Le "menu" complet
 * C'est ici que l'IA découvre tous vos outils
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/mcp/tools</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="kd">const</span> <span class="na">response</span><span class="p">:</span> <span class="nx">DiscoveryResponse</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">protocol_version</span><span class="p">:</span> <span class="nx">MCP_PROTOCOL_VERSION</span><span class="p">,</span>
    <span class="na">server_info</span><span class="p">:</span> <span class="nx">SERVER_INFO</span><span class="p">,</span>
    <span class="na">tools</span><span class="p">:</span> <span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">getAllDescriptions</span><span class="p">()</span>
  <span class="p">};</span>
  
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`📋 Découverte demandée - </span><span class="p">${</span><span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">count</span><span class="p">()}</span><span class="s2"> outils disponibles`</span><span class="p">);</span>
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">response</span><span class="p">);</span>
<span class="p">});</span>

<span class="cm">/**
 * Endpoint d'exécution unifié
 * Format : POST /mcp/execute
 * Body : { "tool": "nomOutil", "params": {...} }
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/mcp/execute</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">tool</span><span class="p">,</span> <span class="nx">params</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">;</span>
  
  <span class="c1">// Validation</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">tool</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">400</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
      <span class="na">error</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Le paramètre 'tool' est requis</span><span class="dl">"</span>
    <span class="p">});</span>
  <span class="p">}</span>

  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`⚙️  Exécution demandée : </span><span class="p">${</span><span class="nx">tool</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  
  <span class="c1">// Exécution via le registre</span>
  <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">execute</span><span class="p">(</span><span class="nx">tool</span><span class="p">,</span> <span class="nx">params</span> <span class="o">||</span> <span class="p">{});</span>
  
  <span class="c1">// Log du résultat</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`✅ Exécution réussie : </span><span class="p">${</span><span class="nx">tool</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`❌ Échec d'exécution : </span><span class="p">${</span><span class="nx">tool</span><span class="p">}</span><span class="s2"> - </span><span class="p">${</span><span class="nx">result</span><span class="p">.</span><span class="nx">error</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="p">}</span>
  
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">});</span>

<span class="cm">/**
 * Endpoint de description d'un outil spécifique
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/mcp/tools/:toolName</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">toolName</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">params</span><span class="p">;</span>
  <span class="kd">const</span> <span class="nx">description</span> <span class="o">=</span> <span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">getDescription</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>
  
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">description</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">404</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
      <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
      <span class="na">error</span><span class="p">:</span> <span class="s2">`Outil '</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">' introuvable`</span>
    <span class="p">});</span>
  <span class="p">}</span>
  
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">description</span><span class="p">);</span>
<span class="p">});</span>

<span class="cm">/**
 * Health check
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/health</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span>
    <span class="na">status</span><span class="p">:</span> <span class="dl">'</span><span class="s1">healthy</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">uptime</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">uptime</span><span class="p">(),</span>
    <span class="na">tools_count</span><span class="p">:</span> <span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">count</span><span class="p">(),</span>
    <span class="na">timestamp</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">()</span>
  <span class="p">});</span>
<span class="p">});</span>

<span class="c1">// ============================================</span>
<span class="c1">// RÉTROCOMPATIBILITÉ (optionnel)</span>
<span class="c1">// ============================================</span>

<span class="cm">/**
 * Ancien endpoint direct (pour tests rapides)
 * @deprecated Utilisez /mcp/execute à la place
 */</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/tools/:toolName</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">toolName</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">params</span><span class="p">;</span>
  <span class="kd">const</span> <span class="nx">params</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">;</span>
  
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`⚠️  Utilisation de l'ancien endpoint /tools/</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2"> (déprécié)`</span><span class="p">);</span>
  
  <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">execute</span><span class="p">(</span><span class="nx">toolName</span><span class="p">,</span> <span class="nx">params</span><span class="p">);</span>
  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">});</span>

<span class="c1">// ============================================</span>
<span class="c1">// DÉMARRAGE DU SERVEUR</span>
<span class="c1">// ============================================</span>

<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="nx">PORT</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">🚀 MCP File Server</span><span class="dl">'</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`📍 URL: http://localhost:</span><span class="p">${</span><span class="nx">PORT</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`📋 Découverte: http://localhost:</span><span class="p">${</span><span class="nx">PORT</span><span class="p">}</span><span class="s2">/mcp/tools`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`⚙️  Exécution: POST http://localhost:</span><span class="p">${</span><span class="nx">PORT</span><span class="p">}</span><span class="s2">/mcp/execute`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`🔧 Outils disponibles: </span><span class="p">${</span><span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">count</span><span class="p">()}</span><span class="s2">`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>

Notre serveur implémente maintenant le protocole MCP complet avec trois endpoints principaux :

GET /mcp/tools : Découverte de tous les outils

POST /mcp/execute : Exécution unifiée de n’importe quel outil

GET /mcp/tools/:toolName : Détails d’un outil spécifique

Tester le Système de Découverte

Relançons notre serveur et testons le système complet :

npm run dev

Vous devriez voir :

═══════════════════════════════════════
🚀 MCP File Server
═══════════════════════════════════════
📍 URL: http://localhost:3000
📋 Découverte: http://localhost:3000/mcp/tools
⚙️  Exécution: POST http://localhost:3000/mcp/execute
🔧 Outils disponibles: 2
═══════════════════════════════════════
✅ Outil enregistré : readFile
✅ Outil enregistré : listFiles

Test 1 : Découverte Complète

curl http://localhost:3000/mcp/tools | json_pp

Réponse (formatée) :

<span class="p">{</span><span class="w">
  </span><span class="nl">"protocol_version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"server_info"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"MCP File Server"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Serveur MCP pour la gestion de fichiers locaux"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"author"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Nicolas Dabène"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"capabilities"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
      </span><span class="s2">"file_reading"</span><span class="p">,</span><span class="w">
      </span><span class="s2">"directory_listing"</span><span class="p">,</span><span class="w">
      </span><span class="s2">"file_search"</span><span class="w">
    </span><span class="p">]</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"tools"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"readFile"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Lit le contenu d'un fichier texte depuis le système de fichiers local. Supporte différents encodages (UTF-8, ASCII, Base64)."</span><span class="p">,</span><span class="w">
      </span><span class="nl">"input_schema"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"object"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"chemin_du_fichier"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Chemin absolu ou relatif vers le fichier à lire"</span><span class="w">
          </span><span class="p">},</span><span class="w">
          </span><span class="nl">"encoding"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Encodage du fichier"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"enum"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"utf-8"</span><span class="p">,</span><span class="w"> </span><span class="s2">"ascii"</span><span class="p">,</span><span class="w"> </span><span class="s2">"base64"</span><span class="p">],</span><span class="w">
            </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"utf-8"</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"required"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"chemin_du_fichier"</span><span class="p">]</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"listFiles"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Liste les fichiers et dossiers dans un répertoire donné. Peut inclure les fichiers cachés et supporter la récursivité."</span><span class="p">,</span><span class="w">
      </span><span class="nl">"input_schema"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"object"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"chemin_du_dossier"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Chemin absolu ou relatif vers le dossier à lister"</span><span class="w">
          </span><span class="p">},</span><span class="w">
          </span><span class="nl">"include_hidden"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"boolean"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Inclure les fichiers cachés (commençant par .)"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
          </span><span class="p">},</span><span class="w">
          </span><span class="nl">"recursive"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"boolean"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Lister récursivement les sous-dossiers"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"required"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"chemin_du_dossier"</span><span class="p">]</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span>

Parfait ! L’IA peut maintenant découvrir tous vos outils avec leurs descriptions complètes.

Test 2 : Exécution via l’Endpoint Unifié

curl <span class="nt">-X</span> POST http://localhost:3000/mcp/execute <span class="se">\</span>
  <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
  <span class="nt">-d</span> <span class="s1">'{
    "tool": "readFile",
    "params": {
      "chemin_du_fichier": "test.txt"
    }
  }'</span>

Réponse :

<span class="p">{</span><span class="w">
  </span><span class="nl">"success"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Ceci est un fichier de test pour le MCP !</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/chemin/absolu/vers/test.txt"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"size"</span><span class="p">:</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w">
    </span><span class="nl">"encoding"</span><span class="p">:</span><span class="w"> </span><span class="s2">"utf-8"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"lastModified"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-11-12T10:30:00.000Z"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span>

Test 3 : Détails d’un Outil Spécifique

curl http://localhost:3000/mcp/tools/listFiles | json_pp

Cela retourne uniquement les informations sur listFiles, utile pour une IA qui veut en savoir plus sur un outil spécifique.

Créer un Client de Test Simple

Pour mieux visualiser le fonctionnement, créons un petit script client. Créez src/test-client.ts :

<span class="c1">// src/test-client.ts</span>

<span class="cm">/**
 * Client de test simple pour démontrer l'interaction MCP
 */</span>

<span class="kd">const</span> <span class="nx">SERVER_URL</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://localhost:3000</span><span class="dl">'</span><span class="p">;</span>

<span class="kr">interface</span> <span class="nx">ToolDescription</span> <span class="p">{</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">description</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">input_schema</span><span class="p">:</span> <span class="kr">any</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">interface</span> <span class="nx">DiscoveryResponse</span> <span class="p">{</span>
  <span class="nl">protocol_version</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">server_info</span><span class="p">:</span> <span class="kr">any</span><span class="p">;</span>
  <span class="nl">tools</span><span class="p">:</span> <span class="nx">ToolDescription</span><span class="p">[];</span>
<span class="p">}</span>

<span class="cm">/**
 * Étape 1 : Découvrir les outils disponibles
 */</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">discoverTools</span><span class="p">():</span> <span class="nb">Promise</span><span class="o"><</span><span class="nx">ToolDescription</span><span class="p">[]</span><span class="o">></span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="se">\n</span><span class="s1">📋 Étape 1 : Découverte des outils...</span><span class="se">\n</span><span class="dl">'</span><span class="p">);</span>
  
  <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">SERVER_URL</span><span class="p">}</span><span class="s2">/mcp/tools`</span><span class="p">);</span>
  <span class="kd">const</span> <span class="na">data</span><span class="p">:</span> <span class="nx">DiscoveryResponse</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>
  
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Serveur : </span><span class="p">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">server_info</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> v</span><span class="p">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">server_info</span><span class="p">.</span><span class="nx">version</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Protocole MCP : </span><span class="p">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">protocol_version</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`\nOutils disponibles : </span><span class="p">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">length</span><span class="p">}</span><span class="s2">\n`</span><span class="p">);</span>
  
  <span class="nx">data</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">tool</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">}</span><span class="s2">. </span><span class="p">${</span><span class="nx">tool</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`   </span><span class="p">${</span><span class="nx">tool</span><span class="p">.</span><span class="nx">description</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`   Paramètres requis : </span><span class="p">${</span><span class="nx">tool</span><span class="p">.</span><span class="nx">input_schema</span><span class="p">.</span><span class="nx">required</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">'</span><span class="s1">, </span><span class="dl">'</span><span class="p">)}</span><span class="s2">`</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">''</span><span class="p">);</span>
  <span class="p">});</span>
  
  <span class="k">return</span> <span class="nx">data</span><span class="p">.</span><span class="nx">tools</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/**
 * Étape 2 : Utiliser un outil
 */</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">useTool</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">params</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`\n⚙️  Étape 2 : Utilisation de l'outil "</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">"...\n`</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Paramètres : </span><span class="p">${</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">params</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span><span class="p">)}</span><span class="s2">`</span><span class="p">);</span>
  
  <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">SERVER_URL</span><span class="p">}</span><span class="s2">/mcp/execute`</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">method</span><span class="p">:</span> <span class="dl">'</span><span class="s1">POST</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
      <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span>
    <span class="p">},</span>
    <span class="na">body</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span>
      <span class="na">tool</span><span class="p">:</span> <span class="nx">toolName</span><span class="p">,</span>
      <span class="na">params</span><span class="p">:</span> <span class="nx">params</span>
    <span class="p">})</span>
  <span class="p">});</span>
  
  <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>
  
  <span class="k">if</span> <span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="se">\n</span><span class="s1">✅ Succès !</span><span class="dl">'</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Résultat : </span><span class="p">${</span><span class="nx">result</span><span class="p">.</span><span class="nx">content</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">)}</span><span class="s2">...`</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">metadata</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Métadonnées : </span><span class="p">${</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">metadata</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span><span class="p">)}</span><span class="s2">`</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="se">\n</span><span class="s1">❌ Échec !</span><span class="dl">'</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Erreur : </span><span class="p">${</span><span class="nx">result</span><span class="p">.</span><span class="nx">error</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Simulation complète d'interaction IA
 */</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">simulateAIInteraction</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">🤖 Simulation d</span><span class="se">\'</span><span class="s1">interaction IA avec MCP</span><span class="dl">'</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
  
  <span class="k">try</span> <span class="p">{</span>
    <span class="c1">// Découverte</span>
    <span class="kd">const</span> <span class="nx">tools</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">discoverTools</span><span class="p">();</span>
    
    <span class="c1">// L'IA "choisit" un outil basé sur une tâche</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="se">\n</span><span class="s1">💭 L</span><span class="se">\'</span><span class="s1">IA analyse la demande : "Liste les fichiers du dossier courant"</span><span class="dl">'</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">💭 L</span><span class="se">\'</span><span class="s1">IA identifie que l</span><span class="se">\'</span><span class="s1">outil "listFiles" correspond à la demande</span><span class="se">\n</span><span class="dl">'</span><span class="p">);</span>
    
    <span class="c1">// Exécution</span>
    <span class="k">await</span> <span class="nx">useTool</span><span class="p">(</span><span class="dl">'</span><span class="s1">listFiles</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
      <span class="na">chemin_du_dossier</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">include_hidden</span><span class="p">:</span> <span class="kc">false</span>
    <span class="p">});</span>
    
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="se">\n</span><span class="s1">═══════════════════════════════════════</span><span class="dl">'</span><span class="p">);</span>
    
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Erreur:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Exécution</span>
<span class="nx">simulateAIInteraction</span><span class="p">();</span>

Ajoutez un script dans votre package.json :

<span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nl">"dev"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ts-node src/index.ts"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"test-client"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ts-node src/test-client.ts"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span>

Exécutez le client de test :

npm run test-client

Vous verrez une simulation complète de l’interaction IA :

═══════════════════════════════════════
🤖 Simulation d'interaction IA avec MCP
═══════════════════════════════════════

📋 Étape 1 : Découverte des outils...

Serveur : MCP File Server v1.0.0
Protocole MCP : 1.0

Outils disponibles : 2

1. readFile
   Lit le contenu d'un fichier texte depuis le système de fichiers local. Supporte différents encodages (UTF-8, ASCII, Base64).
   Paramètres requis : chemin_du_fichier

2. listFiles
   Liste les fichiers et dossiers dans un répertoire donné. Peut inclure les fichiers cachés et supporter la récursivité.
   Paramètres requis : chemin_du_dossier

💭 L'IA analyse la demande : "Liste les fichiers du dossier courant"
💭 L'IA identifie que l'outil "listFiles" correspond à la demande

⚙️  Étape 2 : Utilisation de l'outil "listFiles"...

Paramètres : {
  "chemin_du_dossier": ".",
  "include_hidden": false
}

✅ Succès !
Résultat : [
  {
    "name": "node_modules",
    "type": "directory",
    "size": 4096,
    "lastModified": "2025-12-03T08:15:23.000Z",
    "permissions": 16877
  },
  ...
]
Métadonnées : {
  "path": "/chemin/absolu/vers/projet",
  "count": 8,
  "include_hidden": false
}

═══════════════════════════════════════

Parfait ! Vous venez de simuler exactement comment une IA utilise votre serveur MCP.

Comprendre l’Impact Architecturale

Ce système de découverte change fondamentalement l’architecture des intégrations IA :

Avant MCP : Intégrations Rigides

Chaque IA devait être programmée spécifiquement pour chaque outil :

<span class="c1">// Code dans l'IA pour intégrer un outil spécifique</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">userWantsToReadFile</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">callReadFileAPI</span><span class="p">(</span><span class="nx">userParams</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">userWantsToListFiles</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">callListFilesAPI</span><span class="p">(</span><span class="nx">userParams</span><span class="p">);</span>
<span class="p">}</span>

Après MCP : Auto-Découverte

L’IA découvre dynamiquement les capacités :

<span class="c1">// L'IA peut maintenant découvrir et utiliser n'importe quel outil</span>
<span class="kd">const</span> <span class="nx">tools</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">discoverTools</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">tool</span> <span class="o">=</span> <span class="nx">tools</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">t</span> <span class="o">=></span> <span class="nx">matchesUserRequest</span><span class="p">(</span><span class="nx">t</span><span class="p">));</span>
<span class="k">await</span> <span class="nx">executeTool</span><span class="p">(</span><span class="nx">tool</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="nx">userParams</span><span class="p">);</span>

Avantages pour les Développeurs

Évolutivité

Vous pouvez ajouter de nouveaux outils sans toucher au code de l’IA. Il suffit de les enregistrer dans le registre.

Standardisation

Toutes les IA compatibles MCP peuvent utiliser vos outils automatiquement.

Maintenance Simplifiée

Un seul endroit pour gérer tous vos outils : le registre centralisé.

Sécurité et Bonnes Pratiques

Validation des Requêtes

Toujours valider que l’outil demandé existe avant de l’exécuter :

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">toolRegistry</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">toolName</span><span class="p">))</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">404</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
    <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
    <span class="na">error</span><span class="p">:</span> <span class="s2">`Outil '</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">' non trouvé`</span>
  <span class="p">});</span>
<span class="p">}</span>

Logging et Monitoring

Loggez toutes les interactions pour le debugging et la sécurité :

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`[</span><span class="p">${</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">()}</span><span class="s2">] </span><span class="p">${</span><span class="nx">req</span><span class="p">.</span><span class="nx">ip</span><span class="p">}</span><span class="s2"> - </span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2"> - </span><span class="p">${</span><span class="nx">result</span><span class="p">.</span><span class="nx">success</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">SUCCESS</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">ERROR</span><span class="dl">'</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>

Rate Limiting

Implémentez des limites de fréquence pour éviter les abus :

<span class="c1">// Exemple simple de rate limiting</span>
<span class="kd">const</span> <span class="nx">requests</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="kr">number</span><span class="p">[]</span><span class="o">></span><span class="p">();</span>

<span class="kd">function</span> <span class="nx">isRateLimited</span><span class="p">(</span><span class="nx">ip</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
  <span class="kd">const</span> <span class="nb">window</span> <span class="o">=</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span> <span class="c1">// 1 minute</span>
  <span class="kd">const</span> <span class="nx">maxRequests</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="c1">// 100 requêtes par minute</span>

  <span class="kd">const</span> <span class="nx">userRequests</span> <span class="o">=</span> <span class="nx">requests</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">ip</span><span class="p">)</span> <span class="o">||</span> <span class="p">[];</span>
  <span class="kd">const</span> <span class="nx">recentRequests</span> <span class="o">=</span> <span class="nx">userRequests</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">time</span> <span class="o">=></span> <span class="nx">now</span> <span class="o">-</span> <span class="nx">time</span> <span class="o"><</span> <span class="nb">window</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">recentRequests</span><span class="p">.</span><span class="nx">length</span> <span class="o">>=</span> <span class="nx">maxRequests</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nx">recentRequests</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">now</span><span class="p">);</span>
  <span class="nx">requests</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">ip</span><span class="p">,</span> <span class="nx">recentRequests</span><span class="p">);</span>
  <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>

Conclusion : Un Nouveau Paradigme

Le système de découverte MCP représente un changement de paradigme dans l’intégration des IA. Au lieu de créer des connecteurs spécifiques pour chaque cas d’usage, vous créez des “blocs de construction” standardisés que toutes les IA compatibles peuvent assembler dynamiquement.

Dans cet article, nous avons vu comment :

  • Implémenter le protocole MCP complet avec découverte et exécution
  • Créer un registre centralisé d’outils
  • Structurer les outils avec des schémas JSON Schema
  • Tester le système avec des clients HTTP
  • Simuler l’interaction complète IA-serveur

La prochaine étape ? Connecter votre serveur MCP à une vraie IA comme Claude Desktop. Vous verrez alors la magie opérer : votre IA pourra réellement lire vos fichiers, lister vos dossiers, et utiliser tous vos outils personnalisés.

Le MCP n’est pas qu’un protocole technique : c’est une nouvelle façon de penser l’intégration homme-IA. Vos outils deviennent des extensions naturelles des capacités de l’IA, sans friction technique.


Article publié le 12 novembre 2025 par Nicolas Dabène - Expert PHP & PrestaShop avec 15+ ans d’expérience dans l’architecture logicielle et l’intégration d’IA

À lire aussi :

LinkedIn

Suivez mes analyses IA et e-commerce

Je partage des retours terrain sur les agents IA, PrestaShop, MCP et l automatisation pour les equipes e-commerce.

Me suivre sur LinkedIn