DrissionPage MCP Server · Browser automation for Claude Code, Codex, and MCP clients
<p align="center"> <img src="https://raw.githubusercontent.com/jumodada/Drissionpage-MCP-Server/assets/vision-natural-pointer-demo.gif" width="662" alt="AI vision-directed natural pointer interaction demo"> <br> <sub><strong>A new interaction layer for multimodal AI</strong> — vision coordinates in, natural pointer action chains out.</sub> </p>Professional browser automation for Codex, Claude Code, and MCP clients powered by DrissionPage
Official Repositories: GitHub | GitCode
DrissionPage MCP 0.6.0 provides a complete first-stage interaction layer for multimodal AI: it can turn a vision model's viewport coordinate into a complete, physically plausible pointer action chain—not just a raw teleport-and-click.
One MCP call connects visual understanding to real browser interaction. The model identifies where to act; DrissionPage MCP handles how the pointer gets there and performs the click.
Screenshot / page observation
↓
Multimodal model identifies viewport coordinates
↓
page_click_xy(profile="natural")
↓
Cubic Bézier motion → reaction pause → press → hold → release
↓
Observe and verify the resulting page stateThis makes vision-guided operation practical for canvas controls, visual editors, maps, charts, non-semantic widgets, responsive interfaces, and other surfaces where selectors or accessibility metadata are incomplete. Structured DOM automation remains the preferred path when reliable selectors are available; the vision interaction layer expands what an MCP agent can operate when they are not.
{
"x": 442,
"y": 369,
"start_x": 100,
"start_y": 100,
"profile": "natural",
"button": "left",
"element": "visually identified control"
}Designed for legitimate UI automation, testing, accessibility workflows, and technical research. Security or anti-automation challenge completion is not offered as a guaranteed supported capability.
DrissionPage MCP Server is a local Model Context Protocol (MCP) server that brings DrissionPage browser automation tools to Codex CLI/IDE, Claude Code, Claude Desktop, and other MCP clients.
Structured, deterministic automation remains the default through 57 tools plus MCP Resources/Prompts. When selectors or accessibility metadata are insufficient, 0.6.0 also provides an optional vision-guided human–computer interaction layer that converts viewport coordinates into natural Chromium pointer action chains, powered by DrissionPage.
pip install + Codex TOML or MCP JSON configurationDrissionPage MCP is backed by a strict regression suite and browser-backed scenario checks:
# Install from PyPI
python -m pip install -U drissionpage-mcp
# Verify package and environment
drissionpage-mcp --version
drissionpage-mcp doctorThen add the Codex or MCP client configuration below and restart your client.
<p align="center"> <img src="https://raw.githubusercontent.com/jumodada/Drissionpage-MCP-Server/assets/01-install.png" width="700" alt="pip install drissionpage-mcp"> <br><br> <img src="https://raw.githubusercontent.com/jumodada/Drissionpage-MCP-Server/assets/03-doctor.png" width="700" alt="drissionpage-mcp doctor — all checks green"> </p>Codex supports local stdio MCP servers through config.toml; the CLI and IDE extension share the same MCP configuration.
~/.codex/config.toml.codex/config.toml inside a trusted project[mcp_servers.drissionpage]
command = "drissionpage-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 60/mcp; from a shell, run codex mcp list.For Claude Code, Claude Desktop, and other JSON-based MCP clients, see Integration Examples.
"Visit https://example.com and take a screenshot for me""Go to Wikipedia, search for Python, and get the first paragraph""Fill out the form at https://httpbin.org/forms/post and submit it""Get the top 10 news headlines from news.ycombinator.com"page_navigate - Navigate to any URL; optionally open it in a new tab with new_tab or return an observe change summarypage_go_back / page_go_forward - Browser historypage_refresh - Reload current pagetab_list - List open browser tabs with stable MCP tab IDstab_switch - Switch to a tab returned by tab_listtab_close - Close one tab without closing the whole browserelement_find - Find one element by CSS selector or XPath; bare selectors like h1 are treated as CSSelement_find_all - Extract bounded repeated elements with text, attributes, and recommended selectorselement_click - Click any elementelement_type - Input text into elementselement_upload_file - Upload files from DP_MCP_UPLOAD_ROOT to input[type=file]element_scroll_into_view - Bring an element into the viewport before actingelement_hover - Hover an element to trigger menu/tooltip stateselement_select - Select an option by value, text, or indexelement_check - Check or uncheck checkbox/radio controlselement_get_text - Get element or page textelement_get_attribute - Get an HTML attributeelement_get_property - Get a live DOM property such as an input valueelement_get_html - Get element or page HTMLform_inspect - Inspect forms and controls with labels, selectors, requirements, options, and safe optional valuespage_screenshot - Capture an inline full-page or viewport screenshotpage_screenshot_save - Save a screenshot under DP_MCP_SCREENSHOT_ROOTpage_snapshot - Return a bounded page outline with headings, links, buttons, inputs, forms, and selector recommendationspage_observe - Return a compact page fingerprint with URL, title, counts, visible text samples, active element, and recent console summarypage_evaluate - Run bounded JavaScript in the current page and return a JSON-safe resultpage_scroll - Scroll the page by direction or to a positionkeyboard_press - Send keys to the active element/pagepage_resize - Adjust browser windowpage_pointer_move - Move to vision-model viewport coordinates with a natural Bézier path without clickingpage_pointer_drag - Perform one failure-safe natural drag between viewport coordinatespage_detect_challenges - Read-only detection of verification-widget signals for autonomous model routingpage_click_xy_batch - Execute multiple visual coordinate clicks in one bounded autonomous callpage_wait_challenge_result - Poll token length and configurable success/retry/challenge signals without exposing token valuespage_click_xy - Convert vision-model viewport coordinates into natural Bézier pointer movement and physically timed clickspage_close - Close browserpage_get_url - Get current URLframe_list - List iframe/frame contexts without changing global frame stateframe_snapshot - Inspect a selected iframe with bounded outline dataframe_find - Find an element inside a selected iframeshadow_find - Find one element inside an open shadow rootshadow_find_all - Extract repeated elements inside an open shadow rootbrowser_cookies_get - Read normalized cookies with values redacted by defaultstorage_get - Read localStorage/sessionStorage by key or as a mapstorage_set - Set one localStorage/sessionStorage item without echoing the valuestorage_clear - Clear one storage key or an entire storage areapage_console_logs - Read bounded browser console messages with level filtering, cursor pagination, and limitswait_for_element - Wait for element to appear (with timeout)wait_for_url - Wait until the current URL contains textwait_until - Wait for observable conditions such as clickable, hidden, stable, text, or URL matcheswait_time - Delay executiondrissionpage://session/summary, drissionpage://session/history, drissionpage://session/state, drissionpage://session/config, drissionpage://guide/model-usage, drissionpage://page/current, drissionpage://tools/catalog, drissionpage://policy/summarydrissionpage_mcp_usage_playbook, browser_navigate_and_summarize, browser_extract_structured_data, browser_fill_form_safely, browser_vision_guided_interaction, browser_debug_page_issue| Guide | Description |
|---|---|
| README.md | Installation, tools, and architecture |
| docs/compatibility.md | Supported Python, DrissionPage, MCP, and browser versions |
| docs/tool-contract.md | Public MCP tool names, inputs, annotations, and response shape |
| docs/troubleshooting.md | Doctor command, browser startup, and client setup fixes |
| CHANGELOG.md | Release notes |
Built with clean, modular design:
DrissionMCP/
├── drissionpage_mcp/
│ ├── cli.py # Entry point
│ ├── server.py # MCP server
│ ├── context.py # Browser management
│ ├── response.py # Response formatting
│ ├── tab.py # Page operations
│ └── tools/ # 46 automation, tab/frame/shadow, page-understanding, form, debug, and session-state tools
├── tests/ # Unit tests
└── playground/ # MCP Lab business-scenario playgroundKey Principles:
[mcp_servers.drissionpage]
command = "drissionpage-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 60
# Optional browser/runtime environment variables:
# [mcp_servers.drissionpage.env]
# CHROME_PATH = "/custom/path/to/chrome"
# DP_HEADLESS = "1"You can also add it with the Codex CLI:
codex mcp add drissionpage -- drissionpage-mcpIf Codex/Cursor/Claude Desktop is launched from a GUI and cannot see your shellPATH or virtualenv, use the absolute Python executable instead:
[mcp_servers.drissionpage]
command = "/absolute/path/to/python"
args = ["-m", "drissionpage_mcp.cli"]
startup_timeout_sec = 20
tool_timeout_sec = 60{
"mcpServers": {
"drissionpage": {
"command": "drissionpage-mcp"
}
}
}{
"mcpServers": {
"drissionpage": {
"command": "drissionpage-mcp",
"args": ["--log-level", "DEBUG"],
"env": {
"CHROME_PATH": "/custom/path/to/chrome"
}
}
}
}Absolute-Python fallback for GUI clients:
{
"mcpServers": {
"drissionpage": {
"command": "/absolute/path/to/python",
"args": ["-m", "drissionpage_mcp.cli"],
"env": {
"CHROME_PATH": "/custom/path/to/chrome",
"DP_HEADLESS": "1"
}
}
}
}# Environment diagnostics; add --launch-browser for a browser startup check
drissionpage-mcp doctor
drissionpage-mcp doctor --launch-browser
# Source checkout tests
python -m pip install -e ".[dev]"
python -m pytest tests/
# Coverage report (CI enforces the current 95% floor and uploads coverage.xml)
python -m pytest tests/ --cov=drissionpage_mcp --cov-report=term-missing --cov-report=xml
# Browser-backed MCP Lab scenario checks
DP_HEADLESS=1 python playground/run_mcp_lab.py --all --jsonGitHub Actions runs lint, unit, protocol, package, browser integration, and
coverage jobs. Codecov is configured through codecov.yml and the CI workflow.
# No-browser MCP registry check
python playground/run_mcp_lab.py --case registry
# Local deterministic site check
python playground/run_mcp_lab.py --case site
# Browser-backed form inspection scenario
DP_HEADLESS=1 python playground/run_mcp_lab.py --case form-inspect✅ Automated Testing - Test web applications
✅ Data Scraping - Extract structured data from websites
✅ Form Automation - Fill and submit forms
✅ Monitoring - Check for updates or changes
✅ Screenshot Verification - Capture and verify page state
✅ Content Analysis - Analyze web content programmatically
drissionpage-mcp --versionShould output the installed package version, for example drissionpage-mcp 0.6.0.
# Check browser installation
which google-chrome # Linux
which chromium # macOScodex mcp list; in the TUI, run /mcpdrissionpage-mcp --log-level DEBUGSee docs/troubleshooting.md for the complete troubleshooting guide.
| Component | Status |
|---|---|
| Core Features | ✅ Complete |
| Testing | ✅ Strict unit/protocol/schema checks plus browser-backed scenarios |
| Documentation | ✅ Setup, compatibility, troubleshooting, and public tool contracts |
| Package | ✅ PyPI metadata and build checks |
| Status | 🟡 Beta; real browser behavior depends on local Chrome/Chromium and target sites |
Version: 0.6.0 | License: Apache 2.0 | Maintained: ✅ Active
structuredContent, and typed per-tool MCP outputSchemaerror.details.hints for common failurespage_snapshot output so link-heavy pages still expose controls and formsform_inspect read-only form inventory with labels, selectors, requirements, options, and safe optional valuestab_list, tab_switch, tab_close, and page_navigate(new_tab=true)page_observe, page_evaluate, wait_until, and optional observe=true changes on navigation, click, and typepage_console_logs, console summary in page_observe, and console change fields in observe=truebrowser_open_and_snapshot, browser_extract_links, and form_fill_previewnetwork_listen_start, network_listen_wait, and network_listen_stop for HTTP/XHR/Fetch observationpage_pointer_move, page_pointer_drag, and page_click_xy action chains with cubic Bézier motion, smoothstep easing, bounded jitter, reaction delay, and realistic button hold timeDP_NO_SANDBOX=1 is reserved for restricted container/root environments[mcp_servers.drissionpage]
command = "drissionpage-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 60Verify with:
codex mcp list{
"mcpServers": {
"drissionpage": {
"command": "drissionpage-mcp"
}
}
}Config file: ~/.config/claude-code/mcp_settings.json (macOS/Linux) or%APPDATA%\claude-code\mcp_settings.json (Windows).
{
"mcpServers": {
"drissionpage": {
"command": "drissionpage-mcp"
}
}
}Config file: ~/.cursor/mcp.json (global) or .cursor/mcp.json (project). You
can also add it from Cursor Settings → Tools & MCPs → New MCP Server.
{
"mcpServers": {
"drissionpage": {
"command": "drissionpage-mcp"
}
}
}Once connected, the tools load automatically:
<p align="center"> <img src="https://raw.githubusercontent.com/jumodada/Drissionpage-MCP-Server/assets/07-connected.png" width="700" alt="MCP client with DrissionPage tools loaded"> </p>Contributions are welcome!
See CONTRIBUTING.md for setup, validation, and compatibility expectations.
Best Practices:
Licensed under Apache License 2.0 - see LICENSE
If you find this project useful, please consider:
Made with ❤️ by Wukunyun
Ready to automate your workflows? Install now: python -m pip install -U drissionpage-mcp
Released on 2026-07-13. This release adds autonomous visual orchestration on top of the existing pointer action layer:
page_detect_challenges for read-only iframe, script, DOM-container, and hidden-field signal detection with optional viewport screenshot attachment.page_click_xy_batch for up to 25 ordered viewport clicks from one stable visual state, with natural pointer motion, bounded inter-click delays, fail-fast defaults, URL-change protection, and structured per-target results.page_wait_challenge_result for bounded autonomous polling and classification as passed, needs_retry, new_challenge, timeout, or indeterminate; token values are never returned.wait_until with generic attribute/property equals and non-empty conditions.page_click_xy.delay_before_press_ms as explicit timing control; moving visual targets still require a fresh viewport screenshot and coordinate recomputation.jumodada/Drissionpage-MCP-Server
January 22, 2026
July 13, 2026
Python