Pourquoi ce module
Jour 4 du tronc commun. On connecte Claude Code au monde réel (MCP), on orchestre des sous-agents pour préserver le contexte et spécialiser le travail, et on pose les garde-fous de sécurité IA + l'observabilité en production.
C'est le jour le plus « architecture » : un assistant qui requête une base, lit des tickets, scanne un repo et écrit des fichiers — chaque capacité passe par un serveur MCP qu'il faut configurer et sécuriser.
Objectifs pédagogiques
À l'issue de ce module, vous serez capable de :
- Choisir la bonne brique : savoir quand un
CLAUDE.md, une skill, un hook ou un sous-agent règle le besoin sans monter de MCP - Configurer MCP :
claude mcp add,.mcp.json, transports et scopes - Sécuriser MCP : interpolation
${VAR}, secrets, deny rules, approbation projet - Définir et orchestrer des sous-agents (isolation de contexte,
tools/modelrestreints) - Appliquer le pattern Explore → Plan → Implement
- Mitiger les risques : prompt injection, jailbreaks, fuite du system prompt
- Mettre en place l'observabilité (Langfuse / Helicone / AgentOps)
Plan détaillé
- Avant de coder un MCP : le bon déclencheur
- MCP : à quoi ça sert, transports
- Ajouter un serveur :
claude mcp addet.mcp.json - Scopes et approbation projet
- Sécurité MCP : secrets,
${VAR}, deny rules - Sous-agents : définition et délégation
- Pattern Explore → Plan → Implement
- Sécurité IA : prompt injection & garde-fous
- Observabilité production
- Atelier : MCP sécurisé + serveur custom + traces
Avant de coder un MCP : le bon déclencheur
Le réflexe le plus coûteux en 2026, c'est de monter un serveur MCP là où trois lignes de markdown suffisaient. Claude sait déjà exécuter des commandes : si votre équipe a un CLI maison, dites-le lui et laissez-le lire le --help. Une fois le pattern stabilisé, il se fige dans un CLAUDE.md ou une skill — sans protocole, sans process serveur, sans jeton à faire tourner.
La documentation officielle donne une table de déclencheurs — chaque brique a son signal d'entrée, et ils arrivent généralement dans cet ordre :
| Le déclencheur | Ce qu'on ajoute |
|---|---|
| Claude rate une convention ou une commande deux fois | Une ligne dans CLAUDE.md (J1) |
| Vous retapez le même prompt pour démarrer une tâche | Une skill invocable (J3) |
| Vous recollez le même mode opératoire pour la 3ᵉ fois | Une skill (J3) |
| Vous recopiez des données d'un onglet que Claude ne voit pas | Un serveur MCP ← ici, et pas avant |
| Une tâche annexe inonde la conversation de sortie inutile | Un sous-agent (ci-dessous) |
| Ça doit arriver à tous les coups, sans demander | Un hook (J2) |
| Un deuxième dépôt a besoin du même montage | Un plugin (M16) |
Le critère qui distingue vraiment MCP du reste : l'accès à un système externe que Claude ne peut pas atteindre depuis le shell — une base derrière un VPN, une API avec OAuth, un navigateur à piloter. Si la donnée est joignable par une commande que vous tapez déjà, ce n'est pas un besoin MCP.
💡 MCP et skills ne s'opposent pas, ils se complètent. Le serveur MCP fournit la connexion et les outils ; la skill fournit la connaissance de comment bien s'en servir. Exemple canonique : un MCP branche Claude sur votre base de données, une skill documente votre schéma, vos patterns de requête et les tables à ne pas toucher. L'un sans l'autre donne un agent qui a les clés mais pas la carte.
MCP : transports et configuration
Le Model Context Protocol connecte Claude Code à des outils/bases/API (issue trackers, monitoring, SQL, design…). Trois transports principaux :
| Transport | Quand | Exemple |
|---|---|---|
| stdio | Serveur local (process) | npx, python server.py, docker |
http (streamable-http) | Serveur distant, OAuth | https://mcp.notion.com/mcp |
| sse | Distant, événements poussés | https://mcp.asana.com/sse |
La spec 2026-07-28 : MCP devient sans session
Le protocole est versionné par date (AAAA-MM-JJ), la date marquant le dernier changement non rétrocompatible. La révision 2026-07-28 est la version courante — et la rupture la plus profonde depuis la création du protocole : le handshake initialize disparaît.
Ce qui change concrètement :
Avant (2025-11-25 et antérieures) | Depuis 2026-07-28 |
|---|---|
Un initialize négocie la version une fois, puis la session la porte | Chaque requête déclare sa version via io.modelcontextprotocol/protocolVersion dans son champ _meta |
| Le serveur maintient un état de session par client | Le serveur accepte ou rejette chaque requête indépendamment |
| Découvrir les capacités = ouvrir une session | server/discover — un RPC obligatoire côté serveur — renvoie versions supportées, capacités et identité en un seul appel |
| Version incompatible = échec de connexion | Réponse UnsupportedProtocolVersionError listant les versions acceptées ; le client peut retenter |
En Streamable HTTP, la version voyage aussi dans l'en-tête MCP-Protocol-Version. Appeler server/discover reste optionnel pour le client : il peut envoyer une requête directement et gérer l'erreur de version si elle revient. La rétrocompatibilité avec les révisions à handshake est spécifiée — vos serveurs existants ne cassent pas du jour au lendemain.
💡 Pourquoi c'est un sujet d'architecture, pas de trivia. Un protocole avec session impose une affinité : le client doit retomber sur l'instance qui détient son état. Derrière un load-balancer, ça veut dire sticky sessions, et donc des serveurs MCP qu'on ne peut ni scaler horizontalement ni redéployer sans casser les connexions en vol. Sans session, chaque requête est autoportante : n'importe quelle instance peut y répondre, le scale-out redevient trivial, et un serveur MCP peut enfin tourner en fonction serverless. C'est exactement la même bascule que le passage des sessions serveur aux JWT côté web — avec les mêmes contreparties : plus de métadonnées transportées à chaque appel, et un état applicatif qu'il faut désormais gérer explicitement quand on en a besoin.
Ce que vous devez faire : si vous maintenez un serveur MCP (cf. atelier 4a), vérifiez la version de spec que votre SDK implémente avant de le déclarer prêt pour la production. (Source : spécification MCP — versioning.)

