Summary
When using expect MCP tools from Claude Code, the browser daemon frequently launches stale/unresponsive Chrome sessions that persist even after calling close. Subsequent open calls either reconnect to the dead session or fail silently. Recovery requires manually running pkill -9 -f Chromium and restarting - but this also kills the MCP server process itself, disconnecting the MCP tools entirely and requiring a full session restart.
Success rate for getting a working browser session on first attempt is roughly 5 out of 10 tries in a typical coding session.
Environment
expect-cli --version: 0.1.3
- Node:
v25.9.0
- OS: macOS 26.3 (Darwin 25.3.0, Apple Silicon)
- Agent: Claude Code (Opus 4.6)
- Transport: MCP stdio (configured via Claude Code settings)
Reproduction
This happens during normal Claude Code MCP usage with the open, screenshot, playwright, close tool cycle:
- Claude Code calls
open with a URL, headed=true, cookies=true
- Browser opens successfully, tools work fine
- At some point during the session (after ~5-15 minutes, or after multiple open/close cycles), the browser becomes unresponsive
- Calling
close reports success but the Chromium process remains
- Next
open call either:
- Hangs indefinitely (no response back to Claude Code)
- Opens a blank/stale window that doesn't navigate to the requested URL
- Connects to the orphaned session from step 3, showing old page state
- The only reliable recovery is:
pkill -9 -f Chromium
pkill -9 -f playwright
pkill -9 -f chrome
- But this also kills the MCP server process (
browser-mcp.js), causing all expect MCP tools to become unavailable with:
Error: No such tool available: mcp__expect__open
- At this point the entire MCP connection is dead and Claude Code cannot restart it - the user must manually intervene or start a new session.
Observed failure modes
1. Ghost Chrome after close
Claude Code calls: close
Response: "No browser open."
Reality: Chromium processes still running at 150-400% CPU
2. Stale session reconnection
Claude Code calls: open(url="http://localhost:7510/tasks/...")
Browser window appears but shows previous page, not the requested URL
Screenshot shows old state
3. MCP server crash on process cleanup
# User runs this to clean up ghost Chrome:
pkill -9 -f Chromium
# Result: MCP server also dies
# All subsequent tool calls fail:
# "Error: No such tool available: mcp__expect__open"
# Session is now permanently broken for browser testing
4. Daemon port conflict
After killing processes, the daemon sometimes fails to restart because the port is still held by a TIME_WAIT socket. The open CLI command then fails with exit code 1.
Impact
In a 2-hour coding session involving UI work, I typically need browser testing 10-15 times. With the ~50% failure rate:
- 5-7 attempts require manual
pkill intervention
- 2-3 of those kill the MCP server, requiring workarounds
- ~15-20 minutes lost per session to browser daemon issues
Suggested fixes
-
Robust process cleanup in close: Actually verify Chromium/ffmpeg child processes are terminated, not just the browser context. Use SIGKILL as fallback after SIGTERM timeout.
-
Health check before open: Before launching a new browser, check if stale daemon/Chromium processes exist and clean them up automatically.
-
Separate MCP server from browser daemon lifecycle: The MCP stdio server should survive browser process crashes. Currently killing a stuck browser takes down the entire MCP connection.
-
Daemon PID file staleness detection: The daemon PID file (~/.expect/daemon.json or similar) should be validated against actual running processes on startup, not trusted blindly.
-
Timeout on open: If the browser doesn't reach networkidle within N seconds, kill it and return an error rather than hanging forever.
Related issues
Summary
When using expect MCP tools from Claude Code, the browser daemon frequently launches stale/unresponsive Chrome sessions that persist even after calling
close. Subsequentopencalls either reconnect to the dead session or fail silently. Recovery requires manually runningpkill -9 -f Chromiumand restarting - but this also kills the MCP server process itself, disconnecting the MCP tools entirely and requiring a full session restart.Success rate for getting a working browser session on first attempt is roughly 5 out of 10 tries in a typical coding session.
Environment
expect-cli --version:0.1.3v25.9.0Reproduction
This happens during normal Claude Code MCP usage with the
open,screenshot,playwright,closetool cycle:openwith a URL,headed=true,cookies=trueclosereports success but the Chromium process remainsopencall either:browser-mcp.js), causing all expect MCP tools to become unavailable with:Observed failure modes
1. Ghost Chrome after
close2. Stale session reconnection
3. MCP server crash on process cleanup
4. Daemon port conflict
After killing processes, the daemon sometimes fails to restart because the port is still held by a TIME_WAIT socket. The
openCLI command then fails with exit code 1.Impact
In a 2-hour coding session involving UI work, I typically need browser testing 10-15 times. With the ~50% failure rate:
pkillinterventionSuggested fixes
Robust process cleanup in
close: Actually verify Chromium/ffmpeg child processes are terminated, not just the browser context. UseSIGKILLas fallback afterSIGTERMtimeout.Health check before
open: Before launching a new browser, check if stale daemon/Chromium processes exist and clean them up automatically.Separate MCP server from browser daemon lifecycle: The MCP stdio server should survive browser process crashes. Currently killing a stuck browser takes down the entire MCP connection.
Daemon PID file staleness detection: The daemon PID file (
~/.expect/daemon.jsonor similar) should be validated against actual running processes on startup, not trusted blindly.Timeout on
open: If the browser doesn't reachnetworkidlewithin N seconds, kill it and return an error rather than hanging forever.Related issues