github / github/copilot-cli

[RFC] autoConnect: false — Deferred MCP Server Registration + On-Demand Lifecycle Init

Đang mở
#1,938 1 bình luận 6 reaction 0 người được giao Xem trên GitHub
area:mcp
Ngôn ngữ chính
Shell
Star
11.2k
Fork
1.9k
Merge trung bình
14 giờ 16 phút
Pull request đã merge (30 ngày)
6

Mô tả

## 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/

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.