WIKI
CCAR-F Claude Certified Architect

02 · Concevoir les outils et intégrer MCP

32 min de lecture Mis à jour le 21 octobre 2026
Sur cette page

Version : 1.1 · Date : 2026-10-21 · Domaine 2 : Tool Design & MCP Integration (18 %)

En une phrase : Claude choisit un outil d'après son nom et sa description, votre code l'exécute et lui renvoie un résultat (ou une erreur structurée qui dit quoi faire ensuite) ; chaque agent ne reçoit que les 4 ou 5 outils de son rôle ; MCP branche ces outils sur Claude Code et l'Agent SDK sans code d'intégration, avec un .mcp.json d'équipe qui ne contient jamais de secret.

Le cycle tool use : Claude demande, votre code exécute

Ce que l'examen demande#

Texte officiel du Claude Certified Architect – Foundations Exam Guide v1.0 (juillet 2026), domaine 2 :

TS Task statement (guide officiel, en anglais) Section
2.1 Design effective tool interfaces with clear descriptions and boundaries 2
2.2 Implement structured error responses for MCP tools 3
2.3 Distribute tools appropriately across agents and configure tool choice 4
2.4 Integrate MCP servers into Claude Code and agent workflows 5
2.5 Select and apply built-in tools (Read, Write, Edit, Bash, Grep, Glob) effectively 6

Scénarios d'examen où ce domaine pèse le plus : 1 Customer Support Resolution Agent (outils MCP get_customer, lookup_order, process_refund, escalate_to_human), 3 Multi-Agent Research System et 4 Developer Productivity with Claude (outils intégrés et serveurs MCP). Voir 06-scenarios-examen.md.

Réponse d'examen ou état actuel. Le guide v1.0 date de juillet 2026 et le produit a évolué depuis. À l'examen, on répond selon le guide. Dans ce chapitre, chaque écart est signalé par un encadré « Réponse d'examen / État actuel », vérifié sur la documentation officielle le 21/10/2026.


1. Les bases : tool use et MCP en dix minutes#

1.1 Client tools et server tools#

Tool use (ou function calling) permet à Claude d'appeler des fonctions. Claude décide quand appeler un outil à partir de la demande et de la description de l'outil, puis renvoie un appel structuré.

Client tools Server tools
Qui exécute Votre application L'infrastructure d'Anthropic
Exemples Vos outils (get_customer), bash, text_editor, memory web_search, web_fetch, code_execution, tool_search
Ce que vous gérez Lire le tool_use, exécuter, renvoyer un tool_result Rien : le résultat arrive dans la même réponse

C'est ce que l'examen teste : vos propres outils, donc des client tools.

1.2 Le cycle, pas à pas#

sequenceDiagram
    participant U as Utilisateur
    participant A as Votre application
    participant C as Claude API
    U->>A: demande
    A->>C: messages + tools (name, description, input_schema)
    C-->>A: stop_reason = tool_use, bloc tool_use (id, name, input)
    A->>A: exécute l'outil
    A->>C: message user avec tool_result (tool_use_id, content, is_error)
    C-->>A: stop_reason = end_turn, réponse finale
    A-->>U: réponse

Règles de format à connaître (doc Handle tool calls) :

  • Le tool_result reprend le tool_use_id de l'appel et suit immédiatement le message assistant qui contient le tool_use.
  • Dans le message user, les blocs tool_result viennent en premier ; un texte éventuel vient après.
  • is_error: true signale un échec ; le content explique ce qui s'est passé et quoi essayer ensuite.
  • La boucle continue tant que stop_reason vaut "tool_use" : c'est le sujet de la boucle agentique (01-agentic-architecture.md).

1.3 Une définition d'outil#

{
  "name": "lookup_order",
  "description": "Retrieves one order by its order ID and returns status, items, amount and shipping date. Use it when the customer mentions an order, a delivery or a refund for a specific order. Order IDs look like ORD-12345. It does not return customer profile data: use get_customer for name, email or account status. If the order ID is unknown, ask the customer for it instead of guessing.",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string", "description": "Order ID, format ORD- followed by 5 digits, e.g. ORD-12345" }
    },
    "required": ["order_id"]
  }
}
  • name : ^[a-zA-Z0-9_-]{1,128}$.
  • input_schema : un JSON Schema.
  • Champs optionnels : input_examples (exemples validés par le schéma, utiles pour les entrées complexes), strict: true (entrées garanties conformes au schéma), defer_loading (tool search), cache_control.

Côté résultat :

{
  "role": "user",
  "content": [
    { "type": "tool_result", "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
      "content": "Order service timeout after 10 s. Retry once in 30 seconds.", "is_error": true }
  ]
}

1.4 MCP en une image#

Le Model Context Protocol (MCP) standardise la façon dont une application d'IA, le MCP host (Claude Code, Claude Desktop, votre application Agent SDK), se connecte à des MCP servers qui exposent des tools, des resources et des prompts. Le host crée un MCP client par serveur. Le détail est dans la section 5.

