MCP Client
- Entity ID:
ent-20260410-f669a2041e88 - Type:
service - Scope:
shared - Status:
active - Aliases: MCP transport, MCP connection, connectToServer
Description
The MCP client (src/services/mcp/client.ts) manages connections to MCP servers, handles 8 transport types, converts MCP tools into Claude Code's native Tool format, and provides error recovery with session retry and reconnection. It is the core runtime component of the mcp-subsystem.
Transport types
connectToServer() creates the appropriate transport based on serverRef.type:
| Transport | Type key | SDK class | Auth | Use case |
|---|---|---|---|---|
| stdio | stdio |
StdioClientTransport |
none | Local process servers |
| SSE | sse |
SSEClientTransport |
OAuth via ClaudeAuthProvider |
Remote HTTP/SSE servers |
| SSE-IDE | sse-ide |
SSEClientTransport |
none | IDE extension proxy |
| WebSocket | ws |
WebSocketTransport |
headers, TLS | Remote WebSocket servers |
| WS-IDE | ws-ide |
WebSocketTransport |
authToken header | IDE WebSocket proxy |
| HTTP Streamable | http |
StreamableHTTPClientTransport |
OAuth, session ingress JWT | Modern HTTP servers |
| SDK | sdk |
SdkControlTransport |
in-process | Agent SDK in-process |
| Claude.ai Proxy | claudeai-proxy |
StreamableHTTPClientTransport |
Bearer token, auto-retry 401 | Claude.ai hosted connectors |
Platform-specific behavior
- Bun vs Node: WebSocket creation differs — Bun has native WebSocket with options, Node uses the
wspackage - SSE timeout: EventSource connections have NO timeout (long-lived), but regular requests get a timeout wrapper
- Claude.ai proxy: Uses
createClaudeAiProxyFetch()wrapper that adds OAuth bearer token and automatically retries on 401
Tool conversion
fetchToolsForClient() converts MCP protocol tools to Claude Code Tool objects:
- Requests
tools/listvia MCP protocol - Sanitizes Unicode in tool data
- For each tool, spreads the
MCPTooltemplate and overrides: name— prefixedmcp__<server>__<tool>(unlessCLAUDE_AGENT_SDK_MCP_NO_PREFIX)call— wraps MCP tool invocation with retry logicdescription— capped at 2,048 chars (MAX_MCP_DESCRIPTION_LENGTH)isConcurrencySafe— derived from MCPreadOnlyHintisDestructive— derived from MCPdestructiveHintisOpenWorld— derived from MCPopenWorldHint- Results are LRU-cached (
MCP_FETCH_CACHE_SIZE = 20)
Tool call execution
When an MCP tool is called:
1. ensureConnectedClient() verifies or re-establishes the connection
2. callMCPToolWithUrlElicitationRetry() executes with signal, metadata, and progress callback
3. On McpSessionExpiredError (HTTP 404, JSON-RPC code -32001), retries once (MAX_SESSION_RETRIES = 1)
4. Default timeout is extremely long: DEFAULT_MCP_TOOL_TIMEOUT_MS = 100_000_000 (~27.8 hours)
Error handling
| Error type | Trigger | Recovery |
|---|---|---|
McpAuthError |
Auth failure during tool call | Server transitions to needs-auth state |
McpSessionExpiredError |
HTTP 404 + JSON-RPC -32001 |
Automatic reconnect + retry (1 attempt) |
McpToolCallError |
MCP tool returns isError: true |
Surfaced to agent as tool error |
| Connection lost | Transport disconnect | Exponential backoff reconnect (5 attempts, 1s-30s) |
Auth caching
MCP_AUTH_CACHE_TTL_MS = 15 * 60 * 1000 (15 minutes) — servers that recently returned 401 skip re-probing for this duration, avoiding repeated auth failures.
Trade-offs
- 8 transport types — comprehensive coverage but significant code surface area. Each transport has different auth, error, and timeout behaviors.
- Very long default timeout (~27.8 hours) — prevents premature timeout on slow tools but means truly broken connections take a long time to fail. Individual tools should set shorter timeouts.
- LRU tool cache — avoids re-fetching tool lists on every call but means tool list changes on the server aren't immediately visible. Cache size of 20 is tuned for typical MCP usage.
- Single session retry — recovers from transient session loss without infinite loops. More retries might recover more cases but risk masking server bugs.
Depends on
- mcp-auth — OAuth provider for SSE, HTTP, and claude.ai proxy transports
- mcp-subsystem — parent system, provides server config and connection management
Key claims
- Default MCP tool timeout is ~27.8 hours, designed for long-running tools
- Auth probe results are cached for 15 minutes to avoid repeated failures
- Tool conversion uses MCP hints (readOnlyHint, destructiveHint) to set concurrency and safety flags
- Session retry is limited to 1 attempt per tool call
Relations
part_ofmcp-subsystemdepends_onmcp-authusestool-system (via MCPTool template)
Sources
src-20260409-a5fc157bc756, source code analysis of src/services/mcp/client.ts