DrissionPage BetterMCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DrissionPage BetterMCP Open a new tab and navigate to https://example.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
| No repeated lookups, more efficient interactions |
Native Locator Syntax |
| Full DrissionPage syntax support |
Dual Transport |
| Works with all major AI coding tools |
Related MCP server: DrissionPage MCP Server
Quick Start
Prerequisites
Python >= 3.10
Chrome / Chromium browser
Install
git clone https://github.com/pureTrue/DrissionPage-BetterMCP.git
cd DrissionPage-BetterMCP
uv syncConfigure 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-mcpCursor
.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
serversas the top-level key, notmcpServers.
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-mcpReplace /path/to/DrissionPage-BetterMCP with the actual project path.
Environment Variables
Optional, prefixed with DP_MCP_:
Variable | Default | Description |
|
| Default tool timeout (seconds) |
|
| Logging level |
|
| Max network packets to capture |
Copy .env.example to .env and customize as needed.
Tool List
Browser Management
Tool | Description |
| Connect to an existing Chrome or launch a new instance; supports headless, proxy, user_agent |
| Get browser status: address, tab count, process ID |
| Close the browser and release all resources |
Tab Management
Tool | Description |
| Open a new tab, optionally navigate to a URL |
| Close a tab; defaults to the current tab |
| Switch to a specific tab |
| List all open tabs |
| Search tabs by title and/or URL |
| Get tab details |
Page Navigation
Tool | Description |
| Navigate to a URL; returns final URL and page title |
| Go back or forward in history |
| Refresh the page; optionally ignore cache |
| Stop page loading |
Element Interaction
Tool | Description |
| Find an element; returns a cached |
| Find all matching elements |
| Wait for an element state (present / visible / hidden / deleted) |
| Click an element; supports left / right / middle / double click |
| Type text into an input; optionally clear first |
| Clear an input field |
| Hover over an element |
| Drag to a target element or pixel offset |
| Get visible text content |
| Get an HTML attribute value |
| Get full details: tag, text, rect, attrs, HTML, states |
| Select an option in a |
| Get all options of a |
| Scroll until the element is visible |
Screenshots
Tool | Description |
| Screenshot the page; supports full-page capture |
| Screenshot a specific element |
Page Content
Tool | Description |
| Get the page's plain text |
| Get the HTML source |
| Wait for page load / URL change / title change |
| Scroll the page in a direction |
Iframes
Tool | Description |
| List all iframes |
| Switch into an iframe |
| Return to the parent frame |
| Return to the top-level page |
Network Capture
Tool | Description |
| Start listening for requests matching a URL pattern |
| Wait for and retrieve captured network packets |
Cookies & Storage
Tool | Description |
| Get all cookies; optionally filter by domain |
| Set a cookie |
| Remove a cookie or clear all |
| Read from localStorage / sessionStorage |
| Write to localStorage / sessionStorage |
Keyboard & Dialogs
Tool | Description |
| Press a key or combination (Enter, Ctrl+A, etc.) |
| Type text continuously |
| Handle an alert / confirm / prompt dialog |
| Enable or disable automatic dialog handling |
Advanced
Tool | Description |
| Execute an action sequence: move, click, drag, type, wait |
| Execute JavaScript on the page |
| Execute a raw Chrome DevTools Protocol command |
File Operations
Tool | Description |
| Upload a file; supports hidden inputs |
| Download a file via URL or click trigger |
| 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 cacheRunning 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 -vLocator Syntax
Full DrissionPage locator syntax is supported:
Syntax | Example | Description |
|
| By ID |
|
| By class name |
|
| By attribute |
|
| By visible text |
|
| By tag name |
|
| CSS selector |
|
| XPath |
|
| AND condition |
|
| OR condition |
Use the optional by parameter to disambiguate: css, xpath, text, id, class, attr.
Contributing
Pull requests and issues are welcome.
Fork this repository
Create a feature branch:
git checkout -b feature/my-featureCommit your changes:
git commit -m "feat: add my feature"Push the branch:
git push origin feature/my-featureOpen a Pull Request
Please make sure all tests pass before submitting:
uv run pytest tests/unit -vLicense
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 toolsbrowser_quitA
Close the browser and release all resources.
Call browser_connect to start a new session.
Inputs: no named parameters. Returns: result
cookie_get_allA
Get all cookies for the current page. Optionally filter by domain substring.
Inputs: domain, tab_id. Returns: result
cookie_removeB
Remove a cookie by name, or clear ALL cookies if name is not provided.
Warning: clearing all cookies affects the entire browser, not just the current tab.
Inputs: name, domain, tab_id. Returns: result
cookie_setC
Set a cookie. Domain defaults to current page domain if not specified.
Inputs: name (required), value (required), path, domain, +5 more. 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
Scored across 31 tools
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.
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.
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.
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
Related MCP Connectors
Official Browserless MCP server: browser automation, scraping, screenshots and PDFs for AI agents.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Hyperbrowser MCP — wraps the Hyperbrowser AI-agent browsing API (hyperbrowser.ai). Scrape…
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseBqualityDmaintenanceAn 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.17MIT
- AlicenseCqualityBmaintenanceA 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.6963 PyPI481Apache 2.0
- FlicenseNot gradedqualityDmaintenanceMCP server that enables AI agents to automate browser testing via Chromium, providing tools for navigation, interaction, and inspection.-
- AlicenseNot gradedqualityDmaintenanceA 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