EN DIRECT
Sparks Fly: NVIDIA Accelerates Local AI at IFA 202603/09/26 · NVIDIA|Introducing WeatherNext 3, our most advanced and accurate global weather AI model03/09/26 · Google|Claude outage – Resolved03/09/26 · Anthropic|NeoMME: an efficient Multimodal-native and Multilingual Encoder03/09/26 · Hugging Face|‘NBA 2K27’ With NVIDIA DLSS 5 Leads 28 New Games Coming to GeForce NOW03/09/26 · NVIDIA|NVIDIA to Acquire Hugging Face03/09/26 · NVIDIA|Training a coding model to paint watercolours with TRL and OpenEnv03/09/26 · Hugging Face|Fine-tuning a 350M Model for Better Structured Outputs in 100 GRPO Steps03/09/26 · Hugging Face|Give Your Coding Agents a Memory You Own03/09/26 · Hugging Face|Muse Spark 1.302/09/26|GRADSOLVE: fast exact gradients for ODE ensembles on GPUs02/09/26 · NVIDIA|Proactive cyber defense for governments and enterprises02/09/26 · Google|Sparks Fly: NVIDIA Accelerates Local AI at IFA 202603/09/26 · NVIDIA|Introducing WeatherNext 3, our most advanced and accurate global weather AI model03/09/26 · Google|Claude outage – Resolved03/09/26 · Anthropic|NeoMME: an efficient Multimodal-native and Multilingual Encoder03/09/26 · Hugging Face|‘NBA 2K27’ With NVIDIA DLSS 5 Leads 28 New Games Coming to GeForce NOW03/09/26 · NVIDIA|NVIDIA to Acquire Hugging Face03/09/26 · NVIDIA|Training a coding model to paint watercolours with TRL and OpenEnv03/09/26 · Hugging Face|Fine-tuning a 350M Model for Better Structured Outputs in 100 GRPO Steps03/09/26 · Hugging Face|Give Your Coding Agents a Memory You Own03/09/26 · Hugging Face|Muse Spark 1.302/09/26|GRADSOLVE: fast exact gradients for ODE ensembles on GPUs02/09/26 · NVIDIA|Proactive cyber defense for governments and enterprises02/09/26 · Google|
AvancéNouveau🧰

CCA-F Domaine 2 — Tool Design & MCP Integration (18 %) : la leçon complète

Le domaine des outils : comment un agent choisit le bon outil, pourquoi il se trompe, comment un outil doit échouer, combien d'outils donner à qui, tool_choice, la configuration des serveurs MCP et les outils built-in de Claude Code. Schémas, pièges, checklist de la veille et questions-scénario corrigées.

32 min de lecturePublié le 4 septembre 2026 · aujourd'hui

Le domaine 2 pèse 18 % — environ 11 questions sur 60. Il est plus court que le domaine 1 et beaucoup plus factuel : on te demande rarement d'arbitrer une architecture, on te demande si tu sais pourquoi un agent choisit le mauvais outil, comment un outil doit signaler un échec, combien d'outils un agent doit voir, et où se configure un serveur MCP. Les candidats qui perdent des points ici les perdent presque toujours pour la même raison : ils répondent « ajouter des exemples » ou « ajouter une couche de routage » là où l'examen attend « corriger la description de l'outil ».

Cette leçon suit les 5 task statements du guide officiel v1.0 (juillet 2026). Les scénarios d'examen qui tirent sur ce domaine sont le Customer Support Resolution Agent (scénario 1, outils get_customer, lookup_order, process_refund, escalate_to_human), le Multi-Agent Research System (scénario 3) et le Developer Productivity (scénario 4, outils built-in + MCP). Retiens ces trois cadres : les questions y sont ancrées.

Où se situe cette leçon. Deuxième des cinq leçons domaine par domaine de notre guide complet de la CCA-F, après le Domaine 1 — Architecture agentique. Vérifié le 4 septembre 2026 sur le guide d'examen officiel v1.0. Prérequis : la boucle agentique et le hub-and-spoke du domaine 1.

La carte du domaine

Les cinq task statements se lisent comme le cycle de vie d'un outil : comment il est décrit (2.1), comment il échoue (2.2), à qui on le donne et comment on force son usage (2.3), où il est configuré quand il vient d'un serveur MCP (2.4), et le cas particulier des outils built-in de Claude Code (2.5).

Les 5 task statements du domaine 2 : le cycle de vie d'un outil
2.1 Décrire description = mécanisme de choix formats · exemples · frontières 2.2 Échouer erreur structurée isError · catégorie isRetryable · vide ≠ erreur 2.3 Distribuer 4-5 outils par rôle tool_choice auto · any · forcé 2.4 Configurer .mcp.json (projet) ~/.claude.json (perso) ${VAR} · ressources 2.5 Built-in Grep · Glob Read · Write Edit · Bash Le réflexe qui traverse tout le domaine Quand l'agent se trompe d'outil → corriger la DESCRIPTION, pas ajouter une couche. Quand l'agent gère mal un échec → structurer l'ERREUR, pas réessayer à l'aveugle. Quand l'agent a trop d'outils → RESTREINDRE par rôle, pas rallonger le prompt.
Les questions 2.1 et 2.2 testent la qualité de l'interface (description, erreurs). 2.3 teste la distribution et le contrôle. 2.4 et 2.5 sont les plus factuelles : configuration MCP et sélection des outils built-in.

