Skip to content

Desktop can keep stale local MCP state until full relaunch #35285

Closed as not planned

Description

@Melivo

Summary

OpenCode Desktop can get into a stale local MCP state where newly created Desktop sessions immediately fail on the first MCP tool call with a Serena MCP timeout. A full Desktop quit/relaunch clears the problem temporarily, but creating a new Desktop session does not. The same workflow does not reproduce in the OpenCode TUI.

This looks related to Desktop's persistent sidecar lifecycle and the async prompt path, rather than to Serena's startup configuration itself.

Environment

  • OpenCode Desktop: 1.17.13
  • OS: Windows
  • MCP server: local stdio MCP (serena.exe start-mcp-server ...)
  • The same MCP configuration works in the OpenCode TUI.

Observed behavior

  1. Start OpenCode Desktop after a full quit/relaunch.
  2. Serena MCP tool calls work initially.
  3. After further Desktop usage, create a new Desktop session.
  4. The first LLM-initiated Serena MCP tool call can immediately fail with a timeout.
  5. Creating another new Desktop session does not fix it.
  6. Fully quitting and relaunching OpenCode Desktop fixes it temporarily.
  7. Running the same kind of Serena-heavy work in the TUI does not show the timeout issue.

Expected behavior

A new Desktop session should not inherit a stale/broken local MCP client state, or OpenCode should provide a way to reconnect/restart a local MCP server without fully relaunching Desktop.

Notes from code inspection

I looked for an existing issue and found related but not identical reports:

This report is specifically about Desktop + local stdio MCP + stale sidecar/MCP state.

Relevant implementation details from dev:

  • Desktop starts a persistent sidecar server at app startup and keeps it alive until quit/relaunch.
    • packages/desktop/src/main/index.ts calls spawnLocalServer(...) and stores the listener in a process-level server variable.
    • packages/desktop/src/main/sidecar.ts imports virtual:opencode-server and calls Server.listen(...).
    • Creating a new Desktop session appears to create only a new conversation in the existing sidecar; it does not restart MCP clients.
  • TUI has a worker/server lifecycle tied to the TUI process.
    • packages/opencode/src/cli/cmd/tui.ts starts a worker and terminates it on exit.
    • packages/opencode/src/cli/tui/worker.ts calls InstanceRuntime.disposeAllInstances() during shutdown.
    • This likely gives TUI a fresher instance/MCP lifecycle between launches.
  • Desktop new-session submit uses the async prompt route.
    • packages/app/src/components/prompt-input/submit.ts creates an empty session via client.session.create() and then sends via client.session.promptAsync(...).
  • The TUI main prompt path uses the normal prompt route.
    • packages/tui/src/component/prompt/index.tsx creates a session with agent/model and calls sdk.client.session.prompt(...).
  • Server handlers differ:
    • packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts has prompt, which streams promptSvc.prompt(...).
    • The same file has promptAsync, which forks promptSvc.prompt(...) into a background fiber via Effect.forkIn(scope, { startImmediately: true }) and immediately returns 204 NoContent.
    • This can make Desktop accept the prompt while the actual MCP failure happens later as a session error/event.

Current workaround

Fully quit and relaunch OpenCode Desktop. Creating a new session is not sufficient because the sidecar/MCP state is reused.

Killing only the serena.exe MCP process does not seem like a complete workaround because OpenCode may mark the MCP client failed, and there does not appear to be a local MCP reconnect/restart command.

Potential fixes

Any of these would likely help:

  • Add opencode mcp reconnect <name> or opencode mcp restart <name> for local MCP servers.
  • Add a Desktop UI action to reconnect/restart a configured MCP server.
  • Automatically reconnect/recreate a local MCP client after request timeout or connection close.
  • Surface promptAsync background MCP failures more directly in Desktop.
  • Refresh/reconnect failed MCP clients before sending a new Desktop session's first prompt.

Activity

  1. Melivo commented on Jul 4, 2026

    @Melivo
    Author

    Additional reference: the MCP server involved here is Serena: https://github.com/oraios/serena

    I am mentioning this so maintainers can distinguish the OpenCode Desktop sidecar/MCP lifecycle issue from Serena-specific behavior. The same Serena MCP setup works reliably for me in the OpenCode TUI; the stale-state pattern appears specific to OpenCode Desktop.

  2. liudongyan13701205717-source commented on Aug 9, 2026

    @liudongyan13701205717-source

    Same pain point here — supporting this one.

    User scenario (desktop app, Windows): when an MCP server fails to start (or a remote one drops), the client stays in a broken/stale state and the only working recovery is a full app relaunch. There is no visible "reconnect" affordance in the UI and no retry button; the status stays stale until relaunch, exactly as this issue describes.

    This is the desktop-side half of the MCP resilience family — the other open issues I've found:

    For desktop users specifically, a per-MCP status indicator with a manual "Reconnect/Retry" action (even if auto-reconnect stays conservative) would cover the cases auto-retry can't, without waiting for a full relaunch. Adding this here since stale-state-until-relaunch is the exact symptom.

  3. liudongyan13701205717-source commented on Aug 15, 2026

    @liudongyan13701205717-source

    +1, still relevant — local MCP state persists until a full relaunch. A lighter cache-invalidation path (see the plugin/LSP management GUI request #41037) would help here too.

  4. liudongyan13701205717-source commented on Aug 21, 2026

    @liudongyan13701205717-source

    Still relevant — and it's part of the same Desktop MCP-startup fragility cluster as #40516 (MCP fail to load on startup) and #31554 (duplicate-spawn TasksMax exhaustion). A full relaunch to clear stale state is a painful workaround; surfacing load failures visibly (see the plugin/LSP GUI request #41037) would help. +1.

  5. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions