MCP server (zendriver-mcp)
zendriver-mcp is a Model Context Protocol
server that exposes zendriver-rs through 70 MCP tools (71 with the
optional fingerprints feature), so any
MCP-compatible client (Claude Desktop, Claude Code, custom agents) can
drive a real, stealth-by-default Chrome browser.
Using Claude Code? The
zendriverplugin installs this server plus scraping skills, commands, and a subagent in two commands — see the plugin chapter.
Install
cargo install zendriver-mcp
The default build enables interception, expect, cloudflare,
imperva, datadome, monitor, fetcher, and tracker-blocking. The
fingerprints and geo features are opt-in (add
--features fingerprints,geo). For a lean build:
cargo install zendriver-mcp --no-default-features
Claude Desktop
{
"mcpServers": {
"zendriver": {
"command": "zendriver-mcp"
}
}
}
HTTP mode
zendriver-mcp --http 127.0.0.1:8765
Bind localhost-only by default. It is the operator's responsibility to expose the endpoint via a reverse proxy + mTLS / network policy for remote access.
CLI flags
zendriver-mcp [OPTIONS]
OPTIONS:
--http <ADDR> Run streamable HTTP transport on ADDR
(e.g. 127.0.0.1:8765). Default: stdio.
--stealth-profile <KIND> Default stealth profile.
[auto|native|spoof_macos|spoof_linux|spoof_windows]
Default: auto
--log <FILTER> Tracing log filter (EnvFilter syntax).
Default: info
-h, --help
-V, --version
Tool surface
70 tools across these categories (71 with the optional fingerprints
feature):
| Category | Tools | Count |
|---|---|---|
| Lifecycle | browser_open / _close / _status | 3 |
| Navigation | browser_goto / _back / _forward / _reload / _wait_for_idle / _wait_for_load / _bypass_insecure_warning | 7 |
| Scroll / Window | browser_scroll / _get_window / _set_window | 3 |
| Tabs | browser_tab_list / _new / _switch / _close / _activate | 5 |
| Find | browser_find / _find_all | 2 |
| Actions | browser_click / _hover / _type / _press / _key_sequence / _mouse / _set_value / _clear / _focus / _scroll_into_view / _upload | 11 |
| Reads | browser_element_state / _get_links / _search_resources | 3 |
| Snapshots / Export | browser_html / _screenshot / _pdf / _save_mhtml | 4 |
| Eval | browser_evaluate / _evaluate_main | 2 |
| Network | browser_request | 1 |
| Cookies | browser_cookies_get / _set / _delete / _clear / _persist | 5 |
| Storage | browser_storage_get / _set / _delete / _clear | 4 |
| Downloads | browser_download / _set_download_path | 2 |
| Frames | browser_frame_list / _frame_goto | 2 |
| Stealth | browser_set_stealth_profile / _set_user_agent | 2 |
| Interception (gated) | browser_intercept_add_rule / _remove_rule / _list_rules / _clear_rules | 4 |
| Expect (gated) | browser_expect_register / _await / _cancel | 3 |
| Cloudflare (gated) | browser_solve_turnstile | 1 |
| Imperva (gated) | browser_solve_imperva | 1 |
| DataDome (gated) | browser_solve_datadome | 1 |
| Fetcher (gated) | browser_install_chrome | 1 |
| Monitor (gated) | browser_monitor_start / _read / _stop | 3 |
| Fingerprint (gated) | browser_fingerprint_generate | 1 |
All find / action tools share a Selector arg — one-of css | xpath | text | text_exact | text_regex | role, with modifiers nth / visible_only / timeout_ms / frame_id. State-changing tools accept
return_snapshot: bool for one-call action + observe. browser_pdf /
_save_mhtml / _download return a binary-output shape ({ byte_len, saved_path? , base64? }): bytes go to save_path on the MCP host when
given, else base64-inline (capped at 5 MiB). The default build enables
interception / expect / cloudflare / imperva / datadome /
monitor / fetcher / tracker-blocking; fingerprints and geo are
opt-in.
Full JSON Schema for every tool's input + output is captured in
crates/zendriver-mcp/tests/snapshots/ and changes there require an
explicit cargo insta accept — the wire shape is reviewed.
browser_open options
browser_open accepts opt-in third-party tracker / fingerprinter blocking:
block_trackers: bool— enable blocking with the curated bundled list.tracker_blocklist— one of{ "url": "..." },{ "path": "..." }, or{ "domains": ["..."] }to add custom hosts (implicitly enables blocking). Requires the defaulttracker-blockingfeature.
The stealth-profile override accepts geo_country (ISO 3166-1 alpha-2, e.g.
"DE") to derive a coherent locale + Accept-Language. The field is always
present in the schema but only takes effect when the geo feature is enabled.
Stealth
Stealth is on by default (matching the zendriver library). Configure
the default fingerprint via --stealth-profile at server start; switch
live via browser_set_stealth_profile (takes effect on the next
browser_open).
Troubleshooting
- Logs go to stderr in stdio mode — stdout is reserved for MCP
JSON-RPC. Use
--log debugfor verbose CDP-call logging. - Errors include
_meta.suggested_nexthints when applicable (e.g.ElementNotFoundsuggests reconnaissance viabrowser_htmlor a freshbrowser_find_allsnapshot). - HTTP smoke test binds
127.0.0.1:18765by convention — if your environment has that port taken, set a different port via--http. - Real-Chrome integration tests are gated behind cargo feature
integration-testsand#[ignore]markers: run viacargo test -p zendriver-mcp --features integration-tests -- --ignored.