ultimate-playwright-mcp
Multi-agent Playwright MCP server with tab isolation via targetId, enabling multiple agents to share a single Chrome browser while maintaining isolated tab groups and shared sessions.
README
Ultimate Playwright MCP
Multi-agent Playwright MCP server with tab isolation via targetId. Allows multiple Claude instances (or other MCP clients) to share a single Chrome browser while maintaining isolated tab groups.
Why Ultimate Playwright?
The official @playwright/mcp gives you browser control for a single agent. But what if you have multiple agents sharing one browser?
Ultimate Playwright MCP solves this with tab group isolation:
- 🔀 Multi-agent tab groups — Each agent creates a
groupIdand only sees its own tabs - 🍪 Shared cookies & sessions — All agents share the same BrowserContext (log in once, everyone's authenticated)
- 🎨 Visual Chrome tab groups — Companion extension organizes tabs into color-coded Chrome tab groups
- 💾 Persistent registry — Tab groups survive MCP server restarts (
~/.ultimate-playwright-mcp/tab-groups.json) - 🔌 Connect to existing Chrome — Uses CDP to attach to your running Chrome (keeps your profile, extensions, bookmarks)
Comparison
| Feature | ultimate-playwright-mcp | @playwright/mcp | browser-use-mcp |
|---|---|---|---|
| Multi-agent tab isolation | ✅ Tab groups with groupId |
❌ Single session | ❌ Single session |
| Shared cookies across agents | ✅ Same BrowserContext | N/A | N/A |
| Connect to existing Chrome | ✅ CDP | ❌ Launches new browser | ❌ Launches new browser |
| Visual tab groups in Chrome | ✅ Extension | ❌ | ❌ |
| Persistent tab registry | ✅ Survives restarts | ❌ | ❌ |
| Accessibility tree snapshots | ✅ Element refs (e1, e2…) | ✅ | ❌ Screenshot-based |
| Open source | ✅ MIT | ✅ Apache-2.0 | ✅ MIT |
Features
- ✅ Tab Isolation - Each agent gets its own tabs via unique
targetId - ✅ Shared Cookies - All agents share the same BrowserContext (cookies, sessions, localStorage)
- ✅ Parallel Execution - Multiple agents can operate simultaneously without interference
- ✅ CDP Connection - Connects to existing Chrome via Chrome DevTools Protocol
- ✅ Native Page Checkpoints - Capture structured artifacts and generate reports per
targetId - ✅ Battle-Tested - Extracted from OpenClaw (MIT licensed)
Installation
npm install -g ultimate-playwright-mcp
Or run directly with npx:
npx ultimate-playwright-mcp --cdp-endpoint http://localhost:9222
Quick Start
1. Launch Chrome with Remote Debugging
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-debug
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug
# Windows
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ^
--remote-debugging-port=9222 ^
--user-data-dir=C:\\temp\\chrome-debug
2. Configure Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ultimate-playwright": {
"command": "npx",
"args": [
"ultimate-playwright-mcp",
"--cdp-endpoint",
"http://localhost:9222"
]
}
}
}
3. Restart Claude Desktop
Claude will now have access to browser control tools with tab isolation.
Usage Example
User: Open two tabs and navigate them independently
Claude: I'll create two tabs with separate targetIds:
1. browser_tabs({ action: "new" })
→ **targetId: ABC123...**
2. browser_tabs({ action: "new" })
→ **targetId: XYZ789...**
3. browser_navigate({ targetId: "ABC123...", url: "https://github.com" })
4. browser_navigate({ targetId: "XYZ789...", url: "https://google.com" })
Both tabs are now navigated independently!
Available Tools
| Tool | Description | Key Parameters |
|---|---|---|
browser_tab_group |
Create/list/delete tab groups for isolation | action, name, color, groupId |
browser_tabs |
List, create, close, or select tabs | action, groupId, targetId, index |
browser_navigate |
Navigate to a URL | url, targetId |
browser_snapshot |
Capture accessibility tree with refs | targetId |
browser_click |
Click an element | ref, targetId |
browser_type |
Type text into an element | ref, text, targetId |
browser_hover |
Hover over an element | ref, targetId |
browser_press_key |
Press a keyboard key | key, targetId |
browser_fill_form |
Fill multiple form fields | fields, targetId |
browser_wait_for |
Wait for conditions | text, selector, url, loadState, targetId |
browser_checkpoint |
Capture a structured checkpoint for a tab | name, targetId, collectors |
browser_checkpoint_report |
Generate reports from stored checkpoints | format, resultsDir |
Checkpoints
Use browser_checkpoint when you want a persisted capture of the current page for later review or report generation.
- Checkpoints are scoped to the resolved
targetId, so they work with this server's tab isolation model. - Artifacts and manifests are written under
~/.ultimate-playwright-mcp/checkpointsby default. - Generated reports are written under
~/.ultimate-playwright-mcp/checkpoints/report.
Example:
1. browser_checkpoint({ targetId: "ABC123", name: "after-login" })
2. browser_checkpoint_report({ format: "html" })
Tab Groups (Multi-User Isolation)
When multiple users or agents share one browser instance, tab groups keep everyone's tabs isolated. Each session creates its own group, and all tab operations are scoped to that group.
User: Research product pricing
Claude: I'll create a tab group first, then open tabs within it.
1. browser_tab_group({ action: "create", name: "pricing-research", color: "blue" })
→ **groupId: g_a1b2c3d4e5f6**
2. browser_tabs({ action: "new", groupId: "g_a1b2c3d4e5f6", url: "https://example.com/pricing" })
→ **targetId: ABC123...**
3. browser_tabs({ action: "list", groupId: "g_a1b2c3d4e5f6" })
→ Only shows tabs in this group (not other users' tabs)
Meanwhile, another user on the same server:
1. browser_tab_group({ action: "create", name: "docs-review", color: "green" })
→ **groupId: g_x9y8z7w6v5u4**
2. browser_tabs({ action: "new", groupId: "g_x9y8z7w6v5u4", url: "https://docs.example.com" })
→ **targetId: XYZ789...**
Both users share the same cookies/sessions but only see their own tabs!
Tab Group Lifecycle
- Create a group at the start of your session
- Open tabs within the group using
groupId - Work with tabs using
targetIdas before - Delete the group when done (optionally closes all tabs)
Group state is persisted to ~/.ultimate-playwright-mcp/tab-groups.json so it
survives MCP server restarts.
Architecture
┌─────────────────────────────────────────────┐
│ Single Chrome Process │
│ (--remote-debugging-port=9222) │
│ ┌─────────────────────────────────────┐ │
│ │ Single BrowserContext │ │
│ │ (shared cookies, storage) │ │
│ │ │ │
│ │ Group: alice (blue) │ │
│ │ ┌─────┐ ┌─────┐ │ │
│ │ │ Tab │ │ Tab │ │ │
│ │ │ A │ │ B │ │ │
│ │ └─────┘ └─────┘ │ │
│ │ │ │
│ │ Group: bob (green) │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ Tab │ │ Tab │ │ Tab │ │ │
│ │ │ C │ │ D │ │ E │ │ │
│ │ └─────┘ └─────┘ └─────┘ │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
↑
CDP Connection
↓
┌─────────────────────────────────────────────┐
│ ultimate-playwright-mcp (MCP Server) │
│ - Tab routing via targetId │
│ - Tab groups via groupId │
│ - Shared ownership registry (JSON file) │
│ - Stdio transport │
└─────────────────────────────────────────────┘
↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Alice │ │ Bob │ │ Charlie │
│ (Claude)│ │ (Claude)│ │ (Cursor)│
└─────────┘ └─────────┘ └─────────┘
MCP Configuration
Cursor / Windsurf / Generic MCP Client
{
"mcpServers": {
"ultimate-playwright": {
"command": "npx",
"args": ["ultimate-playwright-mcp", "--cdp-endpoint", "http://localhost:9222"]
}
}
}
With Environment Variable
{
"mcpServers": {
"ultimate-playwright": {
"command": "npx",
"args": ["ultimate-playwright-mcp"],
"env": {
"CDP_ENDPOINT": "http://localhost:9222"
}
}
}
}
CLI Options
ultimate-playwright-mcp [options]
Options:
--cdp-endpoint <url> CDP endpoint URL (e.g., http://localhost:9222)
Can also use CDP_ENDPOINT env var.
If omitted, daemon-managed Chrome is started lazily on first tool call.
--agent-id <id> Optional agent ID for logging/debugging
Can also use AGENT_ID env var
--keep-alive Auto-restart daemon-managed Chrome if it exits
Use --no-keep-alive for testing workflows where you want Chrome to stay down after kill
Default: disabled (no auto-restart)
Can also use KEEP_ALIVE env var (set to "false" to disable)
--checkpoint-output-dir <path>
Root directory for checkpoint manifests, artifacts, and reports
Can also use CHECKPOINT_OUTPUT_DIR env var
-V, --version Output version number
-h, --help Display help
Multi-Agent Setup
Running Multiple Claude Code Instances
Each instance connects to the same MCP server and gets isolated tabs:
Terminal 1:
claude-code --mcp-config ./mcp-config.json
# Agent A creates tabs with targetIds starting from ABC...
Terminal 2:
claude-code --mcp-config ./mcp-config.json
# Agent B creates tabs with targetIds starting from XYZ...
Both agents share cookies and sessions but operate on different tabs!
Persistent Chrome Setup (macOS)
For a Chrome instance that auto-starts with debug port:
Create ~/Library/LaunchAgents/com.user.chrome-debug.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.chrome-debug</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Google Chrome.app/Contents/MacOS/Google Chrome</string>
<string>--remote-debugging-port=9222</string>
<string>--user-data-dir=/Users/YOUR_USERNAME/chrome-debug-profile</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Load with:
launchctl load ~/Library/LaunchAgents/com.user.chrome-debug.plist
Development
# Install dependencies
npm install
# Build
npm run build
# Type check
npm run type-check
# Lint
npm run lint
# Watch mode
npm run watch
License
MIT
Attribution
This project extracts browser control code from OpenClaw (MIT licensed), which provides battle-tested tab isolation and Playwright integration.
Key extracted components:
- CDP session management (
pw-session.ts) - Browser operations (
pw-tools-*.ts) - Role-based element refs (
pw-role-snapshot.ts)
Links
- OpenClaw - Source of browser control code
- MCP Specification - Model Context Protocol
- Playwright - Browser automation library
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。