# Claude Code runs MCP Tasks in public beta

> Source: <https://code.claude.com/docs/en/mcp#mcp-tasks-that-run-on-the-server>
> Published: 2026-10-28 00:00:00+00:00

[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs. Connect a server when you find yourself copying data into chat from another tool, like an issue tracker or a monitoring dashboard. Once connected, Claude can read and act on that system directly instead of working from what you paste. If you’re connecting your first server, start with the

[MCP quickstart](https://code.claude.com/docs/en/mcp-quickstart)for a step-by-step walkthrough. This page is the full reference.

## What you can do with MCP

With MCP servers connected, you can ask Claude Code to:
- **Implement features from issue trackers** : “Add the feature described in JIRA issue ENG-4521 and create a PR on GitHub.”
- **Analyze monitoring data** : “Check Sentry and Statsig to check the usage of the feature described in ENG-4521.”
- **Query databases** : “Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database.”
- **Integrate designs** : “Update our standard email template based on the new Figma designs that were posted in Slack”
- **Automate workflows** : “Create Gmail drafts inviting these 10 users to a feedback session about the new feature.”
- **React to external events** : an MCP server can also act as a[channel](https://code.claude.com/docs/en/channels) that pushes messages into your session, so Claude reacts to Telegram messages, Discord chats, or webhook events while you’re away.

## Find and build MCP servers

Browse reviewed connectors in the
[Anthropic Directory](https://claude.ai/directory). Directory connectors use the same MCP infrastructure as Claude Code, so you can add any remote server listed there with

`claude mcp add`.
To build your own server, see the [MCP server guide](https://modelcontextprotocol.io/docs/develop/build-server)for protocol fundamentals and the

[Claude connector building docs](https://claude.com/docs/connectors/building)for authentication, testing, and Directory submission. You can also have Claude scaffold a server for you with the official

[.](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev)

`mcp-server-dev` plugin
Install the plugin

[Install a plugin](https://code.claude.com/docs/en/plugins/install#install-a-plugin)instead of this step. In a terminal, start Claude Code by running

`claude`, then enter this at its prompt:
- `Marketplace "claude-plugins-official" not found` : add the marketplace with`/plugin marketplace add anthropics/claude-plugins-official` , then retry the install.
- `Plugin "<name>" not found in marketplace "claude-plugins-official"` : your local copy of the marketplace catalog may be out of date. Refresh it with`/plugin marketplace update claude-plugins-official` , then retry the install. If the retry prints the same message, see[Plugin not found in marketplace](https://code.claude.com/docs/en/plugins/troubleshooting#plugin-not-found-in-marketplace) .

`Run /reload-plugins to apply.`, Claude Code then runs that reload for you. If the reload warns that your next message would re-read the conversation, run `/reload-plugins --force`.
Run the build skill

## Installing MCP servers

MCP servers can be configured in several ways depending on your needs:
### Option 1: Add a remote HTTP server

HTTP servers are the recommended option for connecting to remote MCP servers. This is the most widely supported transport for cloud-based services.`.mcp.json`, `~/.claude.json`, or `claude mcp add-json`, the `type` field accepts `streamable-http` as an alias for `http`. The MCP specification uses the name `streamable-http` for this transport, so configurations copied from server documentation work without modification.
A JSON entry that has a `url` but no `type` is a configuration error, because Claude Code reads an entry with no `type` as a stdio server. Claude Code skips that server and reports `MCP server "<name>" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entry`.
Only an SDK host application, such as an [Agent SDK](https://code.claude.com/docs/en/agent-sdk/mcp)application or the

[desktop app](https://code.claude.com/docs/en/desktop), can register an in-process

`"type": "sdk"` server. Claude Code skips a `"type": "sdk"` entry in `.mcp.json`, `~/.claude.json`, or settings and reports `Skipped — MCP server "<name>" declares type "sdk", which only an SDK host application can register`.
`--output-format stream-json` runs, Claude Code also reports a skipped `--mcp-config` entry in the `system/init` event’s [, so scripts can detect that the server never loaded.](https://code.claude.com/docs/en/headless#stream-responses)

`mcp_server_errors` field
### Option 2: Add a remote SSE server

Some services still expose only an SSE endpoint. Add these with the same`claude mcp add --transport http <name> <url>` command as [an HTTP server](#option-1-add-a-remote-http-server). Claude Code tries the HTTP transport first and switches to SSE when the server doesn’t accept it. The automatic switch requires Claude Code v2.1.265 or later. On an earlier version, or to connect over SSE directly, pass

`--transport sse` instead:
### Option 3: Add a local stdio server

Stdio servers run as local processes on your machine. They’re ideal for tools that need direct system access or custom scripts. Claude Code sets`CLAUDE_PROJECT_DIR` in the spawned server’s environment to the project root, so your server can resolve project-relative paths without depending on the working directory. This is the same directory hooks receive in their `CLAUDE_PROJECT_DIR` variable. Read it from inside your server process, for example `process.env.CLAUDE_PROJECT_DIR` in Node or `os.environ["CLAUDE_PROJECT_DIR"]` in Python.
`CLAUDE_PROJECT_DIR` is the stable project root and doesn’t change when you add or remove working directories mid-session. A server that limits its own filesystem access to a set of allowed directories should implement the MCP `roots/list` request instead. Claude Code answers `roots/list` with the session’s launch directory plus every [additional working directory](https://code.claude.com/docs/en/permissions#working-directories)you’ve granted with

`--add-dir`, `/add-dir`, or the `additionalDirectories` setting. Claude Code sends `notifications/roots/list_changed` when that set changes.
This variable is set in the server’s environment, not in Claude Code’s own environment, so referencing it via `${VAR}` expansion in the `command` or `args` of a project-scoped `.mcp.json` entry or a local- or user-scoped server entry in `~/.claude.json` requires a default such as `${CLAUDE_PROJECT_DIR:-.}`. Plugin-provided MCP configurations substitute `${CLAUDE_PROJECT_DIR}` directly and don’t need the default.
`--` (double dash) separates Claude’s own options, such as `--transport`, `--env`, and `--scope`, from the command and arguments that run the server. Everything after `--` is passed to the server untouched.For example:
- `claude mcp add --transport stdio myserver -- npx server` → runs`npx server`
- `claude mcp add --env KEY=value --transport stdio myserver -- python server.py --port 8080` → runs`python server.py --port 8080` with`KEY=value` in environment

`--`, Claude Code would try to parse the server’s flags, like `--port` above, as its own options.`--env` accepts multiple `KEY=value` pairs. If the server name comes directly after `--env`, the CLI reads the name as another pair and rejects it, so place at least one other option, such as `--transport stdio`, between `--env` and the server name.
#### How Claude Code stops a stdio server

When Claude Code disconnects a stdio server, for example when your session ends, it signals the server process and waits briefly for it to exit before forcing it to stop. If your server saves state or removes lock files at shutdown, handle the signal for your platform and finish within that time:
- **On macOS and Linux** : Claude Code sends`SIGINT` , then`SIGTERM` if the process is still running 100 milliseconds later, then`SIGKILL` after a further 400 milliseconds.
- **On Windows** : Claude Code closes the server’s stdin, then ends the server’s process tree if the process is still running 300 milliseconds later.

### Option 4: Add a remote WebSocket server

WebSocket servers hold a persistent bidirectional connection, which suits remote MCP servers that push events to Claude unprompted. Use HTTP instead when your server only responds to requests, since HTTP supports OAuth and the`claude mcp add --transport` flag, while WebSocket supports neither.
Configure WebSocket servers in `.mcp.json` or with `claude mcp add-json`:
`type: "ws"` entry accepts the same `url`, `headers`, `headersHelper`, `timeout`, and `alwaysLoad` fields as `http`. Authentication is header-only, so pass a static token in `headers` or generate one at connect time with [. The](#use-dynamic-headers-for-custom-authentication)

`headersHelper`` claude mcp add --transport` flag doesn’t accept `ws`.
### Add a server from setup instructions written for another client

MCP servers aren’t specific to Claude Code, so a server’s setup instructions may be written for Claude Desktop, Cursor, or another MCP client and give no`claude mcp add` command. To add the server anyway, look in those instructions for a URL, a launch command, or a JSON block:
- **A URL** such as`https://mcp.example.com/mcp` : the server is remote.
- **A launch command** such as`npx -y @example/mcp-server` : the server runs on your machine.
- **An `mcpServers` JSON block** : configuration written for another client’s settings file.

[Installing MCP servers](#installing-mcp-servers)take. Find the shape you have below to turn it into the command Claude Code accepts. Each command writes to

[local scope](#local-scope)unless you add

`--scope project` or `--scope user`.
#### Add a server from a URL

A URL means the server is remote. For an`https://` endpoint, add it with `--transport http`, or follow [Option 2](#option-2-add-a-remote-sse-server)when the instructions say the endpoint uses SSE. For a

`wss://` endpoint, use [Option 4](#option-4-add-a-remote-websocket-server)instead, since

`--transport` doesn’t accept `ws`:
`--header` as shown in [Option 1](#option-1-add-a-remote-http-server).

#### Add a server from an `npx`, `uvx`, or binary command

A launch command means the server runs as a local stdio process. Put the whole command after `--`, so Claude Code passes flags such as `-y` to the command that starts the server instead of reading them as its own options. Pass any environment variables the instructions ask for with `--env`, after the server name and before `--`:
[Option 3](#option-3-add-a-local-stdio-server)covers the

`--` separator in full.
#### Add a server from an `mcpServers` JSON block

An `mcpServers` block written for another MCP client, such as Claude Desktop, uses the wrapper key and entry shape Claude Code reads. Pass `claude mcp add-json` the object inside `mcpServers`, not the wrapper. Two entries need a repair first:
- **A `url` with no `type`** : add`"type": "http"` ,`"type": "sse"` , or`"type": "ws"` to match the endpoint. Claude Code reads an entry with no`type` as a stdio server, so a`url` entry without a`type` fails.
- **A key with characters other than letters, numbers, hyphens, and underscores** : pick a server name that uses only those characters. Otherwise the key is the server name.

[Add MCP servers from JSON configuration](#add-mcp-servers-from-json-configuration)covers shell escaping and the

`--scope` flag for `add-json`. To share the server with your team instead, add `--scope project`, or add the entry under `mcpServers` in `.mcp.json` at your project root and commit it. [Project scope](#project-scope)covers how Claude Code loads and approves that file. Each

`claude mcp add` and `claude mcp add-json` command prints an `Added ...` line on success. To check that Claude Code connected, run `claude mcp get <name>`; [Server status](#server-status)covers the statuses it shows and the approval step for

`.mcp.json` servers.
### Managing your servers

Once configured, you can manage your MCP servers with these commands:
[in your shell before](#authenticate-from-the-command-line)

`claude mcp logout <name>`` claude mcp remove <name>`.
#### Server status

`claude mcp add` confirms a successful add by printing an `Added ...` line, which means the configuration was written. If the command prints a `was not saved` message instead, see [MCP server was not saved or removed](https://code.claude.com/docs/en/errors#mcp-server-was-not-saved-or-removed); for a

`may not have been saved` message, see [MCP server may not have been saved or removed](https://code.claude.com/docs/en/errors#mcp-server-may-not-have-been-saved-or-removed).

`claude mcp list` shows a health status next to each server it lists, such as `✔ Connected`, `! Needs authentication`, or `✘ Failed to connect`. A failure status means Claude Code couldn’t connect to that server, not that the list command failed.
The statuses in this list report a configuration decision rather than a connection attempt, so Claude Code prints them without connecting to the server:
- ``⏸ Pending approval (run `claude` to approve)`` : a project-scoped server from`.mcp.json` that you haven’t approved yet. Claude Code shows it in both`claude mcp list` and`claude mcp get <name>` . Run`claude` interactively to review and approve it.
- `✘ Rejected (see disabledMcpjsonServers in settings)` : a`.mcp.json` server that a[`disabledMcpjsonServers`](https://code.claude.com/docs/en/settings-reference#disabledmcpjsonservers) entry rejects. Claude Code shows it only in`claude mcp get <name>` .
- `⊘ Disabled for this project (re-enable via /mcp)` : a server that the project’s[`disabledMcpServers`](#disable-a-server-without-removing-it) list names. Claude Code shows it in both`claude mcp list` and`claude mcp get <name>` . Turn the server back on from the`/mcp` panel.
- `✘ Blocked by enterprise managed policy` : a server that one of your organization’s policies refuses. Claude Code shows it in both`claude mcp list` and`claude mcp get <name>` . A server blocked by an allowlist, a denylist, or another restriction in[managed MCP configuration](https://code.claude.com/docs/en/managed-mcp#how-restrictions-appear-to-users) is hidden from both commands rather than shown with this status. Ask your administrator which policy blocks the server.

#### Project server approvals and workspace trust

`claude mcp list` and `claude mcp get` read `.mcp.json` approvals only from settings files that aren’t checked into the repository until you trust the workspace by running `claude` in it and accepting the workspace trust dialog. A cloned repository can’t approve its own servers: [or](https://code.claude.com/docs/en/settings-reference#enableallprojectmcpservers)

`enableAllProjectMcpServers`
[committed to the project’s](https://code.claude.com/docs/en/settings-reference#enabledmcpjsonservers)

`enabledMcpjsonServers``.claude/settings.json` is ignored in an untrusted folder, and the server stays at `⏸ Pending approval` instead of being connected and health-checked.
Approvals from these sources still apply in an untrusted folder:
- your user `~/.claude/settings.json`
- managed settings
- settings passed with `--settings`

`.claude/settings.local.json`, but it runs git to check whether the file is tracked, and it runs that check only in a [trusted folder](https://code.claude.com/docs/en/permissions#project-allow-rules-and-workspace-trust). In a folder you’ve never trusted, Claude Code waits for the trust dialog before applying the file’s approvals, unless the folder is your own configuration home: your home directory, or a directory whose

`.claude` you’ve set as [. Before v2.1.207, Claude Code applied approvals from an untracked](https://code.claude.com/docs/en/env-vars)

`CLAUDE_CONFIG_DIR``.claude/settings.local.json` even in a folder you’d never trusted.
A `disabledMcpjsonServers` entry in any settings file still rejects the server.
#### Server status detail

In`/mcp`, including a server’s menu there, and in the [manager, a remote HTTP or SSE server you’ve used before can show a](https://code.claude.com/docs/en/plugins/install)

`/plugin`` cached` status such as `cached 2h ago · connects on first use · 5 tools`. Claude Code loaded the server’s tool list from its discovery cache, saved in a previous session, instead of connecting at startup, and Claude Code connects the server the first time Claude calls one of the server’s tools. The tools are available from your first message, so you don’t need to do anything. The discovery cache and its `cached` status require Claude Code v2.1.221 or later.
The discovery cache is off by default unless a gradual rollout has enabled it for your account. Set [to turn it on, or](https://code.claude.com/docs/en/env-vars)

`MCP_DISCOVERY_CACHE=1`` 0` to keep it off even when the rollout has enabled it. Before v2.1.238, the cache was on by default.
When you select **Disable** or

**Clear authentication** from a server’s menu in

`/mcp`, Claude Code also discards that server’s cache entry. **Reconnect** discards it too on a connected or failed server; on a

`cached` server, **Reconnect** connects the server now and keeps the entry. The next time Claude Code connects to the server after discarding the entry, it fetches the tool list from the server instead of from the cache.

##### Connection failures and unconfigured servers

When a server’s status is`✘ Failed to connect`, `claude mcp list` appends the failure detail to that status line, and `claude mcp get <name>` shows it on an `Issue:` line. The detail is the HTTP status or error code, plus any error text the server returned. The server’s detail view in `/mcp` includes the same server-reported text in its `Issue:` row.
Claude Code redacts credential-like text from this detail and never includes the expanded server URL, which can carry secrets. Claude Code appends no detail to a `✘ Connection error` status, because the exception text it would print there can embed that URL.
When you complete authentication from `/mcp` and the connection still fails with an HTTP status or a transport error code, Claude Code adds that code and the origin of the server’s URL to the message it prints after the attempt. The origin is the scheme and host, plus the port when the URL names one, such as `https://mcp.example.com`.
- The path and query never appear in that message.
- For a server in the local, project, or user [scope](#mcp-installation-scopes) or in managed MCP configuration, the origin shows the host as written in that configuration, so a`${VAR}` reference in the host isn’t expanded in the message.
- For a failure with no status or error code, Claude Code shows the error text without the origin.

`url` shows as `not configured` in `/mcp`, in `claude mcp list`, and in the [manager, and Claude Code doesn’t attempt to connect to it. A plugin can include a placeholder entry like this for a connector you configure later, so Claude Code doesn’t report it as an error or a setup issue. The server’s detail view in](https://code.claude.com/docs/en/plugins/install)

`/plugin``/mcp` reads `No URL configured for this server`; set the entry’s `url` to connect it.
#### Configuration warnings

Claude Code warns about the configuration problems below. Each entry says what Claude Code checks and how to clear the warning:
- **Hidden whitespace** : Claude Code warns when an MCP config value carries hidden leading or trailing whitespace, which often comes from pasting a token with a trailing newline. Claude Code checks`command` ,`url` , each`args` entry, and the values and key names under`env` and`headers` . Claude Code shows the warning in`claude mcp list` output and in`/mcp` , naming the affected fields without echoing their values, for example`Leading or trailing whitespace in: headers.Authorization` . Claude Code doesn’t trim the whitespace and uses the values exactly as written, so edit the configuration to remove it.
- **Same name in more than one scope** : if you define the same server name in more than one[scope](#mcp-installation-scopes) with different endpoints, Claude Code warns about the conflict in`claude mcp list` output and in`/mcp` . Claude Code stores OAuth sign-ins per endpoint, so when you authenticate the definition that loads in one project, you still need to sign in separately in a project where a different definition loads. Keep the endpoint you want and remove the others with`claude mcp remove <name> --scope <scope>` . In the warning, Claude Code quotes each scope’s endpoint as written in your configuration, with[`${VAR}` references](#environment-variable-expansion-in-mcp-json) unexpanded, so it never shows a resolved value such as an API key.
- **Reserved names** : Claude Code reserves the names of its built-in servers, including`workspace` ,`claude-in-chrome` ,`computer-use` ,`Claude Preview` , and`Claude Browser` . If your configuration defines a server with a reserved name, Claude Code skips it at load time and shows a warning asking you to rename it.`claude mcp add` rejects a reserved name with an error.`Claude Preview` and`Claude Browser` both name the built-in server that the[Claude Code desktop app’s preview pane](https://code.claude.com/docs/en/desktop#preview-your-app) uses.
- **Missing environment variable** : if a[`${VAR}` reference](#environment-variable-expansion-in-mcp-json) in a server’s configuration names a variable that isn’t set and has no`:-default` , Claude Code warns in`claude mcp list` output and in`/mcp` , naming the variable, and still loads the server with the`${VAR}` text unexpanded. Set the variable or add a`${VAR:-default}` fallback. In a remote server’s`url` and`headers` , some credential variables[read as empty](#credential-variables-that-read-as-empty) instead, with no warning.

#### Tool availability

The`/mcp` panel shows the tool count next to each connected server and flags servers that advertise the tools capability but expose no tools.
If your request needs tools from a server that is still connecting in the background, Claude waits for that server before continuing. How the wait happens depends on your configuration:
- **With [tool search](#scale-with-mcp-tool-search), the default** : the wait happens inside the`ToolSearch` call.
- **Without tool search** : Claude uses the`WaitForMcpServers` tool instead. Configurations without tool search include`ENABLE_TOOL_SEARCH=false` and a model earlier than Claude Opus 4.5, Claude Sonnet 4.5, and Claude Haiku 4.5 on Google Cloud’s Agent Platform. For an`ANTHROPIC_BASE_URL` gateway, see[Tool search through an LLM gateway](#tool-search-through-a-gateway) .
- **On a Microsoft Foundry [deployment hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options)** : Claude starts on the tool-search path rather than with`WaitForMcpServers` , since Claude Code discovers the deployment’s server-side rejection only from the API. After Claude Code switches that deployment to[upfront loading](#scale-with-mcp-tool-search) , tools from a server that finishes connecting become available on Claude’s next request.

[retrying after a failed attempt](#automatic-reconnection), the call fails with the

`No such tool available` [tool error](https://code.claude.com/docs/en/errors#no-such-tool-available).

### Disable a server without removing it

Toggle a server off in the`/mcp` panel to stop Claude Code from connecting to it without losing its configuration. Claude Code still lists the server in `/mcp`, marked as disabled.
When you toggle a server, Claude Code records your choice per project in `~/.claude.json`, in one of two lists that cover disjoint sets of servers:
- `disabledMcpServers` : an opt-out list for user-configured servers, plugin servers, servers your organization[provides through managed settings](https://code.claude.com/docs/en/managed-mcp#provide-servers-through-managed-settings) , the claude.ai connectors Claude Code[fetches itself](#how-connectors-reach-claude-code) , and built-in servers that default to on. Claude Code doesn’t connect to a server you list here. When you disable a claude.ai connector with the per-project`/mcp` toggle described in[Disable claude.ai connectors](#disable-claude-ai-connectors) , Claude Code writes it to this list under its display name, for example`claude.ai Slack` .
- `enabledMcpServers` : an opt-in list for built-in servers that default to off, such as`computer-use` . Claude Code connects to a default-off server only when you list it here.

`enabledMcpServers`, or a default-off built-in server to `disabledMcpServers`, Claude Code ignores the entry.
`disabledMcpServers` and `enabledMcpServers` are unrelated to [and](https://code.claude.com/docs/en/settings-reference#enabledmcpjsonservers)

`enabledMcpjsonServers`
[, which control approval of servers defined in a project’s](https://code.claude.com/docs/en/settings-reference#disabledmcpjsonservers)

`disabledMcpjsonServers``.mcp.json` file.
### MCP client runtimes

Claude Code connects to MCP servers through one of two client runtimes. The v1 runtime is built on MCP TypeScript SDK 1.x. The v2 runtime is the same code on
[MCP TypeScript SDK 2.0](https://ts.sdk.modelcontextprotocol.io/v2/), which adds MCP protocol revision 2026-07-28. The rest of this page applies to both runtimes, except where a section names the v2 runtime. Claude Code picks a runtime each time you start it and keeps it until you exit. In sessions where it

[fetches feature flags](https://code.claude.com/docs/en/env-vars#features-that-need-feature-flag-fetching), it uses the v2 runtime on Claude Code v2.1.232 or later. In the sessions where it doesn’t fetch feature flags, Claude Code uses the v2 runtime by default on Claude Code v2.1.274 or later:

- Sessions on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry, unless a host platform that embeds Claude Code sets [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](https://code.claude.com/docs/en/env-vars)
- Sessions signed in through a [Claude apps gateway](https://code.claude.com/docs/en/claude-apps-gateway)
- Sessions where you turn off telemetry or feature-flag fetching, for example with `DISABLE_TELEMETRY`

- Asks HTTP, stdio, and claude.ai connector servers whether they support the newer revision and uses it with those that do. That includes the connectors of cloud and [Remote Control](https://code.claude.com/docs/en/remote-control) sessions. Claude Code connects to every other server as v1 does.
- Receives `list_changed` notifications from servers on the newer revision over a[stream it holds open](#notification-streams-on-the-v2-runtime) .
- Doesn’t register a [channel](#push-messages-with-channels) server that connects on the newer revision, because that revision can’t carry channel messages.
- Fails an [MCP OAuth sign-in](#authenticate-with-remote-mcp-servers) whose authorization response names an unexpected issuer.
- Sends [MCP OAuth](#authenticate-with-remote-mcp-servers) credentials only to a token endpoint served over HTTPS or at`localhost` ,`127.0.0.1` , or`::1` . Sign-in fails for a server whose token endpoint is plain`http://` anywhere else, such as a device on your local network. See[Refusing to send credentials to non-https token endpoint](https://code.claude.com/docs/en/errors#refusing-to-send-credentials-to-non-https-token-endpoint) .

[to](https://code.claude.com/docs/en/env-vars)

`MCP_SDK_GENERATION`` v1` or `v2`. To decide whether Claude Code asks, set [to](https://code.claude.com/docs/en/env-vars)

`MCP_PROTOCOL_NEGOTIATION`` auto` or `legacy`.
### Dynamic tool updates

An MCP server can change the tools, prompts, or resources it offers while connected and send a`list_changed` notification. When one arrives:
- **In an interactive terminal session** , Claude Code fetches the updated list from that server, so you don’t need to reconnect it.
- **In [non-interactive mode](https://code.claude.com/docs/en/headless) with the `-p` flag and in the [Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview)** , Claude Code refreshes only the tool list on these notifications.

#### Notification streams on the v2 runtime

On the
[v2 runtime](#mcp-client-runtimes), Claude Code receives

`list_changed` notifications from a server on the newer protocol revision over a stream it holds open. When the stream closes, Claude Code reopens it, with two limits:
- **The stream closes again within 10 seconds** : Claude Code reopens it up to three times, then stops for that connection.
- **The stream stays open longer than 10 seconds, then closes** , as streams to serverless hosts commonly do: after five reopens in an hour, Claude Code waits about six hours before the next one.

`/mcp`.
### Automatic reconnection

Claude Code reconnects a remote server that drops mid-session and retries an HTTP or SSE server’s first connection after a transient error. For a stdio server, see
[Stdio servers that exit or fail to start](#stdio-servers-that-exit-or-fail-to-start).

#### Mid-session drops of a remote server

Claude Code first tries to reconnect a dropped remote server up to five times with exponential backoff, starting at a one-second delay and doubling it each time:
- **In an interactive session** :`/mcp` shows the server as pending while Claude Code reconnects. After five failed attempts, Claude Code marks the server as failed, or as needing authentication when the server needs authorizing again. When it marks the server as failed, you see an`MCP server "<name>" disconnected · open /mcp to reconnect` notification. You can retry manually from`/mcp` .
- **In [`claude -p`](https://code.claude.com/docs/en/headless) runs and [Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview) sessions** : Claude Code makes the same five attempts, with no`/mcp` panel to show them. If all five fail, the run continues without the server’s tools:
  - **After a transient error, such as a 5xx response or a timeout** : Claude Code keeps retrying an HTTP or SSE server in the background. Retries last up to about half an hour, and the server’s tools become available again when one connects. Until then, an Agent SDK session reports the[status](https://code.claude.com/docs/en/agent-sdk/mcp#error-handling)`failed` , and your code can[reconnect the server](https://code.claude.com/docs/en/agent-sdk/mcp#error-handling) . To reconnect it in`claude -p` , start the run again.
  - **When the server [needs you to sign in again](#authenticate-with-remote-mcp-servers)** : Claude Code stops retrying, and an Agent SDK session reports the server’s status as`needs-auth` . Sign in with[`claude mcp login <name>`](#authenticate-from-the-command-line) in your shell. Then start the run again or, in an Agent SDK session,[reconnect the server](https://code.claude.com/docs/en/agent-sdk/mcp#error-handling) instead.

#### Failed first connections

When an HTTP or SSE server’s first connection fails with a transient error, such as a 5xx response, a connection refused, or a timeout, Claude Code retries up to three times. If the connection still fails, Claude Code marks the server as failed. Those retries don’t apply in these cases:
- A stdio server’s first connection. To try it again, see [Stdio servers that exit or fail to start](#stdio-servers-that-exit-or-fail-to-start)
- A WebSocket server’s first connection. To try it again in an interactive terminal session, select **Reconnect** from the server’s menu in`/mcp`
- An authentication or not-found error, because it requires a configuration change to resolve. When a [`headersHelper`](#use-dynamic-headers-for-custom-authentication) is the server’s only source of the`Authorization` header, Claude Code retries an authentication error anyway, because it re-runs the helper on each attempt and can pick up a fresh credential

#### Stdio servers that exit or fail to start

To start a stdio server again, read the column that matches what happened to it. Find your row by how you run Claude Code: an interactive session, a`claude -p` run, or an Agent SDK session.
#### Failed discovery requests

After a server connects, Claude Code sends it capability discovery requests such as`tools/list`, `prompts/list`, and `resources/list`. Claude Code retries those requests up to three times with short backoff after a transient network or server error. It doesn’t retry authentication errors, 4xx responses, or request timeouts.
#### Retry failed servers yourself

To retry every server that failed or needs authentication, run`/mcp reconnect all` at the Claude Code prompt in an interactive terminal session. This requires Claude Code v2.1.284 or later. Earlier versions print `MCP server "all" not found`.
#### How Claude learns that a server failed

Whether Claude Code tells Claude about a configured server that failed to connect depends on
[tool search](#scale-with-mcp-tool-search), which is on by default:

- With tool search, Claude Code tells Claude which server failed and its connection error, so Claude reports the connection failure in its response. Claude Code includes the same information in `ToolSearch` results that find no matching tool.
- In any [configuration without tool search](#configure-tool-search) , Claude Code doesn’t report failed server connections to Claude.

### Push messages with channels

An MCP server can also push messages directly into your session so Claude can react to external events like CI results, monitoring alerts, or chat messages. To enable this, your server declares the`claude/channel` capability and you opt it in with the `--channels` flag at startup. See [Channels](https://code.claude.com/docs/en/channels)to use an officially supported channel, or

[Channels reference](https://code.claude.com/docs/en/channels-reference)to build your own. On the

[v2 runtime](#mcp-client-runtimes), a channel server that negotiates MCP protocol revision 2026-07-28 can’t deliver channel messages, so Claude Code doesn’t register it as a channel. A channel server that doesn’t support that revision connects on the earlier handshake and registers as before. Claude Code asks stdio servers for that revision by default. To keep a stdio channel server on the earlier handshake, set

[to](https://code.claude.com/docs/en/env-vars)

`MCP_PROTOCOL_NEGOTIATION`` legacy`, which keeps every server on it.
### Time limits on MCP tool calls

To limit how long an MCP tool call can run:
- **Per server** : add a`timeout` field in milliseconds to that server’s configuration entry
- **Across servers** : set[`MCP_TOOL_TIMEOUT`](https://code.claude.com/docs/en/env-vars)

`timeout` is a hard wall-clock limit per tool call, and progress notifications from the server don’t extend it. Values below 1000 are ignored and fall through to `MCP_TOOL_TIMEOUT`, or to its default of about 28 hours when that variable is unset. For an HTTP, SSE, or [claude.ai connector](https://code.claude.com/docs/en/mcp#use-mcp-servers-from-claude-ai)server there is also a second, per-request timer that covers each request through to the server’s first response byte. Claude Code sets that timer to the greatest of three values: 60 seconds, the tool timeout that applies to the server, and

`MCP_TIMEOUT`. The 28-hour default of an unset `MCP_TOOL_TIMEOUT` doesn’t enter that comparison, and a value below 60 seconds doesn’t shorten the timer. Stdio and WebSocket servers have no per-request timer.
A per-server `timeout` of at least 1000 also acts as a floor on the idle timeout described below: Claude Code never aborts that server’s tool calls for idleness sooner than the per-server `timeout`.
A tool call to an MCP server that sends no response and no progress notification for the idle window aborts with an error instead of waiting for the wall-clock limit. The idle timeout applies to every server type except IDE servers and SDK in-process servers. The idle window defaults to five minutes for HTTP, SSE, WebSocket, and [claude.ai connector](#use-mcp-servers-from-claude-ai)servers, and to 30 minutes for stdio servers. Set the

[environment variable in milliseconds to change the idle window, or set it to](https://code.claude.com/docs/en/env-vars)

`CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT`` 0` to disable the check.
These timeouts bound how long a call can run, not always how long it blocks the session: a main-conversation call that runs past two minutes moves to a background task first. See [Automatic backgrounding of long tool calls](#automatic-backgrounding-of-long-tool-calls).

### Automatic backgrounding of long tool calls

If a background call’s detail view in
[shows](https://code.claude.com/docs/en/commands#all-commands)

`/tasks`` runs on the server; survives exiting this session`, see [MCP tasks that run on the server](#mcp-tasks-that-run-on-the-server). An MCP tool call in the main conversation that is still running after two minutes moves to a background task instead of blocking the session. Claude receives the task ID immediately and keeps working, and the result arrives as a task notification when the call settles. The task appears in

[, where you can also stop it, and it doesn’t survive exiting the session. The task’s entry shows the latest progress the server has reported. If you stop the task, Claude Code cancels the call and tells Claude that no result is coming. Stopping doesn’t guarantee the server stops: it may already have done some of the work, or may still finish it. The per-call limits still apply while the call runs in the background: the wall-clock limit set by the per-server](https://code.claude.com/docs/en/commands#all-commands)

`/tasks`` timeout` or [, and the idle timeout set by](https://code.claude.com/docs/en/env-vars)

`MCP_TOOL_TIMEOUT`
[. To change or turn off automatic backgrounding:](https://code.claude.com/docs/en/env-vars)

`CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT`
- Set the [`CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`](https://code.claude.com/docs/en/env-vars) environment variable in milliseconds to change the threshold, or set it to`0` to turn automatic backgrounding off. With`0` , Claude also[waits for MCP tasks](#make-claude-wait-for-the-result-of-an-mcp-task) in an interactive session
- Set [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS`](https://code.claude.com/docs/en/env-vars) to` 1` to turn off automatic backgrounding and[background commands](https://code.claude.com/docs/en/tools-reference#background-commands)

- Calls from [subagents](https://code.claude.com/docs/en/sub-agents) ; Claude Code backgrounds only main-conversation calls
- Calls to IDE servers
- Calls in [non-interactive mode](https://code.claude.com/docs/en/headless) , unless`CLAUDE_AUTO_BACKGROUND_TASKS` is set to`1` , since a one-shot run can end before the result arrives

[elicitation dialog](#respond-to-mcp-elicitation-requests)isn’t backgrounded while the dialog is open; the server is blocked on your input, not slow, so Claude Code defers the move until the dialog closes.

### MCP tasks that run on the server

An MCP task is a long job, such as a report export or a build, that an MCP server runs itself using the
[MCP tasks extension](https://modelcontextprotocol.io/extensions/tasks/overview). Claude’s tool call returns once the server accepts the job, so Claude keeps working unless you

[make Claude wait](#make-claude-wait-for-the-result-of-an-mcp-task). When the job ends, the transcript says so and Claude gets the result. Ask Claude for it. Meanwhile, the footer shows a count such as

`1 MCP task`, and Claude Code follows the task by checking its status with the server. A task on a remote server keeps running after you exit. To follow it again, [resume the same session](#exit-clear-or-resume-while-an-mcp-task-runs).

[What a call needs to become an MCP task](#requirements-for-mcp-tasks)lists the sessions and servers that get them.

#### Stop an MCP task or get its result

To stop a running task, select it in
[and press](https://code.claude.com/docs/en/commands#all-commands)

`/tasks`` x`, or ask Claude to. Claude Code stops following the task and asks the server to cancel it, though the server may still finish it. Reconnect a disconnected server from `/mcp` first, or no cancel request goes out and Claude Code forgets the task and can’t follow it again. Pressing `Esc` doesn’t stop a background task.
When the task ends, a line such as this one appears in the transcript:
#### Answer a question from an MCP task

A running task can open an
[elicitation dialog](#respond-to-mcp-elicitation-requests)to ask you for input. While

`/tasks` is open, the dialog stays hidden, so close `/tasks` to answer. Declining or pressing `Esc` is an answer to the server, which then decides whether the task goes on.
In a [non-interactive](https://code.claude.com/docs/en/headless)session, Claude Code asks the server to cancel a task that requests input, without running your

[or calling the Agent SDK’s](https://code.claude.com/docs/en/hooks#elicitation)

`Elicitation` hooks`onElicitation` callback.
#### Exit, clear, or resume while an MCP task runs

A task on a remote server keeps running after you exit. A stdio server’s process stops when Claude Code exits, though its tasks show`runs on the server; survives exiting this session` in `/tasks`. Unless that server’s documentation says the work outlives the process, let those tasks finish or stop them in `/tasks` first.
#### What a call needs to become an MCP task

A tool call becomes an MCP task only when all of these conditions hold:
- The server supports tasks
- The server is an HTTP, stdio, or claude.ai connector server connected on [protocol revision 2026-07-28](#mcp-client-runtimes) . Setting[`MCP_SDK_GENERATION=v1` or `MCP_PROTOCOL_NEGOTIATION=legacy`](https://code.claude.com/docs/en/env-vars) rules that out
- The session [fetches feature flags](https://code.claude.com/docs/en/env-vars#features-that-need-feature-flag-fetching) , so not on a third-party provider such as Amazon Bedrock, and not with telemetry or flag fetching turned off
- Anthropic has turned MCP tasks on for your kind of session. On v2.1.304 or later that covers terminal CLI sessions, [Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview) sessions, and[GitHub Actions](https://code.claude.com/docs/en/github-actions) runs. Other surfaces, such as the[VS Code extension](https://code.claude.com/docs/en/vs-code) and the[desktop app](https://code.claude.com/docs/en/desktop) , don’t have MCP tasks
- The call comes from the main conversation, not from a [subagent](https://code.claude.com/docs/en/sub-agents)
- Either the session is interactive, or an [Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview) session or a`claude -p` run reading`--input-format stream-json` has:
  - [`CLAUDE_AUTO_BACKGROUND_TASKS`](https://code.claude.com/docs/en/env-vars) at` 1`
  - `CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND` not`1`
  - `CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS` not`0`

[Automatic backgrounding of long tool calls](#automatic-backgrounding-of-long-tool-calls)says which of those move to the background. Keep an Agent SDK or stream-json session’s input open, because the run

[doesn’t wait for MCP tasks](https://code.claude.com/docs/en/headless#mcp-work-when-a-non-interactive-run-ends)after input closes. A one-shot

`claude -p "<prompt>"` run doesn’t get MCP tasks.
#### Status messages on an MCP task

These messages, in a task’s`/tasks` entry or its closing transcript line, mean Claude Code can’t reach the server or the task. While one shows in `/tasks`, the job may still be running: Claude Code leaves it alone and keeps checking. The `300s` and configuration messages stay on the entry even after contact returns.
#### Time limits on MCP tasks

By default, a task in the background has no Claude Code time limit. The
[tool call time limits](#time-limits-on-mcp-tool-calls), including the wall-clock limit and the idle timeout, apply until the server answers the call with the task. If you

[make Claude wait](#make-claude-wait-for-the-result-of-an-mcp-task), they apply for the whole task. Answered status checks count as activity for the idle timeout.

#### Make Claude wait for the result of an MCP task

To make Claude wait for a task’s result in an interactive session, set one of two environment variables, for example in the`env` block of [:](https://code.claude.com/docs/en/settings)

`settings.json`
- **[`CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`](https://code.claude.com/docs/en/env-vars) set to `0`** : Claude waits for every MCP tool call until the call ends
- **[`CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND`](https://code.claude.com/docs/en/env-vars) set to `1`** : Claude waits for a task’s result. While[automatic backgrounding](#automatic-backgrounding-of-long-tool-calls) is on, it moves the call after two minutes by default, so short tasks finish in place and long ones don’t block you. The moved call is a plain background call rather than an MCP task. It doesn’t survive exiting the session

`Esc` or reaching the [wall-clock limit or idle timeout](#time-limits-on-mcp-tasks)ends the call, and Claude Code asks the server to cancel the task. If you set

`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` to `1` or start in [bare mode](https://code.claude.com/docs/en/headless#start-faster-with-bare-mode), that alone doesn’t make Claude wait for MCP tasks. This example sets

`CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS` to `0`, so Claude waits for every MCP tool call:
### MCP tasks for server authors

If you build an MCP server, you can answer a long-running`tools/call` with a task. The [MCP tasks extension](https://modelcontextprotocol.io/extensions/tasks/overview)defines the messages you send. On a

[protocol revision 2026-07-28](#mcp-client-runtimes)connection, each request carries Claude Code’s client capabilities at

`params._meta["io.modelcontextprotocol/clientCapabilities"]`, with `"io.modelcontextprotocol/tasks": {}` under `extensions`. A `tools/call` request that [can’t become a task](#requirements-for-mcp-tasks)omits that extension.

#### Answer the call with a task

Answer with a task only when the request carries the extension, or Claude gets the tool error`Unsupported result type 'task' for tools/call`. Claude gets the same error when `taskId`, `status`, `createdAt`, `lastUpdatedAt`, or `ttlMs` is missing. The task object is the JSON-RPC `result` of your `tools/call` response, needs no `content` array, and here includes the optional `statusMessage` and `pollIntervalMs`:
[per-request timer](#time-limits-on-mcp-tool-calls), so accept the job and answer first, then do the work.

#### Report status, results, and questions

Right after the task answer, Claude Code sends`tasks/get` with `{ "taskId": ... }`, then repeats it once per poll interval. The tasks extension requires your response to carry `"resultType": "complete"` along with `taskId`, `status`, `createdAt`, `lastUpdatedAt`, and `ttlMs`. `ttlMs` may be `null`, and `statusMessage` and `pollIntervalMs` are optional. This example reports the build as done:
### Plugin-provided MCP servers

[Plugins](https://code.claude.com/docs/en/plugins/overview)can bundle MCP servers that provide tools and integrations when you enable the plugin.

**How plugin MCP servers work**:

- Plugins define MCP servers in `.mcp.json` at the plugin root or inline in`plugin.json`
- When you enable a plugin, Claude Code starts its MCP servers automatically
- Claude Code offers plugin MCP tools alongside manually configured MCP tools
- You add and remove plugin servers by installing or uninstalling the plugin, not with `/mcp` commands. You can still[toggle an installed plugin server off](#disable-a-server-without-removing-it) in`/mcp` , which stops Claude Code from connecting to it without removing the plugin

**Example plugin MCP configuration**: In

`.mcp.json` at plugin root:
`plugin.json`:
**Plugin MCP features**:

- **Automatic lifecycle** : servers connect and disconnect at these points:
  - At session startup, Claude Code connects the servers for enabled plugins automatically. In `/mcp` , a remote (HTTP or SSE) plugin server you’ve used before can show the[`cached` status](#server-status-detail) instead; Claude Code connects it when Claude first calls one of its tools. When a stdio plugin server’s connection failed less than 15 minutes earlier, Claude Code[skips the connection](https://code.claude.com/docs/en/errors#skipping-connection-recent-failure-cached)
  - If you enable or disable a plugin during a session, Claude Code connects or disconnects its MCP servers when the change applies. [Apply plugin changes without restarting](https://code.claude.com/docs/en/plugins/cli-reference#reload-plugins) describes when that is. In a session without an interactive terminal,`/reload-plugins` doesn’t connect or disconnect plugin MCP servers; those changes take effect in your next session
  - When you reload, Claude Code keeps the live connections of plugin servers whose configuration is unchanged, and does the same when you [replace the session’s MCP server list](https://code.claude.com/docs/en/agent-sdk/typescript#mcpsetserversresult) from the Agent SDK without naming them
  - When you [move the session with `/cd`](https://code.claude.com/docs/en/permissions#move-the-session-to-another-directory) on v2.1.246 or later, Claude Code connects the servers of plugins the new directory’s settings enable and disconnects the servers of plugins that are no longer enabled, so you don’t need to run`/reload-plugins` after the move
  - In [cloud sessions](https://code.claude.com/docs/en/claude-code-on-the-web) , an MCP call to a plugin server that isn’t connected yet, such as right after an idle session wakes, starts the server on demand and waits for it to connect
- At session startup, Claude Code connects the servers for enabled plugins automatically. In 
- **Path placeholders** :`${CLAUDE_PLUGIN_ROOT}` resolves to the plugin’s installation directory,`${CLAUDE_PLUGIN_DATA}` to its[persistent state](https://code.claude.com/docs/en/plugins/components#path-variables-and-persistent-data) directory, and`${CLAUDE_PROJECT_DIR}` to the stable project root. Substitution applies to:
  - `stdio` servers:`command` ,`args` ,`env`
  - `http` ,`sse` , and`ws` servers:`url` ,`headers` , and`headersHelper`
- **User environment access** : access to the same environment variables as manually configured servers
- **Multiple transport types** : support for stdio, SSE, HTTP, and WebSocket transports, though transport support may vary by server

`/mcp` with indicators showing they come from plugins.
`claude mcp get` hides the values configured for a plugin’s stdio or WebSocket server, because they can carry credentials:
- **stdio server** : it prints`Command: stdio` , an empty`Args:` line, and each environment variable as`NAME=[REDACTED]`
- **WebSocket server** : it prints`URL: ws` and each header as`<name>: [REDACTED]` , and`claude mcp list` shows`ws` in place of the URL

[find the plugin on disk](https://code.claude.com/docs/en/plugins/loading#find-plugins-on-disk)and read its

`.mcp.json` or `plugin.json`.
**Plugin MCP tool names**: Tools from a plugin-bundled MCP server include both the plugin name and the server key in their callable name. The full form is

`mcp__plugin_<plugin-name>_<server-name>__<tool-name>`, where any character outside `A-Z`, `a-z`, `0-9`, `_`, and `-` is replaced with `_`. For the `database-tools` server bundled in a plugin named `my-plugin`, a `query` tool is callable as:
[permission rules](https://code.claude.com/docs/en/permissions), a skill’s

`allowed-tools` list, a [subagent’s](https://code.claude.com/docs/en/sub-agents#available-tools), or a

`tools` field
[hook matcher](https://code.claude.com/docs/en/hooks#match-mcp-tools). A hook matcher written against the bare server key, such as

`mcp__database-tools__.*`, never fires for a plugin-bundled server.
The server itself registers under the scoped name `plugin:<plugin-name>:<server-name>`, such as `plugin:my-plugin:database-tools`. Use that name where a configured server name is expected, such as an [. See the](https://code.claude.com/docs/en/hooks#mcp-tool-hook-fields)

`mcp_tool` hook’s `server` field
[plugin components reference](https://code.claude.com/docs/en/plugins/components#mcp-servers)for details on bundling MCP servers with plugins.

## MCP installation scopes

MCP servers can be configured at three scopes. The scope you choose controls which projects the server loads in and whether the configuration is shared with your team. Administrators can also deploy or provide servers for every user via
[managed configuration](#managed-mcp-configuration).

### Local scope

Local scope is the default. A local-scoped server loads only in the project where you added it and stays private to you. Claude Code stores it in`~/.claude.json` under that project’s path, so the same server won’t appear in your other projects. Use local scope for personal development servers, experimental configurations, or servers with credentials you don’t want in version control.
`~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](https://code.claude.com/docs/en/settings#where-settings-live)for details on settings file locations.

`~/.claude.json`. The example below shows the result when you run it from `/path/to/your/project`:
### Project scope

Project-scoped servers enable team collaboration by storing configurations in a`.mcp.json` file at your project’s root directory. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure. Check `.mcp.json` into version control so everyone on your team gets the same MCP tools and services.
`.mcp.json` file follows a standardized format:
`.mcp.json` files. To reset those approval choices, run `claude mcp reset-project-choices`.
In `claude -p` runs, [Agent SDK](https://code.claude.com/docs/en/headless)sessions, and

[cloud sessions](https://code.claude.com/docs/en/claude-code-on-the-web)outside a

[project](https://code.claude.com/docs/en/claude-projects#what-threads-pick-up-from-your-repositories)’s threads, Claude Code can’t show that prompt: it loads project-scoped servers without asking. Claude Code also skips the prompt in a session you start in

`bypassPermissions` mode with [set in your user settings or in managed settings. To keep a server out anyway:](https://code.claude.com/docs/en/settings-reference#skipdangerousmodepermissionprompt)

`skipDangerousModePermissionPrompt`
- Add it to [`disabledMcpjsonServers`](https://code.claude.com/docs/en/settings-reference#disabledmcpjsonservers) , which blocks it in every permission mode.
- Exclude project settings entirely with [`--setting-sources`](https://code.claude.com/docs/en/cli-reference#cli-flags) or the SDK’s` settingSources` option.
- Start the session with [`--strict-mcp-config`](https://code.claude.com/docs/en/cli-reference#cli-flags) . Claude Code then uses only the MCP servers you pass with`--mcp-config` . Skipping the approval prompt for the project-scoped servers Claude Code isn’t loading requires Claude Code v2.1.246 or later; before v2.1.246, a strict session still waited on approval for them, which left background sessions waiting at startup. See[Exclusive control with managed-mcp.json](https://code.claude.com/docs/en/managed-mcp#exclusive-control-with-managed-mcp-json) for what the flag does under a managed MCP file.

[Project server approvals and workspace trust](#project-server-approvals-and-workspace-trust)covers how approvals committed to the repository interact with workspace trust.

### User scope

User-scoped servers are stored in`~/.claude.json` and provide cross-project accessibility, making them available across all projects on your machine while remaining private to your user account. This scope works well for personal utility servers, development tools, or services you frequently use across different projects.
### Scope hierarchy and precedence

When the same server is defined in more than one place, Claude Code connects to it once, using the definition from the highest-precedence source. The entire server entry from that source is used; fields are not merged across scopes.
1. Local scope
2. Project scope
3. User scope
4. [Plugin-provided servers](https://code.claude.com/docs/en/plugins/components#mcp-servers)
5. [claude.ai connectors](#use-mcp-servers-from-claude-ai)

`:443` on `https`, or a trailing slash. A different path, query string, userinfo, or non-default port makes two servers.
A server your organization provides through the [managed setting ranks above all of these, so when one of them duplicates it, Claude Code connects the organization’s definition. Requires Claude Code v2.1.259 or later. If you open a local session in the](https://code.claude.com/docs/en/managed-mcp#provide-servers-through-managed-settings)

`managedMcpServers`
[Desktop app’s Code tab](https://code.claude.com/docs/en/desktop#mcp-servers-from-the-claude-desktop-chat-app)with the same stdio server name at the top level of

`~/.claude.json` (user scope) and in `.mcp.json`, the Code tab uses the `~/.claude.json` definition.
### Environment variable expansion in `.mcp.json`

Claude Code supports environment variable expansion in `.mcp.json` files, allowing teams to share configurations while maintaining flexibility for machine-specific paths and sensitive values like API keys.
You can reference an environment variable in a server’s `command`, `args`, `env`, `url`, or `headers` value, in either of two forms:
- `${VAR}` : expands to the value of environment variable`VAR`
- `${VAR:-default}` : expands to the value of`VAR` if`VAR` is set, or to`default` if it is unset

#### Example with variable expansion

In this server entry, the URL is the value of`API_BASE_URL` followed by `/mcp`, with `https://api.example.com` as the default, and the API key comes from `API_KEY`:
#### Unset variables without a default

If a referenced environment variable isn’t set and has no default value, the config still loads: Claude Code reports a missing-variable warning for that server in`claude mcp list` output and uses the unexpanded `${VAR}` text as-is. Set the variable or add a `:-default` fallback so the server starts with the value you intend. In a remote server’s `url` and `headers`, some credential variables [read as empty](#credential-variables-that-read-as-empty)instead, with no warning.

#### Variables set to an empty string

If you set a variable to an empty string, it counts as set, so a`${VAR:-default}` reference expands to the empty string rather than to `default`. With the [example server](#example-with-variable-expansion), if you set

`API_BASE_URL` to an empty string, its `url` becomes `/mcp` and `claude mcp list` reports `'url' is not a valid URL`. To use the default, unset the variable rather than setting it to an empty string.
#### Credential variables that read as empty

In a remote server’s`url` and `headers`, Claude Code reads credential variables from your environment as empty rather than expanding them. This keeps a project’s `.mcp.json` or a plugin from sending your Claude Code or cloud provider credentials to a server it names. If you write `Bearer ${ANTHROPIC_AUTH_TOKEN}`, the server receives `Bearer`  with no credential and rejects the request, usually with a `401`. Claude Code reports that as a failed connection.
The covered names are:
- Claude Code’s own credentials, such as `ANTHROPIC_API_KEY` and`ANTHROPIC_AUTH_TOKEN`
- Your cloud provider’s credentials, such as `AWS_BEARER_TOKEN_BEDROCK`
- Other credentials your environment carries, such as `HTTPS_PROXY` and`NPM_TOKEN`

`:-default` fallback on it is ignored. A provider base URL such as `ANTHROPIC_BASE_URL` still expands, so `"url": "${ANTHROPIC_BASE_URL}/mcp"` works, unless the URL’s value itself embeds a credential such as a username and password.
A name outside this set, such as `API_KEY`, expands as written. To give the server one of the covered credentials, copy it into a variable with a name of your own and reference that name instead.
When a remote server’s `url` or `headers` references a covered variable you have set, Claude Code names it in a debug-log line. To read the line, run `claude --debug-file /tmp/claude-debug.log` and search that file for `never expanded toward a remote server`.
#### How references appear in `/mcp` and CLI output

For a server in the local, project, or user [scope](#mcp-installation-scopes), the following surfaces show a

`${VAR}` reference by name rather than as its resolved value:
- The URL or command line in a server’s `/mcp` detail view
- `claude mcp list` and`claude mcp get` output

`/mcp` detail view shows references this way in Claude Code v2.1.268 or later.
For a server your organization provides through the `managedMcpServers` setting, these surfaces show [the URL’s host only](https://code.claude.com/docs/en/managed-mcp#what-users-can-see-and-change). To check what

`claude mcp list`, `claude mcp get`, and `/mcp` show when a connection fails, see [Server status detail](#server-status-detail).

## Practical examples

### Example: Connect to GitHub for code reviews

GitHub’s remote MCP server authenticates with a GitHub personal access token passed as a header. To get one, open your
[GitHub token settings](https://github.com/settings/personal-access-tokens), generate a new fine-grained token with access to the repositories you want Claude to work with, then add the server:

`YOUR_GITHUB_PAT` with your personal access token. The `claude mcp add` command saves the configuration without validating credentials, so a placeholder value is accepted here but the server fails to connect later. To verify the connection, run `/mcp` and check that the server’s row shows a checkmark. A server with bad credentials shows an ✘ instead, and its [failure detail](#server-status-detail)includes the HTTP status the server returned, such as a 401. Then work with GitHub:

### Example: Query your PostgreSQL database

[DBHub](https://github.com/bytebase/dbhub), the

`@bytebase/dbhub` package, is an MCP server that connects Claude to a relational database through the connection string you pass in `--dsn`. Use a read-only database user in the connection string so the queries Claude runs can’t modify data:
`/mcp` and check that the `db` row shows a checkmark.
Then query your database naturally:
## Authenticate with remote MCP servers

Many cloud-based MCP servers require authentication. Claude Code supports OAuth 2.0 for secure connections. Claude Code marks a remote server as needing authentication when the server responds with`401 Unauthorized` or `403 Forbidden`. What Claude Code shows depends on the server:
- For a server you haven’t signed in to, either status code flags it in `/mcp` so you can complete the OAuth flow.
- For a [claude.ai connector](#use-mcp-servers-from-claude-ai) , a`401` caused by claude.ai rejecting your session token doesn’t flag the connector, because re-authorizing the connector can’t fix your login. Claude Code shows the[session-token-rejected state](https://code.claude.com/docs/en/errors#claude-ai-rejected-the-session-token) instead.
- For a server whose `Authorization` header you configured, in`headers` or through a[`headersHelper`](#use-dynamic-headers-for-custom-authentication) , a` 401` or`403` while connecting doesn’t flag the server, because the credential to fix is the one you configured. Claude Code reports the connection as failed instead. If you set that header from a`${VAR}` reference, check whether that variable is one Claude Code[reads as empty](#credential-variables-that-read-as-empty) .
- For a connector [delivered to a cloud session](#how-connectors-reach-claude-code) , Claude Code doesn’t run a sign-in flow, because the session’s proxy authenticates to the connector with the authorization you granted in claude.ai. When a connector there needs authorizing again, reconnect it at[claude.ai/customize/connectors](https://claude.ai/customize/connectors) rather than from the session.

`401 Unauthorized`, Claude Code refreshes the token, reconnects, and retries the request once. It flags the server in `/mcp` only if that retry also fails. In a `claude -p` or Agent SDK run on macOS, a request that Claude Code sent while it couldn’t read your stored token fails with a [stored-credentials error](https://code.claude.com/docs/en/errors#couldnt-read-the-stored-credentials-for-mcp-server)instead. When the server rejects the stored refresh token, Claude Code immediately shows a notice pointing at

`/mcp`. Open `/mcp` and select **Re-authenticate** on the server to sign in again before the next tool call fails. A custom server that returns a

`WWW-Authenticate` header pointing to its authorization server gets the same automatic discovery as any other remote server.
Claude Code also shows a startup notice when one or more configured servers need authentication, so you don’t have to open `/mcp` to discover which servers need sign-in. The notice counts only servers you can sign in to from Claude Code. Before v2.1.218, it also counted [claude.ai connectors](#use-mcp-servers-from-claude-ai)that weren’t connected in claude.ai, which you can connect only from claude.ai settings. The notice announces each server once and leaves it out of the count at later launches until that server has connected and needs sign-in again.

`/mcp` still lists every server that needs sign-in.
A `claude -p` or Agent SDK run has no `/mcp` panel, so Claude Code can’t run the OAuth flow there. To use a server that needs authentication, complete the sign-in from an interactive session first: run `/mcp` in the session, or `claude mcp login <name>` in your shell. When a configured server needs authentication during a `claude -p` or Agent SDK run with [tool search](#scale-with-mcp-tool-search)enabled, Claude Code tells Claude that the server’s tools are unavailable until you authorize it. If you configured

`headers.Authorization` for the server and the server rejects that header, Claude Code reports the connection as failed instead of falling back to OAuth. Check that the token is valid for the MCP endpoint, or remove the header to use the OAuth flow.
Add the server that requires authentication

`sentry` server in the [MCP quickstart](https://code.claude.com/docs/en/mcp-quickstart#connect-a-server-that-requires-sign-in), skip this step: running

`claude mcp add` again with the same server name at the same scope fails with `MCP server sentry already exists in local config`. Otherwise, run:
Use the /mcp command within Claude Code

### Authenticate from the command line

The`claude mcp login <name>` command runs a configured server’s OAuth flow directly from your shell, so you don’t need to open the `/mcp` panel inside a session. For a claude.ai connector, follow [Authorize a connector again from your shell](https://code.claude.com/docs/en/remote-control#authorize-a-connector-again-from-your-shell).

`claude mcp logout <name>`.
`claude mcp login` detects when no local browser is available, such as during an SSH session or on Linux without a display server, and prints the authorization URL instead of trying to open a browser. Open the URL on your local machine, then paste the full redirect URL from your browser’s address bar back at the prompt. The command needs an interactive terminal for the paste step, so connect with `ssh -t`. Pass `--no-browser` to force the URL prompt even when a local browser is detected.
### Use a fixed OAuth callback port

Some MCP servers require a specific redirect URI registered in advance. By default, Claude Code picks a random available port for the OAuth callback. Use`--callback-port` to fix the port so it matches a pre-registered redirect URI of the form `http://localhost:PORT/callback`. If sign-in on Claude Code v2.1.229 fails with a redirect URI mismatch, see the version note under [Use pre-configured OAuth credentials](#use-pre-configured-oauth-credentials). You can use

`--callback-port` on its own (with dynamic client registration) or together with `--client-id` (with pre-configured credentials).
### Use pre-configured OAuth credentials

Some MCP servers don’t support automatic OAuth setup via Dynamic Client Registration. If you see an error like “Incompatible auth server: does not support dynamic client registration,” the server requires pre-configured credentials. Claude Code also supports servers that use a Client ID Metadata Document (CIMD) instead of Dynamic Client Registration, and discovers these automatically. If automatic discovery fails, register an OAuth app through the server’s developer portal first, then provide the credentials when adding the server.
Register an OAuth app with the server

`http://localhost:PORT/callback` with that port. You’ll use the same port in the next step.In v2.1.229, Claude Code sent `http://127.0.0.1:PORT/callback` instead, and servers that exact-match the registered redirect URI rejected the sign-in with a redirect URI mismatch. Claude Code v2.1.231 restored the `localhost` form. To recover on v2.1.229, upgrade Claude Code, or temporarily add the `http://127.0.0.1:PORT/callback` form to the server’s registered redirect URIs.
Add the server with your credentials

`claude mcp add` takes your client ID and callback port as flags, and `claude mcp add-json` takes them in an `oauth` object. If you registered a redirect URI, set the callback port to the port in that URI.
- claude mcp add
- claude mcp add-json
- claude mcp add-json (callback port only)
- CI / env var

`--client-id` to pass your app’s client ID. The `--client-secret` flag prompts for the secret with masked input:
Authenticate in Claude Code

`/mcp` in Claude Code and follow the browser login flow.
### Override OAuth metadata discovery

Point Claude Code at a specific OAuth authorization server metadata URL to bypass the default discovery chain. Set`authServerMetadataUrl` when the MCP server’s standard endpoints error, or when you want to route discovery through an internal proxy. By default, Claude Code first checks RFC 9728 Protected Resource Metadata at `/.well-known/oauth-protected-resource`, then falls back to RFC 8414 authorization server metadata at `/.well-known/oauth-authorization-server`.
Set `authServerMetadataUrl` in the `oauth` object of your server’s config in `.mcp.json`:
`https://`. The metadata URL’s `scopes_supported` overrides the scopes the upstream server advertises.
### Restrict OAuth scopes

Set`oauth.scopes` to pin the scopes Claude Code requests during the authorization flow. This is the supported way to restrict an MCP server to a security-team-approved subset when the upstream authorization server advertises more scopes than you want to grant. The value is a single space-separated string, matching the `scope` parameter format in RFC 6749 §3.3.
`oauth.scopes` takes precedence over both `authServerMetadataUrl` and the scopes the server discovers at `/.well-known`. Leave it unset to let the MCP server determine the requested scope set.
When `oauth.scopes` isn’t set, Claude Code doesn’t request the full `scopes_supported` catalog from automatically discovered authorization server metadata. Metadata fetched from a configured `authServerMetadataUrl` still supplies its `scopes_supported` as the requested scopes.
If the authorization server advertises `offline_access` in `scopes_supported`, Claude Code appends it to the pinned scopes so the access token can be refreshed without a new browser sign-in.
If the server later returns a 403 `insufficient_scope` for a tool call, the call fails with a [message that names the scope the server asks for. The server shows as needing authentication in](https://code.claude.com/docs/en/errors#mcp-server-needs-you-to-sign-in-again)

`needs additional permissions``/mcp`.
If that scope isn’t in your pinned `oauth.scopes`, add it, then run `/mcp` and authenticate the server again. Claude Code requests the pinned scopes rather than the scope the server named, so if you authenticate again without adding it, the token you get still lacks it.
### Use OAuth with a server behind an authenticating proxy

If your MCP server uses OAuth behind a proxy or gateway that checks a header of its own, sign-in fails when the OAuth requests arrive without that header. Signing in through the proxy requires Claude Code v2.1.299 or later, with the header and the sign-in both configured:
- **The proxy’s header** : pass it with[`--header`](#option-1-add-a-remote-http-server) , the` headers` field, or a[`headersHelper`](#use-dynamic-headers-for-custom-authentication) , under the name the proxy reads
- **The OAuth sign-in** : keep`Authorization` out of the configured headers, then sign in with`claude mcp login <name>` in your shell. If you configure an`Authorization` header, Claude Code uses it as the server’s credential and doesn’t fall back to OAuth for that server.

### Use dynamic headers for custom authentication

When authentication such as Kerberos, short-lived tokens, or internal SSO needs headers generated at connection time, set the server’s`headersHelper` to a command. Claude Code runs it when connecting and merges its output into the headers it sends. This example uses a script:
**Requirements:**

- The command must write a JSON object of string key-value pairs to stdout
- Claude Code runs the command in a shell and gives up on it after 10 seconds
- Claude Code picks the command’s working directory by [where you configured the server](#where-the-helper-runs) , so give the script as an absolute path or put it on`PATH`
- Dynamic headers override any static `headers` with the same name

[trust rule for project and local-scope servers](#trust-a-folder-before-its-headershelper-runs)lets it run. It doesn’t cache the result, so your script is responsible for any token reuse. If a tool call returns

`401 Unauthorized` or `403 Forbidden`, Claude Code automatically re-runs the helper under the same rule, reconnects with the fresh headers, and retries the call once. Claude Code marks the server as needing authentication in `/mcp` only if that retry also fails.
When the helper’s output includes an `Authorization` header, Claude Code uses that credential as the server’s authentication and doesn’t fall back to OAuth for the server.
If the server rejects the helper’s credential while connecting, Claude Code reports the connection as failed rather than marking the server as needing authentication. Fix the credential your helper returns, then reconnect from `/mcp` to re-run the helper.
Claude Code sets these environment variables when executing the helper:
`headersHelper` can’t reference the plugin’s [values, because the command runs through a shell. Claude Code reports the server as misconfigured with an](https://code.claude.com/docs/en/plugins/manifest-reference#user-configuration)

`${user_config.*}`
[error](https://code.claude.com/docs/en/errors#plugin-command-references-user-config)and doesn’t substitute the value. Put

`${user_config.KEY}` in the server’s `headers` field instead, which isn’t shell-parsed, or have the helper script read the value from a config file. Before v2.1.207, `headersHelper` substituted `${user_config.*}` values.
#### Where the helper runs

Claude Code picks the`headersHelper` command’s working directory from the configuration that declares the server. A `cd` that Claude runs in Bash doesn’t move it, and [moves it only for servers that run from the session’s primary working directory. Each row below gives the directory that a relative path in your](https://code.claude.com/docs/en/permissions#move-the-session-to-another-directory)

`/cd`` headersHelper` command resolves against.
#### Which variables a helper can read

A`headersHelper` that a repository or plugin supplies is a command you didn’t write, so Claude Code runs it without the credential variables from your environment, such as `ANTHROPIC_API_KEY`. Where you configured the server decides whether this applies:
- **Removed** : a server in a project`.mcp.json` or in a plugin, and an inline server in an agent file from your project or from an`--add-dir` directory
- **Not removed** : a server at[user](#user-scope) or[local scope](#local-scope) , in[managed MCP](https://code.claude.com/docs/en/managed-mcp) , from a[claude.ai connector](#use-mcp-servers-from-claude-ai) , or supplied by the SDK or[`--mcp-config`](https://code.claude.com/docs/en/cli-reference) , and an inline server in an agent file from`~/.claude/agents/` , from managed settings, or passed with`--agents`

`GIT_CONFIG_KEY_<n>` variables, Claude Code removes every variable from your environment whose name looks like a credential, such as a name with `TOKEN`, `SECRET`, `PASSWORD`, `KEY`, or `AUTH` in it in either letter case, so `ANTHROPIC_API_KEY` and `MY_REGISTRY_TOKEN` are both removed. Claude Code also removes a fixed list of credential variables whose names don’t follow that pattern, such as `ANTHROPIC_CUSTOM_HEADERS`.
When this applies to your helper, have the script read its credential from a file or a credential store. If the server’s `url` [carries the live value of one of these variables](#environment-variable-expansion-in-mcp-json), such as

`MY_REGISTRY_TOKEN`, the `CLAUDE_CODE_MCP_SERVER_URL` value the helper receives has that part replaced with `REDACTED` as well.
#### Trust a folder before its headersHelper runs

Claude Code executes a`headersHelper` as an arbitrary shell command. For a server in a project `.mcp.json` or at [local scope](#local-scope), it runs the helper only after you accept the

[trust dialog](https://code.claude.com/docs/en/permissions#project-allow-rules-and-workspace-trust)for the project directory the server is declared in. Before v2.1.238, a

`claude -p` or SDK session ran these helpers without checking trust, and an interactive session ran them once you had trusted a parent folder.
- **Trust that doesn’t count** : a parent folder’s trust, and the automatic trust a`claude -p` or SDK session gets for[hooks in settings files](https://code.claude.com/docs/en/permissions#what-runs-before-you-trust-a-folder)
- **Until you trust the folder** : Claude Code connects the server with its static`headers` alone. In a`claude -p` or SDK session it also prints one[`headersHelper not run`](https://code.claude.com/docs/en/errors#headershelper-not-run) line per server to stderr, telling you how to grant the trust.
- **Trust without a dialog** : set`projects["<path>"].hasTrustDialogAccepted` to`true` in`~/.claude.json` .`<path>` is the folder[Project allow rules and workspace trust](https://code.claude.com/docs/en/permissions#project-allow-rules-and-workspace-trust) says Claude Code keys the trust on.

[agent file](https://code.claude.com/docs/en/sub-agents#scope-mcp-servers-to-a-subagent), checking where that agent file came from: your project, for a file in its

`.claude/agents/` directory, or an `--add-dir` directory. Until you [trust that project or directory itself](https://code.claude.com/docs/en/permissions#what-runs-before-you-trust-a-folder), Claude Code doesn’t load the server at all, so its helper never runs either.

### Sign in to an MCP server behind a gateway that requires a header

OAuth sign-in to an MCP server fails when a gateway requires a header, such as`X-API-Key`, and Claude Code doesn’t send it. To have Claude Code send that header, add it to the server’s configuration and use Claude Code v2.1.299 or later:
- **A server whose [configuration](#mcp-installation-scopes) you can edit** : set it in[`headers`](#example-with-variable-expansion) or return it from a[` headersHelper`](#use-dynamic-headers-for-custom-authentication)
- **A server that [managed MCP](https://code.claude.com/docs/en/managed-mcp) or a [plugin](#plugin-provided-mcp-servers) supplies** : ask your administrator or the plugin’s author to add the header to the server’s entry

`Authorization` to the sign-in, token refresh, and token revocation requests it sends to the server’s origin. The server’s origin is the scheme, host, and port in its `url`. A gateway that requires the header can still stop sign-in at the authorization page or at an authorization server on another origin:
- **The authorization page** : you sign in on this page in your browser, which doesn’t send the configured headers. If your browser gets the gateway’s error instead of the page, ask whoever runs the gateway to let the page through without the header.
- **An authorization server on another origin** : if a gateway in front of that server requires the header too, sign-in fails there. Ask whoever runs that gateway to let OAuth requests through without the header.

## Add MCP servers from JSON configuration

If you have a JSON configuration for an MCP server, you can add it directly:
Add an MCP server from JSON

Verify the server was added

## Import MCP servers from Claude Desktop

If you’ve already configured MCP servers in Claude Desktop, you can import them:
Import servers from Claude Desktop

Select which servers to import

Verify the servers were imported

`claude mcp` commands can contain only letters, numbers, hyphens, and underscores. Claude Desktop doesn’t apply that restriction, so a Claude Desktop server whose name contains any other character, such as a space, can’t be imported. The import reports each name it rejects and still imports the other servers you selected.
## Use MCP servers from claude.ai

If you’ve logged into Claude Code with a
[claude.ai](https://claude.ai)account, MCP servers you’ve added in claude.ai, known as

[connectors](https://claude.com/docs/connectors), are automatically available in Claude Code:

Configure MCP servers in claude.ai

[claude.ai/customize/connectors](https://claude.ai/customize/connectors). On Team and Enterprise plans, only admins can add servers.

Authenticate the MCP server

View and manage servers in Claude Code

[Claude Docs](https://code.claude.com/docs/en/artifacts#write-a-document-with-claude-docs)is available,

`/mcp` lists `claude.ai Claude Docs` with no setup, and Claude uses it when you ask for a document meant for other people. To turn off only this connector, see [Disable claude.ai connectors](#disable-claude-ai-connectors). Claude Code marks a connector

`managed` in `/mcp` and in the [manager when your organization manages its authentication in claude.ai. Managed status doesn’t change how Claude Code connects to the connector or applies your organization’s](https://code.claude.com/docs/en/plugins/install)

`/plugin`
[tool controls](#organization-controls-on-connector-tools). Connectors you have never signed in to are collapsed behind a

`Show unused connectors` row at the end of the claude.ai section, so an organization-provisioned list doesn’t fill the panel. Select the row to expand them. A connector you signed in to before stays visible even when it currently needs re-authentication.
Connectors from claude.ai are fetched only when your active [authentication method](https://code.claude.com/docs/en/authentication#authentication-precedence)is a claude.ai subscription login. They aren’t loaded, even if you previously ran

`/login`, when:
- `ANTHROPIC_API_KEY` ,`ANTHROPIC_AUTH_TOKEN` , or`apiKeyHelper` is active
- A third-party provider such as Amazon Bedrock or Google Cloud’s Agent Platform is active
- `ANTHROPIC_PROFILE` , the federation variables, or an active[Anthropic profile](https://code.claude.com/docs/en/authentication#anthropic-profiles-and-federation-credentials) supplies the credential
- `CLAUDE_CODE_OAUTH_TOKEN` holds a token from[`claude setup-token`](https://code.claude.com/docs/en/authentication#generate-a-long-lived-token) , which can only make model requests

`/mcp` doesn’t list a connector you added, run `/status` to confirm which authentication method is active. Unset that environment variable, remove the `apiKeyHelper` setting, or [switch off the profile](https://code.claude.com/docs/en/authentication#anthropic-profiles-and-federation-credentials), then run

`/login` to select your claude.ai account.
If a temporary network problem keeps the connector list from loading when your session starts, Claude Code retries the fetch up to three times in the background, and the connectors appear once a retry succeeds. If they still haven’t appeared, restart Claude Code to fetch the list again.
If `/mcp` shows a connector as `session token rejected`, or its detail view shows [, claude.ai rejected the token from your Claude Code login. Authorizing the connector again doesn’t clear this state, because the connector’s own authorization in claude.ai isn’t what was rejected. To clear it:](https://code.claude.com/docs/en/errors#claude-ai-rejected-the-session-token)

`claude.ai rejected the session token`
1. Run `/login` to sign in again.
2. Reconnect the connector from `/mcp` .

[precedence](#scope-hierarchy-and-precedence)over a claude.ai connector that points at the same URL. When this happens,

`/mcp` lists the connector as hidden and shows how to remove the duplicate if you’d rather use the connector.
Some Anthropic-hosted connectors, such as Microsoft 365, Gmail, and Google Calendar, don’t support local OAuth from Claude Code because the upstream identity provider only accepts the redirect URL that claude.ai registered. When a server you added with `claude mcp add` or in `.mcp.json` points at one of these hosts and you sign in to it from `/mcp` or with `claude mcp login`, Claude Code shows [, directing you to connect the service at](https://code.claude.com/docs/en/errors#anthropic-hosted-and-doesnt-support-local-oauth)

`is Anthropic-hosted and doesn't support local OAuth`
[claude.ai/customize/connectors](https://claude.ai/customize/connectors)instead. After you remove your entry with

`claude mcp remove <name>` and connect the service on claude.ai, the connector appears in Claude Code automatically.
### How connectors reach Claude Code

Which settings govern a claude.ai connector depends on where your session runs, because only some sessions fetch connectors from claude.ai themselves. Each row below names how connectors arrive in one kind of session and what controls them there. The desktop app’s WSL sessions have no row because connectors are
[still rolling out to them](https://code.claude.com/docs/en/desktop-wsl#check-for-the-terminal-and-connectors).

[,](#disable-claude-ai-connectors)

`disableClaudeAiConnectors`` ENABLE_CLAUDEAI_MCP_SERVERS`, and [act only on the first row, the connectors Claude Code fetches itself. The other two rows differ from it in these ways:](https://code.claude.com/docs/en/settings-reference#allowallclaudeaimcps)

`allowAllClaudeAiMcps`
- **Cloud sessions** :`allowedMcpServers` and`deniedMcpServers` entries that reach the session, for example through[server-managed settings](https://code.claude.com/docs/en/server-managed-settings) , filter the delivered connectors too. The session’s proxy rewrites each connector’s URL, so a`serverUrl` pattern written for the connector’s own URL doesn’t match it. To admit delivered connectors alongside a URL allowlist in a self-hosted environment, add the`serverUrl` entries listed under[Connector traffic leaves your network](https://code.claude.com/docs/en/self-hosted-environments-deploy#connector-traffic-leaves-your-network) . Claude Code drops the delivered connectors when a`managed-mcp.json` is present on the host that runs the session, such as a[self-hosted runner host](https://code.claude.com/docs/en/self-hosted-environments-configuration#mcp-servers) , whether or not you set`allowAllClaudeAiMcps` .
- **Desktop app local and SSH sessions** : the desktop app registers the connectors as in-process`type: "sdk"` servers, and no MCP setting or`managed-mcp.json` reaches them. A user keeps a connector out of their own sessions by disconnecting it at[claude.ai/customize/connectors](https://claude.ai/customize/connectors) . An organization blocks a connector’s[tools](#organization-controls-on-connector-tools) or turns off[Claude Code in the desktop app](https://code.claude.com/docs/en/desktop#admin-console-controls) entirely.

### Organization controls on connector tools

Your organization can set per-tool controls on
[claude.ai connectors](https://claude.com/docs/connectors). Claude Code reads these settings at startup and enforces them locally, except in the desktop app’s

[local and SSH sessions](#how-connectors-reach-claude-code). There, the desktop app withholds

`blocked` tools before it delivers a connector, and the `ask` setting doesn’t reach Claude Code, so it applies the session’s ordinary [permission rules](https://code.claude.com/docs/en/permissions)to those tools instead of prompting on every call. In sessions where Claude Code fetches connectors itself, run

`/mcp` to see which setting applies to each tool on a connector.
- **Tool set to `ask`** : Claude Code prompts on every call with the reason` Your organization requires approval for this tool` . The prompt appears even in`acceptEdits` ,`auto` , and`bypassPermissions`[permission modes](https://code.claude.com/docs/en/permissions#permission-modes) . In the terminal, the prompt has no option to remember your choice.[Allow rules](https://code.claude.com/docs/en/permissions) that match the tool don’t skip the prompt either. In`dontAsk` mode, which never prompts, Claude Code denies the call instead.
- **Tool set to `blocked`** : Claude Code filters the tool out before Claude sees it, so it never appears in Claude’s tool list. In sessions where Claude Code fetches connectors itself, the`/mcp` tool list still shows the tool, marked`disabled by your organization` .

`blocked` setting, so Claude can’t use a blocked tool there either, and you can’t withhold a tool from the desktop app’s sessions while keeping it available in chat. The desktop app skips a connector whose tools are all blocked.
### Disable claude.ai connectors

Claude Code applies
[only to the connectors it](https://code.claude.com/docs/en/settings-reference#disableclaudeaiconnectors)

`disableClaudeAiConnectors`
[fetches itself](#how-connectors-reach-claude-code), not to the connectors a cloud host or the desktop app delivers. To turn off the connectors it fetches, set the setting to

`true` in any settings scope:
`true` in any settings source takes precedence. A checked-in project `.claude/settings.json` can opt a repository out of the connectors Claude Code fetches itself, but a project-level `false` can’t re-enable connectors that a user- or policy-level `true` has disabled. Servers passed explicitly via `--mcp-config` are unaffected.
You can also set the `ENABLE_CLAUDEAI_MCP_SERVERS` environment variable to `false`, which has the same effect for the current shell session:
[by name or by URL pattern. For example, a](https://code.claude.com/docs/en/managed-mcp)

`deniedMcpServers`` serverName` entry of `"claude.ai Slack"` blocks the Slack connector. You can also run `/mcp` to toggle any connector Claude Code fetches on or off for the current project only.
## Use Claude Code as an MCP server

You can use Claude Code itself as an MCP server that other applications can connect to:
### Read a background command’s output as an MCP client

A`backgroundOutputPath` field in a Bash or PowerShell result from `claude mcp serve` means the call left its command running [in the background](https://code.claude.com/docs/en/tools-reference#background-commands). A command runs in the background when your client sets

`run_in_background: true` on the call. A foreground command can also [move to the background](https://code.claude.com/docs/en/tools-reference#foreground-commands-that-move-to-the-background)when it reaches its timeout. The field is in the result’s JSON text and holds the path of the command’s output file.

- **To read the output so far** : open the file at that path from your client, or pass the path as`file_path` to the server’s[`Read`](https://code.claude.com/docs/en/tools-reference#read-tool-behavior) tool
- **To tell when the command has finished** : append an`echo` of a fixed string to the`command` value, as in`npm test; echo DONE` . The command has finished once that string appears in the file. Without the string, nothing marks the end, because Claude Code adds no closing line to the file and doesn’t notify your client.
- **To read the end of long output** :`Read` with only`file_path` returns the[first page](https://code.claude.com/docs/en/tools-reference#large-files) , or fails when the file exceeds the size limit. Pass`offset` and`limit` as well, which works at any file size:
  1. Call `Read` with`offset` and`limit` both set to`1` , and take`totalLines` from the result
  2. Call `Read` again with`offset` set to`totalLines` minus nine and`limit` set to`10`
  3. Look for your `echo` string in the last ten lines, which the second call returns
- Call 

`backgroundOutputPath` field requires Claude Code v2.1.295 or later.
## MCP output limits and warnings

When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context:
- **Output warning threshold** : Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens
- **Configurable limit** : you can adjust the maximum allowed MCP output tokens using the`MAX_MCP_OUTPUT_TOKENS` environment variable
- **Default limit** : the default maximum is 25,000 tokens
- **Scope** : the environment variable applies to tools that don’t declare their own limit. Tools that set[`anthropic/maxResultSizeChars`](#raise-the-limit-for-a-specific-tool) use that value instead for text content, regardless of what`MAX_MCP_OUTPUT_TOKENS` is set to. Tools that return image data are still subject to`MAX_MCP_OUTPUT_TOKENS`
- **Over the limit** : when a successful result with no image content exceeds the token limit, Claude Code saves it to a file and replaces it in the conversation with a message that names the file path, so Claude reads the file when it needs the content. The file goes in the session’s`tool-results` directory under[`~/.claude/projects/`](https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically) .
- **Response size from HTTP and SSE servers** : when a response from an[HTTP](#option-1-add-a-remote-http-server) or[SSE](#option-2-add-a-remote-sse-server) server passes 16 MiB, Claude Code stops reading it and the request fails. The limit applies after decompression to one JSON response body or one event of an event stream. If you maintain the server, return less data per response to stay under the limit, for example by paginating results
- **Message size from WebSocket servers** : when a[WebSocket](#option-4-add-a-remote-websocket-server) server sends one message over 16 MiB, Claude Code[closes the connection](#mid-session-drops-of-a-remote-server) , and calls in progress on that server fail. If you maintain the server, return less data per message to stay under the limit

[moved to a background task](#automatic-backgrounding-of-long-tool-calls)reports its result through the task notification. Two more limits apply to a call that completes in the foreground:

- **Character limit for text results** : for a tool that doesn’t declare[`anthropic/maxResultSizeChars`](#raise-the-limit-for-a-specific-tool) , Claude Code saves a successful result with no image content to a file once it’s longer than 50,000 characters, whatever its token count. Setting`MAX_MCP_OUTPUT_TOKENS` doesn’t change this threshold
- **Error results** : when a tool returns a result marked`isError: true` , Claude receives the result’s text as the tool’s error message. Error text longer than about 11,000 characters keeps only its first 5,000 and last 5,000 characters, with a marker between them that says how many characters were removed

`MAX_MCP_OUTPUT_TOKENS` in your shell before starting Claude Code:
### Raise the limit for a specific tool

If you’re building an MCP server, you can allow individual tools to return results larger than the default persist-to-disk threshold of 50,000 characters by setting`_meta["anthropic/maxResultSizeChars"]` in the tool’s `tools/list` response entry. Claude Code raises that tool’s threshold to the annotated value, up to a hard ceiling of 500,000 characters.
This is useful for tools that return inherently large but necessary outputs, such as database schemas or full file trees. Without the annotation, successful results that exceed the default threshold are persisted to disk and replaced with a file reference in the conversation.
`MAX_MCP_OUTPUT_TOKENS` for text content, so users don’t need to raise the environment variable for tools that declare it. Tools that return image data are still subject to the token limit.
### Images in tool results

When an MCP tool returns a PNG, JPEG, GIF, or WebP image, Claude sees the image inline in the conversation. The inline copy may be scaled down or compressed to fit the model’s image size limits. Claude Code also saves the original bytes to a file in the session’s`tool-results` directory under [and gives Claude the path. Claude can then crop, convert, or reuse the full-resolution file with tools such as Bash. If you disable session persistence with](https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically)

`~/.claude/projects/`
[or](https://code.claude.com/docs/en/cli-reference#cli-flags)

`--no-session-persistence`
[, Claude Code writes no image file and Claude receives only the inline copy. Saving MCP image results to a file requires Claude Code v2.1.283 or later.](https://code.claude.com/docs/en/env-vars)

`CLAUDE_CODE_SKIP_PROMPT_HISTORY`
## Tool input schemas with a root-level combinator

Some MCP servers declare a tool’s input schema as a JSON Schema union, with`anyOf`, `oneOf`, or `allOf` at the top level of the schema. The Claude API doesn’t accept those keywords at the schema root. It does accept combinators nested inside `properties`, which Claude Code sends unchanged.
Tools with a root-level combinator stay available. Before sending the tool to the API, Claude Code flattens the schema into a single object and prepends a sentence to the tool’s description that tells Claude which parameter groups belong together:
- `allOf` : properties from every branch are merged, and each branch’s`required` list still applies
- `anyOf` and`oneOf` : properties from every branch are merged, and each branch’s`required` list is described in the tool description instead of enforced by the schema

## Tools with invalid input schemas

[Tool input schema is invalid](https://code.claude.com/docs/en/errors#tool-input-schema-is-invalid).

- Top-level property names must be 1 to 64 characters long and use only ASCII letters and digits, `_` ,`.` , and`-`
- The schema must be valid against the JSON Schema draft 2020-12 meta-schema. Claude Code applies this check to schemas that declare no `$schema` and schemas that declare draft 2020-12. A schema that declares any other dialect skips this check, though the property-name check above still applies

[feature flag fetching](https://code.claude.com/docs/en/env-vars#features-that-need-feature-flag-fetching)is off or the flags have never arrived, as on an air-gapped machine, a tool that breaks a rule isn’t excluded:

- Claude gets the tool unchanged, and the server’s log records `input schema would be rejected by the Anthropic API` for it
- If the API then rejects the schema, see [Tools whose input schema the API refuses](#tools-whose-input-schema-the-api-refuses)

[root-level combinator handling](#tool-input-schemas-with-a-root-level-combinator)is separate and keeps its own behavior when flag fetching is off or the flags have never arrived.

### Tools whose input schema the API refuses

If a line in the debug log contains`the API refused this tool's input schema`, it names a tool whose schema the API rejected in a request. Claude Code resends that request with the tool declared without parameters.
- **If your session fails with a 400 error that names a tool by its position** : follow the steps in[Tool input schema is invalid](https://code.claude.com/docs/en/errors#tool-input-schema-is-invalid)
- **If you use the server** : you don’t need to do anything. Claude can still call the tool, but doesn’t see its parameters
- **If you maintain the server** : fix the tool’s input schema on the server. The log line ends with`The API said:` and the API’s reason for rejecting the schema. Validate the arguments the server receives, because Claude calls the tool without seeing its parameters

[a 400 error naming the tool by its position](https://code.claude.com/docs/en/errors#tool-input-schema-is-invalid).

## Tools with names longer than 128 characters

If`/mcp` lists a tool that Claude can’t call, check whether the tool’s full name is longer than 128 characters. Run `/mcp` in your session and select the tool to see its full name, such as `mcp__<server>__<tool>`. Claude Code leaves an MCP tool out of the tools it sends to Claude when its full name is over 128 characters. The Claude API rejects a request that includes such a tool, so leaving the tool out keeps the server’s other tools working.
For the message that names the tool and the ways to shorten its full name, see [MCP tool name over 128 characters](https://code.claude.com/docs/en/errors#mcp-tool-name-over-128-characters).

## Require approval for a specific tool

If you’re building an MCP server, you can mark a tool as requiring explicit approval on every call by setting`_meta["anthropic/requiresUserInteraction"]` to `true` in the tool’s `tools/list` response entry. The value must be the JSON Boolean `true`; any other value is ignored.
Claude Code shows that tool’s permission prompt on every call, even in `acceptEdits`, `auto`, and `bypassPermissions` [permission modes](https://code.claude.com/docs/en/permissions#permission-modes), and doesn’t offer a “don’t ask again” option for it.

[Allow rules](https://code.claude.com/docs/en/permissions#permission-rule-syntax)that match the tool don’t skip the prompt either. In

`dontAsk` mode, which never prompts, Claude Code denies the call instead.
The prompt has to reach a person. In non-interactive mode with [, an](https://code.claude.com/docs/en/cli-reference#cli-flags)

`--permission-prompt-tool`` allow` result from the prompt tool for a flagged tool is converted to a deny with the message `MCP tool requires user interaction; not supported via --permission-prompt-tool`. The Agent SDK’s [does receive these calls and can approve them, because your SDK application is expected to show them to a user. Use this for tools whose permission prompt is itself the point, such as a consent or access-grant step where auto-approval would mean no human ever agreed. Other tools from the same server keep their normal permission behavior. The following](https://code.claude.com/docs/en/agent-sdk/permissions)

`canUseTool` callback`tools/list` entry marks one tool as always requiring approval.
[Remote Control](https://code.claude.com/docs/en/remote-control)and applications built on the

[Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview), normally let you approve tool calls with one tap. For a tool marked with this annotation, Claude Code withholds the one-tap action and shows the tool’s full permission prompt instead, so approval still comes from a person answering the prompt rather than a tap. Claude Code withholds one-tap approval the same way for any permission request that only the terminal dialog can render in full, such as one that carries a safety warning or an always-allow option the remote surface can’t show. You answer that request in the terminal dialog rather than from Remote Control.

## Mark tools that are safe to call twice

If you build an MCP server, mark the tools that are safe to call twice so Claude Code can repeat a call that was pending when a connection closed. Claude Code can repeat such a call to an HTTP server or a
[claude.ai connector](#use-mcp-servers-from-claude-ai)once, on a new connection. A call Claude Code doesn’t repeat can fail with

[. To mark a tool, set one of these](https://code.claude.com/docs/en/errors#connection-closed-before-the-tool-call-was-answered)

`connection closed before the tool call was answered`` annotations` to `true` in its `tools/list` entry:
- **`idempotentHint`** : the tool can change something, and calling it again with the same arguments is safe
- **`readOnlyHint`** : the tool changes nothing. Claude Code also runs the tool’s calls in parallel with other read-only calls.

`tools/list` entry mark the `set_issue_status` tool as safe to repeat:
## Respond to MCP elicitation requests

MCP servers can request structured input from you mid-task using elicitation. When a server needs information it can’t get on its own, Claude Code displays an interactive dialog and passes your response back to the server. No configuration is required on your side: elicitation dialogs appear automatically when a server requests them. Servers can request input in two ways:
- **Form mode** : Claude Code shows a dialog with form fields defined by the server (for example, a username and password prompt). Fill in the fields and submit.
- **URL mode** : Claude Code asks whether to open a link in your browser. Servers use this mode for a flow that finishes outside the terminal, such as sign-in.

`%` or `&`, counts four times toward the cap: its own character plus three escape characters. A URL with none of them reaches the cap at about 8,000 characters. A URL built largely of percent-escapes, where every third character is a `%`, reaches it at roughly 4,000.
To auto-respond to elicitation requests without showing a dialog, use the [. If you’re building an MCP server that uses elicitation, see the](https://code.claude.com/docs/en/hooks#elicitation)

`Elicitation` hook
[MCP elicitation specification](https://modelcontextprotocol.io/docs/learn/client-concepts#elicitation)for protocol details and schema examples.

### Elicitation modes Claude Code declares

If you build an MCP server, the client capabilities Claude Code sends when it connects tell your server which elicitation modes it can request. Claude Code declares`elicitation: {form: {}, url: {}}` on the following connections, so a server on any of them can request both modes:
- Connections that use [protocol revision 2026-07-28](#mcp-client-runtimes)
- Connections on the earlier protocol revisions, 2025-11-25 and older, to the stdio, `sse` ,`http` , and`ws` servers in a user’s Claude Code MCP configuration. Requires Claude Code v2.1.287 or later

[claude.ai connectors](#use-mcp-servers-from-claude-ai), Claude Code declares the bare

`elicitation: {}`, which permits elicitation requests in form mode only.
A server built on Java MCP SDK 0.17.0 or earlier can refuse a declaration that has `form` and `url` in it. See [MCP server rejected the elicitation capability](https://code.claude.com/docs/en/errors#mcp-server-rejected-the-elicitation-capability).

## Use MCP resources

MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files.
### Reference MCP resources

List available resources

`@` in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu.
Reference a specific resource

`@server:protocol://resource/path` to reference a resource:
Multiple resource references

`ui://` URI or the `text/html;profile=mcp-app` media type: pages for a host application to render rather than content for Claude to read. They don’t appear in the `@` suggestions or in the resource list tool’s results, and a server that offers only UI resources shows an empty resource list. Reading a UI resource by its URI still works.
## Scale with MCP tool search

Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names and server instructions load at session start, so adding more MCP servers has minimal impact on your context window. Claude Code doesn’t impose a fixed per-server tool cap; the practical limit is your context window budget.
[deployments hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options), which reject it server-side: Claude Code detects the rejection and loads MCP tools upfront for that deployment instead.

[can’t override this, since the rejection comes from the deployment itself.](#configure-tool-search)

`ENABLE_TOOL_SEARCH`
### Tool search for MCP server authors

If you’re building an MCP server, the server instructions field becomes more useful with tool search enabled. Server instructions help Claude understand when to search for your tools, similar to how
[skills](https://code.claude.com/docs/en/skills)work. Add clear, descriptive server instructions that explain:

- What category of tasks your tools handle
- When Claude should search for your tools
- Key capabilities your server provides

- **Server instructions, and the description of a tool that loads upfront** : 4,096 characters
- **The description of a tool that Claude loads through tool search** : 16,384 characters

[tool search is off](#configure-tool-search), when the tool is

[marked to load upfront](#per-tool-alwaysload), or when its server is

[exempt from deferral](#exempt-a-server-from-deferral). Before v2.1.296, the shorter limit was 2,048 characters, and before v2.1.295 it applied to every tool description, including one loaded through tool search.

#### Change the description length limits

To change the
[default limits](#for-mcp-server-authors)of 4,096 and 16,384 characters for the MCP servers in your session, set

[to a number of characters. Claude Code uses that number for both limits. With](https://code.claude.com/docs/en/env-vars#variables)

`CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH`` 8192`, for example, you raise the 4,096-character limit on server instructions and tool descriptions loaded upfront, and lower the 16,384-character limit on tool descriptions loaded through tool search. This variable requires Claude Code v2.1.280 or later.
Descriptions and instructions from some of the MCP servers that Anthropic hosts at `api.anthropic.com` reach Claude in full, and setting this variable doesn’t cut them.
#### Mark a tool to load upfront or stay deferred

To control how one of your server’s tools loads, set`"anthropic/alwaysLoad"` in that tool’s `_meta` object. The person who adds your server to Claude Code can also set [for the whole server in their configuration, and their setting can override yours:](#exempt-a-server-from-deferral)

`alwaysLoad`` tools/list` entry asks for one tool to load upfront:
### Configure tool search

Tool search is enabled by default: MCP tools are deferred and discovered on demand. Setting
[keeps tool search off. You can’t override it by setting](https://code.claude.com/docs/en/env-vars)

`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`` ENABLE_TOOL_SEARCH` yourself. On Claude Code v2.1.227 or later, your organization can keep tool search on under this variable through [managed settings](https://code.claude.com/docs/en/managed-settings). In a session that

[gets the HIPAA configuration](https://code.claude.com/docs/en/hipaa-setup#check-how-developers-sign-in-and-connect), tool search is off, and neither

`ENABLE_TOOL_SEARCH` nor managed settings turns it back on. [Disable pre-release capabilities](https://code.claude.com/docs/en/llm-gateway-protocol#disable-pre-release-capabilities)covers where the override applies and what the variable strips. Claude Code uses tool search on Claude Opus 4, Claude Sonnet 4, Claude Haiku 4.5, and later models, or Opus 4.5, Sonnet 4.5, Haiku 4.5, and later models on Google Cloud’s Agent Platform. On earlier models, Claude Code loads all MCP tools upfront, and

`ENABLE_TOOL_SEARCH=true` doesn’t override this.
On Google Cloud’s Agent Platform, Claude Code decides by model generation:
- **Claude Opus 4.5, Sonnet 4.5, Haiku 4.5, and later** : tool search is on by default, the same as on the Anthropic API.
- **Earlier Agent Platform models** : Claude Code loads all MCP tools upfront, because their serving stacks reject the required beta header.`ENABLE_TOOL_SEARCH=true` doesn’t override this.

`ENABLE_TOOL_SEARCH=true`.
Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:
[settings.json](https://code.claude.com/docs/en/settings-reference#env). You can also disable the

`env` field`ToolSearch` tool specifically:
`ToolSearch` or leave it out of [, MCP tools load upfront instead, but a request can still carry a placeholder](https://code.claude.com/docs/en/cli-reference#cli-flags)

`--tools`` defer_loading` entry. If a gateway rejects that entry, see [Tool search through an LLM gateway](#tool-search-through-a-gateway).

#### Tool search through an LLM gateway

- **You’ve set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`** : see[how it affects tool search](#configure-tool-search)
- **A request failed with an error that names `defer_loading` or `tool_reference`** : see[Extra inputs are not permitted](https://code.claude.com/docs/en/errors#extra-inputs-are-not-permitted)

`ANTHROPIC_BASE_URL` points to a gateway, tool search is on by default, so requests include `defer_loading` tool fields and `tool_reference` blocks for the gateway to forward. While tool search is on, MCP tools are [deferred](#scale-with-mcp-tool-search). To load every tool upfront instead, set

`ENABLE_TOOL_SEARCH=false` in your shell or your [settings](https://code.claude.com/docs/en/settings-reference#env). Before v2.1.304, tool search was off behind a gateway unless

`env`` ENABLE_TOOL_SEARCH` was `true`, `auto`, or `auto:N`.
On v2.1.305 or later, Claude Code can [retry a request without tool search](https://code.claude.com/docs/en/llm-gateway-protocol#retry-without-tool-search)after a

`400` or `422` whose cause it doesn’t recognize. When the retry works, nothing shows on screen and you don’t need to do anything: MCP tools load upfront instead. Claude Code tries tool search again later, at the cost of another rejected request. To skip those requests, set `ENABLE_TOOL_SEARCH=false`.
#### Tools that stay deferred below the `ENABLE_TOOL_SEARCH=auto` threshold

If [labels tools](https://code.claude.com/docs/en/commands#all-commands)

`/context``(deferred)` or `(loaded on-demand)` though their definitions total under the `auto` threshold, tool search was already on in this conversation and stayed on. The total can drop later, for example while MCP servers reconnect after you resume a session. You don’t need to do anything: Claude loads each of those tools when a task needs it.
### Exempt a server from deferral

If a server’s tools should always be visible to Claude without a search step, set`alwaysLoad` to `true` in that server’s configuration. The server’s tools then load into context regardless of the `ENABLE_TOOL_SEARCH` setting. Use this for a small number of tools that Claude needs on every turn, since each upfront tool consumes context that would otherwise be available for your conversation.
The following `.mcp.json` entry exempts one HTTP server while leaving other servers deferred:
`alwaysLoad` field is available on all server types.
Setting `alwaysLoad: true` also makes startup wait for the server’s tools, capped at the standard 5-second connect timeout, since they must be present when the first prompt is built. A remote server with a valid [supplies its tools from the cache without connecting, so it doesn’t hold startup. Other servers connect in the background by default; set](#server-status-detail)

`cached` entry
[to make startup wait for them too.](https://code.claude.com/docs/en/env-vars)

`MCP_CONNECTION_NONBLOCKING=0`
### Defer a server’s tools

To keep all of a server’s tools behind tool search, set`"alwaysLoad": false` in that server’s entry in your MCP configuration. That includes tools that the server’s author has [marked to load upfront](#per-tool-alwaysload). If you leave

`alwaysLoad` out, those marked tools load upfront. Requires Claude Code v2.1.287 or later.
## Use MCP prompts as commands

MCP servers can expose prompts that become available as commands in Claude Code. Prompts from a server named`anthropic-skills` don’t appear, because Claude Code [reserves that name](https://code.claude.com/docs/en/skills#names-reserved-for-synced-skills)for skills synced from claude.ai. The server’s tools still work. Rename the server in your MCP configuration to list its prompts.

### Execute MCP prompts

Discover available prompts

`/` to see the commands available to you, including those from MCP servers. Claude Code lists each MCP prompt as `/servername:promptname (MCP)`. Typing `/mcp__servername__promptname` also runs it.
Execute a prompt without arguments

Execute a prompt with arguments

## Managed MCP configuration

For organizations that need centralized control over which MCP servers users can connect to, see
[Managed MCP configuration](https://code.claude.com/docs/en/managed-mcp). It covers deploying a fixed server set with

`managed-mcp.json`, providing servers to every user with `managedMcpServers`, restricting servers with `allowedMcpServers` and `deniedMcpServers`, and what users see when a server is blocked.
