Feature Request: Non-Blocking Session Creation for ACP/SDK Clients
Problem Statement
When using Claude Code via ACP clients (Zed, Neovim, custom TUIs) or the Claude Agent SDK, users cannot interact with Claude until ALL MCP servers finish initializing - which can take 20-35 seconds. This creates a terrible user experience where the client appears frozen.
How This Differs from Existing Issues
| Issue | Focus | This Issue |
|-------|-------|------------|
| #7336 | Reduce context tokens consumed by MCP tools | Reduce startup latency for ACP/SDK clients |
| #6638 | Dynamic /mcp enable/disable during session | Non-blocking session creation |
This issue is specifically about ACP and SDK use cases where:
- External clients spawn Claude Code as a subprocess
session/new(ACP) orquery()(SDK) blocks for 20-35 seconds- Users cannot type or interact until all MCP servers connect
The Core Issue
The Claude Agent SDK's query() function and ACP's session/new method block until every MCP server is connected. Users stare at a loading screen when they could already be:
- Typing their prompt
- Reading Claude's greeting
- Having a conversation (without tools)
- Seeing tools become available progressively
Real-World Impact
I built a TUI client using claude-code-acp and measured the initialization timing:
| Step | Time |
|------|------|
| spawn() process | 1.4ms |
| initialize() ACP handshake | 90ms |
| new_session() - blocked on MCP | 32.6 seconds |
| Total | 32.7 seconds |
Testing each MCP server individually:
| MCP Server | Initialization Time |
|------------|---------------------|
| sequential-thinking | 1.2s |
| memory | 1.3s |
| fetch (uvx) | 1.6s |
| context7 (HTTP) | 2.3s |
| toolbox (smithery) | 2.3s |
| iMCP (Bonjour discovery) | 31.1s |
One slow server (iMCP doing Bonjour discovery) blocks the entire session for 31 seconds.
Proposed Solution: Async MCP Initialization
Primary Goal: Immediate Session Availability
session/new should return immediately with:
- A valid session ID
- Basic conversation capability (Claude can respond)
- MCP servers marked as "pending"
Tools become available progressively as servers connect.
Implementation Approach
1. Non-Blocking Session Creation
Client ACP Agent Claude Code
│ │ │
│─── session/new ──────────>│ │
│ │──── start session ─────>│
│<── session ready ─────────│ (MCP init in background)
│ │ │
│─── prompt "hello" ───────>│ │
│<── response ──────────────│ (works without tools) │
│ │ │
│<── mcp_server_ready ──────│<── server1 connected ───│
│<── mcp_server_ready ──────│<── server2 connected ───│
│ │ │
│─── prompt "read file" ───>│ │
│<── uses Read tool ────────│ (tools now available) │
2. New ACP Notifications for MCP Status
Add notifications to inform clients about MCP server status:
// New notification types
interface McpServerStatusNotification {
sessionUpdate: "mcp_server_status";
serverName: string;
status: "connecting" | "connected" | "failed" | "timeout";
tools?: string[]; // Available tools when connected
error?: string; // Error message if failed
}
interface McpServersReadyNotification {
sessionUpdate: "mcp_servers_ready";
connectedServers: string[];
failedServers: { name: string; error: string }[];
}
3. Updated Session Response
The session/new response should indicate MCP status:
interface NewSessionResponse {
sessionId: string;
models: SessionModelState;
modes: SessionModeState;
// New fields:
mcpStatus: {
pending: string[]; // Servers still connecting
connected: string[]; // Servers ready
failed: string[]; // Servers that failed
};
availableTools: string[]; // Tools available RIGHT NOW
}
4. Graceful Tool Handling
When a user requests a tool that isn't ready yet:
// Option A: Inform and wait
{
type: "tool_call",
status: "waiting",
message: "Waiting for 'memory' server to connect...",
estimatedWait: 5000
}
// Option B: Offer alternatives
{
type: "tool_call",
status: "unavailable",
message: "The 'memory' server is still connecting. Would you like to wait or proceed without it?"
}
Additional Improvements
Parallel MCP Initialization
Even with async init, servers should connect in parallel:
Current (serial):
Server1 (1s) → Server2 (1s) → Server3 (30s) → All ready
Total: 32s
Proposed (parallel):
Server1 (1s) ─┐
Server2 (1s) ─┼─→ All ready
Server3 (30s)─┘
Total: 30s (but session usable at 0s!)
Per-Server Configuration
{
"mcpServers": {
"critical-server": {
"command": "fast-mcp",
"blocking": true // Wait for this before session/new returns
},
"slow-server": {
"command": "slow-mcp",
"blocking": false, // Initialize in background (default)
"timeout": 10000, // Give up after 10s
"optional": true // Session continues if this fails
}
}
}
User Experience Vision
Before (Current)
User opens Claude Code panel
│
├── "Connecting..." (0s)
│ ↓
│ [blocked - cannot type]
│ ↓
│ [still blocked - 10s]
│ ↓
│ [still blocked - 20s]
│ ↓
│ [still blocked - 30s]
│ ↓
└── "Ready!" (32s) ← Finally can interact
After (Proposed)
User opens Claude Code panel
│
├── "Ready!" (0.1s) ← Can immediately type!
│ ↓
│ User: "Hi Claude, what can you help me with?"
│ Claude: "I can help with coding, writing..."
│ ↓
│ [Status: 3/6 tools loading...]
│ ↓
│ [Status: 5/6 tools loading...]
│ ↓
│ [Status: All tools ready! ✓] (32s, but user didn't wait)
│ ↓
└── User: "Read the main.rs file"
Claude: [uses Read tool]
Use Cases
ACP Clients (Zed, Neovim, Custom TUIs)
ACP clients like Zed spawn claude-code-acp which spawns Claude Code for each session. The 30+ second delay makes the experience painful.
SDK Users
Applications using the Claude Code SDK (@anthropic-ai/claude-agent-sdk) face the same issue when calling query() - each call spawns a new process and waits for full MCP initialization.
Plugin Development
Plugin developers testing their MCP servers alongside other servers get blocked by unrelated slow servers.
Related Issues
- #7336 - Lazy Loading for MCP Servers (context tokens, not startup latency)
- #6638 - Dynamic loading/unloading (during session, not at creation)
- #3044 - SDK mode warmup time on slower devices (related)
- #8164 - Claude CLI is slow to start (related)
- #424 - MCP Timeout needs to be configurable (related)
Note: This issue complements #7336 and #6638 but addresses a different problem - the blocking nature of session creation for ACP/SDK clients, not context token usage or mid-session management.
Environment
- Claude Code version: 1.0.x
- Platform: macOS (also affects Linux)
- Using: claude-code-acp v0.12.0
Workaround
Currently, the only workaround is to disable slow MCP servers:
// In settings.json
{
"enabledPlugins": {
"archive@personal": false // Contains slow iMCP server
}
}
Or remove slow servers from .mcp.json entirely.
This is not ideal because:
- Users lose access to useful MCP tools
- No granular control (entire plugins must be disabled)
- No way to set acceptable timeouts
Implementation Considerations
Where Changes Are Needed
| Component | Change Required |
|-----------|-----------------|
| Claude Code (anthropics/claude-code) | Core async MCP init logic |
| Claude Agent SDK | Expose MCP status events in stream |
| claude-code-acp (zed-industries) | Forward MCP status to ACP clients |
| ACP Protocol | New notification types for MCP status |
Backward Compatibility
- Clients that don't understand new notifications simply ignore them
- Default behavior can remain blocking for compatibility
- New
asyncMcpInit: trueoption to opt-in
SDK Changes Required
The Claude Agent SDK needs to:
- Emit
mcp_server_statusevents during initialization - Not block
query()on MCP initialization - Allow tools to be used as soon as their server connects
// Current SDK behavior
const q = query({ prompt, options });
// ↑ Blocks here for 30+ seconds until ALL MCP servers ready
// Proposed SDK behavior
const q = query({ prompt, options: { ...options, asyncMcpInit: true } });
// ↑ Returns immediately, MCP servers connect in background
for await (const message of q) {
if (message.type === 'system' && message.subtype === 'mcp_status') {
console.log(`MCP ${message.server}: ${message.status}`);
}
}
Summary
| Feature | Impact | Effort | Priority |
|---------|--------|--------|----------|
| Async MCP init (non-blocking session) | Critical - instant UX | Medium | P0 |
| Parallel MCP init | High - reduces total time | Medium | P1 |
| MCP status notifications | High - progressive loading UX | Low | P1 |
| Per-server timeout/optional | High - resilience | Medium | P2 |
| Per-server blocking config | Medium - fine control | Low | P3 |
The primary ask is: Don't block session/new on MCP initialization. Let users interact with Claude immediately while tools load in the background.
This would transform the ACP experience from "30 second loading screen" to "instant interaction with progressive tool availability."
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