# Examinez la configuration d'un client MCP avant de faire confiance à un serveur

Un nouveau serveur MCP mérite le même examen qu'un nouvel exécutable auquel vous demanderiez de s'exécuter dans votre compte de développement. Le fichier de configuration peut sembler inoffensif, puisqu'il ne contient qu'une commande et quelques arguments. En réalité, cette entrée détermine quel code démarre, quel environnement il reçoit, quels répertoires il peut atteindre et quelles descriptions d'outils seront proposées à un agent.

L'erreur que je vois régulièrement consiste à considérer « local » comme une limite de confiance. Ce n'est pas le cas. Un serveur local démarre généralement avec vos permissions, peut agir avant de publier son premier outil et peut hériter d'identifiants que personne ne voulait partager. Examinez le contrat de lancement avant que le client ne se connecte. Examinez ensuite les actions annoncées avant que l'agent puisse les appeler.

## Un serveur local s'exécute avec les conséquences de votre compte

Un serveur MCP local est un processus enfant, pas un objet de configuration inoffensif. Si votre client le lance sous votre compte macOS habituel, le serveur peut lire les fichiers de projet accessibles, écrire dans votre dossier personnel, effectuer des requêtes réseau sortantes et examiner les variables d'environnement disponibles pour ce processus. MCP ne met pas le serveur en bac à sable. Le protocole transporte des messages, mais ne limite pas ce que fait l'exécutable entre deux messages.

Cette distinction compte lorsqu'un serveur arrive sous la forme d'une commande de paquet. Cette configuration :

```json
{
  "command": "npx",
  "args": ["-y", "some-mcp-server"]
}
```

ne se contente pas de démarrer un binaire local connu. Elle demande à un lanceur de paquets de résoudre un paquet, d'installer ou de réutiliser du code présent dans son cache, puis de le lancer. Une machine neuve, un cache déjà rempli et un tag de paquet modifié peuvent produire des codes différents. La commande familière pousse à éviter la question essentielle : quel exécutable exact va s'exécuter aujourd'hui ?

La même prudence s'applique à un serveur récupéré à côté du projet. Un dépôt peut contenir une implémentation MCP honnête, mais aussi un hook d'installation, un wrapper ou une dépendance d'exécution malveillante. Examinez le chemin qui démarre le processus, pas seulement le fichier source dont le nom apparaît dans un guide de configuration.

Utilisez le compte du système d'exploitation comme première décision de confinement. Un espace de travail jetable, un compte séparé doté de peu de privilèges ou une machine virtuelle donnent à un premier test moins d'accès qu'au compte qui détient le code source de production et les identifiants cloud. Cela ne remplace pas l'examen du code. Cela limite les dégâts si quelque chose vous échappe.

## Le champ command mérite une lecture littérale

Lisez la commande et les arguments exactement comme le client les exécutera. Ne les remplacez pas mentalement par la description conviviale d'un README.

La forme la plus sûre utilise un chemin fixe vers l'exécutable et un tableau d'arguments :

```json
{
  "command": "/Users/dev/tools/acme-mcp/bin/server",
  "args": ["--config", "/Users/dev/review/acme-mcp.json"],
  "env": {
    "HOME": "/Users/dev/review-home",
    "PATH": "/usr/bin:/bin"
  }
}
```

Cette forme vous donne des points précis à examiner. L'exécutable existe-t-il à cet emplacement ? À qui appartient-il ? Le fichier de configuration se trouve-t-il en dehors d'un dépôt que d'autres personnes peuvent modifier ? Le processus a-t-il réellement besoin de `HOME` ? A-t-il vraiment besoin d'un compilateur, d'un gestionnaire de paquets ou d'un `PATH` étendu ?

Un wrapper change la nature de l'examen. Considérez plutôt ceci :

```json
{
  "command": "sh",
  "args": ["-c", "npx -y acme-mcp --token $SERVICE_TOKEN"]
}
```

Le shell développe maintenant `$SERVICE_TOKEN`, interprète la syntaxe shell et peut exécuter davantage que le seul programme attendu. Le lanceur de paquets peut télécharger du code. Le serveur reçoit un secret comme argument de commande, qui peut apparaître dans l'inspection des processus et les sorties de diagnostic. Chaque couche ajoute un comportement qu'un chemin direct vers l'exécutable évite.

