Playwright pool
Portable collection of Cursor agent and Claude Code agent skills. Paste the repo URL into agent chat to install on any machine
npx -y skills add timi-ty/agent-forge --skill playwright-poolAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up and use the Playwright browser pool MCP server. Enables multiple agents to run isolated browser sessions simultaneously without contention. Works with both Cursor and Claude Code. TRIGGER on "set up playwright pool", "install playwright pool", "browser pool", or any browser automation task where session isolation is needed. Also triggered automatically by sync-skills after first install.
SKILL.md
11.7 KB, as published. Nobody here has run it
Playwright Pool
Manages a pool of isolated @playwright/mcp browser processes so multiple agents can each hold their own browser session simultaneously. Each agent acquires a session_id, passes it to every browser_* call, and releases it when done.
SETUP WIZARD
Run this section when:
- sync-skills just installed this skill and directed you here
- The user says "set up playwright pool", "install playwright pool", or similar
- The user wants to reconfigure the pool
Step 1: Check prerequisites
Node.js — required to run the MCP server:
node --version
If the command fails or returns a version below 18, tell the user:
"Node.js 18 or later is required. Install it from https://nodejs.org and re-run setup." Then stop.
npx — ships with Node.js, but verify:
npx --version
If this fails, tell the user to reinstall Node.js (npx is bundled with it).
@playwright/mcp — the MCP server package:
The pool server fetches this at runtime via npx @playwright/mcp@latest. Pre-cache it now so the first server startup doesn't trigger a silent download:
npx @playwright/mcp@latest --version
This downloads and caches @playwright/mcp and its dependencies. If it fails (network error, proxy issue), stop and tell the user:
"Could not reach the npm registry. Ensure you have internet access (or
HTTPS_PROXYset if behind a proxy) and re-run setup."
Step 2: Detect host tool
Determine whether you are running in Cursor or Claude Code:
- Cursor: Your system prompt identifies you as a Cursor agent, or you have access to the
AskQuestiontool. - Claude Code: Your system prompt identifies you as Claude Code, or you have access to the
AskUserQuestiontool.
Set $TOOL to cursor or claude-code for use in all remaining steps.
Step 3: Check if already installed
Claude Code:
claude mcp list 2>&1 | grep playwright-pool
If output shows playwright-pool ... ✓ Connected, it is already registered.
Cursor:
cat ~/.cursor/mcp.json 2>/dev/null | python -c "import json,sys; d=json.load(sys.stdin); print('found' if 'playwright-pool' in d.get('mcpServers',{}) else 'not found')"
If output is found, it is already registered.
If already registered:
- Ask: "playwright-pool is already registered. Do you want to (1) reconfigure it, or (2) skip to usage docs?"
- If reconfigure → continue from Step 4
- If skip → jump to the USAGE section below
Step 4: Ask configuration preferences
Ask the user these questions one at a time. Accept Enter for defaults:
- Browser — chromium, firefox, or webkit? (default: chromium)
- Acquire timeout — Seconds to wait when at capacity before erroring? (default: 30)
- Max concurrent — Hard cap on simultaneous browser processes? (default: unlimited — the pool grows with demand and shrinks back to 1 idle when sessions are released)
Step 5: Install browser binaries
Now that the browser choice is known, tell the user:
"Playwright needs to download the [chosen browser] binary (~150 MB). This is a one-time download stored in Playwright's local cache. Proceed?"
Wait for confirmation before continuing. If the user declines:
"You can run
npx playwright install [browser]manually whenever you're ready, then re-run this setup." Then stop.
Once confirmed:
npx playwright install <chosen-browser>
Safe to re-run — skips the download if the binary is already installed.
If the install fails:
- On Linux: system dependencies may be missing — run
npx playwright install-deps <browser>first, then retry - Behind a corporate proxy: set the
HTTPS_PROXYenvironment variable
Step 6: Locate the server source files
The server source files were installed alongside this SKILL.md by sync-skills. Find them based on $TOOL:
Claude Code — macOS/Linux:
ls ~/.claude/commands/playwright-pool/server/index.js 2>/dev/null && echo "found at global"
ls .claude/commands/playwright-pool/server/index.js 2>/dev/null && echo "found at workspace"
Claude Code — Windows (Git Bash):
ls "$USERPROFILE/.claude/commands/playwright-pool/server/index.js" 2>/dev/null && echo "found at global"
ls .claude/commands/playwright-pool/server/index.js 2>/dev/null && echo "found at workspace"
Cursor — macOS/Linux:
ls ~/.cursor/skills/playwright-pool/server/index.js 2>/dev/null && echo "found at global"
ls .cursor/skills/playwright-pool/server/index.js 2>/dev/null && echo "found at workspace"
Cursor — Windows (Git Bash):
ls "$USERPROFILE/.cursor/skills/playwright-pool/server/index.js" 2>/dev/null && echo "found at global"
ls .cursor/skills/playwright-pool/server/index.js 2>/dev/null && echo "found at workspace"
Use whichever location has the files. If neither is found: "Server source files are missing. Please re-run sync-skills to reinstall playwright-pool."
Set $SKILL_SERVER_DIR to the directory containing index.js.
Step 7: Deploy the server files
Claude Code — macOS/Linux:
mkdir -p ~/.claude/mcp-servers/playwright-pool
cp "$SKILL_SERVER_DIR/index.js" ~/.claude/mcp-servers/playwright-pool/index.js
cp "$SKILL_SERVER_DIR/package.json" ~/.claude/mcp-servers/playwright-pool/package.json
Claude Code — Windows (Git Bash):
mkdir -p "$USERPROFILE/.claude/mcp-servers/playwright-pool"
cp "$SKILL_SERVER_DIR/index.js" "$USERPROFILE/.claude/mcp-servers/playwright-pool/index.js"
cp "$SKILL_SERVER_DIR/package.json" "$USERPROFILE/.claude/mcp-servers/playwright-pool/package.json"
Cursor — macOS/Linux:
mkdir -p ~/.cursor/mcp-servers/playwright-pool
cp "$SKILL_SERVER_DIR/index.js" ~/.cursor/mcp-servers/playwright-pool/index.js
cp "$SKILL_SERVER_DIR/package.json" ~/.cursor/mcp-servers/playwright-pool/package.json
Cursor — Windows (Git Bash):
mkdir -p "$USERPROFILE/.cursor/mcp-servers/playwright-pool"
cp "$SKILL_SERVER_DIR/index.js" "$USERPROFILE/.cursor/mcp-servers/playwright-pool/index.js"
cp "$SKILL_SERVER_DIR/package.json" "$USERPROFILE/.cursor/mcp-servers/playwright-pool/package.json"
Then write config.json with the user's preferences from Step 4:
{
"playwrightArgs": ["--isolated", "--browser=<browser>"],
"acquireTimeoutMs": <timeout seconds * 1000>
}
If the user specified a maxConcurrent value, add it:
{
"maxConcurrent": <max concurrent>,
"playwrightArgs": ["--isolated", "--browser=<browser>"],
"acquireTimeoutMs": <timeout seconds * 1000>
}
Claude Code: write to ~/.claude/mcp-servers/playwright-pool/config.json
Cursor: write to ~/.cursor/mcp-servers/playwright-pool/config.json
Step 8: Register the MCP server
Claude Code — macOS/Linux:
claude mcp add playwright-pool --scope user -- node "$HOME/.claude/mcp-servers/playwright-pool/index.js"
Claude Code — Windows (Git Bash):
claude mcp add playwright-pool --scope user -- node "$USERPROFILE/.claude/mcp-servers/playwright-pool/index.js"
Cursor (all platforms) — use Python to safely merge into ~/.cursor/mcp.json, creating the file if it doesn't exist:
python -c "
import json, pathlib
home = pathlib.Path.home()
p = home / '.cursor' / 'mcp.json'
cfg = json.loads(p.read_text()) if p.exists() else {}
cfg.setdefault('mcpServers', {})['playwright-pool'] = {
'command': 'node',
'args': [str(home / '.cursor' / 'mcp-servers' / 'playwright-pool' / 'index.js')]
}
p.write_text(json.dumps(cfg, indent=2))
print('Registered playwright-pool in ~/.cursor/mcp.json')
"
Verify registration:
Claude Code:
claude mcp list 2>&1 | grep playwright-pool
Cursor: re-run the check from Step 3 and confirm output is found.
Step 9: Confirm and instruct
Report what was configured:
- Tool: Claude Code or Cursor
- Pool size, browser, and timeout chosen
- Server deployed to:
~/.claude/mcp-servers/playwright-pool/or~/.cursor/mcp-servers/playwright-pool/ - Config at:
[server dir]/config.json
Then tell the user:
Claude Code:
Reload your Claude Code window to activate playwright-pool. After reloading,
browser_pool_acquire,browser_navigate, and all other browser tools will appear in your agent's tool list. To change settings later: edit theconfig.jsonabove and reload the window.
Cursor:
Fully restart Cursor (not just reload window) to activate playwright-pool. After restarting, browser pool tools will appear. You can verify in Cursor Settings > Tools and MCP. To change pool size later: edit the
config.jsonabove and restart Cursor.
USAGE
Use this section when an agent needs browser automation in a multi-agent or parallel context.
Why sessions are required
All agents share one MCP connection. Without the pool, every agent's browser calls go to the same browser instance — causing state contamination and blocking. The pool proxy manages N isolated @playwright/mcp processes and routes each agent's calls to its own dedicated browser.
Mandatory workflow
Every agent that needs a browser must follow this three-step pattern:
1. Acquire a session
browser_pool_acquire({ label: "agent-name-or-task" })
→ { session_id: "s2-1719000000000", pool_status: { total: 2, available: 1, busy: 1, spawning: 0, queued: 0 } }
A warm browser is always kept on standby, so this returns instantly. If the standby is still spawning (rare: burst of concurrent acquires), the call waits for it. If maxConcurrent is set and reached, this call blocks and queues (up to acquireTimeoutMs). Do not poll — just await the result.
2. Use the browser — pass session_id to every call
browser_navigate({ session_id: "s2-...", url: "https://example.com" })
browser_snapshot({ session_id: "s2-..." })
browser_click({ session_id: "s2-...", ref: "button#submit" })
Every browser_* call requires session_id. Calls without it fail immediately.
3. Always release when done
browser_pool_release({ session_id: "s2-..." })
Always release — even if an error occurred. Unreleased sessions stay busy until the pool restarts.
Pool management tools
| Tool | Purpose |
|---|---|
browser_pool_acquire({ label? }) | Get a free browser. Spawns on demand; queues only if maxConcurrent is reached. |
browser_pool_release({ session_id }) | Return browser to pool. |
browser_pool_status() | Check available/busy/spawning/queued counts. |
Pool sizing
The pool is self-sizing: it keeps exactly 1 idle browser (the warm standby) and grows as needed. At any moment, total processes = active sessions + 1. You never configure a pool size.
To add an optional hard cap (e.g. prevent runaway parallelism), set maxConcurrent in config.json:
{
"maxConcurrent": 8,
"playwrightArgs": ["--isolated", "--browser=chromium"],
"acquireTimeoutMs": 30000
}
Without maxConcurrent, the pool is unbounded.
Error reference
| Error | Cause | Fix |
|---|---|---|
session_id is required | Called browser_* without a session | Call browser_pool_acquire first |
No active session for session_id "..." | Session released or never acquired | Re-acquire a new session |
All N browsers are busy and maxConcurrent (M) is reached. Timed out after Xms | Hard cap hit | Increase maxConcurrent or ensure agents release promptly |
Gives 0 of the 12 instructions most mcp tooling skills give
Counted across 638 of the 750 authors here whose files we hold, read 2026-08-06
- create ten complex read-only evaluation questionsin 71 of 638, across 17 files
- test servers using MCP Inspectorin 60 of 638, across 18 files
- provide actionable error messagesin 56 of 638, across 14 files
- prioritize comprehensive API coverage over specific workflowsin 54 of 638, across 12 files
- use TypeScript and Streamable HTTP for remote serversin 53 of 638, across 7 files
- define structured output schemas where possiblein 51 of 638, across 9 files
- use Zod or Pydantic for input schemasin 48 of 638, across 6 files
- fetch MCP specification pages with markdown suffixin 46 of 638, across 4 files
- load framework documentation using WebFetchin 45 of 638, across 3 files
- verify each evaluation answer independentlyin 45 of 638, across 3 files
- implement API client with authentication and paginationin 45 of 638, across 3 files
- Define input schemas with validationin 28 of 638, across 10 files
Said here and by no other author read
- check node and npx versions
- determine host tool
- ask configuration preferences
- install browser binaries
- locate server source files
- deploy server files to mcp directory
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.