Skip to main content
Glama
crmmc

DrissionPage BetterMCP

by crmmc
README.md
# DrissionPage BetterMCP

> A better DrissionPage MCP server — covers most capabilities of the original library, 255 unit tests, 100% service coverage, AI-optimized tool calls and descriptions.

English | [中文](./README.zh.md)

---

## Why BetterMCP

| | BetterMCP | Note |
|---|---|---|
| **55 Tools** | Covers browser, tabs, navigation, elements, forms, screenshots, network, cookies, storage, iframes, files, and more | Most capabilities of the original library, ready out of the box |
| **255 Unit Tests** | 17 test modules + 6 integration test suites | 100% service coverage, verifiable on every commit |
| **AI-Friendly** | Clear tool descriptions, explicit parameter semantics, unified response structure | LLMs understand on first call — fewer retries, less token waste |
| **Element Cache** | `element_find` returns an `element_id` for direct reuse in subsequent calls | No repeated lookups, more efficient interactions |
| **Native Locator Syntax** | `#id` `.class` `@attr` `text:` `css:` `xpath:` `@@AND` `@\|OR` | Full DrissionPage syntax support |
| **Dual Transport** | `stdio` + `streamable-http` | Works with all major AI coding tools |

## Quick Start

### Prerequisites

- Python >= 3.10
- [uv](https://docs.astral.sh/uv/)
- Chrome / Chromium browser

### Install

```bash
git clone https://github.com/pureTrue/DrissionPage-BetterMCP.git
cd DrissionPage-BetterMCP
uv sync
```

### Configure Your AI Tool

<!-- tabs:start -->

#### **Claude Code**

Project root `.mcp.json`:

```json
{
  "mcpServers": {
    "drissionpage": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/DrissionPage-BetterMCP", "dp-mcp"]
    }
  }
}
```

Or via CLI:

```bash
claude mcp add drissionpage -- uv run --directory /path/to/DrissionPage-BetterMCP dp-mcp
```

#### **Cursor**

`.cursor/mcp.json` (project-level) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "drissionpage": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/DrissionPage-BetterMCP", "dp-mcp"]
    }
  }
}
```

#### **VS Code (Copilot)**

`.vscode/mcp.json`:

```json
{
  "servers": {
    "drissionpage": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/DrissionPage-BetterMCP", "dp-mcp"]
    }
  }
}
```

> Note: VS Code uses `servers` as the top-level key, not `mcpServers`.

#### **Codex**

`.codex/config.toml` (project-level) or `~/.codex/config.toml` (global):

```toml
[mcp_servers.drissionpage]
command = "uv"
args = ["run", "--directory", "/path/to/DrissionPage-BetterMCP", "dp-mcp"]
```

Or via CLI:

```bash
codex mcp add drissionpage -- uv run --directory /path/to/DrissionPage-BetterMCP dp-mcp
```

<!-- tabs:end -->

Replace `/path/to/DrissionPage-BetterMCP` with the actual project path.

### Environment Variables

Optional, prefixed with `DP_MCP_`:

| Variable | Default | Description |
|----------|---------|-------------|
| `DP_MCP_DEFAULT_TIMEOUT` | `15.0` | Default tool timeout (seconds) |
| `DP_MCP_LOG_LEVEL` | `INFO` | Logging level |
| `DP_MCP_NETWORK_CAPTURE_SIZE` | `200` | Max network packets to capture |

Copy `.env.example` to `.env` and customize as needed.

## Tool List

### Browser Management

| Tool | Description |
|------|-------------|
| `browser_connect` | Connect to an existing Chrome or launch a new instance; supports headless, proxy, user_agent |
| `browser_info` | Get browser status: address, tab count, process ID |
| `browser_quit` | Close the browser and release all resources |

### Tab Management

| Tool | Description |
|------|-------------|
| `tab_new` | Open a new tab, optionally navigate to a URL |
| `tab_close` | Close a tab; defaults to the current tab |
| `tab_switch` | Switch to a specific tab |
| `tab_list` | List all open tabs |
| `tab_find` | Search tabs by title and/or URL |
| `tab_info` | Get tab details |

### Page Navigation

| Tool | Description |
|------|-------------|
| `page_navigate` | Navigate to a URL; returns final URL and page title |
| `page_back` / `page_forward` | Go back or forward in history |
| `page_refresh` | Refresh the page; optionally ignore cache |
| `page_stop` | Stop page loading |

### Element Interaction

| Tool | Description |
|------|-------------|
| `element_find` | Find an element; returns a cached `element_id` |
| `element_find_all` | Find all matching elements |
| `element_wait` | Wait for an element state (present / visible / hidden / deleted) |
| `element_click` | Click an element; supports left / right / middle / double click |
| `element_input` | Type text into an input; optionally clear first |
| `element_clear` | Clear an input field |
| `element_hover` | Hover over an element |
| `element_drag` | Drag to a target element or pixel offset |
| `element_get_text` | Get visible text content |
| `element_get_attr` | Get an HTML attribute value |
| `element_get_info` | Get full details: tag, text, rect, attrs, HTML, states |
| `element_select` | Select an option in a `<select>` element |
| `element_get_options` | Get all options of a `<select>` element |
| `element_scroll_into_view` | Scroll until the element is visible |

### Screenshots

| Tool | Description |
|------|-------------|
| `page_screenshot` | Screenshot the page; supports full-page capture |
| `element_screenshot` | Screenshot a specific element |

### Page Content

| Tool | Description |
|------|-------------|
| `page_get_text` | Get the page's plain text |
| `page_get_html` | Get the HTML source |
| `page_wait_load` | Wait for page load / URL change / title change |
| `page_scroll` | Scroll the page in a direction |

### Iframes

| Tool | Description |
|------|-------------|
| `frame_list` | List all iframes |
| `frame_switch` | Switch into an iframe |
| `frame_parent` | Return to the parent frame |
| `frame_main` | Return to the top-level page |

### Network Capture

| Tool | Description |
|------|-------------|
| `network_listen_start` | Start listening for requests matching a URL pattern |
| `network_listen_wait` | Wait for and retrieve captured network packets |

### Cookies & Storage

| Tool | Description |
|------|-------------|
| `cookie_get_all` | Get all cookies; optionally filter by domain |
| `cookie_set` | Set a cookie |
| `cookie_remove` | Remove a cookie or clear all |
| `storage_get` | Read from localStorage / sessionStorage |
| `storage_set` | Write to localStorage / sessionStorage |

### Keyboard & Dialogs

| Tool | Description |
|------|-------------|
| `keyboard_press` | Press a key or combination (Enter, Ctrl+A, etc.) |
| `keyboard_type` | Type text continuously |
| `dialog_handle` | Handle an alert / confirm / prompt dialog |
| `dialog_auto` | Enable or disable automatic dialog handling |

### Advanced

| Tool | Description |
|------|-------------|
| `action_chain` | Execute an action sequence: move, click, drag, type, wait |
| `js_execute` | Execute JavaScript on the page |
| `cdp_execute` | Execute a raw Chrome DevTools Protocol command |

### File Operations

| Tool | Description |
|------|-------------|
| `file_upload` | Upload a file; supports hidden inputs |
| `file_download` | Download a file via URL or click trigger |
| `page_save` | Save the page as PDF or MHTML |

## Developer Guide

### Project Structure

```
src/dp_mcp/
├── server.py              # MCP server — 55 tool definitions
├── config.py              # Settings (pydantic-settings)
├── models.py              # ToolResult, BrowserInfo, TabInfo, etc.
├── core/                  # Core services
│   ├── browser.py         # Browser lifecycle
│   ├── tab.py             # Multi-tab management
│   ├── navigation.py      # Page navigation
│   └── element.py         # Element finding & interaction
├── services/              # Domain services
│   ├── screenshot.py      # Screenshots
│   ├── frame.py           # Iframes
│   ├── scroll.py          # Scrolling
│   ├── network.py         # Network capture
│   ├── cookie.py          # Cookies
│   ├── action.py          # Action chains
│   ├── dialog.py          # Dialogs
│   ├── cdp.py             # CDP
│   └── file.py            # File operations
└── utils/
    └── locator.py         # Locator parser + element cache
