SpyBara
Go Premium

agent-sdk/mcp.md 2026-11-03 23:58 UTC to 2026-11-04 23:59 UTC

No changes for this document in this history range.

2026
Mon 9 23:02

Connecter à des outils externes avec MCP

Configurez les serveurs MCP pour étendre votre agent avec des outils externes. Couvre les types de transport, la recherche d'outils pour les grands ensembles d'outils, l'authentification et la gestion des erreurs.

Le Model Context Protocol (MCP) est une norme ouverte pour connecter les agents IA aux outils externes et aux sources de données. Avec MCP, votre agent peut interroger des bases de données, s'intégrer à des API comme Slack et GitHub, et se connecter à d'autres services sans écrire d'implémentations d'outils personnalisés.

Les serveurs MCP peuvent s'exécuter en tant que processus locaux, se connecter via HTTP ou s'exécuter directement dans votre application SDK.

[!NOTE]

Cette page couvre la configuration de MCP pour l'Agent SDK. Pour ajouter des serveurs MCP à l'interface de ligne de commande Claude Code afin qu'ils se chargent dans chaque projet, consultez Portées d'installation MCP.

Démarrage rapide

Cet exemple se connecte au serveur MCP de documentation Claude Code en utilisant le transport HTTP et utilise allowedTools avec un caractère générique pour autoriser tous les outils du serveur.

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

