SpyBara
Go Premium

agent-sdk/mcp.md 2026-11-11 22:59 UTC to 2026-11-12 22:01 UTC

No changes for this document in this history range.

2026
Mon 9 23:02

Hubungkan ke alat eksternal dengan MCP

Konfigurasi server MCP untuk memperluas agen Anda dengan alat eksternal. Mencakup jenis transport, pencarian alat untuk set alat besar, autentikasi, dan penanganan kesalahan.

Model Context Protocol (MCP) adalah standar terbuka untuk menghubungkan agen AI ke alat eksternal dan sumber data. Dengan MCP, agen Anda dapat menanyakan database, mengintegrasikan dengan API seperti Slack dan GitHub, dan terhubung ke layanan lain tanpa menulis implementasi alat khusus.

Server MCP dapat berjalan sebagai proses lokal, terhubung melalui HTTP, atau dieksekusi langsung dalam aplikasi SDK Anda.

[!NOTE]

Halaman ini mencakup konfigurasi MCP untuk Agent SDK. Untuk menambahkan server MCP ke Claude Code CLI sehingga dimuat di setiap proyek, lihat Cakupan instalasi MCP.

Quickstart

Contoh ini terhubung ke server MCP dokumentasi Claude Code menggunakan transport HTTP dan menggunakan allowedTools dengan wildcard untuk mengizinkan semua alat dari server.

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())

Agen terhubung ke server dokumentasi, mencari informasi tentang hooks, dan mengembalikan hasilnya.

Tambahkan server MCP

Anda dapat mengonfigurasi server MCP dalam kode saat memanggil query(), atau dalam file .mcp.json yang dimuat melalui settingSources.

Tambahkan server dalam kode

Teruskan server MCP secara langsung dalam opsi mcpServers. Contoh ini memulai server MCP filesystem lokal untuk /Users/me/projects. Ganti jalur tersebut dengan direktori di mesin Anda:

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())

Tambahkan server dari file konfigurasi

Buat file .mcp.json di root proyek Anda. File ini diambil ketika sumber pengaturan project diaktifkan, yang merupakan default untuk opsi query(). Jika Anda menetapkan settingSources secara eksplisit, sertakan "project" agar file ini dimuat. Ganti /Users/me/projects dengan direktori di mesin Anda:

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

Waktu koneksi

Claude Code mulai menghubungkan server MCP Anda saat sesi dimulai, dan mengirimkan pesan init setelah penantian giliran pertama, jika ada, berakhir. Berapa lama giliran pertama menunggu sebuah server tergantung pada tempat Anda mengonfigurasinya. Jika Anda menetapkan permissionPromptToolName, giliran pertama selalu menunggu server tool tersebut, hingga MCP_TIMEOUT, di mana pun Anda mengonfigurasinya.

Untuk server dalam options.mcpServers, temukan jenisnya di kolom pertama untuk melihat berapa lama giliran pertama menunggunya.

Jenis server Menunda putaran pertama? Batas waktu tunggu putaran pertama
Server stdio, atau server HTTP/SSE tanpa daftar alat yang di-cache Ya, sampai terhubung MCP_TIMEOUT, 30 detik secara default; koneksi gagal pada batas waktu tersebut
Server jarak jauh dengan daftar alat yang di-cache, disimpan oleh Claude Code dari koneksi sebelumnya Tidak; alat yang di-cache tersedia dari putaran pertama Tidak ada; terhubung pada panggilan alat pertamanya, dan koneksi tertunda tersebut memiliki batas waktu sendiri
Server SDK dalam proses Ya, sampai terhubung dan mencantumkan alatnya MCP_TIMEOUT, 30 detik secara default, per upaya koneksi; koneksi gagal pada batas waktu tersebut

Server memiliki daftar tool yang di-cache hanya ketika cache penemuan MCP aktif.