2.1 — Décrire un outil : la description est le mécanisme de sélection

C'est la question 2 du guide officiel, et c'est la plus emblématique du domaine. L'agent appelle get_customer quand l'utilisateur demande « vérifie ma commande #12345 » au lieu de lookup_order. Les deux outils ont des descriptions minimales (« Retrieves customer information » / « Retrieves order details ») et acceptent des identifiants de format proche. Que faire en premier ?

Description minimale vs description qui guide
✗ Minimale — sélection aléatoire get_customer "Retrieves customer information" lookup_order "Retrieves order details" « vérifie ma commande #12345 » → get_customer ? lookup_order ? pile ou face Aucun format d'entrée · aucun exemple Aucune frontière entre les deux Aucun cas limite documenté ✓ Qui guide — sélection fiable lookup_order Quoi : statut, articles, livraison d'UNE commande Entrée : order_id "#12345" ou "ORD-12345" Ex. : "où en est ma commande", "colis 12345" Limite : ne renvoie PAS le profil client → pour le profil, utiliser get_customer get_customer Quoi : profil + vérification d'identité (email/tél) Limite : pas de détail de commande → lookup_order « vérifie ma commande #12345 » → lookup_order, sans hésitation
Le modèle n'a que la description pour choisir. Si deux descriptions se ressemblent, la sélection devient aléatoire. Une bonne description dit : ce que l'outil fait, ce qu'il attend en entrée (format, exemples), ce qu'il renvoie, ses cas limites, et quand NE PAS l'utiliser au profit d'un outil voisin.

Ce qu'il faut savoir

La description est le canal de sélection. Le modèle n'a ni ta doc interne ni ton intention : il a le nom, la description et le schéma d'entrée. Quand les descriptions sont minimales, il ne peut pas distinguer deux outils proches, et le taux de mauvaise sélection devient structurel.

