Browser automation through Chrome DevTools Protocol. No Playwright. No Puppeteer. Just raw CDP over WebSocket.
Playwright MCP runs headless — and many websites detect and block it. Chrome in Claude's computer use struggles with file uploads, making tasks like applying for jobs harder than they should be. Both are heavier and more brittle than they need to be.
CDP MCP talks directly to Chrome over DevTools Protocol, controls a real visible browser, reads the accessibility tree to discover every interactive element on the page, and verifies that interactions actually worked. More lightweight, more robust, and designed for AI agents that need to actually use the web.
| Tool | What it does |
|---|---|
cdp_launch |
Launch Chrome with CDP enabled |
cdp_connect |
Connect to an existing Chrome instance |
cdp_navigate |
Go to URL, back, forward, refresh |
cdp_snapshot |
Get the accessibility tree with numbered [n] refs |
cdp_interact |
Click, type, select, check, press, upload, hover, focus, submit |
cdp_execute |
Run arbitrary JavaScript |
cdp_wait |
Wait for elements, text, navigation, network idle |
cdp_screenshot |
Capture viewport or full page |
cdp_tabs |
List, switch, close, or open tabs |
cdp_cookies |
Get, set, delete, clear cookies |
cdp_console |
Capture console output, JS errors, dialog info |
The core loop is two tools: snapshot and interact.
cdp_snapshot returns the page's accessibility tree — a structured view of every interactive element, each tagged with a numbered ref:
[1] button "Sign In"
[2] textbox "Email" value=""
[3] textbox "Password" value=""
[4] checkbox "Remember me" checked=false
[5] link "Forgot password?"
cdp_interact accepts those [n] refs directly as selectors, along with CSS selectors and text= prefix matching:
cdp_interact(action="type", selector="[2]", value="user@example.com")
cdp_interact(action="click", selector="text=Sign In")
cdp_interact(action="click", selector="#submit-btn")
Interactions are verified — if a React controlled input silently rejects your value, you'll know:
{
"success": true,
"action": "type",
"expected": "user@example.com",
"actual": "user@example.com"
}cdp_interact uses native property setters and dispatches the right events for React, Vue, and Angular inputs. It doesn't just set .value — it triggers the framework's internal change detection. If that fails, it falls back to CDP-level keystroke dispatch.
npm install
npm run buildAdd to your MCP config:
{
"mcpServers": {
"cdp": {
"type": "stdio",
"command": "node",
"args": ["/path/to/cdp-mcp/dist/index.js"]
}
}
}Tested against the-internet.herokuapp.com — 39 automation challenges covering forms, dynamic content, iframes, shadow DOM, drag and drop, and more. An AI agent (Claude) ran every test using only the tools above.
| Test | Result |
|---|---|
| Form Authentication | Pass |
| Checkboxes | Pass |
| Dropdown | Pass |
| File Upload | Pass |
| JS Alert | Pass |
| JS Confirm | Pass |
| JS Prompt | Pass |
| Dynamic Controls | Pass |
| Hovers (CSS :hover) | Pass |
| WYSIWYG Editor (TinyMCE in iframe) | Pass |
| Sortable Data Tables | Pass |
| Key Presses | Pass |
| Shadow DOM | Pass |
| Context Menu (right-click) | Pass |
| Infinite Scroll | Pass |
| Dynamic Loading (render after) | Pass |
| Dynamic Loading (hidden reveal) | Pass |
| Nested Frames (frameset in frameset) | Pass |
| Add/Remove Elements | Pass |
| Disappearing Elements | Pass |
| Horizontal Slider | Pass |
| Inputs (number field) | Pass |
| Forgot Password (form submit) | Pass |
| Challenging DOM (unstable selectors) | Pass |
| Status Codes (404) | Pass |
| Redirect Link | Pass |
| Notification Messages (flash) | Pass |
| Typos (text detection) | Pass |
| Floating Menu | Pass |
| Broken Images (detection) | Pass |
| Drag and Drop (HTML5) | Pass |
| JQuery UI Menus (nested submenus) | Pass |
| Geolocation (API mocking) | Pass |
| A/B Testing | Pass |
| Entry Ad (modal dismiss) | Pass |
| Large & Deep DOM (182KB page) | Pass |
| Shifting Content | Pass |
| Multiple Windows | Pass |
| Dynamic Content | Pass |
39/39.
cdp_tabsaccessesCDPClientprivate fields (port,host) viaas anycast. Works, needs proper getters.
- Node.js 18+
- Chrome, Chromium, or Edge
ws— WebSocket client for CDP- That's it
Copyright (c) 2025 Cassius Oldenburg. All rights reserved.