Server dari file pengaturan seperti .mcp.json, atau dari plugin, sering kali masih menunjukkan pending dalam pesan init. Berapa lama giliran pertama menunggunya tergantung pada options.mcpServers dan pencarian tool:

  • options.mcpServers menyertakan server stdio, HTTP, atau SSE: giliran pertama juga menunggu server file pengaturan dan plugin yang tertunda, hingga MCP_TIMEOUT.
  • Jika tidak, ketika ANTHROPIC_BASE_URL mengarah ke gateway dan ENABLE_TOOL_SEARCH tidak diatur: giliran pertama menunggu hingga 2 detik untuk setiap server file pengaturan dan plugin yang tertunda.
  • Jika tidak, dengan pencarian tool aktif, yang merupakan default: giliran pertama menunggu hingga 2 detik, dan hanya untuk server tertunda yang menetapkan alwaysLoad: true atau yang Anda sebutkan namanya. Server lainnya terus terhubung di latar belakang, dan Claude menjangkau tool-nya setelah server tersebut terhubung.
  • Jika tidak, dengan pencarian tool nonaktif: giliran pertama menunggu hingga 2 detik untuk setiap server file pengaturan dan plugin yang tertunda. Pencarian tool nonaktif ketika nilai ENABLE_TOOL_SEARCH atau model Anda mematikannya, atau ketika Anda mengecualikan tool ToolSearch, misalnya melalui disallowedTools.

Server yang disebutkan namanya

Anda menyebutkan nama sebuah server dengan mencantumkan salah satu tool-nya, seperti mcp__github__list_issues atau mcp__github__*, dalam allowedTools atau dalam aturan permissions.allow pada opsi settings. Hook mcp_tool juga menyebutkan nama server yang dipanggilnya ketika Anda mengonfigurasinya pada event pengiriman prompt, penggunaan tool, izin, subagent, task, elicitation, atau worktree. Sebelum v2.1.284, menyebutkan nama server tidak berpengaruh pada penantian giliran pertama.

Menetapkan sendiri penantian giliran pertama

Untuk menentukan sendiri penantian giliran pertama, atur CLAUDE_CODE_MCP_STARTUP_WAIT_MS dalam opsi env, misalnya CLAUDE_CODE_MCP_STARTUP_WAIT_MS: "5000". Giliran pertama kemudian menunggu hingga sebanyak milidetik tersebut untuk server file pengaturan dan plugin yang tertunda, terlepas dari apakah pencarian tool aktif atau tidak. Batas yang sama menggantikan penantian MCP_TIMEOUT untuk server stdio, HTTP, dan SSE dalam options.mcpServers.

Tiga penantian berlaku berapa pun nilai yang Anda tetapkan, termasuk 0:

  • Server permissionPromptToolName: hingga MCP_TIMEOUT.
  • Server SDK dalam proses: hingga MCP_TIMEOUT per upaya koneksi.
  • Server yang disebutkan namanya yang masih terhubung: setidaknya hingga 2 detik, sehingga nilai di bawah 2000 tidak mempersingkat penantiannya.

Atur variabel ke 0 untuk melewati penantian bagi setiap server lainnya. Server yang masih tertunda ketika penantian berakhir terus terhubung di latar belakang. CLAUDE_CODE_MCP_STARTUP_WAIT_MS memerlukan Claude Code v2.1.274 atau lebih baru.

Membuat startup menunggu server

Dua pengaturan membuat startup itu sendiri menunggu, sebelum Claude Code mengirimkan pesan init:

  • MCP_CONNECTION_NONBLOCKING diatur ke 0: startup menunggu seluruh batch koneksi, hingga 5 detik secara default. Atur MCP_CONNECT_TIMEOUT_MS, dalam milidetik, untuk mengubah batas tersebut. Server yang masih tertunda pada batas tersebut terus terhubung di latar belakang.
  • alwaysLoad: true pada konfigurasi server: startup menunggu hingga batas yang sama untuk tool server tersebut, sehingga giliran pertama memilikinya dengan skema lengkap, dikecualikan dari penundaan pencarian tool. Server jarak jauh dengan daftar tool yang di-cache menyediakannya tanpa terhubung atau menahan startup.

Pesan init melaporkan status setiap server pada saat Claude Code mengirimkannya.

Izinkan alat MCP

Alat MCP memerlukan izin eksplisit sebelum Claude dapat menggunakannya. Tanpa izin, Claude akan melihat bahwa alat tersedia tetapi tidak akan dapat memanggilnya.