Terme Ce que c'est
MCP server Programme qui expose des tools, resources, prompts (local en stdio, distant en Streamable HTTP)
tools/list, tools/call Découverte puis appel d'un outil (JSON-RPC 2.0)
isError Champ du résultat MCP qui signale une erreur d'exécution d'outil (équivalent du is_error de l'API)
.mcp.json Fichier de configuration MCP du projet, versionné dans le dépôt
mcp__{serveur}__{outil} Nom complet d'un outil MCP dans Claude Code et l'Agent SDK

2. TS 2.1 : des interfaces d'outils claires#

2.1 Ce que l'examen teste#

  • La description est le premier mécanisme dont le modèle se sert pour choisir un outil ; une description minimale rend le choix peu fiable entre outils proches.
  • Une bonne description contient les formats d'entrée, des exemples de requêtes, les cas limites et les frontières avec les outils voisins.
  • Des descriptions ambiguës ou qui se recouvrent causent du mauvais routage (analyze_content contre analyze_document).
  • La formulation du system prompt compte : une consigne à mots-clés peut créer une association d'outil non voulue.
  • Savoir renommer, scinder un outil fourre-tout, et relire le system prompt.

Une description d'outil qui oriente le bon choix

2.2 La description d'abord#

La doc officielle est nette : des descriptions « extrêmement détaillées » sont de loin le facteur le plus important pour la performance des outils. Elles disent ce que fait l'outil, quand l'utiliser et quand ne pas l'utiliser, ce que signifie chaque paramètre, et les limites (ce que l'outil ne renvoie pas). Visez au moins 3 ou 4 phrases par outil.

Avant / après, dans le scénario support client :

Outil Avant (mal routé) Après
get_customer « Gets customer info. » « Returns the customer profile (name, email, tier, account status) for a customer ID (CUS-…) or an email. Use it to identify or verify the customer. It does not return orders: use lookup_order for anything about a specific order, delivery or refund. »
lookup_order « Looks up an order. » Voir la définition complète en 1.3

La frontière explicite (« pour X, utilise plutôt Y ») est l'élément qui corrige le plus directement un mauvais routage entre deux outils voisins.

2.3 Renommer, scinder, consolider#

Situation Correction Exemple du guide
Deux outils aux noms et descriptions presque identiques Renommer et réécrire la description analyze_content → extract_web_results (description propre au web)
Un outil générique qui fait tout Scinder en outils à contrat d'entrée/sortie défini analyze_document → extract_data_points, summarize_content, verify_claim_against_source
Plusieurs variantes d'une même opération Consolider en un outil avec un paramètre action (doc actuelle) create_pr, review_pr, merge_pr → un outil

Scinder et consolider ne se contredisent pas : on scinde ce qui fait des choses différentes derrière un même nom, on consolide des variantes de la même opération. Le guide teste surtout le renommage et la scission ; la consolidation et le namespacing par service (github_list_prs, slack_send_message) viennent de la doc et de l'article Writing tools for agents.

2.4 Le system prompt peut défaire une bonne description#

Une consigne comme « analyse toujours le contenu avant de répondre » pousse le modèle vers tout outil nommé analyze_*, même avec de bonnes descriptions. Après avoir réécrit les descriptions, relisez le system prompt et retirez les mots-clés qui orientent vers un outil précis.

2.5 Le bon ordre des corrections#

Quand deux outils sont confondus, l'examen attend la correction la moins chère et la plus directe :

  1. Enrichir les descriptions (formats, exemples, frontières).
  2. Renommer ou scinder si les outils se recouvrent vraiment.
  3. Seulement ensuite : few-shot, classifieur de routage, fusion d'outils. Ce sont des réponses piège en premier recours (coût, complexité, ou traitement du symptôme).

Réponse d'examen / État actuel. Le guide illustre la surcharge par « 18 outils au lieu de 4-5 » (voir 4.1). La doc actuelle du tool search tool indique que la précision de choix se dégrade au-delà de 30 à 50 outils et propose de charger les outils à la demande (defer_loading: true). À l'examen, retenez le cadrage du guide.


3. TS 2.2 : des erreurs structurées pour les outils MCP#

3.1 Ce que l'examen teste#

  • Le mécanisme isError de MCP pour signaler un échec d'outil à l'agent.
  • Quatre familles : transient (timeout, indisponibilité), validation (entrée invalide), business (règle métier), permission.
  • Pourquoi un message uniforme (« Operation failed ») empêche l'agent de choisir la bonne reprise.
  • La différence entre retryable et non-retryable, et comment les métadonnées évitent des réessais inutiles.
  • Savoir renvoyer errorCategory, isRetryable et une description lisible ; retriable: false avec une explication présentable au client pour une règle métier ; récupérer localement dans le subagent ; distinguer échec d'accès et résultat vide valide.

Les erreurs d'un outil MCP : une catégorie, une décision

3.2 Deux couches d'erreur dans MCP#

Protocol error Tool execution error
Cas Outil inconnu, requête mal formée, panne du serveur L'outil a tourné et a échoué : API en panne, entrée refusée, règle métier
Forme Réponse JSON-RPC error (code, message) result avec isError: true et un content explicatif
Qui la traite L'application hôte ; le client peut la transmettre au modèle Le modèle, que le client devrait informer pour qu'il se corrige

Règle pratique du SDK Python MCP : « un modèle plus intelligent aurait-il pu éviter cette erreur ? » Si oui, c'est une erreur d'exécution d'outil (le modèle la voit et corrige) ; sinon, une erreur de protocole.

3.3 Les quatre catégories et isRetryable#

isRetryable répond à une seule question : renvoyer exactement le même appel peut-il réussir ?

errorCategory Exemple isRetryable Reprise attendue
transient timeout, service indisponible true Réessayer après un délai (dans le subagent)
validation ID mal formé, date dans le passé false Corriger l'entrée, puis un nouvel appel
business remboursement au-delà du plafond, politique false Expliquer au client, chemin alternatif, escalade
permission accès refusé false Escalader ou utiliser d'autres droits