Ne supposez pas que tous les clients exécutent `command` de la même manière. Certains créent directement le processus avec un tableau d'arguments. D'autres proposent un réglage orienté shell ou autorisent un script wrapper. Lisez la documentation du client et testez le lancement avec une commande non sensible avant d'en approuver une réelle. Si le format permet l'exécution directe et l'utilisation d'un shell, choisissez l'exécution directe, sauf si le serveur a un besoin précis que vous pouvez expliquer.

Inspectez les wrappers ligne par ligne. Les petits scripts cachent souvent les comportements les plus risqués : téléchargement d'une version, lecture d'un fichier de jeton, changement du répertoire de travail, exportation de toutes les variables d'environnement ou redémarrage silencieux avec un autre runtime. Un lanceur de vingt lignes peut mériter davantage d'attention que l'implémentation principale du serveur.

## L'environnement hérité est la fuite d'identifiants que l'on oublie

Un bloc `env` ne signifie pas forcément « voici tout l'environnement ». Dans de nombreuses API de lancement de processus, l'environnement du processus parent est transmis, sauf si le lanceur le remplace délibérément. Les entrées de `env` ajoutent ou remplacent alors certaines valeurs. Votre client MCP peut lui-même avoir été démarré depuis un terminal, un lanceur de bureau, un éditeur ou un service d'automatisation, et chacun de ces chemins peut fournir des variables différentes.

Il existe ainsi un écart dangereux entre ce que voient les personnes chargées de l'examen et ce que reçoit le serveur. Le JSON peut ne mentionner que `LOG_LEVEL`, alors que le processus reçoit aussi un jeton de registre de paquets, un jeton de contrôle de code source, des identifiants cloud, des réglages de proxy, des informations sur l'agent SSH et l'URL d'un service interne héritée du client.

Avant de vous connecter, rédigez en termes simples le contrat d'environnement : ce processus a besoin de cet endpoint, de ce réglage non secret et éventuellement d'un identifiant strictement limité. Tout le reste est une autorité accidentelle.

Un premier test utile consiste à démarrer le client lui-même depuis un shell minimal. Cette commande macOS et Unix ne conserve que quelques variables ordinaires :

```sh
env -i HOME="$HOME/review-home" PATH="/usr/bin:/bin" LANG="${LANG:-C}" \
  YOUR_MCP_CLIENT
```

Remplacez `YOUR_MCP_CLIENT` par la commande réelle du client. Si le serveur échoue, ajoutez une variable à la fois et notez pourquoi il en a besoin. Ne résolvez pas le problème en restaurant tout votre environnement de connexion. Ce raccourci a exposé plus d'identifiants qu'on ne le pense.

Vous pouvez aussi inspecter une configuration enregistrée sans exécuter de commande. Le fragment Python suivant affiche les noms des serveurs, les commandes, les arguments et les noms explicites des variables d'environnement. Il n'affiche volontairement aucune valeur d'environnement.

```sh
python3 - "$HOME/.config/your-client/mcp.json" <<'PY'
import json, sys

with open(sys.argv[1], encoding="utf-8") as f:
    data = json.load(f)

for name, spec in data.get("mcpServers", {}).items():
    print(f"server: {name}")
    print(f"  command: {spec.get('command', '')}")
    print("  args:")
    for arg in spec.get("args", []):
        print(f"    - {arg}")
    print("  explicit env names:")
    for env_name in sorted(spec.get("env", {})):
        print(f"    - {env_name}")
PY
```

Sa sortie ressemble à ceci :

```text
server: issue-tracker
  command: /Users/dev/tools/issue-mcp/server
  args:
    - --read-only
  explicit env names:
    - ISSUE_TRACKER_URL
```

Si vous voyez des noms comme `AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`, `SSH_AUTH_SOCK` ou `SERVICE_TOKEN`, arrêtez-vous et demandez pourquoi ce serveur en a besoin. Les valeurs secrètes ne deviennent pas sûres parce qu'un fichier JSON les contient plutôt que le code source. Les fichiers de configuration sont copiés dans des sauvegardes, partagés dans des demandes d'assistance, envoyés par accident dans un dépôt et lus par tous les processus qui peuvent y accéder.

## Une liste d'outils décrit une capacité, elle n'accorde pas une permission