Konvensi penamaan alat

Tool MCP diberi nama mcp__<server-name>__<tool-name>, dengan <server-name> adalah nama yang Anda gunakan untuk mendaftarkan server, seperti kuncinya di mcpServers.

Karakter dalam nama server seperti . dan spasi diganti dengan _. Tabel ini menunjukkan nama lengkap tool list_issues untuk dua kunci server:

Kunci di mcpServers Nama tool lengkap
github mcp__github__list_issues
my.server mcp__my_server__list_issues

Gunakan nama tool lengkap di allowedTools dan di aturan izin MCP. Untuk server yang disediakan oleh plugin, <server-name> menggunakan bentuk dengan cakupan plugin dan diawali dengan plugin_.

Auto-approve dengan allowedTools

Gunakan allowedTools untuk auto-approve alat MCP tertentu:

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
    ],
)

Wildcard (*) memungkinkan Anda untuk mengizinkan semua alat dari server tanpa mencantumkan masing-masing secara individual.

[!NOTE]

Lebih suka allowedTools daripada mode izin untuk akses MCP. permissionMode: "acceptEdits" tidak auto-approve alat MCP (hanya edit file dan perintah Bash filesystem). permissionMode: "bypassPermissions" melakukan auto-approve alat MCP tetapi juga menonaktifkan sebagian besar prompt keamanan lainnya, yang lebih luas dari yang diperlukan; lihat Bagaimana izin dievaluasi untuk prompt yang tetap ada. Wildcard dalam allowedTools memberikan akses ke server MCP yang Anda inginkan dan tidak lebih. Lihat Mode izin untuk perbandingan lengkap.

Temukan alat yang tersedia

Untuk melihat alat apa yang disediakan server MCP, periksa dokumentasi server atau inspeksi array tools dalam pesan init system. Nama alat MCP dimulai dengan mcp__.

Claude Code memancarkan pesan init setelah penundaan koneksi giliran pertama untuk server yang dilewatkan dalam options.mcpServers, jadi array tools mencantumkan alat mcp__ dari setiap server yang telah terhubung pada saat itu, ditambah alat dari server dengan daftar alat yang di-cache, yang terhubung pada penggunaan pertama. Alat dari server lain yang belum terhubung tidak ada; lihat Penanganan kesalahan untuk membaca status setiap server.

Filter ini mencetak nama alat 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())

Anda juga dapat meminta Claude untuk mencantumkan alat yang tersedia dari server.

Jenis transport

Server MCP berkomunikasi dengan agen Anda menggunakan protokol transport yang berbeda. Periksa dokumentasi server untuk melihat transport mana yang didukungnya:

  • Jika dokumen memberi Anda perintah untuk dijalankan (seperti npx @modelcontextprotocol/server-filesystem), gunakan stdio
  • Jika dokumen memberi Anda URL, gunakan HTTP atau SSE
  • Jika Anda membangun alat Anda sendiri dalam kode, gunakan server MCP SDK

Server stdio

Proses lokal yang berkomunikasi melalui stdin/stdout. Gunakan ini untuk server MCP yang Anda jalankan di mesin yang sama. Untuk bentuk .mcp.json, gunakan bidang yang sama seperti yang ditunjukkan di Menambahkan server dari file konfigurasi. Dalam kode, teruskan perintah dan argumennya. Ganti /Users/me/projects dengan direktori di mesin Anda:

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"],
)

Server HTTP/SSE

Gunakan HTTP atau SSE untuk server MCP yang dihosting di cloud dan API jarak jauh. Untuk bentuk .mcp.json, gunakan bidang yang sama seperti contoh di Header HTTP untuk server jarak jauh, dengan "type": "sse" untuk server SSE. Dalam kode, teruskan URL server:

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__*"],
)

Untuk transport HTTP yang dapat dialirkan, gunakan "type": "http" sebagai gantinya. Dalam file konfigurasi .mcp.json dan JSON lainnya, "streamable-http" diterima sebagai alias untuk "http". Tipe McpHttpServerConfig SDK hanya mendeklarasikan "http", jadi gunakan "http" untuk server yang Anda teruskan dalam kode.