Ce qu'une bonne description contient. Les formats d'entrée acceptés (avec exemples : #12345, ORD-12345), des exemples de requêtes utilisateur qui doivent aboutir à cet outil, les cas limites (que se passe-t-il si l'identifiant est inconnu, si plusieurs résultats correspondent), et les frontières : quand utiliser cet outil plutôt que son voisin, et vice versa.

Le chevauchement crée le mauvais routage. analyze_content et analyze_document avec des descriptions quasi identiques : l'agent alterne. Deux corrections attendues : renommer pour rendre le périmètre explicite (analyze_contentextract_web_results avec une description orientée web), et scinder un outil générique en outils à contrat précis (analyze_documentextract_data_points, summarize_content, verify_claim_against_source), chacun avec ses entrées et sorties définies.

Le prompt système peut saboter la description. Une instruction sensible aux mots-clés (« pour toute question sur les données client, utilise get_customer ») crée une association involontaire : « données de ma commande » part vers get_customer. Quand la description est bonne et que le routage reste mauvais, relis le prompt système à la recherche de ces raccourcis.

# Avant : deux descriptions interchangeables
TOOLS_BAD = [
    {"name": "get_customer", "description": "Retrieves customer information",
     "input_schema": {"type": "object", "properties": {"id": {"type": "string"}}}},
    {"name": "lookup_order", "description": "Retrieves order details",
     "input_schema": {"type": "object", "properties": {"id": {"type": "string"}}}},
]

# Après : formats, exemples, cas limites, frontières — et des noms de paramètres parlants
TOOLS_GOOD = [
    {
        "name": "get_customer",
        "description": (
            "Récupère le PROFIL d'un client et vérifie son identité. "
            "Entrée : email (jane@ex.com) ou téléphone (+33612345678) ou customer_id (CUS-8841). "
            "Exemples de requêtes : 'c'est bien mon compte ?', 'mets à jour mon adresse'. "
            "Renvoie : customer_id vérifié, nom, adresse, statut du compte. "
            "Ne renvoie AUCUN détail de commande : pour une commande, utiliser lookup_order. "
            "Si plusieurs clients correspondent, renvoie la liste et demande un identifiant supplémentaire."
        ),
        "input_schema": {"type": "object",
                         "properties": {"identifier": {"type": "string",
                                        "description": "email, téléphone E.164 ou customer_id CUS-xxxx"}},
                         "required": ["identifier"]},
    },
    {
        "name": "lookup_order",
        "description": (
            "Récupère le statut, les articles et la livraison d'UNE commande. "
            "Entrée : order_id au format '#12345' ou 'ORD-12345' (le préfixe est optionnel). "
            "Exemples : 'où en est ma commande', 'le colis 12345 est parti ?', 'commande ORD-9910'. "
            "Renvoie : statut, articles, transporteur, ETA, montant. "
            "Ne renvoie PAS le profil client : pour vérifier l'identité, utiliser get_customer d'abord. "
            "order_id inconnu → erreur validation (pas de retry)."
        ),
        "input_schema": {"type": "object",
                         "properties": {"order_id": {"type": "string",
                                        "description": "'#12345', '12345' ou 'ORD-12345'"}},
                         "required": ["order_id"]},
    },
]
Le piège 2.1. Face à un problème de sélection, les distracteurs sont dans l'ordre : (A) « ajouter 5 à 8 exemples few-shot au prompt système » — coûte des tokens et ne corrige pas la cause ; (C) « une couche de routage par mots-clés avant chaque tour » — sur-ingénierie qui contourne le modèle ; (D) « fusionner en un seul lookup_entity » — décision d'architecture valable mais disproportionnée pour une première étape. La réponse attendue est toujours enrichir les descriptions. Le mot « first step » dans l'énoncé est le signal.
🏷️
Le réflexe 2.1
Mauvaise sélection d'outil → description (formats, exemples, cas limites, frontières). Chevauchement → renommer ou scinder. Description correcte mais routage toujours faux → chercher l'instruction à mots-clés dans le prompt système.

2.2 — Échouer proprement : l'erreur structurée

Un outil qui échoue en disant « Operation failed » condamne l'agent à deviner : faut-il réessayer ? changer d'approche ? escalader ? expliquer au client ? Le protocole MCP prévoit un drapeau isError ; l'examen attend que tu ailles bien au-delà.

Quatre catégories d'erreur, quatre réactions attendues
transient timeout, service down, rate limit isRetryable: true → réessayer localement, avec backoff validation format invalide, id inconnu, champ manquant isRetryable: false (tel quel) → corriger l'entrée ou redemander au client business règle métier violée : délai dépassé, plafond retriable: false + explication → expliquer au client message customer-friendly permission droits insuffisants, action réservée isRetryable: false → escalader vers un humain habilité Cas à part : le résultat VIDE légitime « aucune commande trouvée » = succès sans correspondance, pas une erreur → ne pas réessayer, ne pas escalader, informer
La catégorie détermine la réaction de l'agent. Une erreur transitoire se réessaie ; une erreur de validation se corrige ; une erreur métier s'explique au client ; une erreur de permission s'escalade. Une réponse uniforme rend ces quatre décisions impossibles.

Ce qu'il faut savoir

Le drapeau isError. C'est le mécanisme MCP pour signaler un échec de l'outil à l'agent, distinct d'une erreur de protocole. Mais un drapeau seul ne dit pas quoi faire.

Les quatre catégories. Transient (timeout, indisponibilité) : réessayable. Validation (entrée invalide) : non réessayable tel quel, il faut corriger l'entrée. Business (violation de règle : remboursement hors délai) : non réessayable, à expliquer au client. Permission : non réessayable, à escalader.

Pourquoi l'uniforme est un anti-pattern. « Operation failed » ne permet aucune décision de récupération. L'agent réessaie ce qui ne peut pas réussir (gaspillage, latence) ou abandonne ce qui aurait réussi au second essai.

Les métadonnées attendues. errorCategory (transient / validation / permission / business), isRetryable (booléen), et une description lisible. Pour une règle métier, un retriable: false accompagné d'une explication compréhensible par le client que l'agent peut relayer directement.

Récupération locale, propagation sélective. Dans un système multi-agents, un sous-agent gère lui-même ses erreurs transitoires (retry avec backoff) et ne remonte au coordinateur que ce qu'il ne peut pas résoudre — avec les résultats partiels et ce qui a été tenté. Ni suppression silencieuse (renvoyer vide comme un succès), ni propagation brute qui tue le workflow.

Échec d'accès vs résultat vide. Un timeout est un échec d'accès : il appelle une décision (réessayer, alternative). « Aucune commande ne correspond » est un succès avec zéro résultat : il ne déclenche ni retry ni escalade, il s'annonce au client. Confondre les deux produit soit des retries inutiles, soit des échecs masqués.

# Réponse d'outil MCP : structurée, catégorisée, actionnable
def process_refund(order_id: str, amount_eur: float) -> dict:
    order = db.get_order(order_id)
    if order is None:                                    # entrée invalide → validation
        return {"isError": True, "errorCategory": "validation", "isRetryable": False,
                "message": f"Commande {order_id} introuvable. Vérifier l'identifiant."}
    if order.age_days > 30:                              # règle métier → business
        return {"isError": True, "errorCategory": "business", "retriable": False,
                "message": "Délai de remboursement de 30 jours dépassé.",
                "customerMessage": "Le délai de 30 jours pour un remboursement est dépassé ; "
                                   "je peux vous proposer un avoir ou transmettre à un conseiller."}
    if not ctx.user.can("refund"):                       # droits → permission
        return {"isError": True, "errorCategory": "permission", "isRetryable": False,
                "message": "Action réservée : escalader vers un agent habilité."}
    try:
        return {"isError": False, "refund_id": payments.refund(order, amount_eur)}
    except payments.Timeout:                             # infra → transient
        return {"isError": True, "errorCategory": "transient", "isRetryable": True,
                "message": "Service de paiement indisponible, réessayer dans quelques secondes."}

# Résultat vide légitime : un succès, pas une erreur
def search_orders(customer_id: str, since: str) -> dict:
    rows = db.orders(customer_id, since)
    return {"isError": False, "results": rows, "count": len(rows),
            "note": "0 résultat = aucune commande sur la période, requête valide" if not rows else None}
Le piège 2.2. Deux distracteurs récurrents. Le premier : « implémenter un retry automatique avec backoff dans l'outil et renvoyer un statut générique après épuisement » — le retry local est bon, le statut générique est le problème (question 8 du guide). Le second : « attraper l'erreur et renvoyer un résultat vide marqué succès pour ne pas bloquer le workflow » — c'est de la suppression silencieuse, le pire des cas. La réponse attendue combine toujours catégorie + retryable + contexte (ce qui a été tenté, résultats partiels, alternatives).

2.3 — Distribuer les outils et contrôler le choix

Qui voit quels outils, et peut-on forcer un appel ? C'est la section où le domaine 2 rejoint le domaine 1 (sous-agents spécialisés) et le domaine 4 (sortie structurée via tool_choice).

Trop d'outils dégrade la sélection ; le scope par rôle la restaure
✗ 18 outils pour tout le monde Agent de synthèse web_search · fetch_url · process_refund · … → la synthèse lance des recherches web → fetch_url sur des URLs arbitraires complexité de décision × 18, fiabilité en chute ✓ 4-5 outils par rôle + un outil scopé transverse Recherche web web_search · load_document (URL validée, pas fetch_url) Synthèse write_section · cite + verify_fact (scopé) 85 % des vérifs simples, sans aller-retour 15 % complexes Coord. moindre privilège · pas de cross-rôle sauf besoin fréquent
À 18 outils, chaque décision de l'agent est un choix parmi 18 descriptions, et un agent de synthèse finit par lancer des recherches web qu'il n'aurait pas dû faire. À 4-5 outils par rôle, la sélection est fiable. Le besoin transverse fréquent (vérifier un fait) se règle par UN outil scopé, pas par l'ouverture de tout le catalogue.

Ce qu'il faut savoir

Le nombre dégrade la fiabilité. Un agent avec 18 outils choisit moins bien qu'avec 4-5. Ce n'est pas une question de contexte mais de complexité de décision.

Hors rôle = mésusage. Un agent de synthèse avec accès à la recherche web finit par chercher au lieu de synthétiser. Un outil hors spécialisation est un outil qui sera mal utilisé.

Le scope par rôle. Chaque sous-agent reçoit uniquement les outils de sa fonction. Les outils génériques dangereux sont remplacés par des versions contraintes : fetch_url (n'importe quelle URL) → load_document (valide que l'URL appartient au corpus autorisé).

L'outil scopé transverse. C'est la question 9 du guide : la synthèse a besoin de vérifier des faits ; 85 % sont des vérifications simples (dates, noms, chiffres), 15 % demandent une investigation. Réponse attendue : donner à la synthèse un outil verify_fact limité aux vérifications simples, et garder le passage par le coordinateur pour les cas complexes. Pas « tous les outils de recherche » (viole la séparation), pas « batcher les vérifications à la fin » (dépendances bloquantes), pas « pré-cacher spéculativement » (imprévisible).

tool_choice. Trois modes. {"type": "auto"} : le modèle peut appeler un outil ou répondre en texte. {"type": "any"} : le modèle doit appeler un outil, il choisit lequel. {"type": "tool", "name": "extract_metadata"} : le modèle doit appeler cet outil. Usage typique du forçage : garantir qu'une extraction de métadonnées s'exécute avant les étapes d'enrichissement, puis traiter la suite dans des tours ultérieurs. Usage de any : garantir une sortie structurée quand plusieurs schémas d'extraction existent et que le type de document est inconnu.

# tool_choice : trois régimes
client.messages.create(model=M, tools=TOOLS, tool_choice={"type": "auto"}, ...)   # outil OU texte
client.messages.create(model=M, tools=TOOLS, tool_choice={"type": "any"}, ...)    # un outil, au choix
client.messages.create(model=M, tools=TOOLS,
                       tool_choice={"type": "tool", "name": "extract_metadata"}, ...)  # CET outil

# Séquence forcée : métadonnées d'abord, enrichissement ensuite (tours séparés)
meta = call(tool_choice={"type": "tool", "name": "extract_metadata"}, doc=doc)
enriched = call(tool_choice={"type": "any"}, doc=doc, context=meta)   # enrichissement libre parmi les outils

# Outil scopé transverse pour l'agent de synthèse (question 9 du guide)
VERIFY_FACT = {
    "name": "verify_fact",
    "description": ("Vérifie UN fait simple (date, nom, chiffre) contre les sources déjà collectées. "
                    "N'effectue PAS de recherche web. Pour une investigation approfondie, "
                    "renvoyer la question au coordinateur."),
    "input_schema": {"type": "object", "properties": {"claim": {"type": "string"}},
                     "required": ["claim"]},
}

tool_choice : lequel, quand ?

 auto / anyforcé {type: tool, name}
autoOutil ou texte libre — conversation normale
anyUn outil obligatoire, le modèle choisit — sortie structurée avec plusieurs schémas possibles
Garantir UN outil précisNon garantiOui — extraction imposée avant enrichissement
Réponse texte possibleauto : oui · any : nonNon
Étapes suivantesMême tourTours ultérieurs, avec le résultat forcé en contexte
Signal d'examen« doit renvoyer du structuré », « type de document inconnu »« s'assurer que X s'exécute en premier »
Le piège 2.3. « Donner à l'agent de synthèse l'accès à tous les outils de recherche pour supprimer les allers-retours » : ça règle la latence et casse la séparation des rôles — jamais accepté. Autre piège : confondre any et forcé. any garantit un appel d'outil, pas lequel. Si l'énoncé dit « s'assurer que extract_metadata est appelé en premier », c'est le mode forcé.
🎛️
Le réflexe 2.3
4-5 outils par rôle. Générique dangereux → version contrainte. Besoin transverse fréquent → un outil scopé, complexe → via le coordinateur. auto = texte possible, any = un outil obligatoire, forcé = cet outil précis.

2.4 — Intégrer des serveurs MCP dans Claude Code et les agents

Section factuelle : où se configure quoi, comment on gère les secrets, ce que voit l'agent, et quand écrire un serveur soi-même.

Portées de configuration MCP et découverte des outils
Projet · .mcp.json (racine du dépôt) • Versionné → partagé par toute l'équipe • Outillage commun : Jira, GitHub, base interne • Secrets : "${GITHUB_TOKEN}" — expansion env • Jamais un token en clair dans le fichier Un nouvel arrivant clone → il a les serveurs Utilisateur · ~/.claude.json • Personnel → non partagé, hors dépôt • Serveurs expérimentaux, outils perso • Disponible sur tous les projets de l'utilisateur • Un outil d'équipe mis ici = invisible aux autres Erreur classique de diagnostic (cf. domaine 3) Connexion → découverte tous les serveurs, tous les outils, simultanément Agent : outils Jira + outils GitHub + outils perso + built-in — un seul catalogue
Le fichier .mcp.json à la racine du projet est versionné et partagé par l'équipe ; les secrets y passent par expansion de variables d'environnement, jamais en clair. Le fichier ~/.claude.json est personnel : serveurs expérimentaux, non partagés. À la connexion, les outils de TOUS les serveurs configurés sont découverts et disponibles simultanément.

Ce qu'il faut savoir

Deux portées. .mcp.json à la racine du projet : partagé via le contrôle de version, pour l'outillage d'équipe. ~/.claude.json : niveau utilisateur, pour les serveurs personnels ou expérimentaux. Un serveur d'équipe placé au niveau utilisateur n'est pas vu par les coéquipiers — c'est un motif de question de diagnostic.

Secrets par expansion. Dans .mcp.json, un token s'écrit "${GITHUB_TOKEN}" et se résout depuis l'environnement. Le fichier reste committable sans exposer de secret.

Découverte simultanée. À la connexion, les outils de tous les serveurs configurés sont découverts et disponibles ensemble. Il n'y a pas de « serveur actif » à basculer.

Outils vs ressources. Un outil MCP exécute une action (créer un ticket, lancer une requête). Une ressource MCP expose du contenu consultable : un catalogue de tickets, une hiérarchie de documentation, un schéma de base de données. Exposer un catalogue en ressource évite à l'agent une série d'appels d'outils exploratoires pour découvrir ce qui existe.

La description qui perd face à Grep. Si ton serveur MCP expose un outil de recherche sémantique sur le codebase mais que sa description dit « searches code », l'agent préférera le built-in Grep, qu'il connaît. Il faut décrire les capacités et les sorties en détail (« recherche sémantique par intention, renvoie les fonctions pertinentes avec leur signature et leurs appelants, là où Grep ne fait que du motif textuel »).

Communautaire vs custom. Pour une intégration standard (Jira, GitHub, Slack), on prend un serveur communautaire existant. On n'écrit un serveur custom que pour un workflow spécifique à l'équipe qu'aucun serveur ne couvre.

// .mcp.json — à la racine du projet, versionné
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" }
    },
    "jira": {
      "command": "npx",
      "args": ["-y", "mcp-server-jira"],
      "env": { "JIRA_BASE_URL": "${JIRA_URL}", "JIRA_API_TOKEN": "${JIRA_TOKEN}" }
    }
  }
}
# Serveur MCP custom (sketch) : un OUTIL pour agir, une RESSOURCE pour exposer un catalogue
@server.tool(
    name="search_codebase_semantic",
    description=("Recherche SÉMANTIQUE par intention dans le codebase (ex. 'où est validée l'adresse "
                 "de livraison'). Renvoie les fonctions pertinentes avec fichier, signature, appelants "
                 "et score. À préférer à Grep quand on ne connaît pas le nom exact du symbole ; "
                 "Grep reste le bon choix pour un motif textuel précis."),
)
def search_codebase_semantic(query: str, top_k: int = 5) -> dict: ...