false ne veut pas dire « abandonner » : cela veut dire « pas cet appel une deuxième fois ».

Réponse d'examen / État actuel. Le guide donne errorCategory (transient/validation/permission) et isRetryable, et retriable: false pour une règle métier. Ces champs sont une convention applicative, pas des champs de la spécification MCP : la spec définit seulement isError et un content (plus un structuredContent facultatif). Vous les placez dans le texte du résultat ou dans structuredContent.

3.4 À quoi ressemble une bonne erreur#

Résultat MCP d'une règle métier (le modèle le voit) :

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [{ "type": "text", "text": "{\"errorCategory\": \"business\", \"isRetryable\": false, \"description\": \"Refunds above 500 USD need a human agent.\", \"customerMessage\": \"This refund needs a quick review by our team. I'm transferring you now.\"}" }],
    "isError": true
  }
}

Résultat vide valide, à ne surtout pas présenter comme une erreur :

{ "content": [{ "type": "text", "text": "{\"resultCount\": 0, \"customers\": []}" }], "isError": false }

Le même outil avec le SDK Python officiel (classe MCPServer) : une ToolError devient un résultat isError: true que le modèle voit, alors qu'un retour normal reste un succès.

import json
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ToolError

mcp = MCPServer("support")

def erreur(categorie: str, reessayable: bool, description: str) -> ToolError:
    # Métadonnées lisibles par l'agent : il choisit la reprise sans deviner
    return ToolError(json.dumps({"errorCategory": categorie, "isRetryable": reessayable, "description": description}))

@mcp.tool()
def search_customers(email: str) -> str:
    """Finds customer accounts by exact email address. Returns a JSON list of matching customers
    (id, name, tier). An empty list means no account uses this email: do not retry, ask the customer."""
    if "@" not in email:
        raise erreur("validation", False, "Email must contain '@', e.g. [email protected]")
    try:
        comptes = crm.find_by_email(email)          # appel au CRM (votre code)
    except TimeoutError:
        raise erreur("transient", True, "CRM timeout after 10 s, retry in 30 s")
    return json.dumps({"resultCount": len(comptes), "customers": comptes})  # 0 résultat = succès

if __name__ == "__main__":
    mcp.run(transport="stdio")

Le tutoriel officiel Build an MCP server renvoie "Unable to fetch alerts or no alerts found." dans un seul message : c'est exactement la confusion « échec d'accès / résultat vide » que l'examen demande de corriger.

3.5 Récupérer localement, remonter le reste#

flowchart TD
    A["Le subagent reçoit isError: true"] --> B{"isRetryable ?"}
    B -->|"oui (transient)"| C["Réessai local avec délai, nombre limité"]
    C --> D{"Réussi ?"}
    D -->|"oui"| E["Continue la tâche"]
    D -->|"non"| F["Remonte au coordinateur : type d'échec, requête tentée, résultats partiels"]
    B -->|"non"| G{"Catégorie"}
    G -->|"validation"| H["Corrige l'entrée, nouvel appel"]
    G -->|"business"| I["Explique au client, chemin alternatif ou escalade"]
    G -->|"permission"| F

Deux anti-patterns, tous deux testés : masquer l'erreur (renvoyer un résultat vide comme un succès : le coordinateur ne sait plus distinguer « rien trouvé » de « recherche impossible ») et tout arrêter au premier échec. La propagation entre agents est détaillée au domaine 5 (05-context-reliability.md, TS 5.3).


4. TS 2.3 : répartir les outils et régler tool_choice#

4.1 Ce que l'examen teste#

  • Trop d'outils (18 au lieu de 4-5) dégrade la fiabilité du choix.
  • Un agent qui a des outils hors de sa spécialité les utilise mal (un agent de synthèse qui lance des recherches web).
  • Scoped tool access : seulement les outils du rôle, plus quelques outils transverses limités pour des besoins fréquents.
  • Les options de tool_choice : "auto", "any", et la sélection forcée {"type": "tool", "name": "..."}.
  • Remplacer un outil générique par une version contrainte (fetch_url → load_document qui valide les URL de documents).

Répartir les outils : 4 à 5 par agent, selon son rôle

4.2 Un rôle, un petit jeu d'outils#

Principe Pourquoi Exemple
4-5 outils par agent, propres au rôle Moins de décisions, moins d'erreurs de choix Le subagent web n'a que search_web, fetch_page, extract_links, save_snippet
Pas d'outil hors spécialité Il serait mal utilisé L'agent de synthèse n'a pas search_web
Outil contraint plutôt que générique Moindre privilège, moins d'usages détournés load_document (URL de documents seulement) plutôt que fetch_url
Outil transverse limité pour le fréquent Évite les allers-retours par le coordinateur verify_fact sur l'agent de synthèse pour les vérifications simples ; le complexe repasse par le coordinateur
Le coordinateur délègue Il garde la vue d'ensemble Outils Agent (ex-Task), revue, demande de révision

Ajouter un serveur MCP de plus ne règle pas une surcharge : le client présente tous les outils à plat au modèle.

Dans l'Agent SDK, on restreint les outils d'un subagent dans sa définition (tools d'un AgentDefinition), et on autorise les outils MCP par leur nom complet dans allowedTools :

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    mcp_servers={"docs": {"command": "python", "args": ["docs_server.py"]}},
    allowed_tools=["mcp__docs__load_document", "mcp__docs__extract_metadata"],  # seulement ces deux outils
)

4.3 tool_choice#