Server MCP SDK

Tentukan alat khusus langsung dalam kode aplikasi Anda alih-alih menjalankan proses server terpisah. Lihat panduan alat khusus untuk detail implementasi.

Server MCP SDK yang didaftarkan oleh permintaan kontrol initialize mulai terhubung segera setelah Claude Code memproses permintaan.

Pencarian tool MCP

Ketika Anda memiliki banyak tool MCP yang dikonfigurasi, definisi tool dapat mengonsumsi sebagian signifikan dari jendela konteks Anda. Pencarian tool mengatasi ini dengan menahan definisi tool dari konteks dan memuat hanya yang Claude butuhkan untuk setiap giliran.

Pencarian tool diaktifkan secara default. Lihat Pencarian tool untuk opsi konfigurasi, praktik terbaik, dan menggunakan pencarian tool dengan tool SDK kustom.

Autentikasi

Sebagian besar server MCP memerlukan autentikasi untuk mengakses layanan eksternal. Teruskan kredensial melalui variabel lingkungan dalam konfigurasi server.

Teruskan kredensial melalui variabel lingkungan

Gunakan field env untuk meneruskan kunci API, token, dan kredensial lainnya ke server MCP:

[tab] Dalam kode

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}"
      }
    }
  }
}

Sintaks ${API_KEY} memperluas variabel lingkungan saat runtime.

Header HTTP untuk server jarak jauh

Untuk server HTTP dan SSE, teruskan header autentikasi langsung dalam konfigurasi server:

[tab] Dalam kode

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}"
      }
    }
  }
}

Sintaks ${API_TOKEN} memperluas variabel lingkungan saat runtime.

Untuk contoh kerja lengkap dari server jarak jauh yang diautentikasi dengan header, lihat Daftar masalah dari repositori.

Autentikasi OAuth2

Spesifikasi MCP mendukung OAuth 2.1 untuk otorisasi. SDK tidak membuka browser atau menjalankan alur OAuth interaktif. Ketika server yang dikonfigurasi mengembalikan tantangan otorisasi dan Claude Code tidak memiliki token untuk dikirim, SDK melaporkan server tersebut sebagai needs-auth atau failed:

  • needs-auth: Claude Code tidak menemukan proses masuk yang dapat digunakan untuk server tersebut. Teruskan token dalam headers, atau masuk dari sesi Claude Code interaktif pada mesin yang sama sebelum menjalankan.
  • failed, dengan error dalam entri McpServerStatus yang diawali dengan Couldn't read the stored credentials atau A request to MCP server: Claude Code tidak dapat membaca penyimpanan kredensialnya. Untuk langkah yang perlu dilakukan, lihat Couldn't read the stored credentials for MCP server. Sebelum Claude Code v2.1.307, statusnya adalah needs-auth ketika keychain login Mac terkunci.

Dalam kedua kasus, proses agent tetap berlanjut tanpa tool dari server tersebut. Array mcp_servers dari pesan inisialisasi sistem mungkin masih menunjukkan pending untuk server tersebut saat dipancarkan. Untuk mengonfirmasi apakah server memerlukan kredensial, polling mcpServerStatus() dalam SDK TypeScript atau get_mcp_status() dalam Python.

Untuk menyediakan kredensial, selesaikan alur OAuth dalam aplikasi Anda sendiri dan teruskan token akses yang dihasilkan dalam headers server:

// Setelah menyelesaikan alur OAuth dalam aplikasi Anda.
// Implementasikan getAccessTokenFromOAuthFlow untuk penyedia OAuth Anda.
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__*"]
};
# Setelah menyelesaikan alur OAuth dalam aplikasi Anda.
# Implementasikan get_access_token_from_oauth_flow untuk penyedia OAuth Anda.
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__*"],
)

Contoh

Daftar masalah dari repositori

Contoh ini terhubung ke server MCP GitHub jarak jauh untuk mencantumkan masalah terbaru. Contoh ini mencakup logging debug untuk memverifikasi koneksi MCP dan panggilan alat.

