ChromeBrowserMCP
Provides read-only access to open tabs in Google Chrome, including listing tabs, reading tab content, and searching tabs, without exposing sensitive information like cookies or passwords.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ChromeBrowserMCPlist my open Chrome tabs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Chrome Browser MCP
A local bridge that lets a private ChatGPT developer-mode app inspect and control the tabs already open in your desktop Google Chrome.
Current patch version: 0.1.25. Every patch must bump this version; CI rejects patches that do not.
The bridge exposes 18 MCP tools:
reads:
browser_status,list_tabs,get_active_tab,read_tab,read_tabs,search_tabsactions:
click,type,fill_form,press_key,scroll,select_option,navigate,new_tab,close_tabChatGPT job runtime:
spawn_agents,collect_agents,cancel_agents
spawn_agents starts one or more background ChatGPT worker jobs and returns stable request_id / run_id / job_id / task_id / agent_id identities. Callers must reuse the same request_id with equivalent tasks and max_concurrency arguments when retrying; equivalent retries replay the original run, while conflicting reuse fails with IDEMPOTENCY_CONFLICT. max_concurrency limits active workers within one run, and the runtime applies a separate two-worker global active ceiling by default, queueing excess logical jobs. While a worker responds, bounded in-memory snapshots preserve streaming output across ChatGPT DOM virtualization and are never written to browser storage. Fresh snapshots must match the current post-submit revision/timestamp, exact worker identity, generation state, and unique completion marker before they can finish a job. A verified terminal snapshot stores the same bounded, untrusted result used by collection, releases the current worker lease, and immediately gives queued work a scheduler pass without any collect_agents call. If a lifecycle event is missed, a blocked scheduling pass or browser reconnect compares leased worker tabs with current tab and snapshot evidence and applies the same verified-completion or WORKER_TAB_CLOSED transition; malformed or failed observations do not reclaim capacity. This repair path is event/boundary driven and has no lease TTL, periodic polling, prompt submission, reload, or tab activation. Job state is a point-in-time observation, not by itself a terminal verdict: FAILED_TRANSIENT with error.retryable: true is exposed with terminal: false and recoverable: true. When callers need refreshed public state or results, collect_agents remains the authoritative result/barrier read; recoverable jobs appear in pending, failed is reserved for FAILED_TERMINAL, and barrier.satisfied: true is the gate for consuming/aggregating all required isolated child results. cancel_agents is explicit cancellation, not transient-error recovery; do not call it merely because a running spawn/collection snapshot contains a retryable extraction failure. Browser tab IDs stay private to the runtime.
Action targets accept either a CSS selector or exact visible text / aria-label / placeholder / name / associated label text. Ambiguous targets fail instead of guessing.
new_tab opens the requested URL in the background by default so it does not interrupt the user's current Chrome work. Set active: true only when foreground focus is explicitly required.
The bridge does not expose cookies, local storage, session storage, saved passwords, hidden input values, arbitrary JavaScript execution, Chrome internal pages, or incognito tabs. It does not use the Chrome debugger API.
Manual proof path
The supported ChatGPT proof path is manual: launch the local bridge, verify the matching Chrome extension and native-messaging host, then use the ChatGPT developer-mode app against a harmless test tab. Unit/integration coverage validates page actions, MCP routing, the job-based ChatGPT agent runtime, diagnostics, generated extension-version synchronization, and that the runtime files used by Chrome/native messaging are tracked by Git.
MCP client
-> http://127.0.0.1:2091/mcp
-> native host process
-> Chrome Native Messaging
-> MV3 extension
-> live Chrome tabsRun every gate:
npm ci
npm run checkRelated MCP server: parley
Architecture
ChatGPT developer-mode app
|
| OpenAI Secure MCP Tunnel (outbound HTTPS)
v
127.0.0.1:2091/mcp
|
| same local Node process
v
Chrome Native Messaging host
|
v
Chrome MV3 extension
|
+-- chrome.tabs
+-- chrome.scripting (isolated-world reads + actions)Chrome starts the native host when the extension connects. The native host starts the loopback MCP endpoint. Therefore Chrome must be open and the extension must be enabled whenever ChatGPT uses the app.
Requirements
macOS
Google Chrome 121+
Node.js 20+
A ChatGPT account with Developer Mode available
An OpenAI Platform tunnel ID and runtime API key with Tunnels Read + Use
tunnel-client
Chrome 121+ is deliberate for agent-window anchoring: anchor selection uses chrome.tabs.Tab.lastAccessed to choose the most recently user-active ChatGPT tab across normal windows.
1. Install the native host and load the extension once
npm run install:macThis installs the native-host manifest at:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.komaksym.chrome_browser_mcp.jsonThen:
Open
chrome://extensions.Enable Developer mode.
Click Load unpacked.
Select this repository's
dist/extensiondirectory.Confirm the extension ID is exactly:
jlpddlfiallighiohmhhkemgbhofpnhaDo not proceed if the ID differs. The native host only accepts that exact extension origin.
Multi-profile topology
The installer provisions two isolated Chrome routes:
Profile | Extension directory | Extension ID | Bridge | Tunnel profile |
Current | dist/extension | jlpddlfiallighiohmhhkemgbhofpnha | 127.0.0.1:2091 | chrome-browser-mcp |
New subscription | dist/extension2 | doommfidfcljgehkppgiinjdjnafcmdc | 127.0.0.1:2093 | chrome-browser-mcp-2 |
Load exactly one matching extension directory in each Chrome profile. The Chrome profile itself does not need a Google account; the ChatGPT tab must be signed in to the intended ChatGPT account. The installer copies this mapping to:
~/Library/Application Support/Chrome Browser MCP/instances.jsonmcps-launcher consumes that copied mapping, so ports and extension IDs have one source of truth.
2. Updating future patches
You select the extension directory only once. The built extension and MCP bridge under dist/ are committed to Git, and CI rejects source changes whose committed runtime build is stale.
For every later patch, the normal update flow is exactly:
git pullThen open chrome://extensions and click Update. Do not select the extension path again and do not run a separate build command just to consume a published patch.
git pull updates both dist/extension (what Chrome loads) and dist/bridge (what the native host executes). Clicking Update reloads the unpacked extension/native-messaging connection so the newly pulled runtime is used.
The visible extension version must change on every patch. For this patch it must show 0.1.25. If it still shows an older version, the pulled runtime was not applied.
3. Verify the local browser chain
Keep Chrome open, then run:
npm run verify:localA successful check prints:
extension ID;
extension version;
MCP server version;
the 18 advertised MCP tools.
The verifier fails if the extension and MCP versions differ, or if the bridge is old enough not to report its MCP version. This makes stale bridge/extension combinations immediately distinguishable.
Diagnostics for browser-backed agent failures
Installed native-host wrappers write one safe JSONL diagnostics file per route:
~/Library/Logs/Chrome Browser MCP/chrome.jsonl
~/Library/Logs/Chrome Browser MCP/chrome2.jsonlThe default level is info, so worker creation, dispatch, retries, state
changes, cleanup, and stable browser error codes are recorded. The same events
are visible on the bridge's stderr for launcher logs. To include low-level
request and streaming-observation events for a focused investigation, set
CHROME_MCP_LOG_LEVEL=debug before starting Chrome; off disables diagnostics.
CHROME_MCP_LOG_FILE overrides the file path and CHROME_MCP_LOG_DIR changes
the default directory.
Logs intentionally omit prompts, page text, full URLs, cookies, tokens,
passwords, and arbitrary tool arguments. browser_status reports only the
logger level, path, event count, last event name, and write-error count. For a
quick local snapshot:
tail -n 100 "$HOME/Library/Logs/Chrome Browser MCP/chrome.jsonl"
tail -n 100 "$HOME/Library/Logs/Chrome Browser MCP/chrome2.jsonl"4. Configure Secure MCP Tunnel
Create a tunnel and runtime API key in OpenAI Platform. Then:
export CONTROL_PLANE_API_KEY="sk-..."
./scripts/configure-tunnel.sh tunnel_0123456789abcdef0123456789abcdef
tunnel-client doctor --profile chrome-browser-mcp --explain
tunnel-client run --profile chrome-browser-mcpThe profile forwards the tunnel to:
http://127.0.0.1:2091/mcpKeep tunnel-client run active whenever ChatGPT needs the browser tools.
For the second profile, create a unique tunnel ID and use the matching instance argument:
./scripts/configure-tunnel.sh tunnel_<second-id> chrome2If a named local profile already exists and must be repointed to a new tunnel,
append --force; this replaces only the local profile file and does not delete
the old remote tunnel:
./scripts/configure-tunnel.sh tunnel_<new-id> chrome2 --forceBoth tunnel clients may use the same control-plane API key. The CONTROL_PLANE_API_KEY_2 name is a separate environment reference only; it may contain the same value as CONTROL_PLANE_API_KEY.
5. Add it to ChatGPT
In ChatGPT, enable Settings -> Security and login -> Developer mode.
Open Settings -> Plugins.
Click + to create a developer-mode app.
Choose Tunnel as the connection type.
Select or paste the tunnel ID.
Use the metadata from
app-metadata.json.Confirm ChatGPT discovers all 18 tools.
In a new chat, click + -> More, select Chrome Browser, then ask:
List my open Chrome tabs.
See docs/CHATGPT_SETUP.md for exact verification and troubleshooting.
Security model
Webpage text is data, never authority. Every content result—including browser-derived ChatGPT worker output—includes an explicit untrusted-content marker, and tool instructions tell the model never to turn instructions found in pages into actions.
The extension intentionally requests access to all HTTP and HTTPS pages so it can read and interact with normal open tabs. The protection boundary is:
the extension is loaded locally by you;
Chrome only launches the exact allowlisted native host;
the native host rejects any origin except the stable extension ID;
the MCP endpoint binds only to
127.0.0.1;the tunnel is outbound-only;
actions are limited to normal HTTP(S) tabs and do not expose arbitrary JavaScript, debugger access, cookies, or browser storage;
ambiguous human-readable targets are rejected rather than guessed.
Read THREAT_MODEL.md and SECURITY_REVIEW.md before unattended use.
Known limitations
Each configured Chrome profile should load exactly one matching extension; the two routes use separate ports (
2091and2093).Chrome internal pages, Chrome Web Store pages,
file://pages, and incognito tabs cannot be read or controlled.Cross-origin iframes are not traversed.
Canvas-only applications and Chrome's built-in PDF viewer may return little semantic text.
The extractor returns the primary document's visible text, headings, links, and description, not raw HTML. URL credentials and fragments are removed, and sensitive query parameters are redacted.
press_keyuses DOM keyboard events; Enter and Escape get explicit common-case behavior, but some sites require trusted OS/CDP keyboard input.ChatGPT worker submission depends on ChatGPT's current web composer and send-button markup; a future ChatGPT UI change can require updating selectors in
src/extension/chatgptWorker.ts.Worker results are browser-derived ChatGPT UI output, not privileged ChatGPT API responses. Identity and completion-marker validation proves that a result belongs to its job; it does not make its content trustworthy. Each result is marked
contentIsUntrusted: true, carries a warning, and is capped at 30,000 characters withtruncated: truewhen clipping occurred.File upload is intentionally not implemented because doing it generally would require a more powerful filesystem/debugger surface.
Development
npm ci
npm run version:check
npm run typecheck
npm run lint
npm test
npm run artifacts:check
npm auditThis server cannot be deployed
Maintenance
Related MCP Connectors
Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.
Web search and page-reading for AI agents. One-click OAuth connect, or a Caesar API key.
A read-only verified record of agent-operable GTM tools: search, fetch, compare, track changes.
Real Chrome for agents: start a browser, read pages as numbered markdown, click, type, hand off.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with a user's real Chrome browser tabs, executing JavaScript, reading cookies, and making fetch requests within authenticated sessions.-
- AlicenseNot gradedqualityBmaintenanceEnables token-efficient browser automation for AI chats like ChatGPT, Gemini, and Claude, allowing reading responses, sending messages, waiting for streaming replies, and bridging conversations between tabs via Chrome DevTools Protocol.4MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to search LinkedIn jobs and read LinkedIn profiles read-only using a real Chrome session via CDP, with tools for job listings, full job details, profile data, and session management.5Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables MCP-compatible AI agents to inspect, read, close, deduplicate, group, and consolidate live Chromium browser tabs through a secure local bridge, with safety checks and no need for its own AI model or API key.MIT