Skip to content

mcp: Code Mode tool calls fail with Unknown tool for connected servers (codemode:false works) #51849

Closed as not planned

Description

@mjflower

Description

When a local (stdio) MCP server is connected and its tools are announced in the session's Code Mode catalog, calling those tools fails at runtime with Unknown tool '<server>.<tool>', and search() returns no results. The service reports the server as connected: opencode mcp list → ✓ gmail connected, log shows mcp connected server=gmail tools=19, and GET /api/mcp → connected.

Reproduces in fresh sessions — no context compaction involved, so this is distinct from #46190 (tools vanishing after compaction), though it may share the same underlying tool-registry staleness. Cross-referencing #46190.

Workaround that works: setting "codemode": false on the server exposes the tools natively (gmail_list_email_labels) and calls succeed in fresh sessions (verified twice).

Plugins

-opencode.browser, %USERPROFILE%\.config\openchamber\agent-tool\openchamber-agent-tool (OpenChamber agent tool plugin)

OpenCode version

v2.0.18 (channel: latest, npm install)

Steps to reproduce

  1. Configure a local stdio MCP server in %USERPROFILE%\.config\opencode\opencode.jsonc:
    "mcp": { "servers": { "gmail": { "type": "local", "command": ["node.exe", "<path>/dist/index.js"] } } }
  2. opencode service restart
  3. opencode mcp list → ✓ gmail connected (log: mcp connected server=gmail tools=19)
  4. Start a fresh session (reproduced via OpenChamber; local Qwen 27B GGUF model — the registry failure occurs before any model involvement)
  5. In Code Mode, call tools.gmail.list_email_labels()

Result: Unknown tool 'gmail.list_email_labels'. Did you mean tools.opencode.list_mcp_resources? and search({query:"gmail"}) → {items: [], remaining: 0}. Reproduced consistently in ≥4 fresh sessions created while /api/mcp reported connected.

Screenshot and/or share link

No share link. Related: #46190 (MCP tools disappear after context compaction — different trigger, possibly same root cause).

Operating System

Windows 10 (build 19045, x64)

Terminal

OpenChamber desktop app (Electron); no terminal in use

