stdio extensions fail to start on v1.50 when server supports protocol <= 2025-11-25
- Vorherrschende Sprache
- Rust
- Sterne
- 54.2k
- Forks
- 6.2k
- Ø Merge
- 3 T. 2 Std.
- Gemergte PRs (30 T.)
- 262
Beschreibung
**Describe the bug**
On v1.50.0, stdio MCP extensions whose servers support only protocol versions up to **2025-11-25** no longer initialize; the session reports `Failed to start extension ... (process quit before initialization ...)` and the extension is skipped. The same configuration works on v1.49.0. Reproduced with the Vestige MCP server (v3.0.0 and v2.x) — the server boots cleanly (logs show a normal `Starting MCP server on stdio...`), then goose tears it down before completing the handshake.
This looks like it was introduced by #11827 ("prefer latest MCP version"), which changed the `AgentConfig` default in `crates/goose/src/agents/agent.rs`:
```diff
- pub const MCP_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V_2025_11_25;
+ pub const MCP_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V_2026_07_28;
...
- mcp_protocol_version: Some(MCP_PROTOCOL_VERSION), // AgentConfig::default()/new()
+ mcp_protocol_version: None,
```
That value flows into `McpClient::connect_with_container` (`crates/goose/src/agents/mcp_client.rs`):
- `Some(2025-11-25)` (v1.49 default) → `ClientLifecycleMode::Initialize` → legacy `initialize` handshake → works with every 2025-11-25-era server.
- `None` (v1.50 default) → `ClientLifecycleMode::Auto { preferred: [2026-07-28], legacy: 2025-11-25 }` → probes `server/discover` (2026-07-28) first.
I probed Vestige MCP 3.0.0 directly with goose's exact `server/discover` message; it answers **per spec** with its supported versions:
```json
{"result":{"supportedVersions":["2024-11-05","2025-03-26","2025-06-18","2025-11-25"], ...}}
```
Since there is no overlap with the client's preferred `[2026-07-28]`, rmcp's `select_protocol_version` returns `ClientInitializeError::NoCompatibleProtocolVersion`, goose drops the child process, and the error is surfaced (wrapped) as "process quit before initialization". `Auto` mode only falls back to the legacy `initialize` handshake on a 10s discover timeout or a legacy JSON-RPC error — **not** on an empty version intersection with a discover-capable server — so a spec-compliant 2025-11-25 server is the worst case: it fails immediately instead of degrading.
I don't believe Vestige is at fault; it's implementing 2025-11-25-era discovery correctly. The gap is client-side.
---
**To Reproduce**
1. `goose` v1.50.0 (CLI) on Linux x86_64.
2. Enable any `stdio` extension whose server supports protocol ≤ 2025-11-25 (e.g. Vestige MCP `vestige-mcp@3.0.0`).
```yaml
extensions:
vestige:
enabled: true
type: stdio
name: vestige
cmd: vestige-mcp
args: [--data-dir, /path/to/vestige]
timeout: 60
```
3. Start a session. Immediate failure:
```
⚠ Failed to start extension 'vestige' (process quit before initialization: stderr = ...
```
4. Same config with v1.49.0: extension loads normally.
---
**Expected behavior**
A server that does not support the preferred 2026-07-28 protocol should still initialize through the legacy `initialize` handshake (or the default should preserve the v1.49 behavior for extensions). "Prefer latest" is a reasonable goal for modern servers; the regression is that the fallback path for older-but-spec-compliant servers now errors instead of negotiating down.
---
**Proposed fix directions (happy to help)**
1. Restore the v1.49 default: `AgentConfig::default()/new()` sets `mcp_protocol_version: Some(ProtocolVersion::V_2025_11_25)`, so all extensions use the legacy `Initialize` lifecycle as before.
2. Better: make `ClientLifecycleMode::Auto` fall back to the legacy `initialize` handshake when `server/discover` returns a modern response with no mutually-supported version (`NoCompatibleProtocolVersion`), rather than failing initialization. This keeps "prefer latest" for 2026-07-28 servers while degrading gracefully for 2025-11-25 servers — matching what `Auto` already does for timeout/legacy-error cases.
---
**Please provide the following information**
- **OS & Arch:** Linux x86_64
- **Interface:** CLI
- **Version:** v1.50.0 (works on v1.49.0)
- **Extensions enabled:** vestige (stdio)
- **Provider & Model:** openrouter / deepseek-v4-flash-0731
---
**Additional context**
- Bisected to #11827 by comparing the v1.49.0 → v1.50.0 shipped code in `agent.rs` / `mcp_client.rs`; `rmcp` 3.1.4 → 3.2.0 (same PR) has byte-identical client negotiation code, so it's not involved.
- The underlying error (`NoCompatibleProtocolVersion`) is hidden behind the "process quit before initialization" wrapper — the `ProcessExit` error only surfaces child stderr. Might be worth surfacing the underlying `ClientInitializeError` in the extension startup message for debuggability.
Thank you for maintaining goose!
Do not begin implementation until the issue reaches **Ready** on the [Goose Issues board](https://github.com/orgs/aaif-goose/projects/1).
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.