The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the MCP Cdp listing page.
A safe-by-default Model Context Protocol server that drives an Electron or Chrome/Chromium app over the Chrome DevTools Protocol (CDP) — instead of pixel-level GUI automation. Point it at the app's --remote-debugging-port and an agent gets the DOM, console, network requests, real input (click / type / navigate), and — gated — JavaScript evaluation.
Why this beats computer-use for a desktop/web app:
Part of the dockndevai MCP server suite — one governance model across all of them.
Starts read-only (see Safe by default); higher-capability tools are only registered when you raise the mode.
| Tool | For | Needs mode |
|---|---|---|
list_targets | list pages / webviews / Electron windows (id, type, title, url) | read-only |
dom_snapshot | rendered HTML of the page or a selector's subtree | read-only |
query_dom | outer HTML of every element matching a CSS selector | read-only |
console_logs | recent console output + uncaught exceptions | read-only |
network_requests | recent requests (method, url, status, mime; headers never captured) | read-only |
screenshot | a PNG of the viewport | read-only |
click | click the first element matching a selector | read-write |
type_text | type into the page (focus a selector first) | read-write |
press_key | Enter / Tab / Escape / Backspace / Delete / Arrows | read-write |
navigate | navigate a target to a URL (confirmed) | read-write |
evaluate | run a JavaScript expression in the page | admin + CDP_ALLOW_EVAL |
Start your app (or a worktree's dev build) with an explicit port — one per agent:
your-app --remote-debugging-port=9222, or in main-process code
app.commandLine.appendSwitch('remote-debugging-port', '9222') before app.whenReady().chrome --headless=new --remote-debugging-port=9222 --user-data-dir=/tmp/p1 <url>.Check it's up: curl http://127.0.0.1:9222/json/version.
See docs/CLIENTS.md for Claude Code / Cursor / Codex / VS Code / Windsurf, and .env.example for every variable.
Enforced by src/security.ts. The browser process is the real boundary — this keeps an agent inside the targets and actions you intend:
CDP_MODE — read-only (default) → read-write → admin. Tools above the mode aren't registered, so in read-only the agent cannot click, type or navigate at all.CDP_TARGET_ALLOWLIST — confine interactions to targets whose URL matches your patterns (empty = all). Reads (inspection) are always allowed.CDP_PROTECTED_TARGETS — targets that can be inspected but never interacted with. Defaults protect sign-in pages (accounts.google.com, login.microsoftonline.com, …) and browser internals (chrome://, devtools://, extensions).CDP_ALLOW_EVAL — evaluate is arbitrary code execution in the renderer: admin mode plus this flag, refused on protected targets, with a human confirmation.CDP_DRY_RUN — interactions log their intent and return without dispatching.evaluate and navigate also prompt a human via MCP elicitation.127.0.0.1 unless CDP_ALLOW_REMOTE=true.Optional AI risk guard. Set CDP_GUARD_MODE=monitor|enforce to have the evaluate tool consult a local laya-guard daemon (pipx install laya-guard && laya-guard) that classifies the JS expression allow/confirm/block before it runs. It runs after the eval gate and can only tighten, never grant; fails closed.
There is a bundled skill, cdp-safe-operations, that teaches an agent how to expose a port, read the DOM/console/network instead of screenshots, the safety rules, and the "why did this fail?" workflow. See also SECURITY.md.
MIT