Sebelum menjalankan, buat token akses pribadi GitHub dengan akses baca ke repositori yang ingin Anda kueri dan atur sebagai variabel lingkungan:

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())

Pada baris MCP servers:, status sebesar connected untuk github mengkonfirmasi token berfungsi. Jika Claude Code memiliki daftar alat yang di-cache untuk server, status dapat membaca pending sebagai gantinya dan server terhubung pada panggilan alat pertamanya. Jika statusnya adalah failed atau needs-auth, lihat Penanganan kesalahan sebelum mempercayai hasilnya, karena Claude dapat kembali ke alat bawaan ketika server tidak tersedia.

Kueri basis data

Contoh ini menggunakan DBHub untuk mengueri basis data Postgres. Agen secara otomatis menemukan skema basis data, menulis kueri SQL, dan mengembalikan hasilnya.

Alat execute_sql DBHub menjalankan SQL apa pun yang dikeluarkan agen, termasuk penulisan, kecuali Anda membatasinya. Mengatur readonly = true dalam file konfigurasi DBHub membuat DBHub menolak pernyataan INSERT, UPDATE, DELETE, dan DDL, sehingga contoh tidak dapat memodifikasi data Anda bahkan jika agen mengeluarkan penulisan. DBHub menyelesaikan ${DATABASE_URL} dari lingkungan proses ketika memuat konfigurasi, sehingga string koneksi tetap keluar dari file. Buat dbhub.toml ini di sebelah skrip Anda:

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

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

Skrip kemudian menunjukkan DBHub ke file konfigurasi alih-alih melewatkan string koneksi secara langsung. Sebelum menjalankan, atur variabel lingkungan DATABASE_URL ke string koneksi Anda. Ganti nilai placeholder dengan detail basis data Anda sendiri:

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())

Penanganan kesalahan

Server MCP dapat gagal terhubung karena berbagai alasan: proses server mungkin tidak terinstal, kredensial mungkin tidak valid, atau server jarak jauh mungkin tidak dapat dijangkau.

Claude Code mengirimkan pesan system dengan subtype init di awal setiap kueri. Pesan ini mencakup status koneksi untuk setiap server MCP. Bidang status dapat berupa "pending", "connected", "failed", "needs-auth", atau "disabled". Claude Code mengirimkan pesan init setelah waktu tunggu koneksi putaran pertama untuk server yang dilewatkan dalam options.mcpServers, jadi server seperti itu yang terhubung dalam waktu tunggu menunjukkan "connected".

Dalam pesan init, jangan perlakukan "pending" sebagai kegagalan dengan sendirinya. Ini dapat berarti salah satu dari ini:

Periksa "failed" atau "needs-auth" untuk mendeteksi server yang tidak akan dapat digunakan:

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())

Status server jarak jauh juga dapat berubah setelah melaporkan "connected". Ketika koneksi ke server itu terputus di tengah sesi, Claude Code memindahkan server kembali ke "pending" sambil menghubungkan kembali. Panggilan mcpServerStatus() yang lebih baru dalam TypeScript, atau ClaudeSDKClient.get_mcp_status() dalam Python, kemudian dapat melaporkan "pending" untuk server yang Anda lihat terhubung sebelumnya, tanpa perubahan konfigurasi di pihak Anda.

Setelah lima upaya penghubungan kembali gagal, server melaporkan "failed", atau "needs-auth" ketika perlu diotorisasi lagi. Server HTTP atau SSE yang berstatus "failed" masih dapat kembali ke "connected" tanpa panggilan dari Anda, karena Claude Code terus mencoba ulang di latar belakang setelah terjadi kesalahan sementara. Untuk mencoba ulang secara manual, panggil reconnectMcpServer() dalam TypeScript atau ClaudeSDKClient.reconnect_mcp_server() dalam Python.

Troubleshooting

Server menunjukkan status "failed"

Periksa pesan init untuk melihat server mana yang gagal terhubung:

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")

Status "pending" tidak berarti server gagal. Lihat Error handling untuk kasus-kasus yang dicakupnya saat init. Untuk mendapatkan status yang diperbarui nanti dalam sesi, panggil metode mcpServerStatus() query di TypeScript SDK, atau ClaudeSDKClient.get_mcp_status() di Python.