/mcp : l'état des serveurs MCP connectés, leur scope (User / Built-in) et le nombre d'outils exposés par chacun.# Distant HTTP (OAuth)
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Local stdio avec secret par env (le -- sépare les options du process serveur)
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable -- npx -y airtable-mcp
🆕 Authentifier un serveur OAuth depuis le CLI (v2.1.186).
claude mcp login <name>lance le flux d'auth d'un serveur sans passer par une session interactive,claude mcp logout <name>révoque le jeton. Pratique en script/CI ou pour ré-autoriser un serveur expiré. Depuis v2.1.193, l'headersHelperse ré-exécute et reconnecte automatiquement sur un401/403(jeton expiré → refresh transparent).
Ou en JSON (.mcp.json projet, ~/.claude.json, ou claude mcp add-json) :
// .mcp.json (versionné, partagé en équipe)
{
"mcpServers": {
"postgres": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": { "DATABASE_URL": "${DATABASE_URL}" } // interpolé, pas de secret en clair
}
}
}
ℹ️ Claude Code injecte
CLAUDE_PROJECT_DIRdans l'environnement du serveur (racine projet). En.mcp.jsonprojet/user, prévoir un défaut :${CLAUDE_PROJECT_DIR:-.}.
🆕 Les appels MCP lents ne bloquent plus la session (v2.1.212). Un outil MCP qui dépasse 2 minutes bascule automatiquement en arrière-plan ; vous récupérez la main et le résultat arrive quand il arrive. Seuil réglable — ou désactivable — via
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS. Ça change la façon de concevoir un serveur MCP maison : un outil long (export, batch, crawl) n'est plus un anti-pattern à découper artificiellement en appels courts.🔧 Diagnostiquer une connexion qui échoue (v2.1.219).
claude mcp listet/mcpaffichent désormais le statut HTTP et le texte d'erreur renvoyés par un serveur injoignable, au lieu d'un « failed to connect » opaque — et signalent les valeurs de configuration contenant des espaces invisibles en début ou fin de chaîne, cause classique d'un jeton qui « marche pourtant ailleurs ».
Scopes et approbation
--scope détermine où la config est stockée :
local(défaut) : personnel, cette machineproject: partagé via.mcp.json(versionné)user: tous vos projets
Les serveurs project issus de .mcp.json arrivent en ⏸ Pending approval : on les revoit et approuve en session interactive (claude mcp list / claude mcp get <name>). Garde-fou anti-supply-chain : on n'exécute pas un serveur tiers sans validation. Depuis la v2.1.196, ce garde-fou est durci : claude mcp list/get ne lancent plus un serveur .mcp.json qu'un repo aurait auto-approuvé via un .claude/settings.json commité — un workspace non fiable reste en ⏸ Pending approval quoi qu'il embarque.
Sécurité MCP
- Jamais de secret en clair : interpolation
${VAR}ou--env, fichier de secrets en perm600. - Deny rules dans
settings.jsonpour borner les outils MCP sensibles :
{
"permissions": {
"deny": ["mcp__postgres__*delete*", "mcp__*__drop*"],
"ask": ["mcp__postgres__*write*", "mcp__*__update*"]
}
}
- Approbation des serveurs projet (cf. ci-dessus). Détail OAuth 2.1 + PKCE et marketplaces : M7.
⚠️ Sandbox comme défense en profondeur, non comme garantie. La sandbox de Claude Code est la première ligne de défense, mais doit être complétée par des contrôles réseau au niveau infrastructure. Maintenir :
- Contrôles réseau au niveau du firewall / hyperviseur (hors de portée de l'agent)
- Audit trails centralisés pour les sorties sensibles
- Moindre privilège réseau (whitelist d'endpoints, pas d'accès DNS/outbound par défaut)
- Mise à jour systématique de Claude Code
🔒
sandbox.credentials(v2.1.187). Nouveau réglage qui empêche les commandes sandboxées de lire les fichiers de credentials (~/.aws,~/.config/gh,.env, clés SSH…). À activer dès qu'un agent exécute du code non maîtrisé : la sandbox isole déjà le réseau, ce réglage isole aussi les secrets sur disque.{ "sandbox": { "credentials": "block" } } // bloque l'accès aux fichiers sensibles depuis la sandbox
🔒 Deux réglages de sandbox arrivés en juillet 2026. La sandbox se règle désormais sur ses deux axes séparément — système de fichiers et réseau — au lieu d'être un bloc tout-ou-rien :
{ "sandbox": { "credentials": "block", // v2.1.187 — secrets sur disque "filesystem": { "disabled": true }, // v2.1.216 — pas d'isolation FS, on garde le réseau "network": { "strictAllowlist": true } // v2.1.219 — hôte hors allowlist = refus, sans prompt } }
sandbox.filesystem.disabled(v2.1.216) saute l'isolation du système de fichiers tout en conservant le contrôle de l'egress réseau. Contre-intuitif mais utile : sur un poste de dev où l'agent doit écrire partout dans le projet, ce qu'on veut vraiment borner c'est ce qui sort, pas ce qui s'écrit en local.sandbox.network.strictAllowlist(v2.1.219) refuse les hôtes non allowlistés sans poser de question. C'est la posture à adopter en exécution non surveillée : un prompt de permission dans une session AFK, c'est soit un blocage, soit — pire — une approbation réflexe.La règle de conception à enseigner : ces deux axes se règlent en fonction de ce qu'on craint. Contre l'exfiltration → verrouiller le réseau. Contre la destruction → verrouiller le système de fichiers. Contre le vol de secrets →
credentials: block. Cocher les trois par défaut rend l'agent inutilisable et pousse les équipes à tout désactiver ; c'est le mode d'échec classique du durcissement excessif.
🛡️ Advisory « symlink dans
CLAUDE.md» — et la doctrine de sécurité qu'il révèle (juillet 2026). Troisième variante d'une même famille de failles, après CVE-2025-59829 et CVE-2026-25724 (Permission Deny Bypass Through Symbolic Links), auxquelles s'ajoute CVE-2026-39861 (échappement de sandbox par symlink).Le vecteur : un dépôt malveillant place une ligne d'import
@./linkdans sonCLAUDE.md, et committelinkcomme symlink git pointant vers un fichier local hors du dépôt (~/.ssh/id_ed25519,~/.aws/credentials, le.envd'un autre projet…). Au démarrage, le chargeur de mémoire suit le lien et aspire le contenu dans le contexte. Combiné à un.claude/settings.jsoncommitté qui surchargeANTHROPIC_BASE_URL, la requête — et donc les données — part vers un hôte choisi par l'attaquant.Le plus instructif est la réponse d'Anthropic : ce comportement est considéré comme couvert par le modèle de menace, au motif qu'accepter le workspace trust d'un dépôt autorise déjà la lecture de fichiers. La boîte de dialogue d'import externe est une aide à l'usage, pas une frontière de sécurité applicable.
À enseigner tel quel, parce que ça vaut pour tout agent à outils : la seule frontière de sécurité, c'est le moment où vous accordez la confiance à un espace de travail. Tout ce qui vient après — dialogues, confirmations, garde-fous — relève du confort, pas de la garantie. D'où le réflexe : cloner un dépôt inconnu dans un environnement sans secrets (
sandbox.credentials: block, réseau borné, compte jetable) avant d'y lancer Claude Code, et ne jamais accorder la confiance à un dépôt qu'on n'a pas au moins survolé. Même conclusion que les deux advisories ci-dessus, atteinte par un troisième chemin.(Les correctifs symlink des v2.1.210, 212, 216 et 217 — sandbox, worktrees,
/rewind, isolation des sessions en arrière-plan — relèvent de la même campagne de durcissement. Détail dans le CHANGELOG.)
🛡️ Advisory « Agentjacking » via Sentry DSN (juin 2026). Des chercheurs ont montré qu'une clé DSN Sentry exposée (souvent publique dans le front) peut servir à injecter des messages d'erreur piégés que l'agent (Claude Code, Cursor, Codex) lit et exécute — un vecteur de prompt injection par la télémétrie. Garde-fou : traiter toute donnée externe lue par l'agent (logs, tickets, erreurs Sentry, issues) comme non fiable, ne jamais auto-exécuter d'instructions qui en proviennent, et borner les outils via
deny/ask. (Source : The New Stack, 21 juin 2026.)
🛡️ Advisory « poisoned repo » — Mozilla 0DIN (fin juin 2026). Même famille d'attaque, vecteur encore plus sournois : un repo GitHub 100 % propre (aucun code malveillant versionné) fait ouvrir un reverse shell à Claude Code. Mécanique : le setup du projet utilise un package qui échoue volontairement avec un message d'erreur du type « Run:
python3 -m axiom init» ; l'agent, serviable, exécute la commande pour dépanner — et le payload, hébergé dans un enregistrement DNS TXT (jamais dans le repo, modifiable à tout moment), s'exécute avec les droits du développeur :ANTHROPIC_API_KEY,AWS_SECRET_ACCESS_KEY,GITHUB_TOKENexposés. Touche aussi Cursor et Gemini CLI. Garde-fous : les messages d'erreur sont des inputs non fiables (comme les logs Sentry ci-dessus), cloner les repos inconnus dans un environnement sandboxé sans secrets (sandbox.credentials: block+ réseau borné), etasksur les exécutions issues d'un dépannage automatique. (Sources : SecurityWeek · Tom's Hardware, 29–30 juin 2026.)
Autorisation MCP en entreprise (juin 2026) : La couche Enterprise-Managed Authorization (EMA) pour MCP (stable depuis 18 juin 2026) permet une gestion centralisée de l'accès aux serveurs MCP via SSO. Les utilisateurs s'authentifient une fois auprès de leur fournisseur d'identité (Okta est le premier supporté au lancement) et obtiennent automatiquement accès aux serveurs approuvés par l'administrateur. Cela élimine les créds répétées par serveur et facilite les audit trails pour la conformité. Autres fournisseurs seront ajoutés progressivement.
Sous-agents : définition et délégation
Un sous-agent est un assistant spécialisé qui tourne dans son propre contexte, avec un system prompt, des outils et des permissions dédiés. Claude délègue quand une tâche correspond à la description du sous-agent. Bénéfices : préserver le contexte principal, contraindre les outils, router vers un modèle moins cher (Haiku).
🆕 Les sous-agents tournent en arrière-plan par défaut (v2.1.198). Claude ne bloque plus en attendant un sous-agent : il continue à travailler et est notifié à la fin. Corollaire : le sous-agent intégré Explore hérite désormais du modèle de la session (plafonné à Opus) au lieu de tourner d'office sur Haiku — le routage explicite via
model:dans le frontmatter reste la bonne pratique pour maîtriser les coûts.
🆕 Les sous-agents peuvent déléguer à leur tour (v2.1.219) — et l'aller-retour de juillet 2026 mérite d'être raconté. En v2.1.217, Anthropic a désactivé l'imbrication : un sous-agent ne pouvait plus en lancer d'autres. Deux versions plus tard, en v2.1.219, elle revient avec une profondeur de 3 par défaut. Entre les deux, un plafond de 20 sous-agents simultanés est apparu (v2.1.217).
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1 # revenir à « pas d'imbrication » CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS=20 # défaut : 20 agents en vol simultanémentLa leçon d'architecture est plus intéressante que le réglage : le problème n'a jamais été la profondeur, mais l'absence de borne sur le total. Un arbre de profondeur 3 avec un facteur de branchement non maîtrisé, c'est une bombe combinatoire ; le même arbre avec un plafond de concurrence, c'est une file d'attente. Une fois la borne posée, l'imbrication redevient sûre — d'où le retour en arrière. Quand vous concevez vous-même une délégation multi-niveaux (cf. J5), bornez le fan-out total, pas la profondeur.
Autre changement de la même période : le paramètre
modede l'outil Task est déprécié (v2.1.212, désormais ignoré). Les sous-agents héritent du mode de permission de la session parente. On ne peut donc plus élever discrètement les privilèges d'un sous-agent au-dessus de ceux de son parent — ce qui est la bonne propriété, et ce qu'il faut supposer en conception.

Bash), pendant que la session principale reste libre.Définition en Markdown + frontmatter, dans .claude/agents/<nom>.md (projet, versionné) ou ~/.claude/agents/ (perso) :
---
name: code-reviewer
description: Relit le code pour la qualité et les bonnes pratiques. À utiliser après chaque changement notable.
tools: Read, Grep, Glob
model: haiku
---
Tu es relecteur senior. Vérifie : bugs, sécurité, lisibilité, tests.
Renvoie une liste priorisée (bloquant / majeur / mineur) avec fichier:ligne.
- Identité = champ
name(unique). Frontmatter principaux :description,tools,model(+disallowedTools,permissionMode,effort,color…). - Gérer les sous-agents : éditer directement
.claude/agents/ou demander à Claude de créer/modifier un agent — le wizard/agentsa été retiré en v2.1.198. Le suivi des sous-agents en cours se fait dans l'Agent view (claude agents, cf. J5). - Les fichiers sont chargés au démarrage (édition disque → redémarrer).
🧭 Pour paralléliser des sessions indépendantes et les piloter d'une vue, voir l'Agent view (J5). Pour des sessions qui communiquent, voir les agent teams.
Pattern Explore → Plan → Implement
Chargement du schéma…
- Explore (souvent Haiku, read-only) ramène un résumé sans polluer le contexte principal.
- Plan propose une stratégie validable.
- Implement écrit et teste, sous permissions restreintes.
Sécurité IA : prompt injection & garde-fous
- Prompt injection directe : l'utilisateur tente de détourner les consignes.
- Prompt injection indirecte : un contenu lu (page web, ticket, fichier MCP) contient des instructions malveillantes → le risque n°1 des agents à outils.
- Jailbreaks / fuite du system prompt : tentatives d'extraire les consignes internes.
Garde-fous : Constitutional AI (refus calibré — cf. M9), validation de sortie (JSON Schema, regex), deny rules sur les outils dangereux, principe du moindre privilège (chaque sous-agent n'a que ses outils), et audit trails. Règle d'or : ne jamais donner à un agent qui lit du contenu externe des outils d'écriture non bornés.
🛡️ L'injection indirecte se propage par la délégation (durci en v2.1.210). L'outil Agent a été spécifiquement renforcé contre l'injection de prompt véhiculée par le contenu qu'un sous-agent a lu. Le scénario : un sous-agent Explore lit une page web ou un ticket piégé, en fait un résumé — et l'instruction malveillante voyage dans ce résumé jusqu'à la session principale, qui, elle, dispose des outils d'écriture. La délégation avait ainsi blanchi la donnée non fiable au passage.
Le réflexe de conception : le retour d'un sous-agent est un input non fiable, exactement comme une page web ou un log Sentry. Le fait qu'il transite par un composant à vous ne le rend pas sûr. C'est le corollaire direct du pattern Explore → Plan → Implement ci-dessous : Explore n'a que des outils de lecture, mais ce qu'il rapporte mérite la même défiance que ce qu'il a lu.
Observabilité production
Tracer chaque appel (prompt, tokens, latence, coût, erreurs) :
- Langfuse (open-source) : traces, scoring qualité, A/B tests.
- Helicone (open-source) : monitoring coûts/latence.
- AgentOps : suivi d'agents.
Indispensable pour déboguer un agent, mesurer le coût réel (cf. M2) et détecter une dérive de qualité.
🆕 La télémétrie native s'est enrichie (juillet 2026) — de quoi corréler ce que les plateformes ci-dessus voient de l'extérieur avec ce que Claude Code sait de l'intérieur. Nouveaux attributs OpenTelemetry :
Attribut Ce qu'il permet Version workflow.run_id,workflow.nameReconstituer l'activité complète d'un dynamic workflow depuis les seules données OTel — sans ces clés, les dizaines d'agents d'un workflow sont des traces orphelines v2.1.202 message.uuid,client_request_idCorréler une trace à un message précis de la conversation v2.1.214 tool_sourceSavoir d'où vient un outil (natif, MCP, plugin, skill) — indispensable pour attribuer un coût ou un incident au bon composant v2.1.214 CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTHRégler la troncature (60 Ko par défaut) des attributs de contenu v2.1.214 Deux correctifs à connaître si vos exports échouaient silencieusement : les exports HTTP OTel étaient rejetés en 411/400 par Azure Monitor et les endpoints refusant le chunked transfer encoding (corrigé v2.1.212), et l'endpoint Prometheus émettait des lignes
# UNITinvalides (corrigé v2.1.216). Si vous aviez renoncé à brancher la télémétrie faute de données, réessayez.
Atelier (180 min, 2 temps) : MCP sécurisé + sous-agents + traces
Atelier 4a — sécuriser sa .mcp.json (interpolation ${VAR}, deny rules) et implémenter un serveur MCP custom métier (TypeScript SDK officiel ou Python FastMCP), approuvé en scope projet.
Atelier 4b — orchestrer 2 sous-agents (Explore read-only en Haiku + Implement) sur une tâche réelle, puis brancher Langfuse ou Helicone et capturer 5 traces.
Livrable : .mcp.json durci + 1 serveur MCP custom + 2 sous-agents + 5 traces d'observabilité.
Pour aller plus loin
- 📖 Claude Code — MCP
- 📖 Claude Code — Subagents
- 📖 Modèle de menaces / sécurité agents
- 🛠 Langfuse · Helicone
- 🎯 Tronc commun : J3 ← → J5 (agents autonomes) · approfondissement : M7 (MCP OAuth), M9 (Constitutional AI)