{"id":44135307,"url":"https://github.com/pm990320/ultimate-playwright-mcp","last_synced_at":"2026-04-03T18:01:29.039Z","repository":{"id":337310773,"uuid":"1153071186","full_name":"pm990320/ultimate-playwright-mcp","owner":"pm990320","description":"Multi-agent Playwright MCP server with tab group isolation — multiple AI agents share one Chrome browser","archived":false,"fork":false,"pushed_at":"2026-02-09T02:42:57.000Z","size":140,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-09T02:47:26.232Z","etag":null,"topics":["ai-agents","browser-automation","cdp","chrome","claude","cursor","mcp","model-context-protocol","multi-agent","playwright","tab-isolation"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ultimate-playwright-mcp","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pm990320.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-08T21:15:06.000Z","updated_at":"2026-02-09T02:43:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pm990320/ultimate-playwright-mcp","commit_stats":null,"previous_names":["pm990320/ultimate-playwright-mcp"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/pm990320/ultimate-playwright-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pm990320%2Fultimate-playwright-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pm990320%2Fultimate-playwright-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pm990320%2Fultimate-playwright-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pm990320%2Fultimate-playwright-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pm990320","download_url":"https://codeload.github.com/pm990320/ultimate-playwright-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pm990320%2Fultimate-playwright-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31368156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","browser-automation","cdp","chrome","claude","cursor","mcp","model-context-protocol","multi-agent","playwright","tab-isolation"],"created_at":"2026-02-08T23:14:31.258Z","updated_at":"2026-04-03T18:01:28.282Z","avatar_url":"https://github.com/pm990320.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ultimate Playwright MCP\n\n[![npm version](https://img.shields.io/npm/v/ultimate-playwright-mcp)](https://www.npmjs.com/package/ultimate-playwright-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/ultimate-playwright-mcp)](https://www.npmjs.com/package/ultimate-playwright-mcp)\n[![license](https://img.shields.io/npm/l/ultimate-playwright-mcp)](https://github.com/pm990320/ultimate-playwright-mcp/blob/main/LICENSE)\n[![CI](https://github.com/pm990320/ultimate-playwright-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/pm990320/ultimate-playwright-mcp/actions/workflows/ci.yml)\n\nMulti-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.\n\n## Why Ultimate Playwright?\n\nThe official [`@playwright/mcp`](https://github.com/nickmccurdy/playwright-mcp) gives you browser control for a **single agent**. But what if you have **multiple agents** sharing one browser?\n\n**Ultimate Playwright MCP** solves this with **tab group isolation**:\n\n- 🔀 **Multi-agent tab groups** — Each agent creates a `groupId` and only sees its own tabs\n- 🍪 **Shared cookies \u0026 sessions** — All agents share the same BrowserContext (log in once, everyone's authenticated)\n- 🎨 **Visual Chrome tab groups** — Companion extension organizes tabs into color-coded Chrome tab groups\n- 💾 **Persistent registry** — Tab groups survive MCP server restarts (`~/.ultimate-playwright-mcp/tab-groups.json`)\n- 🔌 **Connect to existing Chrome** — Uses CDP to attach to your running Chrome (keeps your profile, extensions, bookmarks)\n\n### Comparison\n\n| Feature | **ultimate-playwright-mcp** | @playwright/mcp | browser-use-mcp |\n|---|---|---|---|\n| Multi-agent tab isolation | ✅ Tab groups with `groupId` | ❌ Single session | ❌ Single session |\n| Shared cookies across agents | ✅ Same BrowserContext | N/A | N/A |\n| Connect to existing Chrome | ✅ CDP | ❌ Launches new browser | ❌ Launches new browser |\n| Visual tab groups in Chrome | ✅ Extension | ❌ | ❌ |\n| Persistent tab registry | ✅ Survives restarts | ❌ | ❌ |\n| Accessibility tree snapshots | ✅ Element refs (e1, e2…) | ✅ | ❌ Screenshot-based |\n| Open source | ✅ MIT | ✅ Apache-2.0 | ✅ MIT |\n\n## Features\n\n- ✅ **Tab Isolation** - Each agent gets its own tabs via unique `targetId`\n- ✅ **Shared Cookies** - All agents share the same BrowserContext (cookies, sessions, localStorage)\n- ✅ **Parallel Execution** - Multiple agents can operate simultaneously without interference\n- ✅ **CDP Connection** - Connects to existing Chrome via Chrome DevTools Protocol\n- ✅ **Battle-Tested** - Extracted from [OpenClaw](https://github.com/openclaw/openclaw) (MIT licensed)\n\n## Installation\n\n```bash\nnpm install -g ultimate-playwright-mcp\n```\n\nOr run directly with npx:\n\n```bash\nnpx ultimate-playwright-mcp --cdp-endpoint http://localhost:9222\n```\n\n## Quick Start\n\n### 1. Launch Chrome with Remote Debugging\n\n```bash\n# macOS\n/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome \\\n  --remote-debugging-port=9222 \\\n  --user-data-dir=/tmp/chrome-debug\n\n# Linux\ngoogle-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug\n\n# Windows\n\"C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe\" ^\n  --remote-debugging-port=9222 ^\n  --user-data-dir=C:\\\\temp\\\\chrome-debug\n```\n\n### 2. Configure Claude Desktop\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ultimate-playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"ultimate-playwright-mcp\",\n        \"--cdp-endpoint\",\n        \"http://localhost:9222\"\n      ]\n    }\n  }\n}\n```\n\n### 3. Restart Claude Desktop\n\nClaude will now have access to browser control tools with tab isolation.\n\n## Usage Example\n\n```\nUser: Open two tabs and navigate them independently\n\nClaude: I'll create two tabs with separate targetIds:\n\n1. browser_tabs({ action: \"new\" })\n   → **targetId: ABC123...**\n\n2. browser_tabs({ action: \"new\" })\n   → **targetId: XYZ789...**\n\n3. browser_navigate({ targetId: \"ABC123...\", url: \"https://github.com\" })\n4. browser_navigate({ targetId: \"XYZ789...\", url: \"https://google.com\" })\n\nBoth tabs are now navigated independently!\n```\n\n## Available Tools\n\n| Tool | Description | Key Parameters |\n|------|-------------|----------------|\n| `browser_tab_group` | Create/list/delete tab groups for isolation | `action`, `name`, `color`, `groupId` |\n| `browser_tabs` | List, create, close, or select tabs | `action`, `groupId`, `targetId`, `index` |\n| `browser_navigate` | Navigate to a URL | `url`, `targetId` |\n| `browser_snapshot` | Capture accessibility tree with refs | `targetId` |\n| `browser_click` | Click an element | `ref`, `targetId` |\n| `browser_type` | Type text into an element | `ref`, `text`, `targetId` |\n| `browser_hover` | Hover over an element | `ref`, `targetId` |\n| `browser_press_key` | Press a keyboard key | `key`, `targetId` |\n| `browser_fill_form` | Fill multiple form fields | `fields`, `targetId` |\n| `browser_wait_for` | Wait for conditions | `text`, `selector`, `url`, `loadState`, `targetId` |\n\n## Tab Groups (Multi-User Isolation)\n\nWhen multiple users or agents share one browser instance, tab groups keep everyone's\ntabs isolated. Each session creates its own group, and all tab operations are scoped\nto that group.\n\n```\nUser: Research product pricing\n\nClaude: I'll create a tab group first, then open tabs within it.\n\n1. browser_tab_group({ action: \"create\", name: \"pricing-research\", color: \"blue\" })\n   → **groupId: g_a1b2c3d4e5f6**\n\n2. browser_tabs({ action: \"new\", groupId: \"g_a1b2c3d4e5f6\", url: \"https://example.com/pricing\" })\n   → **targetId: ABC123...**\n\n3. browser_tabs({ action: \"list\", groupId: \"g_a1b2c3d4e5f6\" })\n   → Only shows tabs in this group (not other users' tabs)\n```\n\nMeanwhile, another user on the same server:\n\n```\n1. browser_tab_group({ action: \"create\", name: \"docs-review\", color: \"green\" })\n   → **groupId: g_x9y8z7w6v5u4**\n\n2. browser_tabs({ action: \"new\", groupId: \"g_x9y8z7w6v5u4\", url: \"https://docs.example.com\" })\n   → **targetId: XYZ789...**\n```\n\nBoth users share the same cookies/sessions but only see their own tabs!\n\n### Tab Group Lifecycle\n\n1. **Create** a group at the start of your session\n2. **Open tabs** within the group using `groupId`\n3. **Work** with tabs using `targetId` as before\n4. **Delete** the group when done (optionally closes all tabs)\n\nGroup state is persisted to `~/.ultimate-playwright-mcp/tab-groups.json` so it\nsurvives MCP server restarts.\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────┐\n│        Single Chrome Process                │\n│    (--remote-debugging-port=9222)           │\n│  ┌─────────────────────────────────────┐   │\n│  │     Single BrowserContext            │   │\n│  │  (shared cookies, storage)           │   │\n│  │                                      │   │\n│  │  Group: alice (blue)                 │   │\n│  │  ┌─────┐ ┌─────┐                    │   │\n│  │  │ Tab │ │ Tab │                    │   │\n│  │  │  A  │ │  B  │                    │   │\n│  │  └─────┘ └─────┘                    │   │\n│  │                                      │   │\n│  │  Group: bob (green)                  │   │\n│  │  ┌─────┐ ┌─────┐ ┌─────┐            │   │\n│  │  │ Tab │ │ Tab │ │ Tab │            │   │\n│  │  │  C  │ │  D  │ │  E  │            │   │\n│  │  └─────┘ └─────┘ └─────┘            │   │\n│  └─────────────────────────────────────┘   │\n└─────────────────────────────────────────────┘\n                   ↑\n           CDP Connection\n                   ↓\n┌─────────────────────────────────────────────┐\n│    ultimate-playwright-mcp (MCP Server)     │\n│    - Tab routing via targetId               │\n│    - Tab groups via groupId                 │\n│    - Shared ownership registry (JSON file)  │\n│    - Stdio transport                        │\n└─────────────────────────────────────────────┘\n         ↓           ↓           ↓\n   ┌─────────┐ ┌─────────┐ ┌─────────┐\n   │ Alice   │ │  Bob    │ │ Charlie │\n   │ (Claude)│ │ (Claude)│ │ (Cursor)│\n   └─────────┘ └─────────┘ └─────────┘\n```\n\n## MCP Configuration\n\n### Cursor / Windsurf / Generic MCP Client\n\n```json\n{\n  \"mcpServers\": {\n    \"ultimate-playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\"ultimate-playwright-mcp\", \"--cdp-endpoint\", \"http://localhost:9222\"]\n    }\n  }\n}\n```\n\n### With Environment Variable\n\n```json\n{\n  \"mcpServers\": {\n    \"ultimate-playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\"ultimate-playwright-mcp\"],\n      \"env\": {\n        \"CDP_ENDPOINT\": \"http://localhost:9222\"\n      }\n    }\n  }\n}\n```\n\n## CLI Options\n\n```bash\nultimate-playwright-mcp [options]\n\nOptions:\n  --cdp-endpoint \u003curl\u003e  CDP endpoint URL (e.g., http://localhost:9222)\n                        Can also use CDP_ENDPOINT env var\n  --agent-id \u003cid\u003e       Optional agent ID for logging/debugging\n                        Can also use AGENT_ID env var\n  -V, --version         Output version number\n  -h, --help            Display help\n```\n\n## Multi-Agent Setup\n\n### Running Multiple Claude Code Instances\n\nEach instance connects to the same MCP server and gets isolated tabs:\n\n**Terminal 1:**\n```bash\nclaude-code --mcp-config ./mcp-config.json\n# Agent A creates tabs with targetIds starting from ABC...\n```\n\n**Terminal 2:**\n```bash\nclaude-code --mcp-config ./mcp-config.json\n# Agent B creates tabs with targetIds starting from XYZ...\n```\n\nBoth agents share cookies and sessions but operate on different tabs!\n\n## Persistent Chrome Setup (macOS)\n\nFor a Chrome instance that auto-starts with debug port:\n\nCreate `~/Library/LaunchAgents/com.user.chrome-debug.plist`:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n    \u003ckey\u003eLabel\u003c/key\u003e\n    \u003cstring\u003ecom.user.chrome-debug\u003c/string\u003e\n    \u003ckey\u003eProgramArguments\u003c/key\u003e\n    \u003carray\u003e\n        \u003cstring\u003e/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\u003c/string\u003e\n        \u003cstring\u003e--remote-debugging-port=9222\u003c/string\u003e\n        \u003cstring\u003e--user-data-dir=/Users/YOUR_USERNAME/chrome-debug-profile\u003c/string\u003e\n    \u003c/array\u003e\n    \u003ckey\u003eRunAtLoad\u003c/key\u003e\n    \u003ctrue/\u003e\n    \u003ckey\u003eKeepAlive\u003c/key\u003e\n    \u003ctrue/\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\n```\n\nLoad with:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.user.chrome-debug.plist\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Type check\nnpm run type-check\n\n# Lint\nnpm run lint\n\n# Watch mode\nnpm run watch\n```\n\n## License\n\nMIT\n\n## Attribution\n\nThis project extracts browser control code from [OpenClaw](https://github.com/openclaw/openclaw) (MIT licensed), which provides battle-tested tab isolation and Playwright integration.\n\nKey extracted components:\n- CDP session management (`pw-session.ts`)\n- Browser operations (`pw-tools-*.ts`)\n- Role-based element refs (`pw-role-snapshot.ts`)\n\n## Links\n\n- [OpenClaw](https://github.com/openclaw/openclaw) - Source of browser control code\n- [MCP Specification](https://spec.modelcontextprotocol.io/) - Model Context Protocol\n- [Playwright](https://playwright.dev/) - Browser automation library\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpm990320%2Fultimate-playwright-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpm990320%2Fultimate-playwright-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpm990320%2Fultimate-playwright-mcp/lists"}