tool_choice : laisser choisir, imposer un appel ou imposer un outil

Valeur Effet Usage type
{"type": "auto"} Claude choisit : un outil ou du texte (défaut quand tools est fourni) Cas général
{"type": "any"} Un outil obligatoire, Claude choisit lequel Garantir un appel plutôt qu'une réponse conversationnelle (extraction parmi plusieurs schémas)
{"type": "tool", "name": "extract_metadata"} Cet outil-là Imposer le premier outil, puis auto aux tours suivants
{"type": "none"} Aucun outil (défaut sans tools) Forcer une réponse texte

Sélection forcée au premier tour, puis retour à auto :

premier = client.messages.create(
    model=MODELE, max_tokens=1024, tools=outils, messages=messages,
    tool_choice={"type": "tool", "name": "extract_metadata"},  # métadonnées d'abord
)
# … exécuter extract_metadata, ajouter le tool_result à messages …
suite = client.messages.create(
    model=MODELE, max_tokens=1024, tools=outils, messages=messages,
    tool_choice={"type": "auto"},                               # enrichissement librement ensuite
)

Réponse d'examen / État actuel. Le guide attend any pour garantir un appel et la sélection forcée pour imposer l'ordre. La doc actuelle précise : avec any ou tool, l'API préremplit la réponse, donc pas de texte ni de thinking avant l'appel ; le thinking manuel (thinking: {type: "enabled"}) les refuse ; Claude Opus 5.5, Claude Sonnet 5.5 et Claude Fable 5.1 renvoient une erreur 400 pour any et tool, y compris sur count_tokens et dans les lots (Claude Opus 5, Claude Fable 5 et Claude Haiku 5.5 les acceptent encore). Sur ces modèles, on utilise auto avec strict tool use (strict: true) ou les structured outputs, et le prompt nomme l'outil attendu. auto ne garantit pas l'appel : le code vérifie qu'un tool_use est bien revenu et relance sinon.


5. TS 2.4 : intégrer des serveurs MCP#

5.1 Ce que l'examen teste#

  • Portées : .mcp.json (projet) pour l'outillage d'équipe ; ~/.claude.json (utilisateur) pour le personnel et l'expérimental.
  • Expansion des variables d'environnement dans .mcp.json (${GITHUB_TOKEN}) pour ne jamais committer de secret.
  • Les outils de tous les serveurs configurés sont découverts à la connexion et disponibles en même temps.
  • Les MCP resources exposent des catalogues (résumés d'issues, arborescence de doc, schémas de base) pour éviter les appels exploratoires.
  • Préférer un serveur communautaire pour une intégration standard (Jira) ; réserver le serveur maison aux workflows propres à l'équipe.
  • Enrichir les descriptions des outils MCP pour que l'agent ne leur préfère pas un outil intégré (Grep) moins adapté.

MCP : un host, un client par serveur, trois primitives

5.2 Architecture et transports#

Élément Rôle
MCP host L'application d'IA (Claude Code, Claude Desktop, votre app Agent SDK)
MCP client Un par serveur, connexion dédiée
MCP server Expose ses primitives ; local ou distant
stdio Serveur local lancé comme processus ; échanges sur stdin/stdout. Ne jamais écrire sur stdout (logs sur stderr)
Streamable HTTP Serveur distant ; transport recommandé pour le distant. SSE est déprécié côté Claude Code
Primitive Contrôlée par Pour quoi faire
Tools Le modèle Agir : tools/call
Resources L'application Donner du contexte : catalogues, schémas, documents (resources/read)
Prompts L'utilisateur Modèles d'invite réutilisables, exposés en commandes dans Claude Code

La découverte, l'hébergement et l'authentification OAuth des serveurs sont hors programme. L'examen porte sur la configuration et la conception des outils et resources.

5.3 Portées et .mcp.json#

Où déclarer un serveur MCP, et où mettre ses secrets

.mcp.json à la racine du dépôt (versionné, partagé avec l'équipe) :

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
    },
    "jira": {
      "command": "npx",
      "args": ["-y", "{serveur-jira-communautaire}"],
      "env": { "JIRA_API_TOKEN": "${JIRA_API_TOKEN}", "JIRA_URL": "${JIRA_URL:-https://jira.example.com}" }
    }
  }
}
  • Un serveur distant déclare "type": "http" et une url ; un serveur local déclare command et args (stdio).
  • ${VAR} est remplacé au chargement ; ${VAR:-défaut} donne une valeur par défaut. L'expansion vaut pour command, args, env, url et headers.
  • Chacun définit ses tokens localement (profil shell, .env ignoré par Git, gestionnaire de secrets). La rotation d'un token ne change pas le fichier.

Ajouter un serveur en ligne de commande :

# Serveur d'équipe, écrit dans .mcp.json
claude mcp add --transport http --scope project github https://api.githubcopilot.com/mcp/

# Serveur personnel en stdio (le "--" sépare les options de Claude de la commande du serveur)
claude mcp add --scope user --env NOTES_DIR=/home/moi/notes mes-notes -- python notes_server.py

claude mcp list      # état des serveurs, avertissement si une variable manque

Réponse d'examen / État actuel. Le guide présente deux niveaux : projet (.mcp.json) et utilisateur (~/.claude.json). Claude Code en a aujourd'hui trois, choisis par -s / --scope :

  • local (par défaut) : ce projet, pour vous seul, stocké dans ~/.claude.json ;
  • project : partagé par .mcp.json ;
  • user : tous vos projets, dans ~/.claude.json.