for await (const message of query({
  prompt: "Use the docs MCP server to explain what hooks are in Claude Code",
  options: {
    mcpServers: {
      "claude-code-docs": {
        type: "http",
        url: "https://code.claude.com/docs/mcp"
      }
    },
    allowedTools: ["mcp__claude-code-docs__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            "claude-code-docs": {
                "type": "http",
                "url": "https://code.claude.com/docs/mcp",
            }
        },
        allowed_tools=["mcp__claude-code-docs__*"],
    )

    async for message in query(
        prompt="Use the docs MCP server to explain what hooks are in Claude Code",
        options=options,
    ):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

L'agent se connecte au serveur de documentation, recherche des informations sur les hooks et retourne les résultats.

Ajouter un serveur MCP

Vous pouvez configurer les serveurs MCP dans le code lors de l'appel de query(), ou dans un fichier .mcp.json chargé via settingSources.

Ajouter un serveur dans le code

Transmettez les serveurs MCP directement dans l'option mcpServers. Cet exemple démarre un serveur MCP de système de fichiers local pour /Users/me/projects. Remplacez ce chemin par un répertoire sur votre machine :

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

for await (const message of query({
  prompt: "List files in my project",
  options: {
    mcpServers: {
      filesystem: {
        command: "npx",
        args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
      }
    },
    allowedTools: ["mcp__filesystem__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            "filesystem": {
                "command": "npx",
                "args": [
                    "-y",
                    "@modelcontextprotocol/server-filesystem",
                    "/Users/me/projects",
                ],
            }
        },
        allowed_tools=["mcp__filesystem__*"],
    )

    async for message in query(prompt="List files in my project", options=options):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

Ajouter un serveur à partir d'un fichier de configuration

Créez un fichier .mcp.json à la racine de votre projet. Le fichier est détecté lorsque la source de paramètre project est activée, ce qui est le cas pour les options query() par défaut. Si vous définissez settingSources explicitement, incluez "project" pour que ce fichier soit chargé. Remplacez /Users/me/projects par un répertoire sur votre machine :

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
    }
  }
}

Délai de connexion

Claude Code commence à connecter vos serveurs MCP au démarrage de la session, et envoie le message init une fois que l'attente du premier tour, le cas échéant, se termine. La durée pendant laquelle le premier tour attend un serveur dépend de l'endroit où vous l'avez configuré. Si vous définissez permissionPromptToolName, le premier tour attend toujours le serveur de cet outil, jusqu'à MCP_TIMEOUT, quel que soit l'endroit où vous l'avez configuré.

Pour un serveur dans options.mcpServers, trouvez son type dans la première colonne pour savoir combien de temps le premier tour l'attend.

Type de serveur Retarde le premier tour ? Délai d'attente du premier tour
Serveur stdio, ou serveur HTTP/SSE sans liste d'outils en cache Oui, jusqu'à ce qu'il se connecte MCP_TIMEOUT, 30 secondes par défaut ; la connexion échoue à cette limite
Serveur distant avec une liste d'outils en cache, enregistrée par Claude Code à partir d'une connexion précédente Non ; les outils en cache sont disponibles dès le premier tour Aucun ; se connecte lors de son premier appel d'outil, et cette connexion différée a son propre délai d'attente
Serveur SDK en processus Oui, jusqu'à ce qu'il se connecte et énumère ses outils MCP_TIMEOUT, 30 secondes par défaut, par tentative de connexion ; la connexion échoue à cette limite

Un serveur possède une liste d'outils en cache uniquement lorsque le cache de découverte MCP est activé.

Les serveurs provenant de fichiers de paramètres tels que .mcp.json, ou de plugins, affichent souvent encore pending dans le message init. La durée pendant laquelle le premier tour les attend dépend de options.mcpServers et de la recherche d'outils :

  • options.mcpServers contient un serveur stdio, HTTP ou SSE : le premier tour attend également les serveurs en attente issus des fichiers de paramètres et des plugins, jusqu'à MCP_TIMEOUT.
  • Sinon, quand ANTHROPIC_BASE_URL pointe vers une passerelle et que ENABLE_TOOL_SEARCH n'est pas défini : le premier tour attend jusqu'à 2 secondes pour chaque serveur en attente issu des fichiers de paramètres et des plugins.
  • Sinon, avec la recherche d'outils activée, ce qui est la valeur par défaut : le premier tour attend jusqu'à 2 secondes, et uniquement pour les serveurs en attente qui définissent alwaysLoad: true ou que vous avez nommés. Les autres continuent de se connecter en arrière-plan, et Claude accède à leurs outils une fois qu'ils sont connectés.
  • Sinon, avec la recherche d'outils désactivée : le premier tour attend jusqu'à 2 secondes pour chaque serveur en attente issu des fichiers de paramètres et des plugins. La recherche d'outils est désactivée lorsque votre valeur ENABLE_TOOL_SEARCH ou votre modèle la désactive, ou lorsque vous excluez l'outil ToolSearch, par exemple via disallowedTools.

Serveurs nommés

Vous nommez un serveur en listant l'un de ses outils, comme mcp__github__list_issues ou mcp__github__*, dans allowedTools ou dans une règle permissions.allow de l'option settings. Un hook mcp_tool nomme également le serveur qu'il appelle lorsque vous le configurez sur un événement de soumission de prompt, d'utilisation d'outil, de permission, de sous-agent, de tâche, d'élicitation ou de worktree. Avant la v2.1.284, nommer un serveur n'avait aucun effet sur l'attente du premier tour.

Définir vous-même l'attente du premier tour

Pour choisir vous-même l'attente du premier tour, définissez CLAUDE_CODE_MCP_STARTUP_WAIT_MS dans l'option env, par exemple CLAUDE_CODE_MCP_STARTUP_WAIT_MS: "5000". Le premier tour attend alors jusqu'à ce nombre de millisecondes pour les serveurs en attente issus des fichiers de paramètres et des plugins, que la recherche d'outils soit activée ou non. Cette même limite remplace l'attente MCP_TIMEOUT pour les serveurs stdio, HTTP et SSE dans options.mcpServers.

Trois attentes s'appliquent quelle que soit la valeur définie, y compris 0 :

  • Un serveur permissionPromptToolName : jusqu'à MCP_TIMEOUT.
  • Un serveur SDK en processus : jusqu'à MCP_TIMEOUT par tentative de connexion.
  • Un serveur nommé encore en cours de connexion : au moins jusqu'à 2 secondes, de sorte qu'une valeur inférieure à 2000 ne raccourcit pas son attente.

Définissez la variable à 0 pour ignorer l'attente de tous les autres serveurs. Les serveurs toujours en attente quand l'attente se termine continuent de se connecter en arrière-plan. CLAUDE_CODE_MCP_STARTUP_WAIT_MS nécessite Claude Code v2.1.274 ou ultérieur.

Faire attendre les serveurs au démarrage

Deux paramètres font attendre le démarrage lui-même, avant que Claude Code n'envoie le message init :

  • MCP_CONNECTION_NONBLOCKING défini à 0 : le démarrage attend tout le lot de connexions, jusqu'à 5 secondes par défaut. Définissez MCP_CONNECT_TIMEOUT_MS, en millisecondes, pour modifier cette limite. Les serveurs toujours en attente à cette limite continuent de se connecter en arrière-plan.
  • alwaysLoad: true dans la configuration d'un serveur : le démarrage attend les outils de ce serveur jusqu'à la même limite, afin que le premier tour en dispose avec leurs schémas complets, exempts du report de recherche d'outils. Un serveur distant avec une liste d'outils en cache les fournit sans se connecter ni bloquer le démarrage.

Le message init rapporte l'état de chaque serveur au moment où Claude Code l'envoie.

Autoriser les outils MCP

Les outils MCP nécessitent une permission explicite avant que Claude puisse les utiliser. Sans permission, Claude verra que les outils sont disponibles mais ne pourra pas les appeler.

Convention de nommage des outils

Les outils MCP sont nommés mcp__<server-name>__<tool-name>, où <server-name> est le nom sous lequel vous enregistrez le serveur, par exemple sa clé dans mcpServers.

Les caractères du nom du serveur tels que . et les espaces sont remplacés par _. Ce tableau indique le nom complet d'un outil list_issues pour deux clés de serveur :

Clé dans mcpServers Nom complet de l'outil
github mcp__github__list_issues
my.server mcp__my_server__list_issues

Utilisez les noms complets des outils dans allowedTools et dans les règles de permission MCP. Pour un serveur fourni par un plugin, <server-name> prend la forme propre au plugin et commence par plugin_.

Auto-approbation avec allowedTools

Utilisez allowedTools pour auto-approuver des outils MCP spécifiques afin que Claude puisse les utiliser sans invite de permission :

const _ = {
  options: {
    mcpServers: {
      // your servers
    },
    allowedTools: [
      "mcp__github__*", // All tools from the github server
      "mcp__db__query", // Only the query tool from db server
      "mcp__slack__send_message" // Only send_message from slack server
    ]
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        # your servers
    },
    allowed_tools=[
        "mcp__github__*",  # All tools from the github server
        "mcp__db__query",  # Only the query tool from db server
        "mcp__slack__send_message",  # Only send_message from slack server
    ],
)

Les caractères génériques (*) vous permettent d'autoriser tous les outils d'un serveur sans lister chacun individuellement.

[!NOTE]

Préférez allowedTools aux modes de permission pour l'accès MCP. permissionMode: "acceptEdits" n'auto-approuve pas les outils MCP (uniquement les modifications de fichiers et les commandes Bash du système de fichiers). permissionMode: "bypassPermissions" auto-approuve les outils MCP mais désactive également la plupart des autres invites de sécurité, ce qui est plus large que nécessaire ; consultez Comment les permissions sont évaluées pour les invites qui restent. Un caractère générique dans allowedTools accorde exactement le serveur MCP que vous souhaitez et rien de plus. Consultez Modes de permission pour une comparaison complète.

Découvrir les outils disponibles

Pour voir quels outils un serveur MCP fournit, consultez la documentation du serveur ou inspectez le tableau tools dans le message init system. Les noms des outils MCP commencent par mcp__.

Claude Code émet le message init après l'attente de connexion au premier tour pour les serveurs passés dans options.mcpServers, donc le tableau tools liste les outils mcp__ de chaque serveur qui s'est connecté à ce moment-là, plus ceux des serveurs avec une liste d'outils en cache, qui se connectent à la première utilisation. Les outils de tout autre serveur qui ne s'est pas connecté sont absents ; consultez Gestion des erreurs pour lire l'état de chaque serveur.

Ce filtre imprime les noms des outils MCP :

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

const options = {
  mcpServers: {
    // your servers
  },
};

for await (const message of query({ prompt: "...", options })) {
  if (message.type === "system" && message.subtype === "init") {
    const mcpTools = message.tools.filter((name) => name.startsWith("mcp__"));
    console.log("Available MCP tools:", mcpTools);
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            # your servers
        },
    )
    async for message in query(prompt="...", options=options):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            mcp_tools = [t for t in message.data.get("tools", []) if t.startswith("mcp__")]
            print("Available MCP tools:", mcp_tools)


asyncio.run(main())

Vous pouvez également demander à Claude de lister les outils disponibles à partir d'un serveur.

Types de transport

Les serveurs MCP communiquent avec votre agent en utilisant différents protocoles de transport. Consultez la documentation du serveur pour voir quel transport il prend en charge :

  • Si la documentation vous donne une commande à exécuter (comme npx @modelcontextprotocol/server-filesystem), utilisez stdio
  • Si la documentation vous donne une URL, utilisez HTTP ou SSE
  • Si vous créez vos propres outils dans le code, utilisez un serveur MCP SDK

Serveurs stdio

Des processus locaux qui communiquent via stdin/stdout. Utilisez ceci pour les serveurs MCP que vous exécutez sur la même machine. Pour le formulaire .mcp.json, utilisez les mêmes champs affichés à À partir d'un fichier de configuration. Dans le code, transmettez la commande et ses arguments. Remplacez /Users/me/projects par un répertoire sur votre machine :

const _ = {
  options: {
    mcpServers: {
      filesystem: {
        command: "npx",
        args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
      }
    },
    allowedTools: ["mcp__filesystem__read_file", "mcp__filesystem__list_directory"]
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        "filesystem": {
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                "/Users/me/projects",
            ],
        }
    },
    allowed_tools=["mcp__filesystem__read_file", "mcp__filesystem__list_directory"],
)

