1. Pourquoi a‑t‑on besoin d’un inspecteur MCP
Imaginez que vous déboguez un front‑end, mais qu’on vous interdit d’ouvrir les DevTools. La vie sans inspecteur MCP ressemble à peu près à cela. Le protocole MCP fonctionne « sous le capot » de ChatGPT et de l’Apps SDK; si vous ne regardez que la réponse dans le chat et que vous vous dites: « Pourquoi ne voit‑il pas mon outil ? », vous tirez, en somme, à l’aveugle.
Des inspecteurs comme MCP Inspector (officiel) ou MCP Jam sont des clients MCP pour développeurs. Ils savent :
- se connecter à votre serveur MCP exactement comme le fait ChatGPT;
- exécuter le handshake / lire les capabilities;
- demander la liste des tools/resources/prompts;
- appeler n’importe quel tool à la main avec des arguments arbitraires;
- afficher les messages JSON bruts (requests / replies / errors).
En substance, c’est « un Postman pour MCP, mais plus intelligent ». Contrairement à un client REST classique, l’inspecteur connaît les spécificités de MCP: il comprend tools/list, tools/call, sait afficher les schémas des arguments et prend parfois en charge le flux OAuth pour des serveurs protégés.
Sans inspecteur, le débogage ressemble à ceci: vous lancez ChatGPT, essayez d’appeler une App, voyez « Error talking to app » ou constatez que le tool n’est pas appelé du tout, et vous commencez à deviner: le modèle n’a pas voulu appeler l’outil, votre MCP n’est pas démarré ou c’est une erreur JSON ? Avec un inspecteur, vous pouvez vérifier chaque couche séparément: d’abord le serveur MCP en tête‑à‑tête avec l’inspecteur, puis le duo ChatGPT ↔ MCP.
2. Aperçu rapide des inspecteurs: MCP Inspector, Jam et consorts
En pratique, vous utiliserez le plus souvent deux types d’inspecteurs pour MCP.
Premièrement, l’officiel MCP Inspector du dépôt Model Context Protocol. C’est une application web (en général une SPA React) qui se lance soit localement, soit via npx/Docker et sait se connecter à votre serveur MCP via HTTP/SSE.
Deuxièmement, il existe des inspecteurs du type MCP Jam, qui ajoutent souvent des commodités autour d’OAuth. Ils peuvent lire .well-known/oauth-protected-resource, en extraire authorization_endpoint et token_endpoint, effectuer un flux PKCE et, une fois autorisés, interroger MCP.
MCP Jam a été créé par des développeurs sur la base de MCP Inspector. Si MCP Inspector implémente un ensemble minimal d’outils de débogage, MCP Jam implémente tout ce dont un développeur a besoin dans son travail quotidien avec MCP. Personnellement, je recommande de passer directement à MCP Jam, pour éviter d’avoir à réapprendre plus tard.
Pour notre cours, la différence est la suivante :
- l’Inspector de base vous est toujours utile, même pour le serveur MCP le plus simple et non protégé;
- MCP Jam (ou équivalent) devient utile lorsque vous abordez les modules sur l’authentification et l’autorisation.
Mais l’idée générale est la même: c’est un client MCP ordinaire, simplement capable d’afficher proprement ce que ChatGPT fait « en silence ».
3. Scénario type de travail avec un inspecteur MCP
Passons par un scénario typique: vous avez écrit un nouveau tool dans votre serveur MCP et vous voulez vous assurer qu’il fonctionne réellement.
Dans le cours précédent, vous avez déjà démarré un serveur MCP minimal. Ajoutons maintenant une approche systématique de la vérification: faisons tourner le cycle complet « serveur → inspecteur → logique JSON » étape par étape.
Étape 1 — lancer le serveur MCP
Vous l’avez déjà fait dans le cours précédent: supposons que vous ayez un script npm run mcp-dev:
# exemple de lancement du serveur MCP
npm run mcp-dev
# sous le capot, quelque chose comme : ts-node src/mcp-server.ts
Il est important que le serveur écoute le transport que vous avez choisi: dans ce cours, c’est généralement un endpoint HTTP /mcp sur un port quelconque, par exemple http://localhost:4001/mcp.
Étape 2 — lancer MCP Jam
Deuxième terminal :
# une des façons de lancer MCP Jam
npx @mcpjam/inspector@latest
# si nécessaire, on peut ajouter --port 4002, etc.
Après cela, l’inspecteur s’ouvre dans le navigateur, le plus souvent sur http://localhost:6274 ou un port similaire.
Sur l’écran d’accueil de MCP Jam, on vous demande d’indiquer l’URL du serveur MCP. Vous saisissez :
http://localhost:4001/mcp
ou votre URL tunnellisé, si vous faites déjà passer le tout via ngrok.
Étape 3 — handshake / capabilities
Dès que MCP Jam se connecte, il fait automatiquement la même chose que ChatGPT :
- Envoie une requête d’initialisation (initialize) avec des informations sur le client.
- Reçoit une réponse avec la version du protocole et les capabilities de votre serveur.
- Sur la base des capabilities, détermine si le serveur prend en charge tools, resources, prompts et autres fonctionnalités.
Dans l’UI, cela s’affiche en général comme ceci :
Connected
Protocol: mcp/2025-06-18
Capabilities:
- tools: list, call
- resources: list, read
- prompts: list, get
Si, dès cette étape, l’inspecteur ne parvient pas à se connecter (connection refused, CORS, 500, etc.), vous voyez immédiatement l’erreur et comprenez que le problème n’est pas dans le modèle ni dans ChatGPT, mais dans votre partie serveur ou le réseau.
Étape 4 — discovery: examiner tools/resources/prompts
Après un handshake réussi, l’inspecteur appelle généralement lui‑même des méthodes telles que tools/list, resources/list, prompts/list, pour remplir le panneau latéral. Vous verrez :
- la liste des outils avec descriptions et JSON Schema des arguments d’entrée;
- la liste des ressources, groupées par collections/chemins;
- la liste des prompts avec brèves descriptions.
Si vous venez d’ajouter un nouveau tool, mais qu’il n’apparaît pas dans la liste, c’est qu’il est mal enregistré sur le serveur ou que le serveur n’a pas été redémarré avec le code mis à jour. Il est bien plus simple de le constater ici que de se demander pourquoi ChatGPT « ne veut pas » appeler votre outil.
4. Appeler des tools manuellement via MCP Jam
La fonction la plus utile de MCP Jam est l’appel manuel des outils. C’est votre UI personnelle pour tools/call.
Choisir l’outil et renseigner les arguments
Supposons que, dans le module précédent, vous ayez écrit un tool suggest_gifts:
// quelque part dans src/mcp/tools/suggestGifts.ts
export const suggestGiftsTool = {
name: "suggest_gifts",
description: "Propose des idées de cadeaux selon l’âge, le budget et les centres d’intérêt",
inputSchema: {
type: "object",
properties: {
age: { type: "number" },
budget: { type: "number" },
interests: {
type: "array",
items: { type: "string" }
}
},
required: ["age", "budget"]
},
// handler défini ailleurs
};
Dans MCP Jam, vous cliquez sur suggest_gifts. À droite s’ouvre un formulaire généré à partir de inputSchema. Vous remplissez par exemple :
{
"age": 30,
"budget": 100,
"interests": ["jeux", "livres"]
}
et cliquez sur « Call » ou un bouton équivalent.
L’inspecteur envoie une requête MCP tools/call, et vous voyez immédiatement :
- les données JSON brutes de la requête (ce qui est envoyé au serveur);
- les données JSON brutes de la réponse (result ou error);
- éventuellement un aperçu formaté du résultat.
Lire les journaux JSON dans l’inspecteur
En général, l’inspecteur affiche quelque chose comme :
// Request
{
"id": "1",
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "suggest_gifts",
"arguments": {
"age": 30,
"budget": 100,
"interests": ["jeux", "livres"]
}
}
}
// Reply
{
"id": "1",
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "1) Un jeu de société ... 2) Un bon cadeau pour une librairie ..."
}
]
}
}
Si votre handler lève une exception, vous verrez un error au format JSON‑RPC :
{
"id": "1",
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Internal error",
"data": "TypeError: Cannot read properties of undefined ..."
}
}
Point crucial: c’est ici que vous voyez le niveau protocolaire. Si la réponse n’a pas le format attendu par l’Apps SDK/ChatGPT, vous pourrez le repérer avant même de blâmer des « bugs GPT ».
5. Débogage des ressources et des prompts
Les outils ne sont pas tout ce que sait faire MCP. Vous savez déjà qu’il existe aussi des resources et des prompts.
Via l’inspecteur, vous pouvez :
- ouvrir la liste des ressources (resources/list) et consulter leurs métadonnées;
- lire une ressource spécifique (resources/read) et vérifier que les données renvoyées sont correctes;
- effectuer une recherche dans les ressources (si vous l’avez implémentée);
- consulter les prompts préparés et leur texte.
Par exemple, si vous avez une ressource gift_catalog:
// pseudo-code d’enregistrement de ressource
registerResource({
uri: "resource://giftgenius/catalog",
name: "Catalogue des cadeaux",
mimeType: "application/json",
handler: async () => {
return JSON.stringify(giftCatalogData);
}
});
Dans l’inspecteur, vous verrez cette ressource, vous cliquerez dessus et pourrez voir le JSON immédiatement. Si le JSON est invalide ou si le type MIME est étrange, vous l’attraperez avant que ChatGPT ne commence à trébucher en essayant de le lire ou de l’intégrer dans un widget.
6. Journaux du serveur MCP: quoi, où et comment journaliser
MCP Jam est utile, mais insuffisant: il vous faut les journaux du serveur MCP lui‑même. Sans eux, n’importe quel environnement de production devient une loterie.
Que journaliser
Le minimum utile :
- chaque message MCP entrant (request/notification) avec :
- l’horodatage;
- la méthode (tools/call, tools/list, etc.);
- le nom de l’outil (le cas échéant);
- des arguments tronqués (sans données sensibles);
- chaque réponse sortante :
- le statut (succès / erreur);
- le temps d’exécution;
- une version abrégée du résultat ou au moins son type;
- les erreurs techniques :
- analyse JSON;
- exceptions inattendues dans les handlers.
Il est par ailleurs essentiel de ne pas journaliser intégralement les PII et les secrets: tokens, mots de passe, textes complets de requêtes confidentielles. Les recommandations de journalisation en production mentionnent explicitement la consignation de données avec PII tronquées.
Où écrire les journaux: stdout / stderr
MCP impose une contrainte importante: les messages JSON doivent aller sur le « bon canal », et tous les journaux de débogage sur un autre. Par exemple, si vous utilisez un transport au‑dessus de stdout/stderr, alors :
- les messages JSON‑RPC doivent aller sur stdout;
- tous les console.log, console.error, etc. doivent être dirigés vers stderr.
Si vous mélangez JSON et journaux texte dans un même flux, le client (MCP Jam ou ChatGPT) sera incapable d’analyser les messages, parce qu’au milieu du JSON apparaîtra soudain une chaîne telle que Server started at http://localhost:4001. C’est l’une des erreurs fréquentes dans les serveurs MCP.
Dans le scénario HTTP, le problème est plus simple, mais le principe reste le même: la réponse HTTP doit être un JSON pur, et tous les journaux doivent aller dans la console/un fichier, mais pas dans le corps de la réponse.
Un logger simple pour un serveur MCP en TypeScript
Ajoutons un petit logger à notre serveur MCP hypothétique :
// src/logger.ts
export function logRequest(method: string, details: unknown) {
console.error(
JSON.stringify({
level: "info",
type: "request",
method,
details,
ts: new Date().toISOString(),
})
);
}
export function logError(method: string, error: unknown) {
console.error(
JSON.stringify({
level: "error",
type: "error",
method,
error: String(error),
ts: new Date().toISOString(),
})
);
}
Et dans le handler des tools :
// src/mcp-server.ts (extrait)
server.setRequestHandler("tools/call", async (req) => {
logRequest("tools/call", {
name: req.params?.name,
// ici, mieux vaut ne pas mettre toute la payload, seulement des champs sûrs
});
try {
const result = await handleToolCall(req);
return result;
} catch (e) {
logError("tools/call", e);
throw e;
}
});
Vous verrez ainsi dans la console des journaux JSON structurés, qu’il est ensuite facile de rapprocher entre eux via le ts ou un requestId supplémentaire.
7. Combinaison: MCP Jam + journaux
La stratégie correcte de débogage MCP ressemble presque toujours à ceci :
- Vous reproduisez le problème dans l’inspecteur: vous voyez que tools/list renvoie une liste vide, que tools/call échoue, que la réponse JSON est étrange, etc.
- En même temps, vous regardez les journaux du serveur MCP: ce qu’il écrit au démarrage, quelles erreurs il sort pour chaque message, s’il y a un stack trace.
- Vous rapprochez id, method, ts dans les journaux avec ce que voit l’inspecteur.
Par exemple, vous voyez dans l’inspecteur :
{
"error": {
"code": -32603,
"message": "Internal error"
}
}
Et en parallèle dans les journaux :
{
"level": "error",
"type": "error",
"method": "tools/call",
"error": "TypeError: Cannot read properties of undefined (reading 'age')",
"ts": "2025-11-21T10:15:12.345Z"
}
Voilà, le diagnostic est clair: quelque part dans le handler, vous attendez age, mais le schéma/les arguments sont différents.
8. Mini check‑list « le serveur MCP est‑il prêt pour l’intégration avec une App »
Avant de connecter un serveur MCP à une véritable ChatGPT App, il est utile de parcourir une petite check‑list via l’inspecteur.
Premièrement, le handshake et les capabilities doivent passer sans erreurs. MCP Jam doit indiquer que le serveur prend en charge les entités dont vous avez besoin: au moins tools et, si utilisé, resources / prompts.
Deuxièmement, la liste des tools/resources/prompts dans l’inspecteur doit correspondre à l’ensemble d’outils, de ressources et de prompts que vous pensez avoir implémentés. Les coquilles dans name, enregistrements oubliés, etc., se détectent ici instantanément.
Troisièmement, les appels d’outils avec des arguments valides doivent renvoyer de manière stable un result correct. Il est souhaitable d’essayer plusieurs cas typiques (les requêtes sur lesquelles vous comptez réellement en production).
Quatrièmement, les appels avec des arguments invalides doivent renvoyer des réponses d’error claires au format JSON‑RPC, et non tomber en 500. Par exemple, s’il manque un paramètre obligatoire, il est souhaitable de renvoyer une erreur structurée que ChatGPT pourra ensuite transformer en message compréhensible pour l’utilisateur.
Cinquièmement, les journaux du serveur ne doivent pas inonder la console de gigaoctets de stack traces au moindre souci. Les erreurs doivent être structurées, et les données sensibles soigneusement filtrées.
Si tout cela fonctionne dans l’inspecteur, vous pouvez connecter votre serveur MCP à l’Apps SDK avec bien plus de sérénité et jouer avec les widgets en mode Dev.
9. Bugs typiques du serveur MCP et comment les détecter via l’inspecteur
Passons maintenant au plus intéressant — ce qui casse le plus souvent et comment le voir.
Configuration et connexion
Parfois, on a l’impression que « le serveur ne fonctionne pas », alors que le problème est qu’il n’écoute pas le port ou l’endpoint requis. Dans ce cas, l’inspecteur indiquera honnêtement connection refused ou sera incapable de se connecter. Causes fréquentes: URL incorrecte (par exemple, /mcp au lieu de /api/mcp), port occupé par un autre processus, tunnel non démarré ou CORS qui bloque les requêtes.
JSON non valide / mélange des journaux et du protocole
L’un des cas les plus douloureux — vous imprimez console.log("Server started") sur stdout, alors que des messages JSON‑RPC doivent passer par‑dessus. Le client attend du JSON pur, mais reçoit du texte + JSON, tente d’analyser et échoue avec une erreur de format.
La solution est simple: séparer strictement ce qui va dans le flux protocolaire (stdout ou corps de la réponse HTTP) et ce qui va dans les journaux (stderr ou un fichier dédié).
Discordance entre le schéma et l’implémentation de l’outil
Autre erreur fréquente: dans inputSchema vous déclarez une chose, et dans le code vous en attendez une autre. Par exemple, le schéma dit: age — nombre, interests — tableau de chaînes optionnel, mais le code essaie de faire arguments.interests.toLowerCase(). Le modèle (et l’inspecteur) envoient honnêtement interests avec la valeur null ou n’envoient pas le champ — et tout casse ici.
L’inspecteur permet de voir explicitement quel JSON part réellement dans tools/call, et de le rapprocher de votre code.
Noms de tools/resources incorrects
Si, dans les capabilities / tools/list, vous exportez un tool sous suggest_gifts_v2, alors que dans le manifeste de l’App ou dans le widget vous attendez suggest_gifts, « outil introuvable » vous poursuivra jusqu’à la fin du projet. Dans l’inspecteur, la liste des tools et leurs champs name rendent cela visible immédiatement, sans essayer de deviner ce que pense GPT.
Tools lents ou bloquants
Si l’appel d’un outil dans l’inspecteur prend 30 secondes, puis tombe en time‑out, n’espérez pas que ChatGPT réagira mieux. L’inspecteur MCP aide à comprendre à quelle étape vous ralentissez: appel réseau, base de données, API externe. Dans les journaux, il est utile d’avoir l’heure de début et de fin du traitement de chaque requête pour repérer d’emblée les valeurs aberrantes.
10. Erreurs typiques lors de l’inspection et du débogage MCP
Erreur n°1: essayer de déboguer MCP uniquement via ChatGPT.
Beaucoup de développeurs connectent d’abord MCP à une App, constatent que « quelque chose ne marche pas », et commencent à changer les prompts, la description de l’outil, parfois même la version du modèle. Pendant ce temps, le serveur MCP ne démarre pas ou tools/list est vide. Commencez toujours par l’inspecteur: si tout va mal là‑bas, le modèle n’y est pour rien.
Erreur n°2: mélanger JSON‑RPC et journaux dans un même flux.
Quand le client MCP attend du JSON pur et que vous imprimez des lignes de débogage sur stdout, le résultat est prévisible — l’analyse casse, l’Inspector affiche des erreurs étranges. Les journaux doivent aller séparément (stderr, fichiers, systèmes de log externes), et les messages du protocole — strictement sur leur canal.
Erreur n°3: ne pas regarder les capabilities et la liste des tools.
Souvent, un outil « disparaît » simplement parce que vous avez oublié de l’enregistrer ou d’activer la capability correspondante. Si vous ne regardez pas les capabilities et tools/list dans l’inspecteur, vous pouvez longtemps penser que le modèle est en cause, et non votre code d’enregistrement.
Erreur n°4: ignorer les erreurs de schéma et les divergences JSON.
Quand inputSchema et le JSON effectif divergent, le modèle et l’inspecteur se comportent logiquement de manière étrange. Si vous ne regardez pas les messages JSON bruts dans l’inspecteur et ne validez pas le schéma, ces erreurs sortiront aux moments les plus inattendus.
Erreur n°5: tout journaliser, y compris PII et tokens.
Dans la fièvre du débogage, on peut facilement commencer à imprimer dans les journaux le corps complet des requêtes, y compris d’éventuelles données personnelles ou des secrets. En production, c’est une bombe à retardement: fuites, problèmes de conformité, etc. Journalisez uniquement ce qui est réellement nécessaire au diagnostic, avec des données tronquées/anonymisées.
Erreur n°6: ne pas reproduire le problème avec des cas minimaux.
Parfois, un bug se manifeste dans un dialogue complexe via ChatGPT, et le développeur tente de le déboguer tel quel. Il est bien plus efficace de reproduire le même scénario dans l’inspecteur avec une ou deux requêtes MCP, d’écarter l’influence des prompts, de l’historique de dialogue et de « l’humeur » du modèle.
GO TO FULL VERSION