aaif-goose / aaif-goose/goose

stdio extensions fail to start on v1.50 when server supports protocol <= 2025-11-25

Đã đóng
#12,040 0 bình luận 0 reaction 1 người được giao Được @DOsinga nhận Xem trên GitHub
Ngôn ngữ chính
Rust
Star
54.2k
Fork
6.2k
Merge trung bình
3 ngày 4 giờ
Pull request đã merge (30 ngày)
240

Mô tả

**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).

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

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

Hướng nghiên cứu

The issue is in crates/goose/src/agents/agent.rs and crates/goose/src/agents/mcp_client.rs. Start by examining the AgentConfig default and the MCP_PROTOCOL_VERSION constant change from PR #11827. Then look at McpClient::connect_with_container and the ClientLifecycleMode::Auto logic in rmcp. The fix involves adjusting the fallback behavior when server/discover returns no compatible version. Test with a stdio extension like vestige-mcp that only supports protocol ≤ 2025-11-25. Done when the extension initializes successfully on v1.50.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Lĩnh vực
backend, cli
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
65/100

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.