Serveurs HTTP/SSE

Utilisez HTTP ou SSE pour les serveurs MCP hébergés dans le cloud et les API distantes. Pour le formulaire .mcp.json, utilisez les mêmes champs que l'exemple à En-têtes HTTP pour les serveurs distants, avec "type": "sse" pour un serveur SSE. Dans le code, transmettez l'URL du serveur :

const _ = {
  options: {
    mcpServers: {
      "remote-api": {
        type: "sse",
        url: "https://api.example.com/mcp/sse",
        headers: {
          Authorization: `Bearer ${process.env.API_TOKEN}`
        }
      }
    },
    allowedTools: ["mcp__remote-api__*"]
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        "remote-api": {
            "type": "sse",
            "url": "https://api.example.com/mcp/sse",
            "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
        }
    },
    allowed_tools=["mcp__remote-api__*"],
)

Pour le transport HTTP en continu, utilisez "type": "http" à la place. Dans .mcp.json et autres fichiers de configuration JSON, "streamable-http" est accepté comme alias pour "http". Le type McpHttpServerConfig des SDK déclare uniquement "http", donc utilisez "http" pour les serveurs que vous transmettez dans le code.

Serveurs MCP SDK

Définissez des outils personnalisés directement dans le code de votre application au lieu d'exécuter un processus serveur séparé. Consultez le guide des outils personnalisés pour les détails de mise en œuvre.