Activity

  1. added
    needs:complianceThis means the issue will auto-close after 2 hours.
    and removed
    needs:complianceThis means the issue will auto-close after 2 hours.
    on Sep 28, 2026
  2. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    Thanks for updating the issue with a clear description, reproduction steps, and system details!

  3. sergiopadure commented on Oct 25, 2026

    @sergiopadure
    Contributor

    Seen on v2.1.4 as well. In our case the whole MCP set drops out of the Code Mode catalog for one model step, then returns on the next step. During that step the catalog has only the built-in namespaces, it says "MCP server instructions are no longer available.", and MCP calls fail with Unknown tool. opencode mcp list reports every server connected throughout, and the server process does not restart.

    It happens when a session that has been idle for more than an hour receives a prompt. That led us to idle location eviction. Source reading of the v2.1.4 tag (not yet reproduced in a test):

    1. An idle location is unloaded after location_idle_timeout, 60 minutes by default (packages/core/src/location-activity.ts:29). The next prompt builds a fresh location graph.
    2. MCP connections start in the background so a slow server does not block startup (packages/core/src/mcp/index.ts:673). Mcp.tools() returns only the tools cached so far.
    3. McpTool registers once from that cached list and exposes flush as "the initial registration is done" (packages/core/src/tool/mcp.ts:140). Later ToolsChanged events reach the registry through a 100 ms debounced reconcile.
    4. SessionContext.select awaits only that flush before taking registry.snapshot and the MCP guidance (packages/core/src/session/context.ts:132). On a fresh graph the snapshot can therefore have no MCP tools, and the instruction diff publishes the removal.
    5. Catalog, search and dispatch share that frozen inventory for the step (packages/core/src/tool.ts:244), so the call fails locally before any MCP server is asked.

    A normal tools/list_changed refresh is not the cause: it keeps the previous tools until the new list succeeds.

    Possible fix: when a location graph is new, let the session preflight wait (bounded) for the initial MCP startup attempts to settle and for their tools to be registered before taking the snapshot, instead of awaiting only the first registration fiber. The same race may also follow an explicit reload or a server reconnect, which this would not cover.

    Workaround we are trying: "experimental": { "location_idle_timeout": "24 hours" }, which avoids the rebuild for sessions woken within a day.

  4. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report. I tried this on v2.0.18 with a minimal local stdio MCP server named gmail (tools list_email_labels, search_emails) configured under mcp.servers.gmail. I drove a fresh session that ran search({query:"gmail"}) and tools.gmail.list_email_labels({}) from Code Mode. I couldn't reproduce it.

    • With the server connected, the Code Mode call succeeded.
    • I only got your exact error (Unknown tool 'gmail.list_email_labels'. Did you mean …?, with an empty search() result) when the server was not connected for that session: either it failed to start, or the turn ran before it finished connecting. Once it connected, the catalog updated and the next call worked.

    So I suspect the gmail server isn't connected in the place where OpenChamber's sessions run, even though opencode mcp list shows it connected from your terminal. MCP connections are tracked per project directory (your log line has a directory= field). If OpenChamber opens sessions in a different directory or against a different server, the gmail server may be failing or missing there. The suggestion in your error, tools.opencode.list_mcp_resources, also points to a catalog with no gmail tools at all.

    These would help:

    1. In the OpenChamber session where it fails, what MCP status is shown for gmail? Or what does GET /api/mcp return when called for that session's directory?
    2. The mcp … log lines (connected, failed, errors) from the same time as a failing session, including their directory= values, compared with the session's working directory.
    3. Does it also happen in the plain opencode TUI, started in the same project directory, with the OpenChamber and opencode.browser plugins temporarily disabled?

    You can reply here, or edit the issue and leave a comment saying you've updated it.

    Related: #46190 (v1: MCP tools disappear after context compaction; a different trigger).

  5. sergiopadure commented on Oct 28, 2026

    @sergiopadure
    Contributor

    I'm not the original reporter, but we see the same symptom and can answer your questions for our setup: Linux,
    opencode serve --service on v2.2.0, several MCP servers (local and remote), sessions driven from OpenChamber and from
    prompts posted through the HTTP API. One model step gets a Code Mode catalog with only the built-in namespaces and
    "MCP server instructions are no longer available.", MCP calls in that step fail with Unknown tool, and the next step
    has every server again.

    1. MCP status for the session's directory. We did not capture GET /api/mcp at a failing moment. The log answers
      it more precisely; see 2.

    2. mcp log lines with directory=. Over about a day on v2.2.0 we found multiple steps with that full drop, across
      several sessions and directories. We excluded one outlier. In every other case:

      • location services booted directory=<session directory> was logged shortly before the step;
      • the step was built (the "no longer available" message is written) before any mcp connected line for the
        session's own directory;
      • the mcp connected ... directory=<session directory> lines followed within a fraction of a second to a few
        seconds after the step.

      Example, with relative times (server and directory names replaced):

      T0         location services booted directory=<session dir>
      T+0.9 s    step starts; catalog has no MCP tools ("MCP server instructions are no longer available.")
      T+1.0 s    mcp connected server=<server 1> directory=<session dir>
      T+1.0 s    mcp connected server=<server 2> directory=<session dir>
      ...
      T+1.9 s    mcp connected server=<last server> directory=<session dir>
      

      So it is your second case, "the turn ran before it finished connecting", and in our logs it happens on every
      first step after a location is booted, not now and then: the servers connect normally about a second later, but
      the step has already taken its tool snapshot. The cause we described above (SessionContext.select waits only for
      McpTool's first registration, not for MCP startup on a new location) still applies on v2.2.0.

    3. Plain TUI with plugins disabled. Not tested yet. Several of these steps were started by prompts posted with
      POST /api/session/<id>/prompt, with no OpenChamber client involved, so OpenChamber does not seem to be needed.
      A likely quick repro: restart opencode serve, then prompt an existing session in a directory with a few MCP
      servers and call one of them from Code Mode in the first step.

    One more observation on v2.2.0, cause not found: with experimental.location_idle_timeout set to 24 hours, the same
    directory was booted again twice within about 75 minutes with no location services evicted or
    location services reloaded line in between. So something other than idle eviction also rebuilds locations, and each
    rebuild opens the window above.

  6. opencodejr commented on Oct 31, 2026

    @opencodejr

    I'm closing this for now because we couldn't reproduce it and haven't heard back. On v2.0.18, a local stdio MCP server that was connected could be called from Code Mode in a fresh session. The Unknown tool '<server>.<tool>' error, with an empty search() result, only showed up when the server wasn't connected for that session.

    If it still happens, please reply here or open a new issue with:

    • the MCP status of gmail in the OpenChamber session where it fails
    • the mcp … log lines from that time, with their directory= values
    • whether it also happens in the plain opencode TUI in the same project directory

    We can reopen it then. Thanks for the detailed report!

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