MCP (Model Context Protocol) connects Claude to external tool servers — databases, browsers, APIs, and custom internal services — without modifying the CLI itself. Servers expose tools, resources, and prompts that Claude discovers at session startup and uses on demand. This chapter covers transports, configuration, debugging, and the performance trade-offs that come with plugging in external capabilities.
Three Transports
MCP servers communicate with Claude through one of three transport mechanisms. The right choice depends on where the server runs and how it is managed.
Transport Comparison
| Transport | Config Key | Best For | Trade-off |
|---|---|---|---|
stdio | command + args | Local tools, per-session isolation | 2-10s startup per session (server spawns as child process) |
sse | url (path ending /sse) | Remote servers already running | Requires a long-running process; older protocol |
streamable-http | url + type: “streamable-http” | Modern remote servers, shared team tools | Better connection handling than SSE; emerging standard |
For most local development, stdio is the default and the right choice. The server process starts when the session begins and is torn down when it ends. Use SSE or streamable-http when the MCP server is a long-running remote service such as a shared database proxy or a team-wide tool server.
Inline Config
Pass MCP server definitions directly on the command line with --mcp-config and a JSON string. No config file needed.
Claude starts the filesystem MCP server as a child process, discovers its tools via the MCP protocol handshake, uses them to fulfill the prompt, and tears down the server when the session ends. The inline JSON follows the same mcpServers schema as file-based config.
You can also point --mcp-config at a file path instead of raw JSON:
claude -p "Query the database" --mcp-config ./mcp-config.jsonFile-Based Config
For repeatable setups, define servers in a JSON config file. This is also the format used by .mcp.json in a project root (auto-discovered by Claude) and ~/.claude/settings.json for user-level tools.
{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@anthropic-ai/mcp-server-filesystem", "/home/user/projects"], "env": {} }, "database": { "command": "python", "args": ["-m", "mcp_server_postgres"], "env": { "DATABASE_URL": "postgresql://user:pass@localhost/mydb" } }, "remote-tools": { "url": "http://internal-tools.company.com:3000/sse" } }}Each server specifies either a command (for stdio) or a url (for SSE / streamable-http). The optional env object passes environment variables to the server process — useful for secrets you do not want hardcoded in prompts.
MCP servers can be defined at five different scopes, and they merge at runtime. When the same server name appears in multiple scopes, the more specific scope wins.
Configuration Scopes
| Scope | Location | Shared? | Use Case |
|---|---|---|---|
| CLI inline | —mcp-config flag | One-shot | Scripts, CI/CD, experimentation |
| Local | .claude/settings.local.json | NOT committed (gitignored) | Local-only tools with secrets |
| Project | .claude/settings.json | Committed to repo | Team-shared tools (e.g., project database) |
| User | ~/.claude/settings.json | All projects | Personal tools you always want available |
| Managed | managed-mcp.json | Org-level, enterprise | Admin-forced or admin-blocked servers |
Precedence order: CLI > Local > Project > User > Managed.
MCP configs walk up the directory tree unconditionally. A .mcp.json at the repo root is visible to every subfolder session. Unlike skills, a .git boundary does not block MCP inheritance. An empty child .mcp.json does not shadow the parent. The only way to prevent parent MCP servers from loading is —strict-mcp-config or separate repositories.
Strict MCP Config
The --strict-mcp-config flag has two uses: fail-fast when a server fails to connect, and MCP isolation — ignoring all .mcp.json files in the directory tree.
# Isolation: only load servers from this specific configclaude -p "Run audit" \ --strict-mcp-config \ --mcp-config ./my-servers.jsonWhen used without --mcp-config, it strips all MCP servers entirely. When used with --mcp-config, it loads only the explicitly specified config. This is essential for subfolder sessions in monorepos that need to avoid inheriting parent MCP servers.
It also serves as a fail-fast mechanism in CI/CD:
This flag is essential in CI/CD pipelines and automated workflows where silent degradation is unacceptable. Without it, a broken server means Claude simply says “I don’t have that capability” instead of raising an error your pipeline can catch.
By default, broken MCP servers are silently skipped. Claude proceeds without those tools and gives no warning. You will only discover the problem when Claude says “I don’t have that capability” for a tool you expected to be available. Always use —strict-mcp-config in automated pipelines.
ToolSearch: Deferred Loading
When many MCP servers are active, their tool descriptions can consume a significant chunk of the context window. Claude automatically activates ToolSearch when MCP tool descriptions exceed approximately 10% of the context window. This is not configurable — it is automatic.
How deferred loading works:
- Tool names are listed in the init event, but full schemas are NOT loaded upfront
- Claude sees the names and knows the tools exist
- When Claude needs a specific tool, it calls
ToolSearchto fetch the full schema - Only then is the schema loaded into context
Without deferred loading, 80 MCP tools with detailed schemas could consume roughly 40K tokens of context. With ToolSearch, the overhead drops to approximately 2K tokens until a tool is actually needed. The trade-off is one extra round-trip per unique MCP tool used during the session.
You can see deferred tools in a session — they appear in the <available-deferred-tools> block, listed by name only with no parameters or descriptions:
{ "name": "mcp__chrome-devtools__take_screenshot", "deferred": true}When Claude needs the tool, it fetches the full schema first:
{ "type": "tool_use", "name": "ToolSearch", "input": { "query": "select:mcp__chrome-devtools__take_screenshot", "max_results": 1 }}MCP tool descriptions persist in context even when unused. With 20+ servers and detailed schemas, effective context can shrink from 200K to ~70K tokens. Monitor usage.input_tokens in response payloads to detect context bloat. ToolSearch mitigates this automatically when descriptions exceed ~10% of the window, but the only real fix is keeping active servers under 10 and total tools under 80.
Init Event: MCP Server Status
When using --output-format stream-json, the init event reports the connection status of every MCP server. Parse this in automation to verify all expected servers are healthy.
Each server shows "status": "connected" or "status": "error". In automation, check this init event to confirm all expected servers started successfully before proceeding:
claude -p "List tools" \ --output-format stream-json \ --verbose \ --mcp-config ./mcp.json | head -1 | jq '.mcp_servers'Debugging MCP Connections
When an MCP server fails to connect, work through these steps:
Test the server binary directly:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{}}}' \ | npx -y @anthropic-ai/mcp-server-filesystem /tmpIf this hangs or errors, the server itself is broken — the problem is not with Claude.
Common failure causes:
- Server binary not installed (
npxdownloads on first run — slow, may timeout) - Missing environment variables (check the
envobject in your config) - Port conflict for SSE/streamable-http servers
disabledMcpServersin~/.claude.jsonoverriding your config
MCP Tool Naming and Filtering
MCP tools follow a strict naming pattern: mcp__<server-name>__<tool-name>. This convention is important for tool filtering with --disallowedTools:
# Block a single MCP toolclaude -p "..." --disallowedTools "mcp__chrome-devtools__click"
# Block an entire MCP server's tools (glob pattern)claude -p "..." --disallowedTools "mcp__chrome-devtools__*"Performance Limits
MCP servers are powerful but have real costs. Keep these constraints in mind.
MCP Performance Constraints
| Constraint | Limit | Recommendation |
|---|---|---|
| Simultaneous servers | No hard cap | Keep under 10 enabled at once |
| Total active tools | No hard cap | Keep under 80 active tools |
| Output warning | 10K tokens | Warning when any MCP tool output exceeds this |
| Output hard cap | 25K tokens (default) | Override with MAX_MCP_OUTPUT_TOKENS env var |
| Context impact | ~200K effective | Too many tool descriptions can shrink effective context to ~70K |
To raise the output cap for data-heavy MCP tools:
MAX_MCP_OUTPUT_TOKENS=50000 claude -p "Fetch large dataset" --mcp-config ./mcp.jsonWhen MAX_MCP_OUTPUT_TOKENS is exceeded, the output is truncated silently — no warning appears in the final result. If MCP tool responses seem incomplete, check whether you are hitting this cap.