Skip to main content
Glama
README.md
# CDP MCP

Browser automation through Chrome DevTools Protocol. No Playwright. No Puppeteer. Just raw CDP over WebSocket.

## Why

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.

## Tools

| 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 |

## How it works

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:

```json
{
  "success": true,
  "action": "type",
  "expected": "user@example.com",
  "actual": "user@example.com"
}
```

## Framework handling

`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.

## Installation

```bash
npm install
npm run build
```

Add to your MCP config:

```json
{
  "mcpServers": {
    "cdp": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/cdp-mcp/dist/index.js"]
    }
  }
}
```

## Test results

Tested against [the-internet.herokuapp.com](https://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.**

### Known code smells

- `cdp_tabs` accesses `CDPClient` private fields (`port`, `host`) via `as any` cast. Works, needs proper getters.

## Requirements

- Node.js 18+
- Chrome, Chromium, or Edge

## Dependencies

- `ws` — WebSocket client for CDP
- That's it

## License

Copyright (c) 2025 Cassius Oldenburg. All rights reserved.

TDQS

B3.4/5.0

Scored across 27 tools

Disambiguation3/5

The tool set has clear distinctions for core browser automation tasks like navigation, interaction, and reading, but there is notable overlap between cdp_interact, cdp_set_value, and cdp_type_text for input handling, and between cdp_find_elements and cdp_site_scan for element discovery. Descriptions help clarify, but an agent might struggle to choose the optimal tool in some scenarios.

Naming Consistency5/5

All tools follow a consistent 'cdp_' prefix with snake_case naming, using clear verb_noun patterns (e.g., cdp_launch, cdp_navigate, cdp_read). This uniformity makes the tool set predictable and easy to navigate, with no deviations in style.

Tool Count2/5

With 27 tools, the count is excessive for a browser automation server, leading to potential confusion and redundancy. While the domain is broad, many tools (e.g., cdp_click_coordinates vs. cdp_interact for clicking) could be consolidated, making the set feel heavy and over-engineered.

Completeness5/5

The tool set comprehensively covers browser automation and site interaction, including connection, navigation, element discovery, interaction, reading, screenshot, form handling, and memory management. There are no obvious gaps; it supports full workflows from launch to debugging, with specialized tools for edge cases like shadow DOM and Monaco editor.