[RFC] autoConnect: false — Deferred MCP Server Registration + On-Demand Lifecycle Init
- 主要语言
- Shell
- 星标
- 11.2k
- 派生
- 1.9k
- 平均合并
- 14 小时 16 分钟
- 30 天内合并 PR
- 6
描述
## Summary
Spec-level RFC proposing `autoConnect: false` for `mcp-config.json` / `.mcp.json` to enable true lazy/deferred server registration — resolving context window token exhaustion, `400 Bad Request` errors under Sonnet 4.6, and the inability to hot-reload `.mcp.json` in active sessions.
**Consolidates upstream issues:** anthropics/claude-code#6638, #11364, #11370, #14879, #16826, #18497
---
## Problem Statement
MCP server lifecycle has one mode: **eager connect at session init**. All configured servers run `initialize → tools/list` before the first prompt regardless of need. Three bugs compound this:
1. **`/mcp disable` does not evict schemas** — tools hidden from selector but schemas remain serialized in context. Token cost paid regardless. *(anthropics/claude-code#11370)*
2. **`/mcp add` permanently mutates `mcp-config.json`** — no session-scoped lazy injection without global config mutation. *(anthropics/claude-code#6638)*
3. **`.mcp.json` disk changes invisible to active session** — no reload, sync, or watch mechanism. *(anthropics/claude-code#6638, #14879)*
**Measured impact:** 10-server unoptimized setup = ~75,000 tokens consumed at session start before any user prompt. Directly causes `400 Bad Request` at Sonnet 4.6 serialization ceiling.
---
## Proposed Config Schema
Add `autoConnect` (boolean, default `true`) to the server entry spec in `mcp-config.json` / `.mcp.json`:
```json
{
"mcpServers": {
"playwright": {
"type": "local",
"command": "npx",
"args": ["@playwright/mcp@latest"],
"tools": ["browser_navigate", "browser_screenshot"],
"autoConnect": false
},
"linear": {
"type": "http",
"url": "https://mcp.linear.app/sse",
"tools": ["create_issue", "list_issues", "update_issue"],
"autoConnect": false
},
"github": {
"type": "local",
"command": "gh",
"args": ["mcp", "serve"],
"autoConnect": true
}
}
}
```
- `autoConnect: true` (default) — current behavior, zero regression
- `autoConnect: false` — registered but dormant: no process spawn, no stdio pipe, no handshake, zero schema tokens until explicitly activated
---
## Lifecycle State Machine
```
┌─────────────────────────────────────────────────────────┐
│ REGISTERED (dormant) │
│ autoConnect: false at config parse │
│ No process. No pipe. No tokens. │
└────────────────────────┬────────────────────────────────┘
│ /mcp enable OR first tool-call trigger
▼
┌─────────────────────────────────────────────────────────┐
│ CONNECTING │
│ Full initialize handshake per MCP spec 2025-11-25 │
│ Identical path to /mcp add mid-session │
└────────────────────────┬────────────────────────────────┘
│ initialized + tools/list complete
▼
┌─────────────────────────────────────────────────────────┐
│ ACTIVE │
│ Schemas injected at next turn boundary only │
└────────────────────────┬────────────────────────────────┘
│ /mcp disable
▼
┌─────────────────────────────────────────────────────────┐
│ SUSPENDED │
│ Process kept alive (fast re-enable) │
│ Schemas EVICTED from context at next turn ← NEW │
└────────────────────────┬────────────────────────────────┘
│ /mcp enable
▼
ACTIVE (re-announce tools at next turn)
```
---
## Required Behavior Changes
| # | Change | Upstream Ref |
|---|---|---|
| 1 | `/mcp disable` MUST evict schemas at next turn boundary — not just hide from selector | anthropics/claude-code#11370 |
| 2 | `autoConnect: false` MUST NOT spawn process, pipe, or handshake at session init | anthropics/claude-code#18497 |
| 3 | `/mcp enable` on dormant server MUST execute full `initialize` handshake (already works for `/mcp add` — formalize as documented contract) | anthropics/claude-code#6638 |
| 4 | New `/mcp sync` command — re-parses `.mcp.json` from `cwd` in-session, registers/deregisters without session restart | anthropics/claude-code#6638, #14879 |
---
## MCP Protocol Spec Extension
For `modelcontextprotocol/specification` RFC — add to `initialize` handshake:
```typescript
// ClientCapabilities
lazyRegistration?: {
supported: boolean; // client can handle deferred tool injection
};
// ServerCapabilities (InitializeResult)
supportsLazyRegistration?: boolean; // server can defer tools/list until client requests
```
Enables bidirectional lazy-connect signaling at protocol layer.
---
## Token Budget Impact
| Configuration | Schema Tokens at Session Start |
|---|---|
| Eager wildcard `*` (current default) | ~75,000 |
| `autoConnect: false` (this RFC) | **0** until `/mcp enable` |
| `autoConnect: true` + `defer loading: true` | ~1,100/server (BM25 meta-tools, v2.1.9+) |
| Dormant + defer loading on activation | **0 → ~1,100 strictly on demand** |
---
## Current Workaround (Windows 11 / Copilot CLI)
```powershell
# Launch: register all, connect none
copilot `
--disable-mcp-server playwright `
--disable-mcp-server linear `
--disable-builtin-mcps
# Mid-session — activate on demand:
/mcp enable linear # Full initialize handshake fires NOW
# Schemas available at NEXT prompt turn
/mcp disable linear # Suspend, evict schemas next turn
/mcp enable playwright
```
Structurally equivalent to `autoConnect: false` using existing primitives. This RFC formalizes it as a first-class config flag and closes the schema-eviction gap in `/mcp disable`.
---
## `/mcp sync` Command Spec
```
/mcp sync [--file PATH]
```
- Re-reads `.mcp.json` from `cwd` (or `--file`) and `~/.copilot/mcp-config.json`
- **New entries:** register per their `autoConnect` value
- **Removed entries:** kill process, deregister, evict schemas
- **Modified entries:** full disconnect + reconnect
- **No session restart required**
- Read-only from CLI perspective — writes nothing to disk
---
## Handshake Path Comparison
| Property | Session Init | `/mcp enable` (post-RFC) |
|---|---|---|
| Trigger | CLI launch | In-session command or first tool call |
| Phase 4 harvest | Eager, ALL servers, blocking | Single server, on-demand |
| Context impact | Immediate, all schemas | Next turn boundary only |
| Config write | Read-only | Read-only (no mutation) |
---
## References
- MCP Lifecycle Spec 2025-11-25: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
- anthropics/claude-code upstream issues: #6638, #11364, #11370, #14879, #16826, #18497
- FastMCP 3.1 Middleware: https://gofastmcp.com/servers/middleware
- tool-gating-mcp: https://github.com/ajbmachon/tool-gating-mcp
- MCP Tool Search (v2.1.9, Jan 2026): partial solution — defers schema injection, not connection
- Copilot CLI GA: https://github.blog/changelog/2026-02-25-github-copilot-cli-is-now-generally-available/
贡献指南
调研方向
首先检查 mcp-config.json 和 .mcp.json 的 server-entry 格式,以及现有的 /mcp add、enable 和 disable 生命周期路径。然后评估延迟注册、schema eviction 和 /mcp sync 如何配合,包括所引用的 MCP initialize 握手。完成的标准是:提议的 config flag 和生命周期行为已得到一致定义,且不需要重启 session。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- github, json, shell
- 领域
- cli, tooling
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 冷清
- 描述清晰度
- 需要澄清
- 新手友好度
- 25/100