[BUG] Claude in Chrome: MCP navigate to any loopback URL issues no HTTP request and lands on Chrome's error page; the same URL loads in a normal tab
Bug Description
MCP-driven navigate to any loopback URL reports success and updates the tab's URL, but Chrome then renders its network-error page and no HTTP request is ever issued. The same URL loads normally in a non-MCP tab of the same Chrome profile, so the server, the port and the browser are all fine — the request never leaves the extension's navigation path.
This is distinct from #83079: there the failure surfaces as Permission denied by user from the approval popup. Here navigate is allowed — it returns Navigated to http://localhost:8080/ and tabs_context_mcp shows the new URL — and the failure is that no connection is attempted.
Evidence
I put a request-logging HTTP server on a spare port and pointed three clients at the identical URL:
| client | server log |
|---|---|
| curl http://localhost:8080/ | HIT GET / host=localhost:8080 ua=curl/8.7.1 |
| a normal Chrome tab (open http://localhost:8080/) | HIT GET / host=localhost:8080 ua=Mozilla/5.0 (Macintosh…) + a follow-up GET /favicon.ico |
| the MCP-driven tab, same URL | nothing — no entry at all |
Same browser, same profile, same second. read_network_requests on the MCP tab returns only three data:image/png;base64,… entries, which are Chrome's own error-page illustrations — further confirmation that no network request was attempted.
Tried and identical in behaviour: http://localhost:PORT, http://127.0.0.1:PORT, two different ports (4818 and 8080).
Reproduction
- Run any local HTTP server that logs requests, e.g.
``jsHIT ${req.method} ${req.url} ua=${req.headers["user-agent"]}
// probe.mjs — node probe.mjs
import { createServer } from "node:http";
createServer((req, res) => {
console.log();``
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end("<!doctype html><title>probe</title><h1>probe OK</h1>");
}).listen(8080, () => console.log("listening on 8080"));
curl http://localhost:8080/→ logs a hit.- Open
http://localhost:8080/in a normal Chrome tab → logs a hit. - From Claude Code:
navigatean MCP tab tohttp://localhost:8080/, thenget_page_text.
Expected: the probe logs a hit and the page text is returned.
Actual: the probe logs nothing. navigate reports Navigated to http://localhost:8080/, and every subsequent tool fails with Frame with ID 0 is showing error page — computer (screenshot), read_page, get_page_text, javascript_tool.
Ruled out
Each of these was checked, not assumed:
- Not the server — listening on the wildcard (
node … TCP *:8080 (LISTEN)), answerscurlfrom inside and outside the agent sandbox. - Not the browser — the same MCP tab loads
https://example.comand returns its text fine, immediately before and after the failing navigations. - Not a proxy —
scutil --proxyshows only*.localand169.254/16exceptions; nohttp_proxy/https_proxyin the environment. - Not Chrome policy — no
/Library/Managed Preferences/com.google.Chrome.plist, noURLBlocklist. - Not a restricted port — neither 4818 nor 8080 is on Chrome's blocked-port list.
- Not the extension's site permission — the site-permission gate produces a different, clearly distinguishable error. Navigating the same MCP tab to a private LAN address (
192.168.x.x:8080) returnsPermission denied for this action on this domain, whereas loopback returnsshowing error page. So loopback is already within the extension's permitted set; the failure is downstream of that check.
Environment
- Extension: Claude (
fcoeoabgfenejglbffodgkkbkcdhcgfn) 1.0.85 - Chrome 151.0.7922.109
- macOS 26.5.2 (arm64)
- Claude Code 2.1.231, MCP bridge
Impact
Local dev servers can't be driven or inspected through the extension at all — the whole point of mcp__claude-in-chrome__* for local work. In my case a static documentation site could be verified only as markup and JSON; nothing could be screenshotted or clicked, so layout and interaction went unverified.
Note on the error surface
Frame with ID 0 is showing error page is the same message for every downstream tool and doesn't say which net::ERR_* Chrome hit. Surfacing the underlying network error code would have made this a one-step diagnosis instead of a process of elimination.