Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
crates/plugin/src/lib.rs is a 1-line stub ("Plugin system — MCP, ACP integrations") — opencodeR has no MCP client/server implementation at all. Upstream just shipped four MCP/plugin fixes that should be baked into opencodeR's design from day one, not rediscovered later:
- SSE error reconnect loops — fix(opencode): stop MCP SSE error reconnect loops anomalyco/opencode#39697 (ports Fix: Handle error responses in Streamable HTTP SSE streams modelcontextprotocol/typescript-sdk#1390): JSON-RPC error responses over MCP Streamable HTTP SSE must be treated as completed requests; the transport must not resume an already-completed error stream (infinite reconnect loop).
- Legacy SDK compatibility breakage — #39373: a transport change silently broke older MCP SDK clients; opencodeR's own SDK must be pinned/tested against a compat matrix.
- Stale tool cache after server restart — #40062 (closes #40015): a restarted MCP server leaves the StreamableHTTP connection dead without firing
onclose, so the cached tool set goes stale and the agent calls a dead server until process restart. Fix: reconnect hook triggered when a tool call fails, refreshing cached tool definitions. - Cold-start catalog partial snapshots — #40070 (closes #36117): catalog reads returned success with a partial snapshot while catalog-producing plugins were still activating. Fix: one-shot initial-readiness barrier;
provider.list/model.listawait it and return 503 if readiness exceeds a bound (10s).
Impact
- No MCP support is a hard blocker for parity with upstream (all plugin-based tools, model catalogs, integrations).
- If implemented naively, all four upstream bugs get re-introduced in Rust.
Spec / Acceptance criteria
Design the MCP client (and minimal server) with:
- Transport: Streamable HTTP + SSE support (or start with stdio). On a JSON-RPC error response over SSE, treat the request as completed — never resume/retry the stream.
- Reconnect: when a tool call fails and the connection is dead, re-establish the session through the normal connect path and refresh cached tool definitions before retrying.
- Readiness: plugin loader exposes a one-shot initial-readiness barrier;
catalog.list_providers/list_models/get_providerawait it and return503 ServiceUnavailableif it exceeds a bounded period (e.g. 10s) — no partial snapshots as authoritative state. - Compat: pin the MCP protocol version; add a test matrix covering at least one legacy-version client against the opencodeR MCP server.
- Cache invalidation: tool definitions must be refreshed on reconnect; document staleness semantics for long-lived sessions.
Reference: upstream anomalyco/opencode#39697, #39373, #40062 (closes #40015), #40070 (closes #36117); our code: crates/plugin/src/lib.rs (stub), crates/core/src/lib.rs:34-38 (CatalogService).
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
feat(plugin): MCP client + plugin system (issue #4, iteration 1)
grave0x commentedon Aug 1, 2026
Iteration 1 landed in ddfaf81: stdio MCP client (pinned protocol version, legacy-version tolerance), reconnect-on-I/O-failure with tool-cache refresh + single retry, JSON-RPC errors as completed requests (no loops), and a background-loading PluginSystem behind a readiness barrier with bounded timeout. 13 new tests incl. subprocess e2e; clippy clean. Deferred: streamable HTTP/SSE transport, AppState wiring, hot-reload.
docs(roadmap): mark completed features green