chrome-devtools-mcp-mux
Uses Puppeteer's bundled Chromium binary by default to control Chrome DevTools Protocol, providing browser automation capabilities through MCP.
Click on "Install 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., "@chrome-devtools-mcp-muxopen a new tab and navigate to example.com"
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-devtools-mcp-mux
Share one Chrome instance across many MCP clients. Each client — a separate Claude Code session, for example — gets its own isolated set of tabs, while they all run against the same single browser and profile.
What problem does this solve
chrome-devtools-mcp exposes Chrome DevTools to an MCP client. It works
perfectly for one client, but if two clients connect at once (two Claude Code
windows, a Claude Code plus a Gemini CLI, etc.) they step on each other's
tabs — list_pages shows everything, select_page races, new_page lands
in the wrong window.
cdmcp-mux sits between clients and chrome-devtools-mcp and gives each
connection its own isolated tab set, while keeping a single Chrome running.
Install and configure (one-time)
git clone <this-repo> chrome-devtools-mcp-mux
cd chrome-devtools-mcp-mux
npm install
npm run build
npm link # exposes `cdmcp-mux` on PATHThen, in every MCP client's .mcp.json:
{
"mcpServers": {
"chrome": { "command": "cdmcp-mux" }
}
}That's it. The first client to connect auto-spawns a shared daemon; subsequent clients attach to the same daemon.
How to verify it's working
Start two MCP clients with the config above. In each, ask the model to:
Open a different URL via
new_page.Run
list_pages.
Each client should see only its own page. On the host, run cdmcp-mux status
to see both contexts side-by-side in the daemon.
For a full scripted demo with a recorded video, see demo/.
Environment variables (optional)
Variable | Purpose |
| Chromium binary (defaults to bundled Puppeteer) |
| Override Chrome profile directory |
| Override unix socket path for the daemon |
|
|
|
|
Debugging
All out-of-band; the mux never exposes debug tools to MCP clients.
Command | What it does |
| daemon pid, upstream state, contexts, owned pages |
| stream the structured mux log |
The log lives at ~/.local/state/cdmcp-mux/mux.log.
How it works
flowchart TB
subgraph clients["one process per MCP client"]
direction LR
C1["Claude Code #1"] -- "stdio (MCP)" --> S1["cdmcp-mux shim"]
C2["Claude Code #2"] -- "stdio (MCP)" --> S2["cdmcp-mux shim"]
end
subgraph shared["shared — auto-spawned on first connect"]
direction TB
D["mux daemon<br/><i>per-connection context table</i><br/>(socket fd → ctxId → owned pageIds)"]
U["chrome-devtools-mcp subprocess<br/><code>--experimentalPageIdRouting</code><br/><code>--userDataDir <fixed></code>"]
B["Chromium<br/><i>one instance, one profile</i>"]
D -- "stdio (MCP)<br/>rewrite + filter" --> U
U -- "CDP" --> B
end
S1 -- "unix socket" --> D
S2 -- "unix socket" --> D
classDef client fill:#e3f2fd,stroke:#1976d2
classDef shim fill:#fff3e0,stroke:#f57c00
classDef core fill:#f3e5f5,stroke:#7b1fa2
classDef browser fill:#e8f5e9,stroke:#388e3c
class C1,C2 client
class S1,S2 shim
class D,U core
class B browserEach MCP client spawns its own cdmcp-mux shim (that's how .mcp.json works —
one child per client). The shim is a pure byte pipe between the client's stdio
and a unix socket; the first shim to connect auto-spawns the shared daemon,
later shims attach to it. The daemon owns one chrome-devtools-mcp
subprocess driving one Chromium with one --userDataDir.
Every unix-socket connection = one fresh BrowserContext (isolated cookies,
localStorage, WebSockets). The daemon advertises exactly the same tool schemas
as vanilla chrome-devtools-mcp — pageId and isolatedContext are stripped
from what the client sees, and re-injected on every tools/call from the
daemon's per-connection ownership table. Atomicity uses upstream's
--experimentalPageIdRouting, so concurrent calls from different contexts
can't clobber each other. When a client disconnects, its tabs are closed and
its browser context destroyed.
Development notes
This project was written end-to-end by a Claude-Code agent in a single working session, driven by live conversational requirements. The full test plan is tiered for functional correctness (58 tests, ~19 s, all passing), and the multiplexer was then visually demonstrated via a VNC-automated reproducer.
For the PRD-to-test mapping see DEMO.md. For the full agentic
development log — requirements discovery, architecture iteration, test
tiering, and the three takes of the video demo — see
demo/README.md.
Testing
# requires a Chromium binary; the smoke/e2e tests need it
CDMCP_MUX_CHROMIUM=/usr/bin/chromium npm testExpected: 8 files, 58 tests, all passing.
Releasing
CI runs on every push and PR against main using Node 22 and 24, building,
typechecking, and executing the full 58-test suite (including the real-Chromium
smoke and binary-e2e tests).
Publishing is automated via .github/workflows/publish.yml, which runs on a
GitHub release being published:
Bump
versioninpackage.json, commit, tag asv<version>.gh release create v<version> --generate-notes.The workflow builds, tests, and runs
npm publishwith npm provenance (signed via GitHub OIDC, the workflow hasid-token: write).
NPM_TOKEN is the only required repo secret. The package is published with
publishConfig.provenance: true, so the --provenance flag is implicit.
Once this repo is registered as a trusted publisher at npmjs.com, the
NPM_TOKEN secret can be removed entirely.
License
Apache-2.0 — see LICENSE. Same as upstream chrome-devtools-mcp.
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ochen1/chrome-devtools-mcp-mux'
If you have feedback or need assistance with the MCP directory API, please join our Discord server