En cas de doublon de nom, local > project > user, et Claude Code demande une approbation avant d'utiliser un serveur de .mcp.json. Une variable absente sans défaut ne bloque pas le chargement : un avertissement s'affiche dans claude mcp list et ${VAR} reste tel quel. Exception de sécurité : dans url et headers d'un serveur distant, certaines variables d'identifiants sensibles (par exemple ANTHROPIC_API_KEY, NPM_TOKEN) sont lues comme vides.

5.4 Découverte, nommage et Agent SDK#

À la connexion, le host appelle tools/list sur chaque serveur : tous les outils de tous les serveurs sont disponibles ensemble, sans étape d'activation. Chaque outil MCP prend le nom mcp__{serveur}__{outil} (par exemple mcp__github__list_issues), qu'on utilise dans les permissions et dans allowedTools.

Agent SDK (TypeScript), serveurs déclarés dans le code ; un .mcp.json du projet est aussi chargé par défaut :

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "List the 3 most recent issues in our repository",
  options: {
    mcpServers: {
      github: { type: "http", url: "https://api.githubcopilot.com/mcp/",
                headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } }
    },
    allowedTools: ["mcp__github__list_issues"]   // ou "mcp__github__*" pour tout le serveur
  }
})) {
  if (message.type === "system" && message.subtype === "init") console.log(message.mcp_servers); // état de chaque serveur
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Sans permission dans allowedTools, Claude voit les outils MCP mais ne peut pas les appeler.

5.5 Les resources comme catalogue#

Sans resource, un agent qui doit écrire une requête SQL appelle list_tables, puis describe_table pour chaque table. Une resource « schéma » lui donne le catalogue d'un coup.

@mcp.resource("db://schema/main", mime_type="application/json")
def schema_principal() -> str:
    """Full schema of the main database: tables, columns, types, foreign keys."""
    return json.dumps(lire_schema())

@mcp.prompt()
def analyse_incident(ticket_id: str) -> str:
    """Prepare an incident analysis for a ticket."""
    return f"Analyse le ticket {ticket_id} : chronologie, cause probable, actions."

Dans Claude Code, on attache une resource par mention, comme un fichier (@db:db://schema/main, @github:issue://123), et un prompt MCP devient une commande (/mcp__github__pr_review 456).

5.6 Communautaire ou maison, et la concurrence des outils intégrés#

Besoin Choix
Intégration standard (GitHub, Jira, Slack…) Serveur communautaire ou officiel existant : maintenu, testé
Workflow propre à l'équipe, logique métier, système interne sans équivalent Serveur maison

Un outil MCP mal décrit perd face à un outil intégré bien décrit : si search_codebase (MCP, avec index sémantique) n'a qu'une ligne de description, Claude utilisera Grep. La correction attendue est d'enrichir la description de l'outil MCP (capacités, sorties, quand le préférer à Grep), pas d'ajouter une règle de prompt ni de retirer Grep.

5.7 Un serveur MCP minimal en TypeScript#

Le SDK TypeScript officiel (McpServer, schémas zod) ; une erreur d'exécution se renvoie avec isError: true :

import { McpServer } from "@modelcontextprotocol/server";
import { serveStdio } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";

function createServer() {
  const server = new McpServer({ name: "orders", version: "1.0.0" });
  server.registerTool(
    "lookup_order",
    {
      description: "Retrieves one order by ID (format ORD-12345): status, items, amount. Not for customer profiles: use get_customer.",
      inputSchema: z.object({ order_id: z.string().describe("Order ID, e.g. ORD-12345") }),
    },
    async ({ order_id }) => {
      if (!/^ORD-\d{5}$/.test(order_id)) {
        return { isError: true, content: [{ type: "text",
          text: JSON.stringify({ errorCategory: "validation", isRetryable: false, description: "Expected ORD- followed by 5 digits" }) }] };
      }
      const commande = await chercherCommande(order_id);            // votre accès aux données
      return { content: [{ type: "text", text: JSON.stringify(commande ?? { resultCount: 0 }) }] };
    },
  );
  return server;
}

serveStdio(createServer, { onerror: (e) => console.error("orders MCP error:", e) });  // logs sur stderr

État actuel (hors examen). La spécification MCP 2026-07-28 rend le protocole sans état : chaque requête porte sa version et ses capacités dans _meta, et la découverte passe par server/discover. serveStdio gère encore les clients de l'ancienne poignée de main initialize. Rien de cela n'est demandé à l'examen.


6. TS 2.5 : les outils intégrés de Claude Code#

6.1 Ce que l'examen teste#

  • Grep cherche dans le contenu (noms de fonctions, messages d'erreur, imports).
  • Glob cherche des chemins par motif (**/*.test.tsx).
  • Read/Write pour un fichier entier ; Edit pour une modification ciblée par texte unique.
  • Quand Edit échoue (texte non unique) : Read + Write en repli.
  • Comprendre un code par étapes : Grep pour les points d'entrée, Read pour suivre les imports, au lieu de tout lire.
  • Suivre une fonction à travers des modules d'enveloppe : relever tous les noms exportés, puis chercher chacun.

Les outils intégrés de Claude Code : le bon outil pour chaque besoin

6.2 Le bon outil#

Outil Fait Permission (mode manuel) Piège
Glob Trouve des fichiers par motif de nom Non Ne lit pas le contenu : inutile pour trouver des appelants
Grep Cherche un motif dans le contenu (ripgrep) Non Pour trouver des fichiers par extension, c'est Glob
Read Lit un fichier Non Lire tout le dépôt sature le contexte
Edit Remplace un old_string exact et unique Oui Échoue si le texte n'est pas unique (protection voulue)
Write Crée ou écrase un fichier Oui Réécrire un fichier entier coûte du contexte
Bash Exécute une commande Oui Pas un remplaçant de Grep/Glob quand ils sont disponibles

6.3 Explorer par étapes#

sequenceDiagram
    participant C as Claude
    participant R as Dépôt
    C->>R: Grep sur processLegacyOrder
    R-->>C: 6 fichiers appelants, dont lib/orders/index.ts
    C->>R: Read lib/orders/index.ts
    R-->>C: réexport sous le nom handleOrder
    C->>R: Grep sur handleOrder
    R-->>C: 4 appelants de plus, via le nom réexporté
    C->>R: Glob sur les fichiers de test order
    R-->>C: fichiers de test à mettre à jour
    C->>R: Read seulement les fichiers retenus, puis Edit

Le piège des réexports : une fonction définie sous un nom, réexportée sous un autre (fichier barrel), échappe à un Grep sur le nom d'origine. On lit les exports du fichier de définition, puis on cherche chaque nom.

Réponse d'examen / État actuel.

  • Édition : le guide attend Read + Write quand Edit échoue sur un texte non unique. La doc actuelle fait d'abord allonger old_string avec plus de contexte, ou utiliser replace_all: true si toutes les occurrences doivent changer.
  • Disponibilité : sur macOS, Linux et WSL, Glob et Grep sont absents par défaut, et Claude cherche avec find et grep via Bash. Sur Windows, ils sont dans le jeu par défaut. À l'examen, considérez-les comme des outils intégrés.

7. Labs conseillés#

Avec un compte API de test et Claude Code ; coût faible (quelques centimes par lab avec un modèle léger). Ne mettez aucun vrai secret dans les fichiers d'exemple.

Lab 1 : corriger un mauvais routage (TS 2.1, 30 min).

  1. Déclarer get_customer et lookup_order avec une description d'une ligne chacune.
  2. Envoyer 10 demandes variées (« où en est ma commande ORD-12345 ? », « changez mon email »…) et noter l'outil choisi.
  3. Réécrire les deux descriptions avec les 5 éléments et une frontière explicite.
  4. Rejouer les 10 demandes. Résultat attendu : le routage devient correct sans few-shot ni classifieur.

Lab 2 : un serveur MCP avec erreurs structurées (TS 2.2, 45 min).

  1. Écrire search_customers (section 3.4) sur une base factice, avec un paramètre de test qui déclenche chaque catégorie.
  2. Renvoyer transient, validation, business, permission, et un résultat vide valide.
  3. L'ajouter à Claude Code (claude mcp add … -- python serveur.py) et lui demander des recherches. Résultat attendu : Claude réessaie seulement le transient, corrige la validation, explique la règle métier et ne réessaie pas le résultat vide.

Lab 3 : tool_choice et sélection forcée (TS 2.3, 20 min).

  1. Sur un modèle qui accepte la sélection forcée, imposer extract_metadata au premier tour, puis auto.
  2. Essayer any sur une demande conversationnelle. Résultat attendu : un appel d'outil, jamais de texte seul.
  3. Rejouer avec Claude Opus 5.5 ou Sonnet 5.5. Résultat attendu : erreur 400 ; passer à auto + strict: true.

Lab 4 : un .mcp.json d'équipe (TS 2.4, 30 min).

  1. Créer .mcp.json avec un serveur distant et "Authorization": "Bearer ${GITHUB_TOKEN}".
  2. Vérifier avec git diff qu'aucun secret n'est indexé ; lancer claude mcp list sans la variable (avertissement), puis avec.
  3. Ajouter un serveur personnel en portée user. Résultat attendu : /mcp montre les deux serveurs, leurs outils sont disponibles en même temps.

Lab 5 : tracer une fonction dépréciée (TS 2.5, 20 min).

  1. Dans un dépôt de test, renommer une fonction via un fichier index.ts qui la réexporte sous un autre nom.
  2. Demander à Claude Code de lister tous les appelants et leurs tests. Résultat attendu : Grep, Read des exports, Grep du nouveau nom, Glob des tests ; aucun « Read de tout le dépôt ».

8. Pièges d'examen#

Piège Bonne réponse
Deux outils confondus : ajouter des few-shot Enrichir les descriptions d'abord (formats, exemples, frontières)
Deux outils confondus : un classifieur de routage en amont Surdimensionné en premier recours ; corriger les descriptions
Descriptions réécrites mais le mauvais outil persiste Relire le system prompt : une consigne à mots-clés attire l'outil
analyze_document fait extraction, résumé et vérification Scinder en outils à contrat défini
Message d'erreur générique « Operation failed » errorCategory, isRetryable, description lisible
Erreur de validation marquée isRetryable: true false : le même appel échouera encore ; corriger l'entrée
Règle métier réessayée isRetryable: false + explication présentable au client
Recherche sans résultat réessayée 3 fois C'est un succès vide : ne pas réessayer
Subagent qui renvoie [] quand la source est inaccessible Masquage : renvoyer une erreur avec ce qui a été tenté
Subagent qui fait échouer tout le workflow au premier timeout Réessai local, puis erreur structurée avec résultats partiels
18 outils à un seul agent 4-5 outils par rôle
Ajouter un serveur MCP pour « isoler » des outils Le client les présente tous à plat : répartir par agent
Agent de synthèse qui demande toujours au coordinateur de vérifier un fait simple Outil transverse limité verify_fact, le complexe passe par le coordinateur
fetch_url pour charger des documents load_document qui valide les URL
Sortie structurée requise avec tool_choice: auto any (ou un outil forcé) selon le guide
Imposer un premier outil {"type": "tool", "name": ...} puis auto aux tours suivants
Serveur d'équipe dans ~/.claude.json .mcp.json du projet
Token collé dans .mcp.json « parce que le dépôt est privé » ${GITHUB_TOKEN} ; un dépôt privé n'est pas un coffre-fort
Construire un serveur Jira maison Évaluer d'abord un serveur communautaire
L'agent préfère Grep à l'outil MCP plus capable Enrichir la description de l'outil MCP
Appels répétés list_tables / describe_table Exposer le schéma en MCP resource
Glob pour trouver les appelants d'une fonction Grep (contenu)
Grep pour trouver tous les fichiers *.test.tsx Glob (chemins)
Lire tous les fichiers avant d'analyser Exploration incrémentale
Edit échoue (texte non unique) Guide : Read + Write (aujourd'hui : plus de contexte ou replace_all)

9. Scénarios corrigés#

Format de l'examen : une seule bonne réponse sauf mention contraire. Les questions officielles du guide sont commentées dans 06-scenarios-examen.md.

1. Customer Support Resolution Agent. Les journaux montrent que l'agent appelle process_refund pour des demandes d'information sur un remboursement déjà fait. Les deux outils process_refund et get_refund_status ont une description d'une ligne. Que faire en premier ?

  • A. Ajouter une règle « n'appelle process_refund qu'après confirmation » au system prompt
  • B. Réécrire les deux descriptions : effet, entrées, cas d'usage, et la frontière « pour connaître l'état d'un remboursement existant, utilise get_refund_status »
  • C. Fusionner les deux outils en refund(action)
  • D. Ajouter un classifieur qui choisit l'outil avant Claude

B. La description est le premier critère de choix ; la frontière explicite corrige la confusion. A est probabiliste et traite le symptôme, C et D sont plus lourds.

2. Multi-Agent Research System. Le subagent de recherche web reçoit un timeout de l'API de recherche, réessaie deux fois sans succès. Que doit-il remonter au coordinateur ?

  • A. Une liste vide, pour ne pas bloquer la synthèse
  • B. « Operation failed »
  • C. Une erreur structurée : type transient, requête tentée, réessais effectués, résultats partiels déjà obtenus
  • D. Rien : il doit arrêter tout le workflow

C. Récupération locale d'abord, puis seulement l'irrécupérable, avec ce qui a été tenté et les résultats partiels. A masque l'échec, B empêche la décision, D est l'autre anti-pattern.

3. Un outil search_customers renvoie isError: true avec « No customer found » quand l'email n'existe pas, et l'agent réessaie trois fois avant d'escalader. Quelle correction ?

  • A. Monter la limite de réessais à 5
  • B. Renvoyer isError: false et resultCount: 0 : c'est une réponse valide
  • C. Interdire les réessais dans le system prompt
  • D. Marquer l'erreur isRetryable: false

B. « Aucune correspondance » n'est pas une erreur. D réduit le gaspillage mais garde un mauvais signal (l'agent croit à un échec).

4. Quelle combinaison est correcte pour une demande de remboursement de 900 USD refusée par une règle « au-delà de 500 USD, validation humaine » ? (2 réponses)

  • A. errorCategory: "business"
  • B. isRetryable: true
  • C. Une explication présentable au client
  • D. errorCategory: "transient"

A et C. Règle métier, non réessayable, avec un message que l'agent peut transmettre ; l'escalade suit (domaine 5).

5. Developer Productivity with Claude. Un agent unique a reçu 19 outils (fichiers, CI, tickets, documentation, base de données) et se trompe souvent d'outil. Quelle approche ?

  • A. Raccourcir les descriptions pour réduire le contexte
  • B. Répartir les outils entre subagents spécialisés de 4 à 5 outils chacun, le coordinateur délégant
  • C. Déplacer la moitié des outils sur un second serveur MCP
  • D. Passer tool_choice à any

B. Trop d'outils dégrade le choix ; C ne change rien (tous les outils restent visibles), D force un appel sans aider le choix.

6. Un pipeline doit toujours exécuter extract_metadata avant les outils d'enrichissement. Quelle configuration le garantit, selon le guide ?

  • A. tool_choice: {"type": "auto"} et une consigne « commence par extract_metadata »
  • B. tool_choice: {"type": "any"}
  • C. tool_choice: {"type": "tool", "name": "extract_metadata"} au premier tour, puis auto
  • D. Retirer les autres outils de la requête définitivement

C. La sélection forcée impose cet outil ; les étapes suivantes se font aux tours suivants. A reste probabiliste, B laisse choisir n'importe quel outil.

7. L'équipe veut que tous les développeurs aient le serveur GitHub dans Claude Code, sans secret dans Git, et un développeur veut tester un serveur expérimental pour lui seul. Quelle configuration ?

  • A. Les deux dans .mcp.json, avec le token en clair puisque le dépôt est privé
  • B. GitHub dans .mcp.json avec ${GITHUB_TOKEN} ; l'expérimental en portée utilisateur (~/.claude.json)
  • C. Les deux dans ~/.claude.json de chaque développeur
  • D. GitHub dans ~/.claude.json, l'expérimental dans .mcp.json

B. Partagé et versionné pour l'équipe, secrets en variables d'environnement ; personnel hors du dépôt.

8. Un serveur MCP maison expose semantic_code_search (index sémantique du code), mais Claude utilise presque toujours Grep. Que faire ?

  • A. Retirer Grep des outils autorisés
  • B. Ajouter au system prompt « utilise toujours semantic_code_search »
  • C. Enrichir la description de semantic_code_search : capacités, format des résultats, et quand le préférer à Grep
  • D. Renommer l'outil en grep_semantic

C. Le guide le cite explicitement. A casse des usages légitimes, B est probabiliste, D crée une confusion de nom.

9. Un agent d'analyse écrit des requêtes SQL et appelle à chaque session list_tables puis describe_table pour 40 tables. Comment réduire ces appels ?

  • A. Exposer le schéma de la base comme MCP resource
  • B. Augmenter max_tokens
  • C. Mettre le schéma complet dans chaque description d'outil
  • D. Ajouter un outil describe_all_tables

A. Les resources servent à exposer des catalogues et évitent les appels exploratoires. D marcherait mais reste un appel exploratoire ; C alourdit chaque requête.

10. Il faut trouver tous les appelants de formatInvoice() dans un dépôt de 8 000 fichiers, puis leurs tests. Bash n'est pas autorisé. Quelle séquence ?

  • A. Glob **/*formatInvoice*, puis Grep sur les résultats
  • B. Grep formatInvoice(, lire les exports pour repérer d'éventuels réexports et les chercher aussi, puis Glob des tests par convention de nommage
  • C. Read de tous les fichiers src/
  • D. Edit sur chaque fichier pour vérifier s'il contient l'appel

B. Grep pour le contenu, suivi des réexports, Glob pour les chemins. A confond les deux outils, C sature le contexte.


10. Pour aller plus loin (hors examen)#

  • Strict tool use : strict: true contraint l'échantillonnage pour que input respecte toujours le schéma (types, champs requis) ; un sous-ensemble de JSON Schema est accepté. Lien avec les sorties structurées : 04-prompt-structured-output.md.
  • Tool search : au-delà de 10 outils ou 10 000 tokens de définitions, defer_loading: true et l'outil tool_search ne chargent que les 3 à 5 outils utiles. Dans Claude Code, la recherche d'outils MCP est activée par défaut (ENABLE_TOOL_SEARCH).
  • Réponses économes : renvoyer des identifiants lisibles et stables, paginer, filtrer, et proposer un paramètre response_format (concise / detailed) ; Writing tools for agents cite une réponse concise à environ un tiers des tokens. Claude Code avertit au-delà de 10 000 tokens de sortie d'un outil MCP et plafonne à 25 000 par défaut (MAX_MCP_OUTPUT_TOKENS).
  • Approbation obligatoire : un serveur peut marquer un outil _meta["anthropic/requiresUserInteraction"]: true ; Claude Code demande alors une confirmation à chaque appel, quel que soit le mode de permission.
  • Elicitation : un serveur MCP peut demander une information à l'utilisateur en cours de tâche (formulaire ou URL).
  • MCP connector : connecter un serveur MCP distant directement depuis l'API Messages, sans client MCP à écrire.
  • Contenu non fiable : un résultat d'outil peut porter une injection de prompt indirecte ; le laisser dans le tool_result, jamais dans le system prompt.

11. Fiche à retenir#

  • Claude choisit un outil d'abord grâce à sa description : ce qu'il fait, entrées et formats, exemples, cas limites, frontière avec l'outil voisin, 3-4 phrases au minimum.
  • Ordre des corrections d'un mauvais routage : descriptions → renommer / scinder → seulement ensuite few-shot ou classifieur ; relire le system prompt.
  • Renommer analyze_content → extract_web_results ; scinder analyze_document en trois outils à contrat défini.
  • tool_result : tool_use_id, en premier dans le message user, is_error: true avec un message qui dit quoi faire.
  • MCP : protocol error (JSON-RPC, l'hôte gère) ≠ tool execution error (isError: true, le modèle voit).
  • errorCategory transient / validation / business / permission, isRetryable vrai seulement pour transient.
  • Résultat vide valide ≠ échec d'accès ; ne jamais masquer une erreur en liste vide.
  • Récupération locale dans le subagent, puis remontée de l'irrécupérable avec tentative et résultats partiels.
  • 4-5 outils par agent, propres au rôle ; outil contraint (load_document) plutôt que générique (fetch_url) ; outil transverse limité (verify_fact) pour le fréquent.
  • tool_choice : auto (défaut), any (un appel garanti), tool (cet outil, puis auto), none. État actuel : refusés (400) par Opus 5.5, Sonnet 5.5, Fable 5.1 → auto + strict: true.
  • .mcp.json = équipe, versionné, ${VAR} ; ~/.claude.json = personnel. État actuel : portées local (défaut), project, user.
  • Tous les outils des serveurs configurés sont découverts à la connexion et disponibles ensemble : mcp__{serveur}__{outil}.
  • Resources = catalogues (schémas, doc, issues) ; tools = actions ; prompts = modèles d'invite.
  • Intégration standard → serveur communautaire ; serveur maison seulement pour le spécifique.
  • Grep = contenu, Glob = chemins, Edit = texte unique, sinon Read + Write (guide) ; explorer par étapes.

Références#

Lues le 21/10/2026.

Guide d'examen et base du cours

API Claude

Claude Code et Agent SDK

Model Context Protocol

Sur cette page
Échap

Tape au moins 2 lettres. Plusieurs mots : tous doivent apparaître.