@server.resource(uri="issues://open", name="Tickets ouverts",
                 description="Catalogue des tickets ouverts : id, titre, priorité, assigné. "
                             "Lire cette ressource avant tout appel de get_issue.")
def open_issues_catalog() -> str: ...
Le piège 2.4. « L'agent n'utilise pas notre outil MCP de recherche pourtant plus puissant que Grep : il faut désactiver Grep. » Non — la réponse est d'améliorer la description de l'outil MCP. Autre piège : « écrire un serveur MCP custom pour Jira » quand un serveur communautaire existe. Et le classique : un token GitHub en clair dans .mcp.json « pour simplifier ». Toute option qui commite un secret est fausse.

2.5 — Les outils built-in : Read, Write, Edit, Bash, Grep, Glob

Le scénario 4 (Developer Productivity) repose sur ces six outils. Les questions testent le choix du bon outil pour une intention donnée, et la stratégie d'exploration d'un codebase.

Quel built-in pour quelle intention ?
Grep — contenu « qui appelle processRefund ? » « où est le message 'Invalid token' ? » « quels fichiers importent stripe ? » motif dans le texte des fichiers Glob — chemins « tous les tests : **/*.test.tsx » « les migrations : db/migrations/*.sql » « les configs : **/config.*.json » motif sur le nom / l'extension Bash — exécution npm test · pytest · git diff build, lint, scripts tout ce qui n'est pas lire/écrire/chercher à restreindre dans allowed-tools si besoin Modifier un fichier Edit remplace une ancre de texte UNIQUE ancre trouvée exactement 1 fois ? oui Edit appliqué non (0 ou plusieurs) Repli : Read (fichier entier) + Write modification fiable sans dépendre de l'unicité Explorer un codebase : Grep (points d'entrée) → Read (suivre les imports) — jamais tout lire d'un coup
Grep cherche DANS les fichiers (un nom de fonction, un message d'erreur, un import). Glob cherche DES fichiers par motif de chemin. Edit modifie par correspondance de texte unique ; si l'ancre n'est pas unique, on lit le fichier entier (Read) et on le réécrit (Write). Bash pour tout le reste : tests, build, git.

Ce qu'il faut savoir

Grep vs Glob. Grep cherche un motif dans le contenu des fichiers : tous les appelants d'une fonction, un message d'erreur, une instruction d'import. Glob cherche des chemins par motif de nom : **/*.test.tsx, db/migrations/*.sql. « Trouve tous les fichiers de test » = Glob. « Trouve où processRefund est appelé » = Grep.

Read / Write / Edit. Read charge un fichier entier, Write l'écrit entier, Edit fait une modification ciblée par correspondance de texte unique. Quand Edit échoue parce que l'ancre apparaît zéro ou plusieurs fois, le repli fiable est Read du fichier entier puis Write — pas des tentatives d'ancres de plus en plus longues.

L'exploration incrémentale. Pour comprendre un codebase inconnu, on part de Grep pour trouver les points d'entrée, puis Read pour suivre les imports et tracer les flux. Lire tous les fichiers d'emblée sature le contexte (thème repris au domaine 5).

Tracer à travers des modules wrapper. Pour suivre l'usage d'une fonction ré-exportée par plusieurs modules : d'abord identifier tous les noms exportés (le nom d'origine et ses alias), puis chercher chacun dans le codebase. Chercher uniquement le nom d'origine rate les usages via alias.

