Skip to content

No MCP/plugin system — spec client to avoid upstream's SSE reconnect, stale-tool, and readiness bugs #4

Description

@grave0x

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:

  1. SSE error reconnect loopsfix(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).
  2. 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.
  3. 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.
  4. 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.list await 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:

  1. 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.
  2. 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.
  3. Readiness: plugin loader exposes a one-shot initial-readiness barrier; catalog.list_providers/list_models/get_provider await it and return 503 ServiceUnavailable if it exceeds a bounded period (e.g. 10s) — no partial snapshots as authoritative state.
  4. Compat: pin the MCP protocol version; add a test matrix covering at least one legacy-version client against the opencodeR MCP server.
  5. 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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions