Skip to main content
Glama
DrissionPage BetterMCP

DrissionPage BetterMCP

by crmmc

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


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

Related MCP server: DrissionPage MCP Server

Quick Start

Prerequisites

  • Python >= 3.10

  • uv

  • Chrome / Chromium browser

Install

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

Configure Your AI Tool

Claude Code

Project root .mcp.json:

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

Or via CLI:

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

Cursor

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

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

VS Code (Copilot)

.vscode/mcp.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):

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

Or via CLI:

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

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

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

uv run pytest tests/unit -v

License

This project's code is licensed under BSD 3-Clause.

Note: This project depends on DrissionPage, which uses a custom non-commercial license that prohibits unauthorized commercial use. Users must independently comply with DrissionPage's license terms.

Available Tools

31 tools
browser_quitA

Close the browser and release all resources.

Call browser_connect to start a new session.

Inputs: no named parameters. Returns: result

dialog_autoA

Enable or disable automatic handling of alert/confirm/prompt dialogs.

When enabled, all future dialogs are automatically accepted (accept=true)
or dismissed (accept=false) without manual intervention. Disable with
enabled=false when you need to inspect dialog content with dialog_handle.
Auto mode is automatically disabled on browser disconnect.

Inputs: enabled (required), accept, tab_id. Returns: result

dialog_handleA

Handle the currently open alert/confirm/prompt dialog.

Returns dialog type, message, and whether it was accepted. Fails immediately
if no dialog is present — use dialog_auto for pre-emptive handling.
For prompt dialogs, pass text to fill the input field before accepting.

Inputs: text, accept, tab_id. Returns: result

element_clearC

Clear the value of an input element. Provide locator or element_id.

Inputs: by, by_js, tab_id, locator, +1 more. Returns: result

element_dragA

Drag an element to a target element or by pixel offset.

Provide either target_locator/target_element_id (drag to target) or
offset_x/offset_y (drag by pixels). Duration controls drag speed in seconds.

Inputs: by, tab_id, locator, duration, +5 more. Returns: result

element_findA

Find a single element and return its info including element_id for future reference.

Locator syntax: #id | .class | @attr=val | text:str | tag:name |
css:selector | xpath:expr | @@a@@b (AND) | @|a@|b (OR)

Use element_id from result to interact with the element without re-finding it.
If parent is provided, finds the locator within the parent element (two-step find).

Inputs: locator (required), by, parent, tab_id, +1 more. Returns: result

element_find_allC

Find all matching elements. Returns list with element_id for each.

Locator syntax: #id | .class | @attr=val | text:str | tag:name |
css:selector | xpath:expr | @@a@@b (AND) | @|a@|b (OR)

Returns empty list (not error) when no elements match.

Inputs: locator (required), by, limit, parent, +2 more. Returns: result

element_get_infoA

Get full element details: tag, text, rect, attrs, html, states.

Provide locator or element_id. Returns richer info than element_find.

Inputs: by, tab_id, locator, element_id. Returns: result

element_get_optionsA

Get all options of a element with text, value, index, and selected status.

Use before element_select to see available choices.
Provide locator or element_id.

Inputs: by, tab_id, locator, element_id. Returns: result

element_get_textB

Get the visible text content of an element. Provide locator or element_id.

Inputs: by, tab_id, locator, element_id. Returns: result

element_waitA

Wait for an element to reach the given state.

state: present (default) | visible | hidden | deleted
Default timeout is 15s, max is 60s.

Inputs: locator (required), by, state, tab_id, +1 more. Returns: result

frame_mainB

Return to the top-level page from any nested iframe. Clears frame context entirely.

Inputs: tab_id. Returns: result

js_executeA

Execute JavaScript code on the current page and return the result.

Code runs as a function body — access injected args via arguments[0], arguments[1], etc.
Returns serialized result: primitives directly, DOM elements as summary strings,
non-serializable values as "[object Object]". Fails if an alert dialog is open.
Use specific tools (element_click, page_navigate, etc.) when available;
this is an escape hatch for unsupported operations.

Inputs: code (required), args, tab_id. Returns: result

keyboard_pressA

Press a key or key combination on the current page.

Single keys: "enter", "tab", "escape", "backspace", "delete", "f1".."f12".
Combinations: "ctrl+a", "ctrl+c", "ctrl+shift+t", "alt+f4".
Operates on the currently focused element. For typing text, use keyboard_type instead.

Inputs: key (required), tab_id. Returns: result

keyboard_typeA

Type text continuously on the current page as keyboard input.

Types each character sequentially. For filling form fields, prefer element_input
which targets a specific element. Use this for page-level typing when no specific
element reference is needed.

Inputs: text (required), tab_id. Returns: result

network_listen_startA

Start listening for network requests matching a URL pattern on the current tab.

Only one listener per tab — starting a new one stops the previous. The listener
auto-expires after `expire` seconds if network_listen_wait is not called. After
starting, perform the action that triggers the request (e.g., click a button),
then call network_listen_wait to capture packets.

Inputs: url_pattern (required), expire, method, tab_id, +2 more. Returns: result

network_listen_waitA

Wait for network packets captured by a previously started listener.

Returns captured packets written to a JSONL file. Automatically stops the listener after waiting. If timeout occurs with partial captures, returns what was captured (not an error). Use count=1 for a single expected request, higher for multiple.

Inputs: count, tab_id, timeout. Returns: result

page_forwardA

Go forward in browser history. Optionally specify number of steps.

Inputs: steps, tab_id. Returns: result

page_get_textB

Get the plain text content of the current page (no HTML tags).

Useful for reading page content without markup.

Inputs: tab_id. Returns: result

page_refreshA

Refresh the current page. Set ignore_cache=true to bypass browser cache.

Inputs: tab_id, ignore_cache. Returns: result

page_scrollA

Scroll the page in a direction.

direction: up | down | left | right | top | bottom.
pixels is ignored for top/bottom (they scroll to absolute position).

Inputs: direction (required), pixels, tab_id. Returns: result

storage_getB

Read a value from localStorage or sessionStorage.

Set storage_type to 'local' (default) or 'session'.

Inputs: key (required), tab_id, storage_type. Returns: result

storage_setB

Write a value to localStorage or sessionStorage.

Set storage_type to 'local' (default) or 'session'.

Inputs: key (required), value (required), tab_id, storage_type. Returns: result

tab_findA

Search tabs by title and/or URL substring. Returns matching tabs.

Inputs: url, title. Returns: result

tab_infoB

Get details of a specific tab or the current tab.

Inputs: tab_id. Returns: result

tab_listA

List all open tabs with their tab_id, title, URL, and which is current.

Inputs: no named parameters. Returns: result

tab_newA

Open a new browser tab. Optionally navigate to URL. Automatically switches to the new tab.

Inputs: url. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    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 recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      An MCP server providing robust browser automation tools for AI assistants, including page navigation, element interaction, and screenshot capabilities. It leverages the DrissionPage library to enable standardized DOM analysis, network monitoring, and complex web task automation.
      17
      MIT
    • A
      license
      C
      quality
      B
      maintenance
      A professional browser automation server that enables MCP clients to perform structured web navigation, element interaction, and data extraction using the DrissionPage framework. It features 14 deterministic tools optimized for LLMs to automate web workflows efficiently without relying on vision-based models.
      69
      63 PyPI
      481
      Apache 2.0
    • A
      license
      Not graded
      quality
      D
      maintenance
      A browser automation MCP server providing 30 tools for navigation, interaction, page information, state checks, tab management, and more, enabling natural language control of browsers via MCP-compatible clients.
      MIT