{"id":"f1cc598a-2db8-4a71-824a-c4ab355ac0cc","slug":"chrome-devtools-mcp-wrapper","kind":"mcp","name":"chrome-devtools-mcp-wrapper","summary":"Share one Chrome across all your AI coding sessions — MCP proxy for chrome-devtools-mcp with Chrome lifecycle management, tool filtering and anti-detect","owner":"CornWorld","repoUrl":"https://github.com/CornWorld/chrome-devtools-mcp-wrapper","license":"MIT","licenseTier":"permissive","trust":"community","stars":2,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-09-08T05:12:53.000Z","addedAt":"2026-10-21T05:05:59.002Z","logoUrl":"https://avatars.githubusercontent.com/u/43746030?u=d8953d85187fbe655db918607d1e06292f00e690&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["browser-web","cloud-infra"],"tags":["ai-tools","browser-automation","chrome-devtools"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-28T00:05:20.016Z","sample":false,"url":"https://conduits.dev/tools/chrome-devtools-mcp-wrapper","language":"JavaScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# chrome-devtools-mcp-wrapper\n\n**Share one Chrome across all your AI coding sessions.**\n\nA thin proxy wrapper around Google's [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) that adds what the upstream server assumes away: multiple MCP clients are going to run at the same time, and they shouldn't each own a browser.\n\n```\n omp ─┐\nclaude ├─ stdio ──▶ chrome-devtools-mcp-wrapper ── npx ──▶ chrome-devtools-mcp ──CDP──▶ Chrome (shared)\ncursor ┘             lifecycle · filtering ·             (official, unmodified)\n                     anti-detect · logging\n```\n\n## The problem\n\n`chrome-devtools-mcp` is a single-client server: every MCP client that spawns it launches its **own** Chrome instance. Run three AI assistants (or three sessions of one) and you get three browsers competing for memory — each with a separate profile, separate login state, and no coordination on shutdown.\n\n## What this adds\n\n| Capability | What it does |\n|---|---|\n| **Chrome lifecycle & refcounting** | First client launches Chrome; later clients attach to the same instance via a PID-verified lock file. The browser shuts down only when the last client disconnects. Works across different MCP clients and across sessions. |\n| **Anti-detect launch** | Hides automation flags (`AutomationControlled`, `navigator.webdriver`, infobars, …) plus a set of stability args distilled from a production crawler. Pages that treat headless/automated browsers differently see a normal browser. |\n| **Tool filtering** | `--block-tools` / `--allow-only` to hide upstream tools from the model — useful when an agent keeps reaching for destructive tools. |\n| **Custom tools** | `--init-script` loads your own JS that registers extra MCP tools alongside the upstream ones. |\n| **Structured logging** | Per-session log files with size caps, rotation and rate limiting under `~/.cache/cdp-wrapper/logs/`. |\n\nThe upstream server itself runs **unmodified** — the wrapper spawns it via `npx chrome-devtools-mcp@latest`, wires its Chrome connection, and filters what passes through.\n\n## Requirements\n\n- Node ≥ 18\n- Google Chrome (any recent stable; the wrapper locates it, including Playwright-managed installs)\n- `npx` (bundled with npm) — the upstream server is fetched on first run\n\n## Quickstart\n\n```bash\ngit clone https://github.com/CornWorld/chrome-devtools-mcp-wrapper.git\ncd chrome-devtools-mcp-wrapper\nnpm install\n\n# smoke test: launches Chrome (or reuses a running one) and starts the proxy\nnpm start -- --profile=default\n```\n\nRegister it with your MCP client instead of the plain server. For Claude-style `mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"chrome-devtools\": {\n      \"command\": \"node\",\n      \"args\": [\n        \"/absolute/path/to/chrome-devtools-mcp-wrapper/index.mjs\",\n        \"--profile=default\"\n      ]\n    }\n  }\n}\n```\n\nFor [OMP](https://github.com/can1357/oh-my-pi), put the same block in `~/.omp/agent/mcp.json` (user scope — applies to every project) or `<project>/.omp/mcp.json` (project scope).\n\nSee [.mcp.json.example](.mcp.json.example) for a config with tool filtering and debug logging enabled.\n\n## CLI reference\n\n```\nnode index.mjs [options] [-- upstream-args...]\n```\n\n| Flag | Effect |\n|---|---|\n| `--profile=<name>` | Named Chrome profile. All clients using the same name share one browser instance. Omitted → `shared-lite` (a single shared instance). |\n| `--headless` / `--no-headless` | Headless (default) vs. visible browser window. |\n| `--block-tools=t1,t2` | Hide the named upstream tools from clients. |\n| `--allow-only=t1,t2` | Inverse: expose **only** these tools (wins over `--block-tools`). |\n| `--init-script=<path>` | JS module exporting custom MCP tool definitions to register. |\n| `--chrome-arg=<arg>` | Append a raw Chrome launch arg (repeatable). |\n| `--no-chrome` | Don't manage a browser; connect to an existing one via `--browser-url`. |\n| `--browser-url=<url>` | CDP endpoint of an externally managed Chrome (with `--no-chrome`). |\n| `--debug` | Verbose wrapper logging (or `DEBUG=wrapper:*`). |\n| `-- <args>` | Anything after `--` is passed through to the upstream server verbatim. |\n\n### Profiles\n\nA profile is a Chrome user-data directory plus a lock file. Clients that agree on a profile name share its browser; different profiles mean different browsers (useful to isolate work projects from personal ones, or headed from headless).\n\n- `--profile=work` and `--profile=personal` → two independent Chrome instances\n- no flag → `shared-lite`, one instance for everything\n- profile state (lock files, user-data dirs) lives under `~/.cache/cdp-wrapper/`\n\n## Upstream version policy\n\nThe wrapper launches the upstream server with `npx chrome-devtools-mcp@latest` and currently passes `--experimentalPageIdRouting` / `--experimentalStructuredContent`. This means:\n\n- upstream fixes and features arrive automatically; no version pin to maintain\n- **but** an upstream breaking change to those experimental flags can break the wrapper on a fresh `npx` fetch. If you need stability, change `upstreamArgs` in `index.mjs` to a pinned version (`chrome-devtools-mcp@1.8.0`).\n\n## Logging\n\nEach session writes `~/.cache/cdp-wrapper/logs/wrapper-YYYYMMDD-HHMMSS-<pid>.log` (path also printed to stderr at startup). Tunables via environment:\n\n| Var | Default | Meaning |\n|---|---|---|\n| `LOG_DIR` | `~/.cache/cdp-wrapper/logs` | log directory |\n| `LOG_MAX_BYTES` | 10485760 | rotate threshold per file |\n| `LOG_MAX_FILES` | 5 | rotated files kept per session |\n| `LOG_RATE_LIMIT_COUNT` / `LOG_RATE_LIMIT_WINDOW_MS` | 200 / 1000 | write-rate circuit breaker |\n| `DEBUG` | — | `wrapper:*` for wrapper-only, `*` for everything |\n\n## Notes & disclaimers\n\n- The anti-detect layer exists to keep automation from being *needlessly* flagged while testing your own sites and apps. Using it against services you don't have permission to automate may violate their terms of service — that's on you.\n- The wrapper is a transparent pass-through for MCP traffic; it does not inspect or alter tool results beyond dropping filtered tools.\n\n## License\n\n[MIT](LICENSE)\n"}