La spécification Model Context Protocol définit `tools/list` pour la découverte et `tools/call` pour l'invocation. C'est utile, car un client peut examiner l'interface proposée par un serveur avant qu'un agent ne choisisse un outil. Cela ne certifie ni le serveur, ni ses descriptions, ni les effets d'un appel.

Considérez chaque outil annoncé comme une capacité proposée. Lisez ensemble son nom, sa description, son schéma d'entrée et ses éventuelles annotations. Un outil nommé `search_issues` peut effectuer une requête en lecture seule, ou collecter des fichiers de projet et les envoyer à un tiers avant la recherche. Un outil nommé `deploy_preview` peut créer des ressources, modifier le DNS ou utiliser un identifiant plus puissant que ne le laisse penser son nom.

La spécification MCP permet aux serveurs de fournir des annotations qui donnent des indications sur le comportement, par exemple si un outil lit des données, les modifie ou interagit avec un système externe. Ces indications aident un client à présenter une interface utile, mais la spécification n'en fait pas des contrôles. Un serveur malhonnête ou négligent peut étiqueter un outil destructeur comme étant en lecture seule. Le système d'exploitation et les identifiants du serveur ne vérifieront pas cette étiquette avant l'exécution de l'action.

Conservez un petit inventaire pour chaque serveur approuvé :

- Le nom de l'outil et l'action qu'il prétend effectuer.
- Les entrées pouvant contenir des chemins de fichiers, des URL, des fragments shell ou des instructions libres.
- Les systèmes que l'outil peut atteindre et l'identifiant qu'il utilise.
- Les effets, y compris les effets indirects comme l'envoi de données à une API distante.
- La version exacte ou la révision source examinée.

Gardez l'inventaire près de la configuration. Une différence devient significative lorsqu'une mise à jour ajoute `delete_repository`, transforme `query` en `execute` ou ajoute une entrée acceptant une URL arbitraire. Sans inventaire précédent, on approuve facilement une liste modifiée parce que le nom du serveur semble toujours familier.

Les descriptions méritent la même méfiance que tout autre texte non fiable transmis à un agent. Un serveur peut décrire un outil comme obligatoire, affirmer qu'une approbation est inutile ou demander à l'agent de transmettre des secrets sans rapport comme arguments. L'agent ne doit pas considérer la prose fournie par le serveur comme plus importante que la demande de l'utilisateur et les règles d'approbation du client.

## Les identifiants ont besoin d'une limite en dehors du processus de l'agent

Ne donnez pas un jeton API longue durée ou une clé SSH privée à un serveur simplement parce qu'il s'exécute sur le même ordinateur portable. Dès que le processus serveur reçoit un secret, il peut l'enregistrer, le transférer, l'écrire sur le disque ou l'exposer dans le résultat d'un outil. Le client ne peut pas récupérer ce secret après sa lecture par le processus.

Séparez deux décisions souvent confondues. Autoriser le démarrage d'un serveur, c'est autoriser l'exécution de code. Autoriser un identifiant de production, c'est autoriser une action sur un système externe. Un serveur peut mériter la première permission dans un espace de test sans mériter la seconde.

Pour un usage de développement simple, créez un identifiant limité et de courte durée qui ne peut accéder qu'à des données de test. Écrivez précisément sa portée. « Utilisé par le serveur de tickets » est vague ; « peut lire les tickets du projet sandbox et ne peut ni créer, ni commenter, ni modifier les membres » fournit des éléments que les personnes chargées de l'examen peuvent tester.

Pour les actions qui exigent un identifiant important, gardez le secret dans une limite locale et n'exposez que l'opération strictement nécessaire. Sallyport suit cette approche pour les actions HTTP et SSH : l'agent ne reçoit ni la clé API ni la clé SSH, tandis que l'application effectue l'action et renvoie le résultat.

Cette limite modifie la gestion des secrets, mais ne supprime pas la nécessité d'examiner le serveur. Un serveur malveillant peut toujours demander à un agent d'effectuer un appel autorisé mais dangereux. Placez l'approbation là où la conséquence se produit, limitez les identifiants à l'autorité minimale utile et lisez chaque requête qui atteint un système important pour vous.

Ne transmettez pas d'identifiants dans les arguments de commande. Les listes de processus, les rapports de plantage, les diagnostics et les processus parents peuvent les exposer. Évitez aussi les secrets en clair dans les fichiers de configuration. Si un guide d'installation exige un secret à l'un de ces endroits, vérifiez d'abord si le serveur peut utiliser un coffre d'identifiants du système d'exploitation, un jeton de courte durée ou un service d'actions externe.