Le piège 2.5. « Utiliser Glob pour trouver tous les appelants d'une fonction » (Glob ne voit pas le contenu) ou « utiliser Grep pour lister les fichiers de test » (ça marche par accident si le mot "test" est dans le fichier, mais Glob est l'outil). Et sur Edit : une option qui propose « allonger l'ancre jusqu'à ce qu'elle soit unique » est un bricolage ; la réponse attendue est Read + Write.

Les pièges transversaux du domaine 2

Grille de lecture d'une question du domaine 2
Symptôme dans le scénario Réponse attendue Distracteurs mauvais outil appelé, descriptions « minimales » Enrichir les descriptions formats, exemples, frontières « few-shot », « routeur », « fusionner les outils » retries inutiles ou échecs masqués Erreurs structurées catégorie + isRetryable + contexte « retry + statut générique », « renvoyer vide = succès » agent qui utilise un outil hors de son rôle Restreindre par rôle + outil scopé si besoin fréquent « donner tous les outils pour réduire la latence » un coéquipier n'a pas le serveur MCP .mcp.json projet avec ${VAR} pour les secrets « token en clair », « serveur custom pour Jira » Règle d'or : corrige l'INTERFACE de l'outil avant d'ajouter quoi que ce soit autour
Le domaine 2 a une signature : la bonne réponse touche à l'interface de l'outil (description, erreur, scope), pas à une couche ajoutée autour. Identifie le symptôme, remonte à l'interface.
  1. L'interface avant la couche. Description, erreur, scope : trois propriétés de l'outil lui-même. Toute option qui ajoute un composant (routeur, classifieur, cache) sans corriger l'interface est un distracteur.
  2. « First step » = le geste le moins coûteux. Quand l'énoncé demande une première étape, la réponse est celle qui traite la cause racine avec le moins d'effort — presque toujours une description ou une configuration.
  3. Le moindre privilège gagne toujours. Entre une option qui ouvre des accès et une qui les restreint (avec un outil scopé pour le besoin réel), c'est la seconde.
  4. Les secrets ne se commitent pas. Quel que soit le confort, une option qui écrit un token en clair est fausse.

