12 KiB
11. MCP Deep Dive
The Model Context Protocol subsystem -- transports, tool wrapping, authentication, and server lifecycle.
What is MCP?
MCP (Model Context Protocol) is an open protocol for connecting AI models to external tools and data sources. Claude Code is both an MCP client (connecting to external MCP servers) and can act as an MCP server (exposing its own tools to other systems).
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#4a9eff', 'primaryBorderColor': '#4a9eff'}}}%%
graph TB
subgraph ClaudeCode["Claude Code"]
CLIENT["MCP Client<br/>Connects to external servers"]:::client
SERVER["MCP Server Mode<br/>Exposes tools to other systems"]:::server
TOOLS["42 Built-in Tools<br/>+ MCP tools merged in"]:::tools
end
subgraph External["External MCP Servers"]
STDIO_S["stdio servers<br/>Local processes"]:::external
SSE_S["SSE/HTTP servers<br/>Remote endpoints"]:::external
WS_S["WebSocket servers<br/>Persistent connections"]:::external
CLAUDE_AI["claude.ai proxy<br/>Managed connectors"]:::external
IDE_S["IDE servers<br/>Editor integration"]:::external
end
CLIENT --> STDIO_S
CLIENT --> SSE_S
CLIENT --> WS_S
CLIENT --> CLAUDE_AI
CLIENT --> IDE_S
STDIO_S --> TOOLS
SSE_S --> TOOLS
WS_S --> TOOLS
CLAUDE_AI --> TOOLS
IDE_S --> TOOLS
classDef client fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px
classDef server fill:#2d1b4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px
classDef tools fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
classDef external fill:#333,stroke:#888,color:#aaa,stroke-width:1px,stroke-dasharray: 5 5
Transport Types
Claude Code supports 6 transport types for connecting to MCP servers:
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#17a2b8', 'primaryBorderColor': '#17a2b8'}}}%%
flowchart TD
subgraph Local["Local Transports"]
STDIO["stdio<br/>Spawn local process<br/>Communicate via stdin/stdout<br/>Most common type"]:::local
SDK_T["sdk<br/>In-process transport<br/>SDK-managed placeholder<br/>Tool calls route to SDK"]:::local
end
subgraph Remote["Remote Transports"]
SSE["sse<br/>Server-Sent Events<br/>Legacy remote protocol<br/>OAuth authentication"]:::remote
HTTP["http<br/>Streamable HTTP<br/>Modern remote protocol<br/>Per-request timeouts"]:::remote
WS["ws<br/>WebSocket<br/>Persistent bidirectional<br/>TLS/proxy support"]:::remote
CLAUDEAI["claudeai-proxy<br/>Via claude.ai OAuth<br/>Managed connectors<br/>Auto token refresh"]:::remote
end
subgraph IDE["IDE Transports"]
SSE_IDE["sse-ide<br/>IDE SSE connection<br/>No authentication"]:::ide
WS_IDE["ws-ide<br/>IDE WebSocket<br/>Auth token in header"]:::ide
end
classDef local fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
classDef remote fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px
classDef ide fill:#0d4f4f,stroke:#17a2b8,color:#e0e0e0,stroke-width:2px
Connection Lifecycle
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#28a745', 'actorTextColor': '#e0e0e0', 'actorBorder': '#28a745', 'signalColor': '#28a745', 'noteBkgColor': '#16213e', 'noteTextColor': '#e0e0e0', 'activationBkgColor': '#1b3a1b', 'activationBorderColor': '#28a745'}}}%%
sequenceDiagram
participant H as useManageMCPConnections
participant C as connectToServer (memoized)
participant T as Transport Layer
participant S as External Server
H->>H: getAllMcpConfigs - merge all sources
H->>H: Batch servers (local=3, remote=20)
loop For each server
H->>C: connectToServer(name, config)
activate C
alt Auth cached as needed
C-->>H: return needs-auth
else Server disabled
C-->>H: return disabled
else Policy blocked
C-->>H: return not allowed
end
C->>T: Create transport (stdio/sse/http/ws)
T->>S: Connect
activate S
alt auth required (401/403)
S-->>C: Auth error
C-->>H: return needs-auth
else connection timeout
S-->>C: Timeout (30s default)
C-->>H: return error
else success
S-->>T: Connected
deactivate S
C->>S: tools/list
S-->>C: Available tools
C->>C: Wrap as MCPTool objects
C-->>H: return connected + tools
end
deactivate C
end
H->>H: Update AppState.mcp
Batched Connections
Servers are connected in parallel batches to avoid overwhelming the system:
- Local (stdio) servers: batch size of 3 (spawning processes is heavy)
- Remote servers: batch size of 20 (network connections are lighter)
The batch sizes are configurable via MCP_SERVER_CONNECTION_BATCH_SIZE and MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE environment variables.
Tool Wrapping
Each MCP tool is wrapped in a MCPTool object that implements the standard Tool interface:
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#ffc107', 'primaryBorderColor': '#ffc107'}}}%%
flowchart LR
MCP_TOOL["MCP Server Tool<br/>name, inputSchema,<br/>description"]:::raw
WRAP["MCPTool wrapper<br/>Implements Tool interface<br/>name: mcp__server__tool"]:::wrap
subgraph Lifecycle["Tool Call Lifecycle"]
VALIDATE["Validate input<br/>via JSON Schema"]:::step
PERM["Check permissions<br/>Same system as built-in"]:::step
CALL["Forward to MCP server<br/>tools/call RPC"]:::step
RESULT["Process result<br/>Truncate if needed<br/>Handle images"]:::step
end
MCP_TOOL --> WRAP --> VALIDATE --> PERM --> CALL --> RESULT
classDef raw fill:#333,stroke:#888,color:#e0e0e0,stroke-width:1px
classDef wrap fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px
classDef step fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
Naming Convention
MCP tools are named mcp__<server>__<tool>:
mcp__slack__send_messagemcp__github__create_issuemcp__ide__getDiagnostics
The double-underscore separators prevent ambiguity. In SDK no-prefix mode, tools keep their original names.
Description Capping
MCP tool descriptions are capped at 2,048 characters. OpenAPI-generated servers have been observed dumping 15-60KB of endpoint docs into descriptions, which wastes context tokens.
Configuration Sources
MCP server definitions come from multiple sources, merged with priority rules:
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#dc3545', 'primaryBorderColor': '#dc3545'}}}%%
flowchart TD
subgraph Sources["MCP Config Sources"]
ENT["Enterprise managed-mcp.json<br/>Exclusive control if present"]:::ent
GLOBAL["Global ~/.claude/settings.json<br/>mcpServers field"]:::user
LOCAL[".claude/settings.local.json<br/>Local project overrides"]:::local
PROJECT[".mcp.json at project root<br/>Committed to repo"]:::proj
PLUGIN["Plugin MCP servers<br/>From installed plugins"]:::plugin
CLAUDEAI["claude.ai connectors<br/>Fetched at startup"]:::claudeai
CLI["--mcp-config flag<br/>Runtime override"]:::cli
SDK_CFG["SDK mcp_set_servers<br/>Programmatic control"]:::sdk
end
MERGE["getAllMcpConfigs<br/>Merge + dedup + policy filter"]:::merge
POLICY{"Enterprise policy<br/>allowedMcpServers?<br/>deniedMcpServers?"}:::check
ALLOWED["Allowed servers<br/>proceed to connect"]:::allow
BLOCKED["Blocked servers<br/>silently dropped"]:::deny
Sources --> MERGE --> POLICY
POLICY -->|"allowed"| ALLOWED
POLICY -->|"denied"| BLOCKED
classDef ent fill:#4a1a1a,stroke:#dc3545,color:#e0e0e0,stroke-width:2px
classDef user fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px
classDef local fill:#3d2b00,stroke:#fd7e14,color:#e0e0e0,stroke-width:2px
classDef proj fill:#0d4f4f,stroke:#17a2b8,color:#e0e0e0,stroke-width:2px
classDef plugin fill:#2d1b4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px
classDef claudeai fill:#1a1a4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px
classDef cli fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px
classDef sdk fill:#333,stroke:#888,color:#e0e0e0,stroke-width:1px
classDef merge fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
classDef check fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px
classDef allow fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
classDef deny fill:#4a1a1a,stroke:#dc3545,color:#e0e0e0,stroke-width:2px
Deduplication
Plugin and claude.ai connector servers are deduplicated against manually-configured servers:
- Signature-based: Same
command+args(stdio) or sameurl(remote) = same server - Manual wins: If a user manually configured a server, the plugin/connector duplicate is suppressed
- First-loaded wins: Between plugins, the first one loaded takes priority
Authentication
Remote MCP servers may require OAuth authentication:
%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#dc3545', 'primaryBorderColor': '#dc3545'}}}%%
flowchart TD
CONNECT["Connect to remote server"]:::start
AUTH{"Auth required?"}:::check
PROVIDER["ClaudeAuthProvider<br/>OAuth flow per server"]:::auth
TOKENS["Retrieve/refresh tokens"]:::auth
OK["Connection established"]:::success
NEEDS["Status: needs-auth<br/>Cached for 15 min"]:::needsauth
CALL["MCP tool call"]:::start
CALL_AUTH{"401 on call?"}:::check
RETRY["Refresh token<br/>retry once"]:::auth
MCE["McpAuthError<br/>Update status to needs-auth"]:::error
CONNECT --> AUTH
AUTH -->|"no"| OK
AUTH -->|"yes"| PROVIDER --> TOKENS
TOKENS -->|"success"| OK
TOKENS -->|"failure"| NEEDS
CALL --> CALL_AUTH
CALL_AUTH -->|"no"| OK
CALL_AUTH -->|"yes"| RETRY
RETRY -->|"success"| OK
RETRY -->|"failure"| MCE
classDef start fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px
classDef check fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px
classDef auth fill:#2d1b4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px
classDef success fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px
classDef needsauth fill:#3d2b00,stroke:#fd7e14,color:#e0e0e0,stroke-width:2px
classDef error fill:#4a1a1a,stroke:#dc3545,color:#e0e0e0,stroke-width:2px
Session Expiry Handling
MCP servers return HTTP 404 + JSON-RPC error code -32001 when a session expires. Claude Code detects this, clears the connection cache, and reconnects automatically (McpSessionExpiredError).
Key Files
src/services/mcp/client.ts(3,349 lines) -- Connection manager, tool wrapping, transport creationsrc/services/mcp/config.ts(1,579 lines) -- Config merging, policy filtering, deduplicationsrc/services/mcp/types.ts-- Type definitions for server configs and connectionssrc/services/mcp/auth.ts-- OAuth provider and step-up authenticationsrc/services/mcp/useManageMCPConnections.ts-- React hook managing connection lifecyclesrc/tools/MCPTool/MCPTool.ts-- MCPTool wrapper implementing the Tool interface
Previous: <- Configuration | Next: Data Flow Walkthrough ->