## Le premier contact doit avoir lieu dans un compte de test sans intérêt

Exécutez un serveur inconnu dans un compte contrôlé avant de lui donner un projet, un environnement étendu ou de vrais identifiants. Ce test répond à une question limitée : que fait le programme au démarrage et lorsque le client lui demande ses outils ?

Utilisez un nouveau répertoire contenant des fichiers inoffensifs dont les noms rendent les lectures inattendues évidentes. Donnez au processus un `HOME` temporaire. Commencez avec un `PATH` minimal. Ne montez pas un répertoire rempli de code source sous prétexte que vous testez un serveur de contrôle de code source. Commencez par un faux dépôt ou une copie sans identifiants.

Observez le comportement avant tout appel d'outil. Un serveur qui ouvre une connexion réseau, parcourt votre dossier personnel, lit les données du navigateur ou crée des fichiers de persistance au démarrage a déjà dépassé ce qu'exigent la plupart des cas d'utilisation MCP. Certains serveurs vérifient légitimement un endpoint ou chargent une configuration locale. Ce comportement doit rester facile à expliquer et à désactiver.

Demandez ensuite l'inventaire des outils, examinez-le et effectuez un appel inoffensif avec une entrée connue. Capturez la requête, le résultat, la sortie du processus et les fichiers modifiés dans le répertoire de test. Si l'outil renvoie du contenu provenant d'un autre système, rendez les données de test clairement reconnaissables afin de vérifier qu'il a accédé au bon endroit.

Une séquence d'examen de base ressemble à ceci :

1. Vérifiez le chemin de l'exécutable, la version du paquet, la somme de contrôle ou la révision source, ainsi que chaque script de lancement.
2. Lancez-le avec un environnement minimal dans un compte de test ou un espace de travail isolé.
3. Capturez le premier résultat de `tools/list` et comparez chaque outil à la tâche prévue.
4. Appelez une opération de lecture inoffensive avec de fausses données et observez les fichiers, les processus enfants et les destinations réseau.
5. Ajoutez uniquement les identifiants et les accès aux répertoires nécessaires au comportement confirmé.

Ne confondez pas une réponse réussie avec un serveur sûr. Un serveur peut renvoyer la réponse attendue tout en copiant des fichiers ou en utilisant ailleurs un jeton hérité. Le test fournit des éléments, pas une preuve. Il détecte les conceptions négligentes et les surprises évidentes avant qu'elles n'atteignent les accès de production.

## La commodité des paquets crée un chemin de mise à jour dont vous êtes responsable

Les gestionnaires de paquets et les lanceurs de runtime rendent la configuration MCP agréablement courte. Ils créent aussi un chemin de mise à jour. Une plage de versions, un tag de paquet flottant ou un simple nom de paquet peuvent modifier le serveur lancé la semaine suivante sans changement dans la configuration.

Épinglez une version lorsque votre écosystème le permet et notez la source du paquet avec l'inventaire des outils. Mieux encore, utilisez un artefact local examiné ou un fichier de verrouillage déjà vérifié par votre équipe. Le but pratique est simple : un lancement ultérieur doit résoudre vers un code que vous pouvez identifier.

Ne laissez pas l'agent installer lui-même son serveur MCP pendant une tâche. Cela rassemble l'acquisition du logiciel, son exécution et l'autorisation des outils dans une seule demande conversationnelle. Une personne doit ajouter la configuration du serveur après avoir examiné le code et son contrat de lancement. Si un flux de développement nécessite beaucoup de serveurs, tenez un catalogue examiné plutôt que d'accepter des extraits de configuration provenant de commentaires d'incidents ou de sorties d'outils.

Les mises à jour méritent un nouvel examen bref. Comparez l'exécutable ou le fichier de verrouillage des dépendances, la commande et les arguments, les noms explicites des variables d'environnement et l'inventaire `tools/list`. L'ajout d'un outil peut être inoffensif. Il peut aussi introduire un accès en écriture que l'examen précédent n'avait jamais envisagé. Il en va de même lorsqu'un serveur modifie ses identifiants, son endpoint ou sa bibliothèque d'authentification.

