Blog · October 5, 2026 · 10 min read · by Vilva Athiban P B
Claude Code MCP Servers Explained: Adding Servers, Choosing a Scope, Handling Secrets, and Why Long Tool Calls Go to the Background
MCP servers are how Claude Code reaches things outside your repository: an issue tracker, a database, a browser, a design tool, your company's internal API. The protocol is open, the server list is long, and the configuration surface in Claude Code has grown enough that the questions people search for are now specific: which scope should I use, why is my.mcp.json server "pending approval", why did a tool call vanish into the background, and where did the output go. This guide answers those from the current documentation, with the exact commands. Everything below is from the official Claude Code MCP docs as of October 2026; flags change, so check there if something does not match.
Adding a server: claude mcp add
The command has one shape, claude mcp add [options] <name> <url-or-command>, and three transports you will meet in practice. HTTP is the recommended one for anything remote; SSE still works but is deprecated; stdio runs a local process and talks to it over pipes.
# Remote server over HTTP (recommended)
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Remote server that needs a header
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# Local process over stdio. The -- separates Claude's flags from the command.
claude mcp add --transport stdio airtable \
--env AIRTABLE_API_KEY=YOUR_KEY \
-- npx -y airtable-mcp-serverThe -- separator is the detail that bites most often: without it, Claude Code tries to parse the server's own flags as its own. Once a server is added, claude mcp list shows them all, claude mcp get <name> shows one, and claude mcp remove <name> deletes it. If you already have servers configured in Claude Desktop, claude mcp add-from-claude-desktop imports them from its config file in one go.
The three scopes, and which to pick
Every server lives in exactly one scope, and the scope decides who else gets it.
- local (the default): stored in
~/.claude.jsonunder the current project's path. Only you, only in this directory. Right for personal experiments and for servers that carry your own credentials. - project (
--scope project): written to.mcp.jsonat the repository root, meant to be committed. Everyone who clones the repo gets the same servers. Right for the shared tools a team agrees on: the issue tracker, the docs search, the test database. - user (
--scope user): stored in~/.claude.jsonglobally, available in every project on this machine. Right for the servers you want everywhere, such as a browser or a notes tool.
A project-scoped .mcp.json looks like this, and it is the one file in this guide worth memorising:
{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}Two rules of the file. A server with a url must also have a type (http, sse or ws); leaving it out is a schema error. And a handful of names are reserved for built-in integrations (workspace, claude-in-chrome, computer-use and a couple of others), so pick something else for your own servers.
Why a project server says "pending approval"
Because .mcp.json arrives with the repository, Claude Code treats it as untrusted until you say otherwise: in an interactive session it asks you to approve the project's servers before connecting to them, and /mcp shows them as Pending approval until you do. In claude -p, the Agent SDK and cloud sessions there is nobody to ask, so they load without prompting. If you answered the prompt wrongly, claude mcp reset-project-choices clears your choices so it asks again.
Secrets: environment variables and OAuth
Do not paste tokens into .mcp.json. The file supports ${VAR} and ${VAR:-default} expansion in command, args, env, url and headers, so the committed file names the variable and each developer sets it locally:
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headers": { "Authorization": "Bearer ${INTERNAL_MCP_TOKEN}" }
}
}
}One deliberate exception: Claude Code's own credentials (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN) and a short list of cloud and registry secrets are never expanded into a remote server's URL or headers, so a malicious .mcp.json cannot exfiltrate them. Your own variable names expand normally.
For servers that speak OAuth, you usually need no token at all. Add the server, open /mcp, and follow the browser login; the server registers itself dynamically. claude mcp login <name> and claude mcp logout <name> do the same from the command line, and --client-id, --client-secret and --callback-port cover servers that need pre-registered credentials. For anything stranger, a headersHelper script in .mcp.json can produce the headers at connect time.
/mcp: what the status words mean
Inside a session, /mcp opens the server panel. The status next to each server is more informative than it looks:
- Connected: working. Needs authentication: run the OAuth flow from the panel.
- Failed to connect: shows the HTTP status or error;
/mcp reconnect allretries every failed server without restarting the session. - Pending approval: the project-scope trust prompt from above. Disabled for this project: you switched it off here.
- cached: the server's tool list was loaded from the discovery cache and it will connect the first time a tool is actually called. This is normal, not an error.
That last status exists because of how Claude Code now scales to many servers. Rather than loading every tool definition into context up front, it indexes them and searches on demand, deferring slow connections until needed. That is on by default on current models; if you need the old behaviour, ENABLE_TOOL_SEARCH=false turns it off.
Long tool calls, timeouts and where big output goes
This is the section that explains the surprises. Four timeouts and one size limit govern MCP tool calls, each with an environment variable:
MCP_TIMEOUT=10000 claude # server startup, ms
MCP_TOOL_TIMEOUT=600000 claude # one tool call, ms (default is ~28 hours)
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT=300000 # idle: 5 min HTTP/SSE, 30 min stdio
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=120000 # auto-background threshold, default 2 min
MAX_MCP_OUTPUT_TOKENS=50000 claude # output cap, default 25,000 tokensThe auto-background threshold is the one people trip over. A tool call in the main conversation that runs longer than two minutes is moved to a background task: Claude gets a task ID immediately, carries on, and the result arrives as a notification when the call finishes. You can watch it in /tasks, the same view as other background tasks. If that behaviour breaks a workflow, raise the threshold per run, or set CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 to switch background tasks off entirely (the trade-offs of doing that are in this post).
A single server can also carry its own "timeout" in milliseconds inside .mcp.json, which is cleaner than a global variable when only one server is slow.
Output has a budget too. Above about 10,000 tokens Claude Code warns; above 25,000 (configurable with MAX_MCP_OUTPUT_TOKENS) it stops putting the result in context and instead saves it to a file under ~/.claude/projects/tool-results/ and tells Claude where it is. So when a database query "disappears", look there first. Server authors can raise a single tool's limit by setting _meta["anthropic/maxResultSizeChars"] on the tool definition, up to 500,000 characters.
Using what a server offers: tools, resources, prompts
Tools are what Claude calls on its own; you will see them named mcp__<server>__<tool> in permission prompts, which is also the form to use in --allowedTools for headless runs (the claude -p guide covers that). Resources, such as a document or a database schema the server exposes, can be pulled into the conversation with an @ mention, the same way you reference a file. Prompts the server publishes appear as slash commands. None of that needs extra configuration; it follows from the server being connected.
Starting Claude with a specific set of servers
For scripts, CI and reproducible demos, you can hand Claude Code a config file instead of relying on whatever is in ~/.claude.json:
claude --mcp-config ci-servers.json
claude --strict-mcp-config --mcp-config ci-servers.json # only these, ignore the rest
claude --mcp-config a.json --mcp-config b.json # several files--strict-mcp-config is the one to use in CI: it guarantees the run sees exactly the servers in the file and nothing a developer left in their user config. In the other direction, Claude Code can itself be an MCP server for other clients with claude mcp serve, and if you log in with a claude.ai account, the connectors configured there are available automatically; ENABLE_CLAUDEAI_MCP_SERVERS=false or a deniedMcpServers list in settings turns individual ones off.
A sane setup for a team
- Put the shared servers in
.mcp.jsonat project scope, with every secret as a${VAR}reference and a line in the README saying which variables to set. - Keep personal servers (your notes app, your browser) at user scope so they do not leak into the repo.
- Prefer HTTP transport and OAuth where the vendor offers it; fall back to stdio only for local tools.
- Set a per-server
timeoutfor the slow ones rather than a global override, and know that calls over two minutes go to the background by design. - Treat every server as an input: a server that fetches external content can carry prompt injection, so review what a new server does before approving it, and do not approve
.mcp.jsonfrom a repository you do not trust.
When a server does a lot of the work in a session, the run gets quieter and longer: a migration tool grinding through a schema, a browser server walking through a sign-up flow, a search server paging through results. Those are precisely the runs where you walk away, and precisely where a done notification earns its keep.
Keep reading
Desk Exercises for Programmers: 15 Moves to Do While Your AI Agent Codes
7 min read
Exercise While Coding: Turn Claude Code Wait Time Into Micro-Workouts
7 min read
Claude Code Notch Notifications on Mac: See When Claude Is Done Without Watching the Terminal
7 min read
Claude Code Tips and Tricks: 12 Ways to Use Claude Code Effectively
8 min read
Claude Code Multiple Sessions: How to Run Agents in Parallel Without Losing Track
6 min read
A Claude Code Workflow That Doesn't Involve Watching the Terminal
5 min read
Claude Code Hooks: A Practical Guide to Automating Your Agent Workflow
7 min read
Claude Code Auto Mode: Fewer Permission Prompts Without Living Dangerously
7 min read
Claude Code Subagents: How to Delegate Work to Specialized Agents
7 min read
Claude Code Context Management: Treat the Context Window Like a Budget
6 min read
Per-Subagent Model Selection: Route the Grunt Work Down, Keep the Judgment Up Top
7 min read
Skills and Plugins: How to Teach Claude Code Your Way of Working
7 min read
Claude Code Background Tasks: Run Long Commands Without Blocking Your Session
6 min read
Codex CLI Notifications: How to Get a Ding When Codex Is Done or Needs Input
7 min read
Cursor Notification When Done: Every Way to Get Notified When Cursor Finishes
6 min read
Claude Code Notifications: How to Get Notified When Claude Code Finishes or Needs Your Input
6 min read
Want to Be Notified When Claude Responds? How Claude Notifications Work on Web, Desktop, and Mobile
5 min read
Claude Code Notification Scripts: Copy-Paste Recipes for Every Platform
6 min read
Get a Ding the Moment Codex Needs Your Response
6 min read
Get Notified the Moment Claude Code Is Waiting for Your Input
6 min read
“Notifications Are Turned Off for Claude” — Here Is the Fix
6 min read
Codex Sound When Done: Make Codex CLI Play a Sound When It Finishes
6 min read
terminal-notifier + Claude Code: Native macOS Alerts When Your Agent Finishes
6 min read
Gemini CLI Notifications: How to Get a Sound or Alert When Gemini Finishes
6 min read
Get Claude Code Notifications on Your Phone
6 min read
Claude Code Remote Control, Explained
7 min read
preferredNotifChannel: Claude Code's Built-In Notification Setting
6 min read
Claude Code Notifications in tmux and Over SSH
7 min read
Claude Code Effort Levels: Why Your Setting Keeps Getting Ignored
8 min read
Codex vs Claude Code Notifications: How Each One Tells You It Is Done
8 min read
Claude Code Notifications Not Working: A Diagnostic Checklist
10 min read
Claude Code Notifications Inside Your Editor's Terminal
7 min read
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS Explained
7 min read
CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP Explained
8 min read
Cursor Alerts Explained: Every Alert Cursor Raises, and How to Control Them
7 min read
Claude Code Environment Variables: The Groups That Actually Matter
10 min read
Claude Code Notifications on WSL and Windows
9 min read
Claude Code Checkpoints and /rewind
8 min read
Claude Remote Control: How It Works, Turning It Off, and Auto Mode
7 min read
Claude Code /loop: Poll a Deploy, Babysit a PR, and Get Told When It's Done
8 min read
Setting Up NotchFit With OpenAI Codex CLI: Hooks, $notchfit-plan, and the Daily Flow
7 min read
Claude Mods Explained: What the New Plugin Layer Can Do, and How to Turn On 'You Should Know'
9 min read
NotchFit vs Mac Break Reminder Apps: A Clock or a Signal From Your Coding Agent?
8 min read
Claude Code Headless Mode: Running claude -p in Scripts and CI, and the Three Signals That It Finished
10 min read
Building a Movement Habit at a Desk: Use the Agent Run as the Cue, One Set as the Unit, and Streaks Carefully
8 min read
/notchfit:plan Explained: How Claude Code or Codex Writes a Weekly Workout Plan the Notch Can Actually Run
8 min read