Bug: Claude Preview MCP panel opens in wrong session (multi-session Desktop)
The Problem
When I have multiple Claude Code Desktop sessions open, calling preview_start in Session A frequently opens the preview panel in Session B instead. The preview content appears in a completely unrelated conversation. I've had to tell Claude "you're opening it up in the wrong chat" and "its in the wrong chat" multiple times. In one session I noted "this is the 3rd time it has happened." This has happened at least 4 times over the past week.
When It Happens
- Multiple Claude Code Desktop sessions are open simultaneously
- All sessions share the same primary working directory (
~/.claude) - I call
preview_startwith a named server from.claude/launch.json - The preview panel renders in a different session's workspace panel, not the one that requested it
Root Cause (as I understand it)
The Claude Preview MCP server is a built-in singleton service injected at Desktop app startup. The preview_start tool accepts only a name parameter (the server name from launch.json). It does NOT accept a session ID, tab group ID, or any routing hint. There is no mechanism for the MCP server to route the resulting preview panel back to the specific session that called it.
This appears to be part of a broader session isolation problem:
- JSONL cross-session contamination (#26964): Events from one session get written to another session's log file at contamination rates of 23-77%. If event routing is broken, it follows that MCP tool call routing uses the same flawed infrastructure.
- Full session cross-contamination (#27658, #7702, #1985): Multiple confirmed bugs show concurrent sessions sharing state they should not — command history, context, and even file paths leaking between unrelated sessions.
- Built-in MCP servers unconditionally injected (#37284): Even when Preview is disabled in Desktop preferences, the
isDisabled()callback is never checked and the server is registered anyway.
Secondary Issues
- Port conflicts from zombie servers: When Session A starts a preview server on port 8770, then Session B tries
preview_startfor the same server, it getsEADDRINUSEbecause Session A's dev server process is still running. Session B then gets "Server not found" errors because it has noserverIdfor Session A's server. - Orphaned processes: Preview dev servers spawned by closed sessions remain running on their ports (e.g., I currently have orphaned Python processes on ports 8770 and 8765 from previous sessions).
Suggested Fix
- Add session affinity to
preview_start: The MCP server should track which session ID initiated thepreview_startcall and route the preview panel exclusively to that session's UI pane. The session ID is already available in the MCP server's context — it just needs to be used for routing.
- Add a
sessionIdortabGroupIdparameter topreview_start: As a fallback, allow the tool to explicitly specify which session should receive the preview panel.
- Clean up orphaned dev servers: When a session closes, its spawned preview servers should be terminated. Currently they linger as zombie processes occupying ports.
- Respect the
isDisabled()callback (#37284): If a user disables Preview in Desktop preferences, don't inject the MCP server.
Environment
- Windows 11 Home (10.0.26200)
- Claude Code Desktop (latest auto-update channel)
- Typical usage: 2-4 concurrent sessions across different projects
- Primary working directory:
C:\Users\abelj\.claude .claude/launch.jsonwith 7-13 named server entries
Workaround I'm Currently Using
My Claude sessions now avoid preview_start entirely and instead start dev servers via Bash, then use preview_eval with window.location.href to point at localhost:<port>. This is clunky but avoids the routing problem.
Happy to provide session transcripts or logs if that helps.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