You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
mcp: Code Mode tool calls fail with Unknown tool for connected servers (codemode:false works) #51849
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).
Start a fresh session (reproduced via OpenChamber; local Qwen 27B GGUF model — the registry failure occurs before any model involvement)
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
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):
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.
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.
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.
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.
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.
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:
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?
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.
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).
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.
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.
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.
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.
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!
Activity
github-actions commentedon Sep 28, 2026
Thanks for updating the issue with a clear description, reproduction steps, and system details!
sergiopadure commentedon Oct 25, 2026
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 listreports 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.4tag (not yet reproduced in a test):location_idle_timeout, 60 minutes by default (packages/core/src/location-activity.ts:29). The next prompt builds a fresh location graph.packages/core/src/mcp/index.ts:673).Mcp.tools()returns only the tools cached so far.McpToolregisters once from that cached list and exposesflushas "the initial registration is done" (packages/core/src/tool/mcp.ts:140). LaterToolsChangedevents reach the registry through a 100 ms debouncedreconcile.SessionContext.selectawaits only thatflushbefore takingregistry.snapshotand 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.packages/core/src/tool.ts:244), so the call fails locally before any MCP server is asked.A normal
tools/list_changedrefresh 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.opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I tried this on v2.0.18 with a minimal local stdio MCP server named
gmail(toolslist_email_labels,search_emails) configured undermcp.servers.gmail. I drove a fresh session that ransearch({query:"gmail"})andtools.gmail.list_email_labels({})from Code Mode. I couldn't reproduce it.Unknown tool 'gmail.list_email_labels'. Did you mean …?, with an emptysearch()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 listshows it connected from your terminal. MCP connections are tracked per project directory (your log line has adirectory=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:
gmail? Or what doesGET /api/mcpreturn when called for that session's directory?mcp …log lines (connected, failed, errors) from the same time as a failing session, including theirdirectory=values, compared with the session's working directory.opencodeTUI, started in the same project directory, with the OpenChamber andopencode.browserplugins 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).
sergiopadure commentedon Oct 28, 2026
I'm not the original reporter, but we see the same symptom and can answer your questions for our setup: Linux,
opencode serve --serviceon v2.2.0, several MCP servers (local and remote), sessions driven from OpenChamber and fromprompts 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 stephas every server again.
MCP status for the session's directory. We did not capture
GET /api/mcpat a failing moment. The log answersit more precisely; see 2.
mcplog lines withdirectory=. Over about a day on v2.2.0 we found multiple steps with that full drop, acrossseveral sessions and directories. We excluded one outlier. In every other case:
location services booted directory=<session directory>was logged shortly before the step;mcp connectedline for thesession's own directory;
mcp connected ... directory=<session directory>lines followed within a fraction of a second to a fewseconds after the step.
Example, with relative times (server and directory names replaced):
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.selectwaits only forMcpTool's first registration, not for MCP startup on a new location) still applies on v2.2.0.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 MCPservers 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_timeoutset to 24 hours, the samedirectory was booted again twice within about 75 minutes with no
location services evictedorlocation services reloadedline in between. So something other than idle eviction also rebuilds locations, and eachrebuild opens the window above.
opencodejr commentedon Oct 31, 2026
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 emptysearch()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:
gmailin the OpenChamber session where it failsmcp …log lines from that time, with theirdirectory=valuesopencodeTUI in the same project directoryWe can reopen it then. Thanks for the detailed report!