Skip to content

fix(opencode): auto-reconnect MCP clients on unexpected transport close - #31312

Closed
sulthonzh wants to merge 2 commits into
anomalyco:devfrom
sulthonzh:fix/mcp-onclose-reconnect
Closed

sulthonzh wants to merge 2 commits into
anomalyco:devfrom
sulthonzh:fix/mcp-onclose-reconnect

Conversation

@sulthonzh

@sulthonzh sulthonzh commented Jun 8, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #17099

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

When an MCP server process dies or the HTTP transport drops, the client stays in connected state with stale tool definitions. Tools vanish permanently for the session because nothing listens for transport closure.

The watch() function only subscribes to ToolListChangedNotification. It never registers an onclose handler on the client, so when the SDK fires client.onclose after transport death, nothing handles it.

This PR registers client.onclose in watch() that:

  1. Checks s.clients[name] !== client to skip intentional disconnects
  2. Marks status as failed and clears cached defs
  3. Calls createAndStore() with the original config to reconnect
  4. Publishes ToolsChanged so the UI updates

To prevent intentional disconnects from triggering reconnect, closeClient() now deletes s.clients[name] before calling client.close(). The finalizer also snapshots and clears s.clients before closing clients during instance disposal.

How did you verify your code works?

  • 2 new tests in packages/opencode/test/mcp/lifecycle.test.ts:
    • onclose triggers automatic reconnect when transport closes unexpectedly — simulates transport close by calling client.onclose(), verifies the server reconnects and tools update from the new client
    • onclose does not trigger reconnect on intentional disconnect() — calls mcp.disconnect(), verifies status stays disabled with no reconnect
  • All 26 tests pass (24 existing + 2 new)
  • Full typecheck across 23 packages passes (pre-push hook runs bun turbo typecheck)
  • Manual verification steps:
    1. Configure a local MCP server
    2. Start OpenCode, confirm tools available
    3. Kill the MCP server process
    4. Observe log: MCP transport closed unexpectedly
    5. Restart the MCP server
    6. Confirm tools reappear without restarting OpenCode

Screenshots / recordings

N/A — no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

When an MCP server process dies or the HTTP transport drops, the client
was left in connected state with stale tool definitions. No reconnect
was attempted, so tools permanently vanished for the session.

Register an onclose handler on each MCP client that:
- Detects unexpected transport closure (not intentional disconnect)
- Marks the server as failed and clears cached defs
- Re-creates the client via createAndStore() using the original config
- Publishes ToolsChanged event so the UI updates

Guard all intentional close paths (disconnect, finalizer, closeClient)
by deleting s.clients[name] BEFORE calling client.close(), so the
onclose handler sees s.clients[name] !== client and returns early.

Fixes anomalyco#17099
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Jun 8, 2026
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: MCP tools permanently lost mid-session after single transient listTools() failure — no retry, no reconnect

1 participant