Un serveur MCP SDK enregistré par une demande de contrôle initialize commence à se connecter dès que Claude Code traite la demande.

Recherche d'outils MCP

Lorsque vous avez de nombreux outils MCP configurés, les définitions d'outils peuvent consommer une part importante de votre fenêtre de contexte. La recherche d'outils résout ce problème en retenant les définitions d'outils du contexte et en chargeant uniquement ceux dont Claude a besoin à chaque tour.

La recherche d'outils est activée par défaut. Consultez Recherche d'outils pour les options de configuration, les meilleures pratiques et l'utilisation de la recherche d'outils avec les outils SDK personnalisés.

Authentification

La plupart des serveurs MCP nécessitent une authentification pour accéder aux services externes. Transmettez les identifiants via des variables d'environnement dans la configuration du serveur.

Transmettre les identifiants via des variables d'environnement

Utilisez le champ env pour transmettre les clés API, les jetons et autres identifiants au serveur MCP :

[tab] Dans le code

const _ = {
  options: {
    mcpServers: {
      "api-server": {
        command: "npx",
        args: ["-y", "@your-org/api-mcp-server"],
        env: {
          API_KEY: process.env.API_KEY
        }
      }
    },
    allowedTools: ["mcp__api-server__*"]
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        "api-server": {
            "command": "npx",
            "args": ["-y", "@your-org/api-mcp-server"],
            "env": {"API_KEY": os.environ["API_KEY"]},
        }
    },
    allowed_tools=["mcp__api-server__*"],
)