Checklist de la veille

À relire la veille de l'examen — domaine 2
- La description est le mécanisme de sélection : formats d'entrée, exemples de requêtes, cas limites, frontières « X plutôt que Y ». - Chevauchement → renommer (extract_web_results) ou scinder (extract_data_points / summarize_content / verify_claim_against_source). - Routage faux malgré une bonne description → chercher l'instruction à mots-clés dans le prompt système. - Erreur d'outil = isError + errorCategory (transient / validation / business / permission) + isRetryable + message lisible. - Règle métier → retriable: false + message customer-friendly relayable. - Sous-agent : récupération locale des transitoires, propagation uniquement de l'irrésolu, avec partiels + tentatives. - Échec d'accès (timeout) ≠ résultat vide légitime (succès sans correspondance). - 4-5 outils par rôle, pas 18 ; hors rôle = mésusage. - Générique dangereux → version contrainte (fetch_urlload_document). - Besoin transverse fréquent → un outil scopé (verify_fact) ; complexe → via le coordinateur. - tool_choice : auto (texte possible), any (un outil obligatoire), forcé (cet outil). - Forcé pour « X d'abord », puis tours suivants ; any pour garantir du structuré à schéma inconnu. - .mcp.json racine projet = équipe, versionné, ${VAR} ; ~/.claude.json = perso. - Tous les serveurs découverts à la connexion, disponibles simultanément. - Outil = action ; ressource = catalogue consultable (réduit les appels exploratoires). - Outil MCP ignoré au profit de Grep → enrichir sa description. - Communautaire pour le standard (Jira), custom pour le spécifique équipe. - Grep = contenu ; Glob = chemins ; Edit = ancre unique, sinon Read + Write. - Explorer : Grep (entrées) → Read (imports) ; tracer via wrappers : lister les exports puis chercher chaque nom.