Penyebab umum:

  • Variabel lingkungan yang hilang: Pastikan token dan kredensial yang diperlukan telah diatur. Untuk server stdio, periksa bahwa field env cocok dengan apa yang diharapkan server.
  • Server tidak terinstal: Untuk perintah npx, verifikasi bahwa paket ada dan Node.js berada di PATH Anda.
  • String koneksi tidak valid: Untuk server database, verifikasi format string koneksi dan bahwa database dapat diakses.
  • Masalah jaringan: Untuk server HTTP/SSE jarak jauh, periksa bahwa URL dapat dijangkau dan firewall apa pun memungkinkan koneksi.

Tools tidak dipanggil

Jika Claude melihat tools tetapi tidak menggunakannya, periksa bahwa Anda telah memberikan izin dengan 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
)

Tool hilang dari server MCP SDK

Di TypeScript SDK, ketika skema input suatu tool tidak dapat dikonversi ke JSON Schema, server yang Anda buat dengan createSdkMcpServer() menghilangkan tool tersebut saat mencantumkan tool-nya. SDK mengeluarkan peringatan pada saat itu. Di bawah Node.js, peringatan tersebut adalah process warning dengan kode CLAUDE_SDK_MCP_TOOL_SCHEMA_UNCONVERTIBLE, dan diawali dengan teks berikut:

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

Bagian selanjutnya dari peringatan tersebut memberikan pesan kesalahan konversi jika ada, lalu menyebutkan apa yang perlu diperiksa dan diubah.

Sebelum TypeScript Agent SDK v0.3.286, satu skema yang tidak dapat dikonversi membuat seluruh daftar tool server gagal tanpa peringatan ini, sehingga tidak ada satu pun tool dari server tersebut yang sampai ke Claude.

Connection timeouts

Koneksi server MCP habis waktu setelah 30 detik secara default. Untuk mengubah berapa lama panggilan tool yang sedang berjalan dapat memakan waktu, atur MCP_TOOL_TIMEOUT. Jika server Anda membutuhkan waktu lebih lama untuk memulai, koneksi gagal. Naikkan batas koneksi dengan variabel lingkungan MCP_TIMEOUT, dalam milidetik. Untuk server yang membutuhkan lebih banyak waktu startup, pertimbangkan juga:

  • Menggunakan server yang lebih ringan jika tersedia
  • Pre-warming server sebelum memulai agent Anda
  • Memeriksa log server untuk penyebab inisialisasi yang lambat

Di TypeScript, Anda dapat mengatur batas panggilan tool untuk SDK MCP server tunggal dengan melewatkan timeout ke createSdkMcpServer().

Tool output melebihi token maksimal yang diizinkan

SDK menerapkan batas output MCP yang sama dengan Claude Code. Ketika hasil tool yang berhasil tanpa konten gambar lebih besar dari 25.000 token, Claude Code menyimpan output ke file dan mengganti hasil tool dengan pesan kesalahan yang menyebutkan jalur file, sehingga agent dapat membaca output kembali dalam porsi.

Untuk mengubah batas token, atur environment variable MAX_MCP_OUTPUT_TOKENS. Kecuali tool mendeklarasikan anthropic/maxResultSizeChars, hasil teks yang berhasil dengan panjang lebih dari 50.000 karakter disimpan ke file terlepas dari batas token. Lihat MCP output limits and warnings untuk perilaku lengkap, termasuk bagaimana server mendeklarasikan anotasi tersebut.

Sumber daya terkait

  • Panduan alat kustom: Bangun server MCP Anda sendiri yang berjalan dalam proses dengan aplikasi SDK Anda
  • Izin: Kontrol alat MCP mana yang dapat digunakan agen Anda dengan allowedTools dan disallowedTools
  • Referensi TypeScript SDK: Referensi API lengkap termasuk opsi konfigurasi MCP
  • Referensi Python SDK: Referensi API lengkap termasuk opsi konfigurasi MCP
  • Direktori server MCP: Jelajahi server MCP yang tersedia untuk database, API, dan lainnya