[tab] .mcp.json

{
  "mcpServers": {
    "api-server": {
      "command": "npx",
      "args": ["-y", "@your-org/api-mcp-server"],
      "env": {
        "API_KEY": "${API_KEY}"
      }
    }
  }
}

La syntaxe ${API_KEY} développe les variables d'environnement au moment de l'exécution.

En-têtes HTTP pour les serveurs distants

Pour les serveurs HTTP et SSE, transmettez les en-têtes d'authentification directement dans la configuration du serveur :

[tab] Dans le code

const _ = {
  options: {
    mcpServers: {
      "secure-api": {
        type: "http",
        url: "https://api.example.com/mcp",
        headers: {
          Authorization: `Bearer ${process.env.API_TOKEN}`
        }
      }
    },
    allowedTools: ["mcp__secure-api__*"]
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        "secure-api": {
            "type": "http",
            "url": "https://api.example.com/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},
        }
    },
    allowed_tools=["mcp__secure-api__*"],
)

[tab] .mcp.json

{
  "mcpServers": {
    "secure-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      }
    }
  }
}

La syntaxe ${API_TOKEN} développe les variables d'environnement au moment de l'exécution.

Pour un exemple complet et fonctionnel d'un serveur distant authentifié avec des en-têtes, consultez Lister les problèmes d'un référentiel.

Authentification OAuth2

La spécification MCP prend en charge OAuth 2.1 pour l'autorisation. Le SDK n'ouvre pas de navigateur ni n'exécute de flux OAuth interactif. Lorsqu'un serveur configuré retourne un défi d'autorisation et que Claude Code n'a aucun jeton à envoyer, le SDK signale le serveur comme needs-auth ou failed :

  • needs-auth : Claude Code n'a trouvé aucune connexion utilisable pour ce serveur. Transmettez un jeton dans headers, ou connectez-vous depuis une session Claude Code interactive sur la même machine avant l'exécution.
  • failed, avec une error dans son entrée McpServerStatus qui commence par Couldn't read the stored credentials ou A request to MCP server : Claude Code n'a pas pu lire son magasin d'identifiants. Pour savoir quoi faire, consultez Couldn't read the stored credentials for MCP server. Avant Claude Code v2.1.307, le statut était needs-auth à la place lorsque le trousseau de session d'un Mac était verrouillé.

Dans les deux cas, l'exécution de l'agent continue sans les outils de ce serveur. Le tableau mcp_servers du message d'initialisation du système peut toujours afficher pending pour ce serveur lors de son émission. Pour confirmer si un serveur a besoin d'identifiants, interrogez mcpServerStatus() dans le SDK TypeScript ou get_mcp_status() en Python.

Pour fournir les identifiants, complétez le flux OAuth dans votre propre application et transmettez le jeton d'accès résultant dans les headers du serveur :

// After completing OAuth flow in your app.
// Implement getAccessTokenFromOAuthFlow for your OAuth provider.
const accessToken = await getAccessTokenFromOAuthFlow();

const options = {
  mcpServers: {
    "oauth-api": {
      type: "http",
      url: "https://api.example.com/mcp",
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
    }
  },
  allowedTools: ["mcp__oauth-api__*"]
};
# After completing OAuth flow in your app.
# Implement get_access_token_from_oauth_flow for your OAuth provider.
access_token = await get_access_token_from_oauth_flow()

options = ClaudeAgentOptions(
    mcp_servers={
        "oauth-api": {
            "type": "http",
            "url": "https://api.example.com/mcp",
            "headers": {"Authorization": f"Bearer {access_token}"},
        }
    },
    allowed_tools=["mcp__oauth-api__*"],
)

Exemples

Lister les problèmes d'un référentiel

Cet exemple se connecte au serveur MCP GitHub distant pour lister les problèmes récents. L'exemple inclut la journalisation de débogage pour vérifier la connexion MCP et les appels d'outils.

Avant d'exécuter, créez un jeton d'accès personnel GitHub avec accès en lecture aux référentiels que vous souhaitez interroger et définissez-le comme variable d'environnement :