Cinq questions-scénario originales, corrigées

Questions écrites par nAIvigate dans l'esprit de l'examen, sans reproduction d'items réels. Cache les corrections, réponds, compare.

Question 1 — Scénario recherche. Ton système a deux outils, analyze_content (« Analyzes content and returns insights ») et analyze_document (« Analyzes a document and returns insights »). Les logs montrent que l'agent les alterne au hasard pour les pages web comme pour les PDF. Meilleure première correction ?

A. Ajouter au prompt système une règle : « pages web → analyze_content, PDF → analyze_document ». B. Renommer analyze_content en extract_web_results avec une description centrée sur les pages web (entrée : URL, sortie : titres, extraits, dates), et préciser dans analyze_document qu'il traite des fichiers fournis. C. Fusionner les deux en analyze_anything avec détection automatique du type. D. Ajouter 6 exemples few-shot de sélection.

📚Correction Q1

B. Chevauchement de descriptions → renommer et différencier. A ajoute une règle à mots-clés qui contourne le mécanisme de sélection. C est une décision d'architecture disproportionnée pour une première étape. D coûte des tokens sans traiter la cause.

Question 2 — Scénario support. process_refund renvoie « Refund failed » dans tous les cas d'échec. L'agent réessaie trois fois les remboursements refusés pour dépassement de délai, puis dit au client « une erreur technique est survenue ». Quelle correction ?

A. Limiter le retry à une seule tentative. B. Renvoyer une erreur structurée : errorCategory: "business", retriable: false, et un message expliquant le dépassement de délai que l'agent peut relayer. C. Ajouter au prompt : « si le remboursement échoue, ne réessaie pas ». D. Faire remonter l'exception brute au coordinateur.

📚Correction Q2

B. L'erreur uniforme empêche toute décision de récupération. A et C traitent le symptôme (le retry) sans donner à l'agent l'information pour réagir correctement. D propage sans structurer.

Question 3 — Scénario recherche. L'agent de synthèse dispose de 14 outils, dont web_search et fetch_url. On observe qu'il lance des recherches au lieu de synthétiser, et qu'il a récupéré des URLs hors corpus. Que faire ?

A. Retirer tous les outils sauf ceux de rédaction et de citation ; ajouter un verify_fact scopé pour les vérifications simples ; remplacer fetch_url côté recherche par load_document qui valide l'URL. B. Ajouter au prompt de la synthèse : « n'utilise pas web_search sauf nécessité ». C. Augmenter le contexte pour que l'agent voie mieux les 14 descriptions. D. Faire passer toutes les vérifications par le coordinateur, sans exception.

📚Correction Q3

A. Scope par rôle + outil scopé transverse + version contrainte du générique. B est probabiliste. C confond taille de contexte et complexité de décision. D ignore le besoin fréquent et recrée la latence de la question 9.

Question 4 — Scénario productivité. Un développeur a configuré le serveur MCP Jira de l'équipe dans ~/.claude.json avec son token en clair. Un nouveau collègue clone le dépôt et n'a aucun outil Jira. Configuration correcte ?

A. Demander au collègue de copier le bloc dans son ~/.claude.json. B. Déplacer la configuration dans .mcp.json à la racine du projet, avec "${JIRA_TOKEN}" résolu depuis l'environnement de chacun. C. Mettre .mcp.json à la racine avec le token en clair, le dépôt étant privé. D. Écrire un serveur MCP custom pour Jira embarquant les credentials.

