MCP を使用して外部ツールに接続する
MCP サーバーを設定してエージェントを外部ツールで拡張します。トランスポートタイプ、大規模なツールセット向けのツール検索、認証、エラーハンドリングについて説明します。
Model Context Protocol(MCP)は、AI エージェントを外部ツールおよびデータソースに接続するためのオープンスタンダードです。MCP を使用すると、エージェントはデータベースをクエリし、Slack や GitHub などの API と統合し、カスタムツール実装を記述することなく他のサービスに接続できます。
MCP サーバーはローカルプロセスとして実行したり、HTTP 経由で接続したり、SDK アプリケーション内で直接実行したりできます。
このページは Agent SDK の MCP 設定について説明しています。Claude Code CLI に MCP サーバーを追加してすべてのプロジェクトで読み込むには、MCP インストールスコープを参照してください。
クイックスタート
この例は、HTTP トランスポートを使用して Claude Code ドキュメンテーションMCP サーバーに接続し、allowedToolsとワイルドカードを使用してサーバーからすべてのツールを許可します。
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())
エージェントはドキュメンテーションサーバーに接続し、hooks に関する情報を検索して、結果を返します。
MCP サーバーを追加する
query() を呼び出すときにコード内で MCP サーバーを設定するか、settingSources経由で読み込まれる .mcp.json ファイルで設定できます。
コード内で
mcpServers オプションで MCP サーバーを直接渡します:
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())
設定ファイルから
プロジェクトルートに .mcp.json ファイルを作成します。project 設定ソースが有効な場合、ファイルが取得されます。これはデフォルトの query() オプションの場合です。settingSources を明示的に設定する場合は、このファイルを読み込むために "project" を含めます:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
}
}
}
MCP ツールを許可する
MCP ツールは Claude が使用する前に明示的な許可が必要です。許可がない場合、Claude はツールが利用可能であることを認識しますが、呼び出すことはできません。
ツール命名規則
MCP ツールは mcp__<server-name>__<tool-name> という命名パターンに従います。たとえば、"github" という名前の GitHub サーバーに list_issues ツールがある場合、mcp__github__list_issues になります。
allowedTools でアクセスを許可する
allowedTools を使用して、Claude が使用できる MCP ツールを指定します:
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
]
}
};
ワイルドカード(*)を使用すると、各ツールを個別にリストアップすることなく、サーバーからすべてのツールを許可できます。
MCP アクセスには allowedTools をパーミッションモードより優先してください。 permissionMode: "acceptEdits" は MCP ツールを自動承認しません(ファイル編集とファイルシステム Bash コマンドのみ)。permissionMode: "bypassPermissions" は MCP ツールを自動承認しますが、他のすべてのセーフティプロンプトも無効にするため、必要以上に広範です。allowedTools のワイルドカードは、必要な MCP サーバーのみを許可し、それ以上は許可しません。完全な比較については、パーミッションモードを参照してください。
利用可能なツールを検出する
MCP サーバーが提供するツールを確認するには、サーバーのドキュメンテーションを確認するか、サーバーに接続して system init メッセージを検査します:
for await (const message of query({ prompt: "...", options })) {
if (message.type === "system" && message.subtype === "init") {
console.log("Available MCP tools:", message.mcp_servers);
}
}
トランスポートタイプ
MCP サーバーはさまざまなトランスポートプロトコルを使用してエージェントと通信します。サーバーのドキュメンテーションを確認して、どのトランスポートをサポートしているかを確認してください:
- ドキュメンテーションに実行するコマンド(
npx @modelcontextprotocol/server-githubなど)が記載されている場合は、stdio を使用します - ドキュメンテーションにURL が記載されている場合は、HTTP または SSE を使用します
- コード内で独自のツールを構築している場合は、SDK MCP サーバーを使用します
stdio サーバー
stdin/stdout 経由で通信するローカルプロセス。同じマシンで実行する MCP サーバーに使用します:
const _ = {
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: process.env.GITHUB_TOKEN
}
}
},
allowedTools: ["mcp__github__list_issues", "mcp__github__search_issues"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
}
},
allowed_tools=["mcp__github__list_issues", "mcp__github__search_issues"],
)
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
HTTP/SSE サーバー
クラウドホストされた MCP サーバーとリモート API に HTTP または SSE を使用します:
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__*"],
)
{
"mcpServers": {
"remote-api": {
"type": "sse",
"url": "https://api.example.com/mcp/sse",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}
ストリーミング可能な HTTP トランスポートの場合は、代わりに "type": "http" を使用します。.mcp.json およびその他の JSON 設定ファイルでは、"streamable-http" は "http" のエイリアスとして受け入れられます。プログラマティック mcpServers オプションは "http" のみを受け入れます。
SDK MCP サーバー
別のサーバープロセスを実行する代わりに、アプリケーションコード内でカスタムツールを直接定義します。実装の詳細については、カスタムツールガイドを参照してください。
MCP ツール検索
多くの MCP ツールを設定している場合、ツール定義はコンテキストウィンドウの大部分を消費する可能性があります。ツール検索は、コンテキストからツール定義を保留し、各ターンで Claude が必要とするツールのみを読み込むことでこれを解決します。
ツール検索はデフォルトで有効になっています。設定オプションと詳細については、ツール検索を参照してください。
カスタム SDK ツールでのベストプラクティスとツール検索の使用を含む詳細については、ツール検索ガイドを参照してください。
認証
ほとんどの MCP サーバーは外部サービスにアクセスするために認証が必要です。サーバー設定の環境変数を通じて認証情報を渡します。
環境変数を通じて認証情報を渡す
env フィールドを使用して、API キー、トークン、およびその他の認証情報を MCP サーバーに渡します:
const _ = {
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: process.env.GITHUB_TOKEN
}
}
},
allowedTools: ["mcp__github__list_issues"]
}
};
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
}
},
allowed_tools=["mcp__github__list_issues"],
)
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
${GITHUB_TOKEN} 構文は実行時に環境変数を展開します。
デバッグログを含む完全な動作例については、リポジトリからの問題のリストを参照してください。
リモートサーバーの HTTP ヘッダー
HTTP および SSE サーバーの場合、サーバー設定で認証ヘッダーを直接渡します:
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__*"],
)
{
"mcpServers": {
"secure-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}
${API_TOKEN} 構文は実行時に環境変数を展開します。
OAuth2 認証
MCP 仕様は OAuth 2.1 をサポートしています。SDK は OAuth フローを自動的に処理しませんが、アプリケーションで OAuth フローを完了した後、ヘッダー経由でアクセストークンを渡すことができます:
// After completing OAuth flow in your app
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
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__*"],
)
例
リポジトリから問題をリストする
この例は、GitHub MCP サーバーに接続して最近の問題をリストします。この例には、MCP 接続とツール呼び出しを検証するためのデバッグログが含まれています。
実行する前に、repo スコープを持つ GitHub 個人用アクセストークンを作成し、環境変数として設定します:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
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: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
GITHUB_TOKEN: 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": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": 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())
データベースをクエリする
この例は、Postgres MCP サーバーを使用してデータベースをクエリします。接続文字列はサーバーへの引数として渡されます。エージェントは自動的にデータベーススキーマを検出し、SQL クエリを記述して、結果を返します:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Connection string from environment variable
const connectionString = process.env.DATABASE_URL;
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",
// Pass connection string as argument to the server
args: ["-y", "@modelcontextprotocol/server-postgres", connectionString]
}
},
// Allow only read queries, not writes
allowedTools: ["mcp__postgres__query"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
# Connection string from environment variable
connection_string = os.environ["DATABASE_URL"]
options = ClaudeAgentOptions(
mcp_servers={
"postgres": {
"command": "npx",
# Pass connection string as argument to the server
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
connection_string,
],
}
},
# Allow only read queries, not writes
allowed_tools=["mcp__postgres__query"],
)
# 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())
エラーハンドリング
MCP サーバーはさまざまな理由で接続に失敗する可能性があります。サーバープロセスがインストールされていない、認証情報が無効である、またはリモートサーバーに到達できない可能性があります。
SDK は各クエリの開始時に、サブタイプ init の system メッセージを発行します。このメッセージには、各 MCP サーバーの接続ステータスが含まれます。status フィールドをチェックして、エージェントが作業を開始する前に接続失敗を検出します:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Process data",
options: {
mcpServers: {
"data-processor": dataServer
}
}
})) {
if (message.type === "system" && message.subtype === "init") {
const failedServers = message.mcp_servers.filter((s) => s.status !== "connected");
if (failedServers.length > 0) {
console.warn("Failed to connect:", failedServers);
}
}
if (message.type === "result" && message.subtype === "error_during_execution") {
console.error("Execution failed");
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage
async def main():
options = ClaudeAgentOptions(mcp_servers={"data-processor": data_server})
async for message in query(prompt="Process data", options=options):
if isinstance(message, SystemMessage) and message.subtype == "init":
failed_servers = [
s
for s in message.data.get("mcp_servers", [])
if s.get("status") != "connected"
]
if failed_servers:
print(f"Failed to connect: {failed_servers}")
if (
isinstance(message, ResultMessage)
and message.subtype == "error_during_execution"
):
print("Execution failed")
asyncio.run(main())
トラブルシューティング
サーバーが「失敗」ステータスを表示する
init メッセージをチェックして、どのサーバーが接続に失敗したかを確認します:
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`);
}
}
}
一般的な原因:
- 環境変数の欠落:必要なトークンと認証情報が設定されていることを確認します。stdio サーバーの場合、
envフィールドがサーバーが期待するものと一致することを確認します。 - サーバーがインストールされていない:
npxコマンドの場合、パッケージが存在し、Node.js が PATH にあることを確認します。 - 無効な接続文字列:データベースサーバーの場合、接続文字列の形式を確認し、データベースにアクセス可能であることを確認します。
- ネットワークの問題:リモート HTTP/SSE サーバーの場合、URL に到達可能であり、ファイアウォールが接続を許可していることを確認します。
ツールが呼び出されていない
Claude がツールを認識しているが使用していない場合は、allowedTools で許可を付与していることを確認します:
const _ = {
options: {
mcpServers: {
// your servers
},
allowedTools: ["mcp__servername__*"] // Auto-approve calls from this server
}
};
接続タイムアウト
MCP SDK のサーバー接続のデフォルトタイムアウトは 60 秒です。サーバーの起動に時間がかかる場合、接続は失敗します。より多くの起動時間が必要なサーバーの場合は、以下を検討してください:
- 利用可能な場合は、より軽量なサーバーを使用する
- エージェントを開始する前にサーバーをプリウォーミングする
- 遅い初期化の原因についてサーバーログを確認する
関連リソース
- カスタムツールガイド:SDK アプリケーションと同じプロセスで実行される独自の MCP サーバーを構築します
- パーミッション:
allowedToolsとdisallowedToolsを使用してエージェントが使用できる MCP ツールを制御します - TypeScript SDK リファレンス:MCP 設定オプションを含む完全な API リファレンス
- Python SDK リファレンス:MCP 設定オプションを含む完全な API リファレンス
- MCP サーバーディレクトリ:データベース、API など、利用可能な MCP サーバーを参照します