export GITHUB_TOKEN=YOUR_GITHUB_PAT
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "List the 3 most recent issues in anthropics/claude-code",
  options: {
    mcpServers: {
      github: {
        type: "http",
        url: "https://api.githubcopilot.com/mcp/",
        headers: {
          Authorization: `Bearer ${process.env.GITHUB_TOKEN}`
        }
      }
    },
    allowedTools: ["mcp__github__list_issues"]
  }
})) {
  // Verify MCP server connected successfully
  if (message.type === "system" && message.subtype === "init") {
    console.log("MCP servers:", message.mcp_servers);
  }

  // Log when Claude calls an MCP tool
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if (block.type === "tool_use" && block.name.startsWith("mcp__")) {
        console.log("MCP tool called:", block.name);
      }
    }
  }

  // Print the final result
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
import asyncio
import os
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    ResultMessage,
    SystemMessage,
    AssistantMessage,
)


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            "github": {
                "type": "http",
                "url": "https://api.githubcopilot.com/mcp/",
                "headers": {"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"},
            }
        },
        allowed_tools=["mcp__github__list_issues"],
    )

    async for message in query(
        prompt="List the 3 most recent issues in anthropics/claude-code",
        options=options,
    ):
        # Verify MCP server connected successfully
        if isinstance(message, SystemMessage) and message.subtype == "init":
            print("MCP servers:", message.data.get("mcp_servers"))

        # Log when Claude calls an MCP tool
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if hasattr(block, "name") and block.name.startswith("mcp__"):
                    print("MCP tool called:", block.name)

        # Print the final result
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

Dans la ligne MCP servers :, un status de connected pour github confirme que le jeton fonctionne. Si Claude Code dispose d'une liste d'outils mise en cache pour le serveur, le statut peut afficher pending à la place et le serveur se connecte lors de son premier appel d'outil. Si le statut est failed ou needs-auth, consultez Gestion des erreurs avant de faire confiance au résultat, car Claude peut revenir aux outils intégrés lorsque le serveur n'est pas disponible.

Interroger une base de données

Cet exemple utilise DBHub pour interroger une base de données Postgres. L'agent découvre automatiquement le schéma de la base de données, écrit la requête SQL et retourne les résultats.

L'outil execute_sql de DBHub exécute toute requête SQL que l'agent émet, y compris les écritures, sauf si vous la limitez. Définir readonly = true dans le fichier de configuration DBHub fait que DBHub rejette les instructions INSERT, UPDATE, DELETE et DDL, de sorte que l'exemple ne peut pas modifier vos données même si l'agent émet une écriture. DBHub résout ${DATABASE_URL} à partir de l'environnement du processus lorsqu'il charge la configuration, de sorte que la chaîne de connexion reste en dehors du fichier. Créez ce dbhub.toml à côté de votre script :

[[sources]]
id = "production"
dsn = "${DATABASE_URL}"

[[tools]]
name = "execute_sql"
source = "production"
readonly = true

Le script pointe ensuite DBHub vers le fichier de configuration au lieu de passer une chaîne de connexion directement. Avant d'exécuter, définissez la variable d'environnement DATABASE_URL sur votre chaîne de connexion. Remplacez les valeurs d'espace réservé par les détails de votre propre base de données :

export DATABASE_URL=postgresql://user:password@localhost:5432/mydb
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  // Natural language query - Claude writes the SQL
  prompt: "How many users signed up last week? Break it down by day.",
  options: {
    mcpServers: {
      postgres: {
        command: "npx",
        // dbhub.toml sets readonly = true, so execute_sql rejects writes
        args: ["-y", "@bytebase/dbhub", "--config", "dbhub.toml"]
      }
    },
    allowedTools: ["mcp__postgres__execute_sql"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            "postgres": {
                "command": "npx",
                # dbhub.toml sets readonly = true, so execute_sql rejects writes
                "args": [
                    "-y",
                    "@bytebase/dbhub",
                    "--config",
                    "dbhub.toml",
                ],
            }
        },
        allowed_tools=["mcp__postgres__execute_sql"],
    )

    # Natural language query - Claude writes the SQL
    async for message in query(
        prompt="How many users signed up last week? Break it down by day.",
        options=options,
    ):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