📚Correction Q4

B. Outillage d'équipe → portée projet, versionnée, secrets par expansion. A ne passe pas à l'échelle. C commite un secret. D réinvente un serveur communautaire existant et embarque des credentials.

Question 5 — Scénario productivité. Tu veux modifier une ligne return null; dans un fichier de 900 lignes. Edit échoue : l'ancre apparaît 11 fois. Approche fiable ?

A. Allonger l'ancre en incluant les 3 lignes précédentes et réessayer. B. Utiliser Grep pour trouver la bonne occurrence, puis Edit avec le numéro de ligne. C. Read le fichier entier, appliquer la modification, Write le fichier. D. Utiliser Bash avec sed pour remplacer la 7e occurrence.

📚Correction Q5

C. Le repli documenté quand Edit ne trouve pas d'ancre unique est Read + Write. A est un bricolage fragile. B : Edit fonctionne par correspondance de texte, pas par numéro de ligne. D est risqué et hors du pattern attendu.

Quiz de validation

🧠 Quiz
Question 1 sur 8

L'agent confond deux outils aux descriptions minimales. Première étape attendue ?

📚Lexique du domaine 2 (déroulez)

Description d'outil — Texte que le modèle utilise pour choisir un outil ; doit contenir formats d'entrée, exemples de requêtes, cas limites et frontières avec les outils voisins.

Frontière (boundary) — Partie de la description qui dit quand ne PAS utiliser cet outil et lequel utiliser à la place.

Chevauchement fonctionnel — Deux outils aux descriptions quasi identiques, source de mauvais routage ; se corrige en renommant ou en scindant.

Instruction à mots-clés — Consigne du prompt système qui associe un mot à un outil et peut supplanter une bonne description.

isError — Drapeau MCP signalant qu'un appel d'outil a échoué, distinct d'une erreur de protocole.

errorCategory — Métadonnée d'erreur : transient, validation, business ou permission ; détermine la réaction de l'agent.

isRetryable / retriable — Booléen indiquant si un nouvel essai a une chance de réussir.

Erreur transitoire — Timeout, indisponibilité, rate limit : réessayable avec backoff.

Erreur de validation — Entrée invalide (format, identifiant inconnu) : corriger l'entrée avant tout nouvel essai.

Erreur métier (business) — Violation d'une règle (délai, plafond) : non réessayable, à expliquer au client.

Erreur de permission — Droits insuffisants : non réessayable, à escalader.

Résultat vide légitime — Requête réussie sans correspondance ; n'est pas une erreur et ne déclenche ni retry ni escalade.

Récupération locale — Gestion des erreurs transitoires par le sous-agent lui-même avant toute propagation.

Scope d'outils — Restriction de chaque agent aux seuls outils de son rôle (4-5), pour fiabiliser la sélection.

Outil scopé transverse — Outil limité (ex. verify_fact) donné à un agent hors de son rôle principal pour un besoin fréquent et simple.

Outil contraint — Version restreinte d'un outil générique (load_document validant l'URL au lieu de fetch_url).

tool_choice — Paramètre de l'API Messages : auto (outil ou texte), any (un outil obligatoire), forcé ({"type":"tool","name":…}).

.mcp.json — Configuration MCP au niveau projet, versionnée, partagée par l'équipe, avec secrets en ${VAR}.

~/.claude.json — Configuration MCP au niveau utilisateur, personnelle, non partagée.

Expansion de variables d'environnement — Syntaxe ${GITHUB_TOKEN} résolue à l'exécution pour ne jamais committer un secret.

Ressource MCP — Contenu consultable exposé par un serveur (catalogue de tickets, hiérarchie de docs, schéma BDD), par opposition à un outil qui agit.

Serveur communautaire — Serveur MCP existant pour une intégration standard (Jira, GitHub) ; à préférer à un serveur custom.

Grep — Outil built-in de recherche de motif dans le contenu des fichiers.

Glob — Outil built-in de recherche de fichiers par motif de chemin (**/*.test.tsx).

Edit — Modification ciblée par correspondance de texte unique ; repli Read + Write si l'ancre n'est pas unique.

Exploration incrémentale — Grep pour les points d'entrée puis Read pour suivre les imports, au lieu de tout lire d'emblée.

Pour aller plus loin

La suite est le Domaine 3 — Claude Code Configuration & Workflows (20 %), qui reprend la portée projet/utilisateur pour CLAUDE.md, les commandes, les skills et les règles par chemin. Les erreurs structurées et la propagation reviennent au domaine 5, et tool_choice au domaine 4 pour la sortie structurée. Pour voir des outils MCP réels décrits et scopés, notre fiche 40 outils Claude Code / MCP et la formation architecture des systèmes agentiques donnent le contexte.

Si tu veux certifier une équipe entière — ou faire concevoir des interfaces d'outils MCP propres (descriptions, erreurs structurées, scopes) pour un système réellement déployé — c'est ce que nAIvigate Studio fait en Sprint.

Tags
certificationclaudeccacca-fmcpagents-iaagentssdkclaude-codeformationpython
⚡ FICHE #005Skills & MCP : la fiche qui référence tout le parcours2 MIN

À lire ensuite