Metadata-Version: 2.5
Name: chrome-mcp
Version: 0.2.0
Summary: MCP server for browser automation using DrissionPage
Author: xiyiyiru
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: automation,browser,chrome,claude,drissionpage,llm,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: drissionpage>=4.1
Requires-Dist: loguru>=0.7.3
Requires-Dist: mcp<3,>=2.1
Description-Content-Type: text/markdown

# chrome-mcp

[English](./README.md) | [简体中文](./README.zh-CN.md)

A [Model Context Protocol](https://modelcontextprotocol.io) server for browser automation, powered by [DrissionPage](https://github.com/g1879/DrissionPage).

Lets MCP clients (Claude Desktop, Claude Code, Cursor, etc.) drive a real Chromium browser through a minimal 7-tool surface — all sharing one "current tab" pointer.

## Why

- **Zero learning curve for agents.** Facade tools (`execute_js`, `run_cdp`, `navigate`, `capture`) speak only universal knowledge — JavaScript, the CDP protocol, URLs. No niche-library syntax required for the 90% cases.
- **Full power underneath.** `run_drission_code` is the complete-capability base: execute DrissionPage Python code in-process with `page` / `browser` / `context` (persistent dict) / `switch_tab()` / `tabs()` / `relaunch()` injected — loops, waits, multi-tab orchestration, anything one tool call can't express.
- **One pointer, always in sync.** Switch tabs via DrissionPage code or `Target.createTarget`/`Target.activateTarget` CDP commands — every tool follows. (Call tools serially per session; the shared pointer is not concurrency-safe.)
- **Multi-instance safe.** Per-process isolation (atomic port allocation via `socket.bind` + PID/UUID private user-data dirs) — spawn N servers, zero conflicts.
- **Self-documenting.** `get_manual` returns a compact built-in cheat sheet (DrissionPage locator syntax, error-prone CDP recipes, capture workflow, launch options) — agents fetch it on demand, zero token cost otherwise.

## Installation

```bash
uv tool install chrome-mcp
# or
uvx chrome-mcp
# or
pip install chrome-mcp
```

Requires Python ≥ 3.10 and a local Chromium-based browser.

## Usage

Add to your MCP client config (e.g. `claude_desktop_config.json`). Two equivalent forms:

```json
{
  "mcpServers": {
    "chrome": {
      "command": "chrome-mcp"
    }
  }
}
```

Or run on the fly with `uvx` (no install needed):

```json
{
  "mcpServers": {
    "chrome": {
      "command": "uvx",
      "args": ["chrome-mcp"]
    }
  }
}
```

A typical agent flow:

```
navigate("https://httpbin.org/get")                  → returns tab list
execute_js("return document.body.innerText")         → page data as JSON
capture(action="start", url_filter="api/")
... trigger requests ...
capture(action="get")                                → overview inline,
                                                       full bodies in $TMPDIR/chrome-mcp-captures/*.json
```

### Tools

| Tool | Description |
|---|---|
| `navigate` | Navigate in current tab, or open a new tab (`new_tab`) and switch the pointer to it. Returns the full tab list |
| `execute_js` | Run JavaScript in the current tab (must `return` the result). `preset: "dom_tree"` outputs a DOM structure tree without writing the template |
| `run_cdp` | Raw CDP passthrough to the current tab. `Target.createTarget` / `activateTarget` auto-switch the pointer — no `attachToTarget` needed |
| `run_drission_code` | **Full-capability base**: execute DrissionPage Python code with injected `page`/`browser`/`context`/`switch_tab()`/`tabs()`/`relaunch()` |
| `capture` | Network capture in one tool: `action` = `start` / `get` / `stop`. Overview returned inline; full data (with bodies) saved to `$TMPDIR/chrome-mcp-captures/capture_*.json` |
| `get_manual` | Return the built-in authoring manual (locator syntax, CDP recipes, capture workflow, launch options) |
| `close_browser` | Close the browser instance |

### Launch options

Customize browser startup via command-line args:

```json
{
  "mcpServers": {
    "chrome": {
      "command": "chrome-mcp",
      "args": ["--headless", "--proxy", "http://127.0.0.1:7890", "--arg", "--lang=zh-CN"]
    }
  }
}
```

| Arg | Description |
|---|---|
| `--headless` | Run browser headless |
| `--proxy URL` | Proxy server |
| `--user-agent UA` | Custom User-Agent |
| `--user-data PATH` | User data dir to reuse login state. ⚠️ Conflicts if your system Chrome is using the same profile |
| `--browser-path PATH` | Path to a specific browser binary |
| `--incognito` | Incognito mode |
| `--no-imgs` | Don't load images. ⚠️ May be ignored by recent Chrome versions — reliable alternative: `run_cdp("Network.setBlockedURLs", {"urls": ["*.png", "*.jpg"]})` |
| `--arg ARG` | Pass through any Chrome flag (repeatable) |

Options can also be changed mid-session (destructive, restarts the browser) from inside `run_drission_code`:

```python
return relaunch(headless=True, user_agent="Mozilla/5.0 ...")
```

## Testing

8 scenario suites run against the real MCP stdio protocol (each spawns an independent server + headless browser — itself a multi-instance concurrency test):

```bash
uv run python tests/run_all.py            # full regression
uv run python tests/run_all.py --only smoke,c
```

Covers: data extraction (DOM tree/pagination/iframes), form interaction (DP actions + CDP input sequences), network capture (filters/timing traps/body fidelity), multi-tab pointer consistency, CDP capabilities (screenshots/emulation/cookies), lifecycle (relaunch/kill-recovery), and real-site scenarios (httpbin/TLS).

## License

[GPL-3.0-only](./LICENSE)