Gestion des erreurs

Les serveurs MCP peuvent échouer à se connecter pour diverses raisons : le processus du serveur pourrait ne pas être installé, les identifiants pourraient être invalides, ou un serveur distant pourrait être inaccessible.

Claude Code émet un message system avec le sous-type init au début de chaque requête. Ce message inclut l'état de la connexion pour chaque serveur MCP. Le champ status peut être "pending", "connected", "failed", "needs-auth", ou "disabled". Claude Code émet le message init après le délai d'attente de connexion à la première requête pour les serveurs passés dans options.mcpServers, donc un tel serveur qui s'est connecté dans le délai d'attente affiche "connected".

Dans le message init, ne traitez pas "pending" comme un échec en soi. Cela peut signifier l'une de ces situations :

Vérifiez "failed" ou "needs-auth" pour détecter les serveurs qui ne seront pas utilisables :

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

try {
  for await (const message of query({
    prompt: "Process data",
    options: {
      mcpServers: {
        // Replace dataServer with your server configuration
        "data-processor": dataServer
      }
    }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      const unavailableServers = message.mcp_servers.filter(
        (s) => s.status === "failed" || s.status === "needs-auth"
      );

      if (unavailableServers.length > 0) {
        console.warn("Unavailable MCP servers:", unavailableServers);
      }
    }

    if (message.type === "result" && message.subtype === "error_during_execution") {
      console.error("Execution failed");
    }
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result. If the
  // failure was an error result, the error subtype branch above has
  // already run; a failure to start or reach the Claude Code process
  // yields no result message. MCP servers that fail to connect don't
  // throw: use the status check above, and note that servers still
  // "pending" at init need a later status check.
  console.log(`Session ended with an error: ${error}`);
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage


async def main():
    # Replace data_server with your server configuration
    options = ClaudeAgentOptions(mcp_servers={"data-processor": data_server})

    try:
        async for message in query(prompt="Process data", options=options):
            if isinstance(message, SystemMessage) and message.subtype == "init":
                unavailable_servers = [
                    s
                    for s in message.data.get("mcp_servers", [])
                    if s.get("status") in ("failed", "needs-auth")
                ]

                if unavailable_servers:
                    print(f"Unavailable MCP servers: {unavailable_servers}")

            if (
                isinstance(message, ResultMessage)
                and message.subtype == "error_during_execution"
            ):
                print("Execution failed")
    except Exception as error:
        # A single-shot query() raises after yielding an error result. If the
        # failure was an error result, the error subtype branch above has
        # already run; a failure to start or reach the Claude Code process
        # yields no result message. MCP servers that fail to connect don't
        # raise: use the status check above, and note that servers still
        # "pending" at init need a later status check.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

L'état d'un serveur distant peut également changer après qu'il rapporte "connected". Lorsque la connexion à celui-ci s'interrompt en cours de session, Claude Code ramène le serveur à "pending" pendant la reconnexion. Un appel ultérieur à mcpServerStatus() en TypeScript, ou ClaudeSDKClient.get_mcp_status() en Python, peut alors rapporter "pending" pour un serveur que vous aviez vu connecté plus tôt, sans aucun changement de configuration de votre côté.

Après cinq tentatives de reconnexion échouées, le serveur rapporte "failed", ou "needs-auth" lorsqu'il a besoin d'être autorisé à nouveau. Un serveur HTTP ou SSE à l'état "failed" peut encore revenir à "connected" sans appel de votre part, car Claude Code continue de réessayer en arrière-plan après une erreur transitoire. Pour réessayer manuellement, appelez reconnectMcpServer() en TypeScript ou ClaudeSDKClient.reconnect_mcp_server() en Python.

Dépannage

Le serveur affiche un statut « failed »

Vérifiez le message init pour voir quels serveurs n'ont pas pu se connecter :

if (message.type === "system" && message.subtype === "init") {
  for (const server of message.mcp_servers) {
    if (server.status === "failed") {
      console.error(`Server ${server.name} failed to connect`);
    }
  }
}
if isinstance(message, SystemMessage) and message.subtype == "init":
    for server in message.data.get("mcp_servers", []):
        if server.get("status") == "failed":
            print(f"Server {server['name']} failed to connect")

Un statut "pending" ne signifie pas que le serveur a échoué. Consultez Gestion des erreurs pour connaître les cas qu'il couvre à l'initialisation. Pour obtenir les statuts mis à jour plus tard dans la session, appelez la méthode mcpServerStatus() de la requête dans le SDK TypeScript, ou ClaudeSDKClient.get_mcp_status() en Python.

Causes courantes :

  • Variables d'environnement manquantes : Assurez-vous que les jetons et identifiants requis sont définis. Pour les serveurs stdio, vérifiez que le champ env correspond à ce que le serveur attend.
  • Serveur non installé : Pour les commandes npx, vérifiez que le package existe et que Node.js se trouve dans votre PATH.
  • Chaîne de connexion invalide : Pour les serveurs de base de données, vérifiez le format de la chaîne de connexion et que la base de données est accessible.
  • Problèmes réseau : Pour les serveurs HTTP/SSE distants, vérifiez que l'URL est accessible et que les pare-feu autorisent la connexion.

Les outils ne sont pas appelés

Si Claude voit les outils mais ne les utilise pas, vérifiez que vous avez accordé la permission avec allowedTools :

const _ = {
  options: {
    mcpServers: {
      // your servers
    },
    allowedTools: ["mcp__servername__*"] // Auto-approve calls from this server
  }
};
options = ClaudeAgentOptions(
    mcp_servers={
        # your servers
    },
    allowed_tools=["mcp__servername__*"],  # Auto-approve calls from this server
)

Un outil est absent d'un serveur MCP du SDK

Dans le SDK TypeScript, lorsque le schéma d'entrée d'un outil ne peut pas être converti en JSON Schema, le serveur que vous avez créé avec createSdkMcpServer() omet cet outil lorsqu'il liste ses outils. Le SDK émet alors un avertissement. Sous Node.js, l'avertissement est un avertissement de processus avec le code CLAUDE_SDK_MCP_TOOL_SCHEMA_UNCONVERTIBLE, et il commence par ce texte :

Tool "<name>" on SDK MCP server "<server>" was left out of the server's tool list, because its input schema cannot be converted to JSON Schema

Le reste de l'avertissement indique le message de l'erreur de conversion lorsqu'il y en a un, puis précise ce qu'il faut vérifier et modifier.

Avant la version v0.3.286 du TypeScript Agent SDK, un seul schéma non convertible faisait échouer toute la liste des outils du serveur sans cet avertissement, de sorte qu'aucun des outils de ce serveur n'atteignait Claude.

Délais d'expiration de la connexion

Les connexions au serveur MCP expirent après 30 secondes par défaut. Pour modifier la durée maximale d'un appel d'outil en cours, définissez MCP_TOOL_TIMEOUT. Si votre serveur met plus de temps à démarrer, la connexion échoue. Augmentez la limite de connexion avec la variable d'environnement MCP_TIMEOUT, en millisecondes. Pour les serveurs qui ont besoin de plus de temps de démarrage, envisagez également :

  • Utiliser un serveur plus léger si disponible
  • Préchauffer le serveur avant de démarrer votre agent
  • Vérifier les journaux du serveur pour les causes d'initialisation lente

En TypeScript, vous pouvez définir la limite d'appel d'outil pour un seul serveur MCP du SDK en passant timeout à createSdkMcpServer().

La sortie de l'outil dépasse le nombre maximum de jetons autorisés

Le SDK applique les mêmes limites de sortie MCP que Claude Code. Lorsqu'un résultat d'outil réussi sans contenu image est supérieur à 25 000 tokens, Claude Code enregistre la sortie dans un fichier et remplace le résultat de l'outil par un message d'erreur qui nomme le chemin du fichier, afin que l'agent puisse relire la sortie par portions.

Pour modifier la limite de tokens, définissez la variable d'environnement MAX_MCP_OUTPUT_TOKENS. À moins que l'outil ne déclare anthropic/maxResultSizeChars, un résultat textuel réussi de plus de 50 000 caractères est enregistré dans un fichier, quelle que soit la limite de tokens. Consultez Limites et avertissements de sortie MCP pour le comportement complet, y compris la façon dont un serveur déclare cette annotation.

Ressources connexes