cdp-browser-mcp
# cdp-browser-mcp
MCP server that **attaches to an already-running Chromium browser** over the Chrome DevTools Protocol (CDP). It does not launch a browser. One process can hold many sessions, so an agent can drive several profiles at once.
Works with:
- Chrome / Edge started with `--remote-debugging-port=9222`
- Fingerprint browsers (AdsPower, BitBrowser, GoLogin, Multilogin, …)
- Cloud or local CDP endpoints (`http://127.0.0.1:9222`, `ws://…`)
Uses [Patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright) (`connectOverCDP`) so the attached context is less likely to be patched by anti-bot checks than stock Playwright.
Install from GitHub (no npm publish). Requires **Node.js 18+**. No Chromium download is needed.
```text
npx -y github:killaragorn/cdp-browser-mcp
```
## Cursor
Add to `~/.cursor/mcp.json` (or project `.cursor/mcp.json`):
```json
{
"mcpServers": {
"cdp-browser-mcp": {
"command": "npx",
"args": ["-y", "github:killaragorn/cdp-browser-mcp"]
}
}
}
```
## Claude Desktop
Add to `claude_desktop_config.json`:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"cdp-browser-mcp": {
"command": "npx",
"args": ["-y", "github:killaragorn/cdp-browser-mcp"]
}
}
}
```
## Claude Code
```bash
claude mcp add --scope user cdp-browser-mcp -- npx -y github:killaragorn/cdp-browser-mcp
```
Or commit `.mcp.json` in a project so teammates get the same server:
```json
{
"mcpServers": {
"cdp-browser-mcp": {
"command": "npx",
"args": ["-y", "github:killaragorn/cdp-browser-mcp"]
}
}
}
```
## Codex
```bash
codex mcp add cdp-browser-mcp -- npx -y github:killaragorn/cdp-browser-mcp
```
Or add to `~/.codex/config.toml`:
```toml
[mcp_servers.cdp-browser-mcp]
command = "npx"
args = ["-y", "github:killaragorn/cdp-browser-mcp"]
```
## Local clone
```bash
git clone https://github.com/killaragorn/cdp-browser-mcp.git
cd cdp-browser-mcp
npm install
```
Then point the client at `node /absolute/path/to/cdp-browser-mcp/index.mjs`.
## Typical flow
1. Start a browser with CDP, for example:
```bash
chrome --remote-debugging-port=9222
```
Or copy the debug URL from AdsPower / BitBrowser (often `http://127.0.0.1:xxxx`).
2. Ask the agent to connect, then operate the page:
- `cdp_connect` → `{ "cdp_url": "http://127.0.0.1:9222", "capture_dir": "D:/captures/run1" }`
- or `cdp_network_start` with `dir` after connect
- Each request is saved as `{dir}/000001_GET_host-path.json` plus `requests.jsonl`
- `cdp_close` when finished
## Tools
Connect first with `cdp_connect`. Network capture stays **off** unless you pass `capture_dir` or call `cdp_network_start`.
**Session / navigation**
| Tool | Purpose |
| --- | --- |
| `cdp_connect` | Attach to a CDP URL; optional `capture_dir` starts saving requests to that folder |
| `cdp_navigate` | Open a URL |
| `cdp_reload` | Reload |
| `cdp_go_back` | History back |
| `cdp_page_info` | URL, title, frames |
| `cdp_content` | Page HTML or a selector's innerHTML |
| `cdp_screenshot` | PNG screenshot |
| `cdp_list_sessions` | List active sessions |
| `cdp_close` | Disconnect one session |
**Input**
| Tool | Purpose |
| --- | --- |
| `cdp_click` | Click selector or `(x, y)`; `button`, `click_count`, `modifiers` |
| `cdp_hover` | Hover a selector |
| `cdp_mouse_move` | Move mouse to coordinates |
| `cdp_type` | Input text: `mode=fill` / `type` (key events) / `insert` (paste-like); optional `press_enter` |
| `cdp_press` | Key or shortcut: `Enter`, `Tab`, `Control+A` |
| `cdp_select` | `<select>` by value / label / index |
| `cdp_check` | Check or uncheck |
| `cdp_upload` | File input (`files` are local paths on the MCP host) |
| `cdp_scroll` | Into view, mouse wheel, or `scrollTo` |
| `cdp_evaluate` | Run JavaScript |
| `cdp_wait` | Wait for a selector or a timeout |
**Network**
Capture is off by default. Pass `capture_dir` on connect, or call `cdp_network_start`. Every matching request is written to disk with **no count limit**. xhr/fetch/document/JSON response bodies are stored in full.
```
{capture_dir}/
capture.json
requests.jsonl
000001_GET_example.com-.json
000002_POST_api.example.com-login.json
```
| Tool | Purpose |
| --- | --- |
| `cdp_network_start` | Start capture into `dir`; optional `url_contains` / `method` / `resource_type` |
| `cdp_network_stop` | Stop capture; files on disk are kept |
| `cdp_network_log` | List saved files (default last 50 summaries) |
| `cdp_wait_response` | Wait for a response whose URL contains a string |
**Cookies**
| Tool | Purpose |
| --- | --- |
| `cdp_get_cookies` | Read cookies |
| `cdp_set_cookies` | Write cookies |
## Why this exists
`@playwright/mcp` launches (or binds) a single browser from CLI flags. This server is the opposite shape:
- **Connect is a tool**, not a startup flag — the agent picks the CDP URL at runtime
- **Many sessions** in one MCP process (one AdsPower profile per `session_id`)
- **Patchright** instead of Playwright, aimed at already-fingerprinted browsers
## License
MIT
TDQS
Scored across 26 tools
Each tool targets a distinct browser action or resource, and even similar tools like cdp_hover and cdp_mouse_move are clearly differentiated by element targeting vs coordinates. No two tools have overlapping purposes.
All tools share the cdp_ prefix, but the suffix is inconsistent: most are verb_noun (cdp_navigate, cdp_click), but several are noun_verb (cdp_mouse_move, cdp_network_start) or pure nouns (cdp_content, cdp_page_info). This creates mild inconsistency but remains readable.
26 tools is slightly high but appropriate for a comprehensive CDP browser automation server; each tool maps to a distinct browser feature (navigation, input, network, cookies, sessions), so none feel redundant.
The set covers navigation, interaction, network, cookies, and sessions well, but lacks tab management (new/switch/close tabs), dialog handling (alert/confirm/prompt), and iframe/frame context switching—gaps that could hinder full browser automation scenarios.