[BUG] mcp__Claude_Preview__preview_eval hangs the entire preview session without returning any error
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The mcp__Claude_Preview__preview_eval tool silently fails to return any response. Once this happens, subsequent tool calls (e.g. preview_resize) within the same preview session also stop returning results.
There is no error, no malformed payload, and no timeout signal — the tool call simply never completes. The model has no way to detect this from inside its loop, so the session appears to hang until the user manually intervenes (Ctrl+C / new chat).
Observed pattern in a single session:
preview_list→ success (empty array)preview_start→ successpreview_screenshot→ success (image returned)preview_eval(initial attempt, ~10 lines IIFE) → no responsepreview_eval(retry, 1-linescrollIntoViewcall) → no responsepreview_eval(3rd attempt, further simplified) → no responsepreview_resize(preset: "desktop") → no response
All preview_* tools stopped returning results from the first preview_eval call onward.
What Should Happen?
preview_evalshould either return a result or surface a timeout/error to the model within a reasonable time bound.- A hung page-side JS context should not silently block all subsequent tool calls on the same browser session.
- The MCP server should detect a non-responsive page (unsettled Promise, blocking dialog, infinite loop, etc.) and either kill the page or return an explicit timeout error so the model can recover.
Error Messages/Logs
No error message returned. No log output. Tool calls silently fail to return any response.
This is the core issue: the failure is invisible to the model and there is no signal to act on.
Steps to Reproduce
- Start a preview session with
mcp__Claude_Preview__preview_start(succeeds) - Call
mcp__Claude_Preview__preview_screenshot(succeeds, image returned) - Call
mcp__Claude_Preview__preview_evalwith a short synchronous JS expression
(e.g. document.querySelector('h3').scrollIntoView()) — no response returned
- Retry
preview_eval2 more times with progressively simpler arguments — still no response - Call any other
preview_*tool on the same session (e.g.preview_resizewithpreset: "desktop") — also no response
Argument size is small in all cases (1 to ~10 lines of plain JS). The hang starts immediately after the first preview_eval call and persists across all subsequent tool calls in the same session.
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
Unknown — this is the first time the issue has been investigated systematically.
Claude Code Version
2.1.145 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Windows Terminal
Additional Information
Frequency
Reproducible: this is the 3rd consecutive failure in the current session. Has occurred in earlier sessions as well.
Hypothesis (not confirmed)
The first preview_eval call appears to leave the page's JS execution context in a non-responsive state. All subsequent tool calls share the same browser session and execution queue, so they get stuck behind the hung context. The pattern (only preview_eval triggers the hang; preview_screenshot always works until the hang occurs) suggests the issue is specific to the JS-eval code path on the page side, not a general MCP transport issue.
Impact on the model
The model has no built-in timeout mechanism, so it cannot self-recover from this hang. The user is the only one who can detect that nothing is happening, and must manually cancel and restart the preview session. This wastes tokens on retry attempts and breaks longer agentic workflows that involve UI inspection.
Current workaround
Project-level rules in ~/.claude/CLAUDE.md to restrict preview_eval arguments to short synchronous expressions, avoid alert/confirm/await fetch in eval'd code, and recover by restarting the preview session when a hang is suspected. This is purely a workaround — the underlying issue requires server-side timeout handling.
Suggested fix direction
- Add a server-side timeout to
preview_eval(e.g. 10s default, configurable) that returns an explicit timeout error to the model. - Detect non-responsive page contexts and either reset the page or kill the session, returning a clear error.
- Optionally: surface a
preview_healthorpreview_statustool so the model can probe session liveness without committing to another eval call.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