```

### Running Tests

```bash
# Unit tests (no browser needed)
uv run pytest tests/unit -v

# Integration tests (requires Chrome)
uv run pytest tests/integration -v -m integration

# All tests
uv run pytest -v
```

### Locator Syntax

Full DrissionPage locator syntax is supported:

| Syntax | Example | Description |
|--------|---------|-------------|
| `#id` | `#login-btn` | By ID |
| `.class` | `.submit` | By class name |
| `@attr=val` | `@name=email` | By attribute |
| `text:str` | `text:Login` | By visible text |
| `tag:name` | `tag:input` | By tag name |
| `css:selector` | `css:div.card>h2` | CSS selector |
| `xpath:expr` | `xpath://div[@id='app']` | XPath |
| `@@a@@b` | `@@class=btn@@text()=OK` | AND condition |
| `@\|a@\|b` | `@\|class=btn@\|class=link` | OR condition |

Use the optional `by` parameter to disambiguate: `css`, `xpath`, `text`, `id`, `class`, `attr`.

## Contributing

Pull requests and issues are welcome.

1. Fork this repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Commit your changes: `git commit -m "feat: add my feature"`
4. Push the branch: `git push origin feature/my-feature`
5. Open a Pull Request

Please make sure all tests pass before submitting:

```bash
uv run pytest tests/unit -v
```

## License

This project's code is licensed under [BSD 3-Clause](./LICENSE).

> **Note**: This project depends on [DrissionPage](https://github.com/g1879/DrissionPage), which uses a custom non-commercial license that prohibits unauthorized commercial use. Users must independently comply with DrissionPage's license terms.

TDQS

B3.2/5.0

Scored across 31 tools

Disambiguation5/5

Each tool targets a distinct resource and action: page, tab, element, keyboard, network, cookie, storage, dialog, or JS. Even similar tools like keyboard_type vs keyboard_press and page_get_text vs element_get_text are clearly separated by scope and descriptions.

Naming Consistency4/5

Most tools follow a consistent resource_action pattern like page_navigate, element_find, cookie_set, and storage_get. A few names break the pattern with adjectives instead of verbs, notably tab_new, frame_main, and dialog_auto.

Tool Count2/5

31 tools is above the heavy threshold and includes a wide spread of peripheral features like network listeners, storage, cookies, and dialogs. The count feels imbalanced because several core browser automation tools are missing while the surface is still very large.

Completeness1/5

The tool set has severe gaps: browser_connect is referenced by browser_quit but does not exist, and element_click, element_input, and element_select are referenced in descriptions but not provided. This makes core workflows like clicking buttons or filling forms impossible without falling back to js_execute.

Maintenance

ActivityInactive
ResponsivenessNo issues