Skip to content

fix: resolve server.close recursion, add MV3 keep-alive ping, and clean up Windows port kill - #201

Open
dfgr wants to merge 1 commit into
BrowserMCP:mainfrom
dfgr:fix/stability-mv3-keepalive-and-server-close
Open

fix: resolve server.close recursion, add MV3 keep-alive ping, and clean up Windows port kill#201
dfgr wants to merge 1 commit into
BrowserMCP:mainfrom
dfgr:fix/stability-mv3-keepalive-and-server-close

Conversation

@dfgr

@dfgr dfgr commented Sep 8, 2026

Copy link
Copy Markdown

Summary

This PR addresses three critical stability issues affecting the core MCP server and browser connection reliability:

  1. Infinite Recursion on server.close() (CWE-674 / Closes DoS via infinite recursion in server.close() on client disconnect (CWE-674) #163):

    • The server.close override was recursively calling await server.close(), leading to an immediate RangeError: Maximum call stack size exceeded whenever a client disconnected or the server was closed.
    • Fix: Retain a reference to originalClose = server.close.bind(server) and invoke it prior to cleaning up the WebSocket server and context.
  2. Chrome Manifest V3 Background Worker Idle Disconnect (Resolves MV3 service worker killed on idle — popup shows stale 'Disconnect' state, WebSocket never reconnects #192):

    • Chrome MV3 terminates idle extension service workers after ~30 seconds of inactivity. Without active frames on the WebSocket, the service worker goes to sleep, leaving the UI in a stale "Disconnect" state while tool calls fail with "No connection to browser extension".
    • Fix: Implemented a 5-second websocket.ping() heartbeat in server.ts. Active ping frames keep the Chromium network stack and background worker alive during idle periods. Also clears stale WebSocket references in Context on close.
  3. Windows Port Kill Stderr Pollution:

    • On Windows, netstat -ano | findstr :${port} returns exit code 1 if no process is currently listening on the port. Even though wrapped in try/catch, console.error logged an extensive error stack trace to stderr, causing some strict MCP client launchers to treat initialization as failed.
    • Fix: Redirect stderr (2>nul), pass { stdio: 'ignore' }, and ignore expected non-zero exits when the port is already free.

Testing

  • Verified on Windows 11 with Node.js and Antigravity / Claude Code MCP clients.
  • Confirmed clean server startup, JSON-RPC handshake, tool invocation (browser_snapshot, browser_navigate), and termination without recursion crashes or unhandled exceptions.
  • Verified persistent connection with the Chrome extension across idle periods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant