| name | chrome-mcp-server |
| description | Setup and configure Chrome MCP Server (hangwin/mcp-chrome) for browser automation via MCP |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["macos","linux","windows"] |
| metadata | {"hermes":{"tags":["MCP","Chrome","Browser","Automation"],"related_skills":["mcp/native-mcp","browser"]}} |
Chrome MCP Server Setup
Complete setup guide for hangwin/mcp-chrome - a Chrome extension-based MCP server that enables AI assistants to control Chrome browser for automation, content analysis, and semantic search.
Overview
Unlike Playwright-based solutions, Chrome MCP Server directly uses your daily Chrome browser, leveraging existing login states, cookies, and user configurations.
Architecture:
- Chrome Extension (loaded in browser)
- mcp-chrome-bridge (local service)
- Native Messaging Host (Chrome <-> bridge communication)
- MCP Server (exposes tools to AI assistants)
Prerequisites
- Chrome browser installed
- Node.js 18-22 (NOT v26+ - see Pitfalls)
- Hermes Agent with MCP support
Installation Steps
1. Install mcp-chrome-bridge
npm install -g mcp-chrome-bridge
2. Download Chrome Extension
Download latest release from: https://github.com/hangwin/mcp-chrome/releases
Extract to permanent location (e.g., ~/chrome-mcp-server/).
3. Load Extension in Chrome
- Navigate to
chrome://extensions/
- Enable "Developer mode" (toggle in top-right)
- Click "Load unpacked"
- Select the extracted extension folder
4. Register Native Messaging Host
mcp-chrome-bridge register --detect
mcp-chrome-bridge register --browser chrome
Verify registration:
mcp-chrome-bridge doctor
Expected output includes:
[OK] Chrome manifest: ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.chromemcp.nativehost.json
[OK] Port config: http://127.0.0.1:12306/mcp
Note: If you see [WARN] Connectivity: GET http://127.0.0.1:12306/ping failed, that's expected - the service only starts after clicking "Connect" in the extension.
5. Configure Hermes MCP Client
Add to ~/.hermes/config.yaml:
mcp_servers:
chrome:
url: http://127.0.0.1:12306/mcp
timeout: 120
connect_timeout: 60
Important: Port is 12306, not 3000. Verify with mcp-chrome-bridge doctor if unsure.
Restart Hermes Gateway:
hermes gateway restart
6. Start the Service
In Chrome:
- Click the Chrome MCP Server extension icon
- Click "Connect" button
- Wait for status to show "Connected"
7. Verify Connection
Two-part verification for full-stack confidence:
1) Ping the HTTP endpoint:
curl http://127.0.0.1:12306/ping
Should return: {"status":"ok"}
2) Exercise an MCP tool (verifies the full stack: bridge → communication channel → Hermes MCP client):
Ask your agent to call mcp_chrome_get_windows_and_tabs. A successful response with window/tab details confirms the entire pipeline works. A Failed to connect to MCP server error despite a passing ping indicates a stale native messaging host manifest (see pitfall below) or a Hermes config issue.
Pitfalls
Node.js v26+ Incompatibility
Symptom: Errors like:
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined by "exports"
or native module compilation failures for better-sqlite3.
Root Cause: Node.js v26 has breaking V8 API changes that affect native modules (better-sqlite3) and zod package exports.
Fix: Downgrade to Node.js 20:
brew install node@20
brew unlink node
brew link --overwrite node@20
node --version
Then reinstall mcp-chrome-bridge:
npm uninstall -g mcp-chrome-bridge
npm install -g mcp-chrome-chrome-bridge
mcp-chrome-bridge register --detect
Note: pnpm may have compatibility issues with Node v20. Use npm for global installation.
Zod Package Version Conflict
Symptom: Extension connects but service fails with:
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined
at ... @modelcontextprotocol/sdk/dist/cjs/types.js
Root Cause: @modelcontextprotocol/sdk v1.29.0 requires zod v4, but mcp-chrome-bridge bundles v3.24.4.
Fix: Downgrade SDK to compatible version (v1.11.0):
MCP_PATH=$(find ~/Library/pnpm -name "mcp-server-stdio.js" 2>/dev/null | head -1 | xargs dirname)
cd "$MCP_PATH/.."
npm install @modelcontextprotocol/sdk@1.11.0 --save-exact --legacy-peer-deps
Then reload the Chrome extension and click Connect again.
STDIO Mode (Alternative to HTTP)
If HTTP mode has issues, use STDIO mode which is more reliable:
mcp_servers:
chrome:
command: node
args:
- /path/to/mcp-chrome-bridge/dist/mcp/mcp-server-stdio.js
timeout: 120
connect_timeout: 60
Find the exact path:
find ~/Library/pnpm -name "mcp-server-stdio.js" 2>/dev/null
Test STDIO server manually:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | node /path/to/mcp-server-stdio.js
Should return JSON response with server capabilities.
Wrong Port Configuration
Symptom: Connection refused on port 3000.
Fix: Chrome MCP Server uses port 12306 by default. Always verify:
mcp-chrome-bridge doctor | grep "Port config"
Extension Not Connected
Symptom: curl http://127.0.0.1:12306/ping fails with "Connection refused"
Fix: Click "Connect" in the Chrome extension. The service only starts on-demand.
Native Messaging Host Not Registered
Symptom: Extension shows "Failed to connect to native host"
Fix: Re-run registration and check permissions:
mcp-chrome-bridge register --detect
mcp-chrome-bridge fix-permissions
Stale Native Messaging Host Manifest
Symptom: mcp-chrome-bridge doctor shows:
[ERROR] Chrome manifest: Invalid manifest (path does not match installed wrapper)
While all other checks pass (installation, host files, port config).
Hermes MCP tools fail with Failed to connect to MCP server even though the extension shows "Connected".
Root Cause: The Native Messaging Host manifest on disk points to a stale path (e.g., from a previous pnpm store location or an older installation). This happens after Node version switches, package manager migrations (pnpm → npm), or when the bridge is moved/reinstalled.
Fix: Re-register the native messaging host with the specific browser flag:
mcp-chrome-bridge register --browser chrome
This rewrites the manifest file at ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.chromemcp.nativehost.json with the current correct path.
Verify:
mcp-chrome-bridge doctor
Single-transport limit: multiple Hermes processes compete for one bridge slot
Symptom (2026-08-07): mcp_chrome_* tools fail with Failed to connect to MCP server, then MCP server 'chrome' is unreachable after N consecutive failures, then ClosedResourceError — while hermes mcp test chrome succeeds (144ms, 27 tools). The server is healthy; the problem is client-side connection competition.
Root cause: mcp-chrome-bridge 1.0.31's /mcp POST endpoint calls getMcpServer().connect(transport) for every new connection — a singleton Protocol that can only connect() once. Only ONE MCP client can hold the bridge at a time; every later client gets HTTP 500 Already connected to a transport. Every Hermes process initializes chrome MCP (gateway, dashboard, each CLI session), so with 3-6 Hermes processes running, they all fight for the single slot. The bridge can also crash under concurrent requests (ERR_HTTP_HEADERS_SENT in ~/Library/Logs/mcp-chrome-bridge/native_host_stderr_*.log), leaving a stale transport in transportsMap — TCP connects fine but the MCP handshake always fails (ClosedResourceError).
Diagnosis order:
hermes mcp test chrome — if it succeeds, server + config are healthy; the fault is connection competition or a stale session client.
lsof -iTCP:12306 | grep ESTABLISHED — each ESTABLISHED line is a stdio server holding/contending for the slot; trace ps -o pid,ppid to find which Hermes process owns it (watchdog mcp_stdio_watchdog.py → hermes main process).
curl -X POST http://127.0.0.1:12306/mcp with an initialize payload — HTTP 500 Already connected to a transport with NO ESTABLISHED connections = bridge has stale internal transport state.
Recovery chain (order matters):
- Kill competing stdio servers + their watchdogs, keeping only the current session's:
ps aux | grep -E "mcp-server-stdio|mcp_stdio_watchdog", kill -9 the non-current watchdogs, then the orphaned stdio servers (ppid=1 after watchdog death).
- If bridge internal state is stale (500 with no connections), kill the bridge process itself (
node .../mcp-chrome-bridge/dist/index.js, parent is usually Chrome). It does NOT auto-restart reliably.
- The bridge can ONLY be restarted by the Chrome extension (click "Connect" in the extension popup; there is no
mcp-chrome-bridge serve CLI command, and running node dist/index.js directly exits immediately — it's a native-messaging-host entry, not a standalone HTTP server).
- A session client that has burned through the circuit breaker needs its auto-retry window (~15s), or
/reload-mcp, or a session restart.
Pitfall: Temporary Unavailability and Recovery
Symptom: mcp_chrome_* tools suddenly fail with MCP server 'chrome' is unreachable after 3 consecutive failures. Auto-retry available in ~51s.
Root Cause: Chrome MCP server's native messaging host can transiently disconnect due to Chrome background process management, extension sleep, or bridge process issues. Unlike permanent config failures, this resolves on its own within ~60s.
Recovery pattern:
- Wait ~60s — the auto-retry window is real; the server often comes back on its own
- Fallback to agent-browser — while waiting, use
agent-browser for urgent tasks:
agent-browser open "<url>" --headed=false
agent-browser get text "<selector>"
agent-browser screenshot /tmp/screenshot.png
- After recovery — verify with
mcp_chrome_get_windows_and_tabs before resuming Chrome MCP usage
Important: Do NOT restart Hermes gateway or re-register the native messaging host — these are heavy operations for a transient issue.
Limitation of agent-browser fallback: It spawns a Playwright-controlled browser (not your real Chrome). Sites with aggressive anti-crawling (Xiaohongshu, WeChat MP) may still block it. For those, wait for Chrome MCP recovery.
Pitfall: Multi-instance Bridge Single-Transport Lockout (2026-08-07)
Symptom: Multiple Hermes instances (several CLI sessions + gateway) run at once; only ONE can use chrome MCP. Others get:
Failed to connect to MCP server: ... "Already connected to a transport. Call close() before connecting to a new transport"
or ClosedResourceError / TimeoutError on tool calls, while hermes mcp test chrome (fresh process) succeeds.
Root Cause 1 (single-transport Server singleton): dist/mcp/mcp-server.js caches a SINGLETON Server and calls .connect() per new transport. MCP SDK Server.connect() only allows ONE transport. First client wins, all others 500.
Fix (patch applied 2026-08-07): rewrite getMcpServer() to build a FRESH Server per call (setupTools re-runs per instance):
const getMcpServer = () => {
const server = new index_js_1.Server({ name: 'ChromeMcpServer', version: '1.0.0' }, { capabilities: { tools: {} } });
(0, register_tools_1.setupTools)(server);
return server;
};
NOTE: this file lives in /opt/homebrew/lib/node_modules/mcp-chrome-bridge/dist/mcp/mcp-server.js — npm upgrades will overwrite it; keep a re-apply script.
Root Cause 2 (wrong bridge process): native messaging is a stdio pipe — the bridge that actually talks to the extension is the one spawned by the extension's connectNative, NOT one started by a standalone script. If you kill bridges and START via script, the HTTP server runs but tool calls time out (30s+) because the extension's port points at a different (now dead) bridge.
Fix: kill ALL mcp-chrome-bridge/dist/index.js processes, trigger extension reconnect (ensure_native from offscreen page via CDP), confirm exactly ONE bridge remains, then send START to THAT bridge. Verify with tools/call over HTTP (should return in <1s, not 30s).
Root Cause 3 (wechat-profile manifest missing): Chrome launched with --user-data-dir=~/.hermes/chrome-wechat-profile looks for native messaging manifests ONLY in <user-data-dir>/NativeMessagingHosts/. mcp-chrome-bridge doctor checks the default path and reports all OK — misleading. Copy the manifest:
cp "/Users/jinguo/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.chromemcp.nativehost.json" \
/Users/jinguo/.hermes/chrome-wechat-profile/NativeMessagingHosts/
Root Cause 4 (extension not loaded in CDP Chrome): Extensions.loadUnpacked via CDP loads at runtime only — Chrome restart loses it. Persist via launchd plist --load-extension=/Users/jinguo/chrome-mcp-server (com.hermes.wechat-chrome.plist). Extension ID from manifest key: compute properly (CDP returns the real ID on loadUnpacked — trust that).
Diagnostic sequence that works:
curl -s http://127.0.0.1:12306/ping — bridge up?
- Full MCP protocol probe over HTTP (initialize → initialized → tools/list → tools/call) — isolates bridge vs client. tools/list takes ~20s (listDynamicFlowTools queries extension with 20s timeout — NORMAL, don't panic).
hermes mcp test chrome — fresh-process connect (bypasses stuck client state).
- If tool call hangs 30s over HTTP: bridge is not the extension's bridge (Root Cause 2).
Verification
After setup, these tools become available (prefixed with mcp_chrome_):
chrome_navigate - Navigate to URL
chrome_get_web_content - Extract page content
chrome_click_element - Click elements
chrome_screenshot - Capture screenshots
chrome_get_interactive_elements - List clickable elements
chrome_fill_or_select - Form input
chrome_history - Access browsing history
chrome_bookmark_search/add/delete - Bookmark management
Troubleshooting
Quick Diagnostic Commands
mcp-chrome-bridge doctor
tail -50 ~/Library/Logs/mcp-chrome-bridge/native_host_stderr_*.log
cat ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.chromemcp.nativehost.json
find ~/Library/pnpm -name "mcp-server-stdio.js" 2>/dev/null
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | node /path/to/mcp-server-stdio.js
curl http://127.0.0.1:12306/ping
mcp-chrome-bridge report
Check Logs
ls ~/Library/Logs/mcp-chrome-bridge/
cat ~/Library/Logs/mcp-chrome-bridge/native_host_stderr_unix_*.log
Full Diagnostic Report
mcp-chrome-bridge report
Reset Everything
npm uninstall -g mcp-chrome-bridge
rm ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.chromemcp.nativehost.json
References
- Browser automation patterns — Techniques for interacting with complex SPAs (Excalidraw, etc.) via Chrome MCP tools: dismissing overlays, typing Chinese text, keyboard shortcuts, coordinate-based clicks, localStorage injection
- Browser automation tools on this Mac — Decision framework for Chrome MCP vs agent-browser vs AutoCLI: when to use each, install paths, and key limitations
- Bookmarks file fallback — Direct Chrome Bookmarks JSON manipulation when MCP tools are unreachable (read, analyze duplicates, find duplicates, kill stale bridge processes)
- Session-specific troubleshooting logs — Error transcripts, fixes, and configuration details from July 2026 setup session
- Single-transport competition 2026-08-07 — full diagnosis transcript for multi-process bridge slot contention (
Already connected to a transport HTTP 500, ERR_HTTP_HEADERS_SENT crash residue, kill-chain recovery, extension-only bridge restart)
- Port configuration details
- Node version compatibility matrix
- Chrome MCP Server GitHub
- MCP Documentation