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
preview_* tools silently disappear from running agents after a server restart #7870
After the server restarts, agents in already-running threads lose their preview_* tools. The agent reports that the tools do not exist; nothing is logged and no error surfaces in the UI.
Why
McpSessionRegistry keeps issued credentials only in memory:
The acquireRelease finalizer only clears the module-level activeMcpSessionRegistry pointer, so the map simply dies with the process. A resumed provider session keeps presenting the bearer token it was issued before the restart, the auth middleware no longer has a record for that token hash, and every tool call is rejected.
This is reachable through ordinary use — anything that restarts the backend (an update, the desktop app restarting its server) while a thread has an active provider session.
Reproduce
Start a thread with a provider that gets the t3-code MCP server attached.
Restart the server.
Ask the agent to use a preview_* tool.
The agent reports the tool does not exist rather than reporting an auth failure.
One thing worth knowing before fixing it
issueActiveMcpCredential revokes the thread's existing credentials before issuing new ones:
That matters if the fix is "re-issue on resume": a resumed session that is still using its old credential can have it revoked out from under it while the new config is in flight. Persisting credentials and reloading them on boot sidesteps that, but it needs the liveness writes to coalesce or every turn writes a row.
Context
Found downstream in a fork (thedouglenz/trellis), where the same registry serves an additional toolkit and the symptom was more obvious. Happy to leave this as a report — I know large PRs are not what you are looking for.
Observed from the other side of this on OpenCode server 2.0.29: after a service restart under heavy load, the restarted server logged an authentication failure while terminating an MCP session belonging to one of the thread-scoped t3-code-* servers. Log fields, with the connection UUID shortened:
timestamp=2026-10-15T03:02:21.898Z message="mcp http authentication rejected" status=401 method=DELETE server=t3-code-4c2f11b8-…
timestamp=2026-10-15T03:02:21.899Z message="failed to terminate MCP session" server=t3-code-4c2f11b8-… error="Failed to terminate session: Unauthorized"
At 03:04:33.614Z the same named server logged mcp connected, tools=83, and the associated session ultimately reports outcome: succeeded.
This establishes a cleanup-path authentication failure after a restart, consistent with the in-memory McpSessionRegistry analysis above, but I have not confirmed the disappearing-preview_* symptom or that the rejected token was absent from the restarted registry.
This no longer reproduces on current main (71ba6b3), so I'm closing it as fixed.
The fix is de34391 (#2829, the new orchestrator). The revokeThread-then-issue path in issueActiveMcpCredential is no longer used. ProviderSessionManager.prepareMcpSession now resolves the thread's stored credential against the registry. After a restart the registry has no record of it, so the thread gets a fresh credential, and every adapter reads it when it starts its provider process. Neither the registry nor the old in-memory session config survives the restart, and no provider process does either, so nothing is left presenting a pre-restart token.
What I ran, on a dev server with a fresh database:
OpenCode, idle restart. An OpenCode thread (anthropic/claude-sonnet-5-5) called preview_status, and it returned normally. I stopped the server with SIGTERM (its opencode serve child exited with it) and started it again on the same database. The same thread called preview_status again: same result.
Claude, mid-turn restart. A Claude thread called preview_status. Its next turn ran sleep 40 and then preview_status. I restarted the server during the sleep. After boot, the interrupted turn resumed and preview_status returned normally.
Server trace. It shows one fresh McpSessionRegistry.issue per thread after each restart, and no /mcp authentication rejections.
@satyalyadav, about the 401 on DELETE: that is the old provider session trying to end its MCP session with the old server's token while the server restarts. It fails without consequence, which matches the reconnect with 83 tools you saw two minutes later. If tools ever go missing after a restart on a current build, please open a new issue with the provider, the version, and the server log around the restart.
Activity
satyalyadav commentedon Oct 15, 2026
Observed from the other side of this on OpenCode server 2.0.29: after a service restart under heavy load, the restarted server logged an authentication failure while terminating an MCP session belonging to one of the thread-scoped
t3-code-*servers. Log fields, with the connection UUID shortened:At
03:04:33.614Zthe same named server loggedmcp connected, tools=83, and the associated session ultimately reportsoutcome: succeeded.This establishes a cleanup-path authentication failure after a restart, consistent with the in-memory
McpSessionRegistryanalysis above, but I have not confirmed the disappearing-preview_*symptom or that the rejected token was absent from the restarted registry.juliusmarminge commentedon Oct 27, 2026
This no longer reproduces on current main (71ba6b3), so I'm closing it as fixed.
The fix is de34391 (#2829, the new orchestrator). The
revokeThread-then-issuepath inissueActiveMcpCredentialis no longer used.ProviderSessionManager.prepareMcpSessionnow resolves the thread's stored credential against the registry. After a restart the registry has no record of it, so the thread gets a fresh credential, and every adapter reads it when it starts its provider process. Neither the registry nor the old in-memory session config survives the restart, and no provider process does either, so nothing is left presenting a pre-restart token.What I ran, on a dev server with a fresh database:
anthropic/claude-sonnet-5-5) calledpreview_status, and it returned normally. I stopped the server with SIGTERM (itsopencode servechild exited with it) and started it again on the same database. The same thread calledpreview_statusagain: same result.preview_status. Its next turn ransleep 40and thenpreview_status. I restarted the server during the sleep. After boot, the interrupted turn resumed andpreview_statusreturned normally.McpSessionRegistry.issueper thread after each restart, and no/mcpauthentication rejections.@satyalyadav, about the 401 on
DELETE: that is the old provider session trying to end its MCP session with the old server's token while the server restarts. It fails without consequence, which matches the reconnect with 83 tools you saw two minutes later. If tools ever go missing after a restart on a current build, please open a new issue with the provider, the version, and the server log around the restart.