github / github/copilot-cli

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

Ouverte
#1,938 1 commentaire 6 réactions 0 personnes assignées Voir sur GitHub
area:mcp
Langage dominant
Shell
Étoiles
11.2k
Forks
1.9k
Merge moyen
14 h 16 min
PR mergées (30 j)
6

Description

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

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.