Bug Description
After the first successful element selection, all subsequent Option+Click selections fail to update the MCP server data. The get-pointed-element tool keeps returning the stale first element.
Steps to Reproduce
- Restart browser (or restart Claude Code which restarts the MCP server)
- Refresh the target webpage
- Option+Click an element → works (MCP server receives the data)
- Wait ~10+ seconds
- Option+Click a different element → fails (MCP server still returns the old element)
Root Cause Analysis
After reading the source code, I believe this is related to the Manifest V3 service worker lifecycle:
- First click works because the service worker is active after browser startup
ElementSenderService has a 10-second IDLE_DURATION that disconnects the WebSocket
- After disconnect, Chrome kills the idle service worker (MV3 behavior)
- On subsequent clicks,
chrome.runtime.sendMessage from content script wakes up the service worker
- However, there's a race condition:
chrome.runtime.onMessage.addListener in background.ts may not be registered before the message arrives, OR initialize() hasn't completed yet when the message handler fires
Suggested Fix
Consider one of:
- Use
chrome.runtime.onMessage at the top level (before initialize()) to ensure the listener is always registered on service worker startup
- Add a keep-alive mechanism (e.g., periodic
chrome.alarms) to prevent service worker termination
- In
sendElement, add a retry when the first WebSocket connection attempt after idle fails
Environment
- macOS Darwin 25.2.0
- Chrome (latest)
- MCP Pointer Chrome Extension v0.6.0
- MCP Server:
@mcp-pointer/server@latest via npx
- Client: Claude Code
Bug Description
After the first successful element selection, all subsequent Option+Click selections fail to update the MCP server data. The
get-pointed-elementtool keeps returning the stale first element.Steps to Reproduce
Root Cause Analysis
After reading the source code, I believe this is related to the Manifest V3 service worker lifecycle:
ElementSenderServicehas a 10-secondIDLE_DURATIONthat disconnects the WebSocketchrome.runtime.sendMessagefrom content script wakes up the service workerchrome.runtime.onMessage.addListenerinbackground.tsmay not be registered before the message arrives, ORinitialize()hasn't completed yet when the message handler firesSuggested Fix
Consider one of:
chrome.runtime.onMessageat the top level (beforeinitialize()) to ensure the listener is always registered on service worker startupchrome.alarms) to prevent service worker terminationsendElement, add a retry when the first WebSocket connection attempt after idle failsEnvironment
@mcp-pointer/server@latestvia npx