Add a server with claude mcp add <name> -- <command> for a local stdio process, or claude mcp add --transport http <name> <url> for a remote one. Choose a scope: local (you, this project, the default), project (written to a committed .mcp.json), or user (you, everywhere). Check what actually connected with claude mcp list or /mcp. The critical security point: the permission system governs what the agent does directly, not what a tool server reaches on its behalf.
- Three scopes: local (default), project (committed
.mcp.json), user (everywhere). - Transports:
stdio,http,sse, pluswsviaclaude mcp add-jsononly. - The sandbox does not cover MCP servers. A server runs with its own credentials and reach.
- Tool search is on by default as of August 2026, so extra servers no longer flood your context.
claude mcp listshows health;/mcpshows tool counts and runs OAuth sign-in.
Adding a server
Two shapes. A local stdio server is a process on your machine and everything after the -- is the command that runs it. A remote server is a URL and needs an explicit --transport.
# local stdio server: just me, just this project (the default scope)
claude mcp add db -- npx -y @bytebase/dbhub --dsn "$READONLY_DATABASE_URL"
# the whole team, written to a committed .mcp.json
claude mcp add --transport http --scope project linear https://mcp.linear.app/mcp
# me, in every project
claude mcp add --transport http --scope user sentry https://mcp.sentry.dev/mcp
# a server that needs a header credential
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer $GITHUB_PAT"
# a transport --transport does not accept (ws), via JSON
claude mcp add-json events \
'{"type":"ws","url":"wss://mcp.example.com/socket"}'
Which scope to use, and where it is written.
| Scope | Stored in | Use for |
|---|---|---|
local (default) | Your ~/.claude.json, keyed per project | Anything with a personal credential |
project | .mcp.json at the repo root, committed | Servers the whole team should have |
user | Your ~/.claude.json, top level | Personal tools you want everywhere |
Keep credentials out of the committed file
.mcp.json supports environment expansion, so a shared config can reference a secret each developer supplies themselves. Both ${VAR} and ${VAR:-default} work, in command, args, env, url, and headers.
{
"mcpServers": {
"db": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${READONLY_DATABASE_URL}"]
},
"docs": {
"type": "http",
"url": "${DOCS_MCP_URL:-https://mcp.example.com/v1}"
}
}
}
The security model, stated plainly
Claude Code has a permission system that governs what the agent does directly: which files it may edit, which commands it may run. That system does not extend through an MCP server.
- Scope the credential, not the prompt. Give the database server a read-only role. That is a boundary; an instruction is not.
- Read the server code, or at least know who wrote it. A stdio server runs as you, with your files and your network.
- Prefer project scope for shared servers, so additions arrive in a pull request rather than each person quietly adding their own.
- Deny the tools you never want. MCP permission rules use the server name:
mcp__puppeteermatches every tool on that server,mcp__puppeteer__puppeteer_navigatematches one. - Be careful with anything that fetches external content. Anthropic’s own docs flag this: a server that pulls arbitrary URLs turns outside content into a possible instruction channel.
- Audit periodically.
claude mcp list. Servers accumulate and nobody removes them.
{
"permissions": {
"deny": [
"mcp__puppeteer",
"mcp__db__execute_sql"
],
"allow": [
"mcp__db__query"
]
}
}
Debugging a server that will not connect
Check the health line
claude mcp list prints a status next to each server. The command succeeding does not mean the servers did.
# configured servers plus a health status each
claude mcp list
# one server in full
claude mcp get sentry
# from inside a session: tool counts, disable toggle, OAuth
/mcp
Match the status to the cause
What each status means. Statuses as of August 2026.
| Status | Means | Do this |
|---|---|---|
Connected | Working | Nothing |
Needs authentication | Server returned 401 or 403 | claude mcp login <name>, or Re-authenticate in /mcp |
Failed to connect | Process died, bad URL, or a rejected header credential | Run the command by hand; check the token |
Pending approval | Project server from .mcp.json not yet approved | Run claude interactively and approve it |
Rejected | Listed in disabledMcpjsonServers | Remove it from that settings array |
cached | Remote server, tool list reused from a previous session | Nothing; it connects on first tool call |
Run the server by hand
For a stdio server, this is almost always where the answer is. The process either fails to start, or it starts and pollutes the protocol channel.
npx -y @bytebase/dbhub --dsn "$READONLY_DATABASE_URL"
# raise the 30s startup timeout while you investigate
MCP_TIMEOUT=60000 claude
The failures, roughly in order of frequency.
| Symptom | Cause | Fix |
|---|---|---|
Server missing from /mcp | Process failed to start | Run the command by hand |
| Starts, then disconnects | Wrote to stdout | stdio owns stdout as the protocol channel; log to stderr |
| Auth errors on a stdio server | Env var not visible to the process | Pass it with --env, or export it |
Needs authentication on a remote server | OAuth not completed, or a stale refresh token | claude mcp login <name> |
| Works for you, not the team | Local scope | Re-add with --scope project |
| Server ignored on a fresh clone | Workspace not trusted yet | Run claude in it and accept the trust dialog |
npx hangs | Package resolution over the network | Install it and use an absolute path |
| Tool call aborts with no error from the server | Idle timeout | 5 min remote, 30 min stdio; tune CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT |
| Server name refused outright | Reserved name | workspace, claude-in-chrome, computer-use and two others are reserved |
Timeouts, output limits, and the context question
MCP has more clocks than most people realise, and a slow server hits a different one depending on how it is failing.
MCP limits and where to change them. As of August 2026.
| Limit | Default | Control |
|---|---|---|
| Server startup | 30 seconds | MCP_TIMEOUT (milliseconds) |
| Tool call, wall clock | About 28 hours | Per-server timeout in .mcp.json, or MCP_TOOL_TIMEOUT |
| First response byte, remote only | 60 seconds | Raised by setting the per-server timeout to 60s or more |
| Idle with no progress | 5 min remote, 30 min stdio | CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT, or 0 to disable |
| Tool output warning | 10,000 tokens | Fixed |
| Tool output cap | 25,000 tokens | MAX_MCP_OUTPUT_TOKENS |
Tool search changed the token maths
For a long time the honest advice was that every connected server contributed its tool definitions to context on every turn, so servers you forgot about were a permanent tax. As of August 2026 that is no longer the default. Tool search is on by default: only tool names and server instructions load at session start, and full schemas load when Claude searches for them.
ENABLE_TOOL_SEARCH values.
| Value | Behaviour |
|---|---|
| (unset) | All MCP tools deferred, loaded on demand. The default. |
true | Force deferral, including through a proxy that may not support it |
auto | Load upfront if the schemas fit in 10% of the context window, defer the rest |
auto:N | Same, with your own percentage, such as auto:5 |
false | Load every schema upfront. The old behaviour. |
- Add servers for work you actually do repeatedly, not for capability you might want.
- Prefer local or user scope for personal experiments so you do not impose them on the team.
- Write real server instructions if you author a server. With tool search on, that text is how Claude decides to go looking for your tools. Descriptions and instructions are truncated at 2KB each.
Sharing servers with a team
Project scope is the point at which MCP stops being a personal convenience and becomes shared infrastructure, which means it needs the same review as code.
Add at project scope and commit
claude mcp add --scope project ... writes .mcp.json at the repo root. Review the diff like any other config change: the file is exactly as public as your repository.
Expect an approval prompt on every teammate’s first run
Claude Code asks before using project-scoped servers in interactive sessions. Reset those choices with claude mcp reset-project-choices. Approvals are read only from settings files that are not checked into the repo, and only after the workspace trust dialog is accepted, so a cloned repository cannot approve its own servers.
Decide what happens in headless runs
claude -p, Agent SDK sessions, and cloud sessions cannot show that prompt, so they load project-scoped servers without asking. To keep one out everywhere, add it to disabledMcpjsonServers; to drop project settings entirely, use --setting-sources.
Pin the approvals you do want
Set enabledMcpjsonServers to a list, or enableAllProjectMcpServers to true, in a settings file that is not committed. Those keys are ignored in an untrusted folder by design.
Questions people ask
Run claude mcp add <name> -- <command> for a local stdio server, or claude mcp add --transport http <name> <url> for a remote one. Add --scope project to commit it as .mcp.json for the team, or --scope user to have it in every project.
local is you in this project and is stored in your own config; project writes .mcp.json at the repo root and is shared through version control; user applies to all your projects. Put anything with a personal credential in local.
Only at the call boundary. You can allow or deny individual tools with mcp__server__tool rules, but the server itself runs with its own credentials and reach, so a read-only agent with a write-capable database server can still write. Scope the credential.
Most often because it wrote to stdout. The stdio transport uses stdout as the protocol channel, so any stray print corrupts the stream. Log to stderr. Run the server command by hand to see the real error.
claude mcp list from the shell shows a health status per server, and claude mcp get <name> shows one in full. Inside a session, /mcp shows tool counts, lets you toggle a server off, and runs the OAuth flow.
Not by default as of August 2026. Tool search defers schemas, so only tool names and server instructions load at session start. Set ENABLE_TOOL_SEARCH=false to go back to loading everything upfront, and note that a non-first-party ANTHROPIC_BASE_URL falls back to that automatically.
For OAuth servers, run claude mcp login <name> from the shell, or open /mcp and complete the browser flow. For token-based servers, pass --header "Authorization: Bearer ..." when adding. Claude Code does not validate the credential at add time, so a bad token shows up later as a failed connection.
.mcp.json is project scope at the repo root and is meant to be committed. ~/.claude.json holds your local-scope servers keyed per project and your user-scope servers at the top level, and is never shared.
Sources
Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.