La recommandation populaire « utilisez toujours le dernier paquet pour profiter des correctifs de sécurité » est incomplète pour les serveurs MCP. Il faut appliquer rapidement les correctifs de sécurité, mais une modification automatique non examinée peut changer le code qui s'exécute à côté de vos identifiants. Utilisez un processus de mise à jour contrôlé qui vous permet d'examiner le changement et de revenir en arrière si le nouveau serveur se comporte différemment.

## L'approbation doit suivre l'action, pas le nom du serveur

Une approbation ponctuelle du processus serveur répond à une seule question : cet exécutable peut-il participer à cette session ? Elle ne peut pas répondre en toute sécurité à toutes les questions ultérieures concernant la suppression d'une branche distante, l'envoi de données client ou l'ouverture d'une commande SSH sur un hôte de production.

Séparez la découverte ordinaire des actions lourdes de conséquences. Lister les projets disponibles, lire un ticket public et récupérer un schéma local nécessitent souvent moins d'attention que modifier des enregistrements ou envoyer des données hors de la machine. Votre client ou votre limite d'identifiants doit demander une nouvelle approbation humaine lorsqu'un appel franchit cette frontière. Si chaque lecture demande une intervention, les utilisateurs finiront par cliquer machinalement. Si un seul clic au démarrage accorde un accès illimité à la production, ils le regretteront tôt ou tard.

L'identité du processus compte également. Une demande d'approbation doit indiquer quel processus signé a demandé l'accès, et pas seulement afficher une étiquette choisie par le serveur. Un nom comme `database-helper` peut être copié par n'importe quel programme. Le chemin de l'exécutable, l'identité de signature lorsqu'elle est disponible et les arguments de lancement offrent une meilleure surface d'examen.

Conservez un historique à deux niveaux : la session de l'agent qui a demandé le travail et l'action individuelle qui a utilisé un identifiant ou atteint un service externe. Vous avez besoin de l'enregistrement de session pour comprendre pourquoi un agent disposait de cette autorité. Vous avez besoin de l'enregistrement de l'action pour savoir ce qui a réellement changé. Un seul journal ne peut répondre clairement aux deux questions s'il omet l'appelant ou la requête exacte.

Un enregistrement rendant les altérations détectables aide lorsque le serveur, le client ou l'opérateur conteste ensuite ce qui s'est passé. Il ne rend pas une action dangereuse sûre au moment de l'approbation. Lisez la cible, la méthode, la commande et les paramètres importants avant d'autoriser une action difficile à annuler.

## Un serveur rejeté doit être nettoyé, pas seulement supprimé

Si vous décidez qu'un serveur n'est pas fiable après l'avoir connecté, supprimez immédiatement son entrée du client, mais ne vous arrêtez pas là. Le processus peut avoir écrit des fichiers, modifié la configuration du shell, créé une tâche planifiée, changé un hook de dépôt ou copié des identifiants pendant son exécution.

Conservez les éléments avant de tout supprimer. Enregistrez la configuration, la version du paquet ou la révision source, la sortie du processus et les journaux d'actions. Inspectez ensuite le `HOME` de test, le répertoire de travail du serveur, le cache des paquets, les fichiers de démarrage du shell, les agents de lancement, les hooks de dépôt et tous les répertoires dans lesquels le serveur pouvait écrire. Vérifiez les processus actifs et les connexions réseau récentes tant que les éléments sont encore disponibles.

Faites tourner tous les secrets que le processus aurait pu lire, pas uniquement celui que vous lui avez fourni volontairement. Cela inclut les jetons hérités, l'accès à l'agent SSH, les identifiants de paquets et, le cas échéant, les sessions de développement liées au navigateur. Supprimer une ligne d'un fichier de configuration ne révoque pas un jeton déjà copié.

Renforcez ensuite le processus d'examen qui a permis la connexion. Si le problème venait d'un environnement hérité, utilisez un lanceur minimal. S'il venait d'une mise à jour inattendue du paquet, épinglez et examinez les artefacts. S'il venait d'une description d'outil trompeuse, exigez un inventaire capturé avant l'approbation. Le résultat utile est un contrôle amélioré, pas une vague promesse d'être plus prudent la prochaine fois.

Un nouveau serveur MCP obtient son accès au moment le plus dangereux, avant d'avoir gagné la moindre confiance. Rendez sa commande littérale, son environnement réduit, sa liste d'outils examinée et ses identifiants séparés de l'agent. C'est à ce moment que vous contrôlez encore le résultat.
