This page covers MCP configuration for the Agent SDK. To add MCP servers to the Claude Code CLI so they load in every project, see MCP installation scopes.
Quickstart
This example connects to the Claude Code documentation MCP server using HTTP transport and usesallowedTools with a wildcard to permit all tools from the server.
Add an MCP server
You can configure MCP servers in code when callingquery(), or in a .mcp.json file loaded via settingSources.
Add a server in code
Pass MCP servers directly in themcpServers option. This example starts a local filesystem MCP server for /Users/me/projects. Replace that path with a directory on your machine:
Add a server from a config file
Create a.mcp.json file at your project root. The file is picked up when the project setting source is enabled, which it is for default query() options. If you set settingSources explicitly, include "project" for this file to load. Replace /Users/me/projects with a directory on your machine:
Connection timing
Claude Code starts connecting your MCP servers when the session starts, and sends the init message once the first-turn wait, if any, ends. How long the first turn waits for a server depends on where you configured it. If you setpermissionPromptToolName, the first turn always waits for that tool’s server, up to MCP_TIMEOUT, wherever you configured it.
For a server in options.mcpServers, find its type in the first column to see how long the first turn waits for it.
A server has a cached tool list only when the MCP discovery cache is on.
Servers from settings files such as
.mcp.json, or from plugins, often still show pending in the init message. How long the first turn waits for them depends on options.mcpServers and tool search:
options.mcpServersincludes a stdio, HTTP, or SSE server: the first turn waits for the pending settings-file and plugin servers too, up toMCP_TIMEOUT.- Otherwise, when
ANTHROPIC_BASE_URLpoints to a gateway andENABLE_TOOL_SEARCHis unset: the first turn waits up to 2 seconds for every pending settings-file and plugin server. - Otherwise, with tool search on, which is the default: the first turn waits up to 2 seconds, and only for pending servers that set
alwaysLoad: trueor that you named. The rest keep connecting in the background, and Claude reaches their tools once they connect. - Otherwise, with tool search off: the first turn waits up to 2 seconds for every pending settings-file and plugin server. Tool search is off when your
ENABLE_TOOL_SEARCHvalue or model turns it off, or when you exclude theToolSearchtool, for example throughdisallowedTools.
Named servers
You name a server by listing any of its tools, such asmcp__github__list_issues or mcp__github__*, in allowedTools or in a permissions.allow rule in the settings option. An mcp_tool hook also names the server it calls when you configure it on a prompt-submission, tool-use, permission, subagent, task, elicitation, or worktree event. Before v2.1.284, naming a server had no effect on the first-turn wait.
Set the first-turn wait yourself
To choose the first-turn wait yourself, setCLAUDE_CODE_MCP_STARTUP_WAIT_MS in the env option, for example CLAUDE_CODE_MCP_STARTUP_WAIT_MS: "5000". The first turn then waits up to that many milliseconds for pending settings-file and plugin servers, whether or not tool search is on. The same limit replaces the MCP_TIMEOUT wait for the stdio, HTTP, and SSE servers in options.mcpServers.
Three waits apply whatever value you set, including 0:
- A
permissionPromptToolNameserver: up toMCP_TIMEOUT. - An in-process SDK server: up to
MCP_TIMEOUTper connect attempt. - A still-connecting named server: at least up to 2 seconds, so a value below
2000doesn’t shorten its wait.
0 to skip the wait for every other server. Servers still pending when the wait ends keep connecting in the background. CLAUDE_CODE_MCP_STARTUP_WAIT_MS requires Claude Code v2.1.274 or later.
Make startup wait for servers
Two settings make startup itself wait, before Claude Code sends the init message:MCP_CONNECTION_NONBLOCKINGset to0: startup waits for the whole connection batch, up to 5 seconds by default. SetMCP_CONNECT_TIMEOUT_MS, in milliseconds, to change that cap. Servers still pending at the cap keep connecting in the background.alwaysLoad: trueon a server’s config: startup waits up to the same cap for that server’s tools, so the first turn has them at full schema, exempt from tool search deferral. A remote server with a cached tool list supplies them without connecting or holding startup.
Allow MCP tools
MCP tools require explicit permission before Claude can use them. Without permission, Claude will see that tools are available but won’t be able to call them.Tool naming convention
MCP tools are namedmcp__<server-name>__<tool-name>, where <server-name> is the name you register the server under, such as its key in mcpServers.
Characters in the server name such as . and spaces are replaced by _. This table shows the full name of a list_issues tool for two server keys:
Use the full tool names in
allowedTools and in MCP permission rules. For a server that a plugin provides, <server-name> takes the plugin-scoped form and starts with plugin_.
Auto-approve with allowedTools
UseallowedTools to auto-approve specific MCP tools so Claude can use them without a permission prompt:
*) let you allow all tools from a server without listing each one individually.
Prefer
allowedTools over permission modes for MCP access. permissionMode: "acceptEdits" does not auto-approve MCP tools (only file edits and filesystem Bash commands). permissionMode: "bypassPermissions" does auto-approve MCP tools but also disables most other safety prompts, which is broader than necessary; see How permissions are evaluated for the prompts that remain. A wildcard in allowedTools grants exactly the MCP server you want and nothing more. See Permission modes for a full comparison.Discover available tools
To see what tools an MCP server provides, check the server’s documentation or inspect thetools array in the system init message. MCP tool names start with mcp__.
Claude Code emits the init message after the first-turn connection wait for servers passed in options.mcpServers, so the tools array lists the mcp__ tools of each server that has connected by then, plus those of servers with a cached tool list, which connect on first use. Tools of any other server that hasn’t connected are absent; see Error handling for reading each server’s status.
This filter prints the MCP tool names:
Transport types
MCP servers communicate with your agent using different transport protocols. Check the server’s documentation to see which transport it supports:- If the docs give you a command to run (like
npx @modelcontextprotocol/server-filesystem), use stdio - If the docs give you a URL, use HTTP or SSE
- If you’re building your own tools in code, use an SDK MCP server
stdio servers
Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine. For the.mcp.json form, use the same fields shown at Add a server from a config file. In code, pass the command and its arguments. Replace /Users/me/projects with a directory on your machine:
HTTP/SSE servers
Use HTTP or SSE for cloud-hosted MCP servers and remote APIs. For the.mcp.json form, use the same fields as the example at HTTP headers for remote servers, with "type": "sse" for an SSE server. In code, pass the server’s URL:
"type": "http" instead. In .mcp.json and other JSON config files, "streamable-http" is accepted as an alias for "http". The SDKs’ McpHttpServerConfig type declares only "http", so use "http" for servers you pass in code.
SDK MCP servers
Define custom tools directly in your application code instead of running a separate server process. See the custom tools guide for implementation details. An SDK MCP server registered by aninitialize control request begins connecting as soon as Claude Code processes the request.
MCP tool search
When you have many MCP tools configured, tool definitions can consume a significant portion of your context window. Tool search solves this by withholding tool definitions from context and loading only the ones Claude needs for each turn. Tool search is enabled by default. See Tool search for configuration options, best practices, and using tool search with custom SDK tools.Authentication
Most MCP servers require authentication to access external services. Pass credentials through environment variables in the server configuration.Pass credentials via environment variables
Use theenv field to pass API keys, tokens, and other credentials to the MCP server:
- In code
- .mcp.json
HTTP headers for remote servers
For HTTP and SSE servers, pass authentication headers directly in the server configuration:- In code
- .mcp.json
OAuth2 authentication
The MCP specification supports OAuth 2.1 for authorization. The SDK doesn’t open a browser or run an interactive OAuth flow. When a configured server returns an authorization challenge and Claude Code has no token to send, the SDK reports the server asneeds-auth or failed:
needs-auth: Claude Code found no sign-in it can use for the server. Pass a token inheaders, or sign in from an interactive Claude Code session on the same machine before the run.failed, with anerrorin itsMcpServerStatusentry that starts withCouldn't read the stored credentialsorA request to MCP server: Claude Code couldn’t read its credential store. For what to do, see Couldn’t read the stored credentials for MCP server. Before Claude Code v2.1.307, the status wasneeds-authinstead when a Mac’s login keychain was locked.
mcp_servers array of the system init message may still show pending for that server when it’s emitted. To confirm whether a server needs credentials, poll mcpServerStatus() in the TypeScript SDK or get_mcp_status() in Python.
To supply credentials, complete the OAuth flow in your own application and pass the resulting access token in the server’s headers:
Examples
List issues from a repository
This example connects to the remote GitHub MCP server to list recent issues. The example includes debug logging to verify the MCP connection and tool calls. Before running, create a GitHub personal access token with read access to the repositories you want to query and set it as an environment variable:MCP servers: line, a status of connected for github confirms the token works. If Claude Code has a cached tool list for the server, the status can read pending instead and the server connects on its first tool call. If the status is failed or needs-auth, see Error handling before trusting the result, since Claude can fall back to built-in tools when the server is unavailable.
Query a database
This example uses DBHub to query a Postgres database. The agent automatically discovers the database schema, writes the SQL query, and returns the results. DBHub’sexecute_sql tool runs whatever SQL the agent emits, including writes, unless you restrict it. Setting readonly = true in the DBHub configuration file makes DBHub reject INSERT, UPDATE, DELETE, and DDL statements, so the example cannot modify your data even if the agent emits a write. DBHub resolves ${DATABASE_URL} from the process environment when it loads the config, so the connection string stays out of the file. Create this dbhub.toml next to your script:
dbhub.toml
DATABASE_URL environment variable to your connection string. Replace the placeholder values with your own database details:
Error handling
MCP servers can fail to connect for various reasons: the server process might not be installed, credentials might be invalid, or a remote server might be unreachable. Claude Code emits asystem message with subtype init at the start of each query. This message includes the connection status for each MCP server. The status field can be "pending", "connected", "failed", "needs-auth", or "disabled". Claude Code emits the init message after the first-turn connection wait for servers passed in options.mcpServers, so such a server that connected within the wait shows "connected".
In the init message, don’t treat "pending" as a failure on its own. It can mean any of these:
- The server hasn’t connected yet. See how long Claude Code waits for it before the first turn
- The server’s tool list was served from the cache, with a connection made on first use
- The connection deadline expired. Such a server reports
"pending"or"failed"depending on timing
"failed" or "needs-auth" to detect servers that won’t be usable:
"connected". When the connection to it drops mid-session, Claude Code moves the server back to "pending" while reconnecting. A later mcpServerStatus() call in TypeScript, or ClaudeSDKClient.get_mcp_status() in Python, can then report "pending" for a server you saw connected earlier, with no configuration change on your side.
After five reconnection attempts fail, the server reports "failed", or "needs-auth" when it needs authorizing again. A "failed" HTTP or SSE server can still return to "connected" without a call from you, because Claude Code keeps retrying in the background after a transient error. To retry manually, call reconnectMcpServer() in TypeScript or ClaudeSDKClient.reconnect_mcp_server() in Python.
Troubleshooting
Server shows “failed” status
Check theinit message to see which servers failed to connect:
"pending" status doesn’t mean the server failed. See Error handling for the cases it covers at init. To get updated statuses later in the session, call the query’s mcpServerStatus() method in the TypeScript SDK, or ClaudeSDKClient.get_mcp_status() in Python.
Common causes:
- Missing environment variables: Ensure required tokens and credentials are set. For stdio servers, check the
envfield matches what the server expects. - Server not installed: For
npxcommands, verify the package exists and Node.js is in your PATH. - Invalid connection string: For database servers, verify the connection string format and that the database is accessible.
- Network issues: For remote HTTP/SSE servers, check the URL is reachable and any firewalls allow the connection.
Tools not being called
If Claude sees tools but doesn’t use them, check that you’ve granted permission withallowedTools:
A tool is missing from an SDK MCP server
In the TypeScript SDK, when a tool’s input schema can’t be converted to JSON Schema, the server you created withcreateSdkMcpServer() leaves that tool out when it lists its tools. The SDK emits a warning at that point. Under Node.js the warning is a process warning with code CLAUDE_SDK_MCP_TOOL_SCHEMA_UNCONVERTIBLE, and it starts with this text:
Connection timeouts
MCP server connections time out after 30 seconds by default. To change how long a running tool call may take, setMCP_TOOL_TIMEOUT. If your server takes longer to start, the connection fails. Raise the connection limit with the MCP_TIMEOUT environment variable, in milliseconds. For servers that need more startup time, also consider:
- Using a lighter-weight server if available
- Pre-warming the server before starting your agent
- Checking server logs for slow initialization causes
timeout to createSdkMcpServer().
Tool output exceeds maximum allowed tokens
The SDK applies the same MCP output limits as Claude Code. When a successful tool result with no image content is larger than 25,000 tokens, Claude Code saves the output to a file and replaces the tool result with an error message that names the file path, so the agent can read the output back in portions. To change the token limit, set theMAX_MCP_OUTPUT_TOKENS environment variable. Unless the tool declares anthropic/maxResultSizeChars, a successful text result longer than 50,000 characters is saved to a file regardless of the token limit. See MCP output limits and warnings for the full behavior, including how a server declares that annotation.
Related resources
- Custom tools guide: Build your own MCP server that runs in-process with your SDK application
- Permissions: Control which MCP tools your agent can use with
allowedToolsanddisallowedTools - TypeScript SDK reference: Full API reference including MCP configuration options
- Python SDK reference: Full API reference including MCP configuration options
- MCP server directory: Browse available MCP servers for databases, APIs, and more