pw-mcp
It enables each agent session to have its own isolated Chrome browser with a persistent profile, avoiding profile-lock conflicts and shared tab spaces, while resumed sessions reattach to the same browser and tabs. It can also seed new sessions with a saved login template so they start signed in.
README
pw-pool
One browser per agent session for the Playwright MCP.
@playwright/mcp assumes one server and one browser. If you run two agent sessions on one machine and
they either fail on the profile lock or, with a shared browser, work in the same tab space and
navigate each other's pages. pw-pool gives every session its own Chrome and remembers which one
is whose.
Profiles
Chrome keeps everything about a "person" in a profile directory (--user-data-dir): cookies,
local storage, saved passwords, open tabs. That is what keeps you signed in between runs. Only one
Chrome can use a profile at a time. pw-pool creates one profile per session, keeps it between runs,
and can seed a new one from a template — a copy of the login files of a profile you are already
signed in with — so a new session starts signed in without sharing a browser with anyone.
Install
Needs Node 22+ and macOS or Linux.
git clone https://github.com/ckarnell/pw-pool && cd pw-pool
npm install # pins @playwright/mcp and patches it
node bin/pw-pool.js install # checks the setup; offers to download Chrome for Testing if missing
Or globally, which puts pw-mcp and pw-pool on your PATH: npm install -g github:ckarnell/pw-pool.
Then use pw-mcp as the Playwright MCP command. Claude Code (~/.claude.json or a project
.mcp.json):
"playwright": { "type": "stdio", "command": "pw-mcp" }
(or "command": "node", "args": ["/path/to/pw-pool/bin/pw-mcp.js"] for a clone that is not on PATH).
Other MCP flags (--caps, --output-dir, …) can be added to args; they pass through.
--headless is applied to the pool's launch. --cdp-endpoint, --user-data-dir, --isolated and
--browser are dropped with a warning, because the pool chooses the browser.
By default browsers are Playwright's Chrome for Testing. To use the Chrome already installed on the
machine: pw-pool config set channel '"chrome"' (also chrome-beta, chrome-canary, msedge), or
config.chrome for an explicit path.
Optional, to start every session signed in:
pw-pool template save main --from ~/path/to/a/signed-in/user-data-dir
pw-pool config set defaultTemplate '"main"'
Switching while sessions are open
You can change the MCP config at any time; nothing running is affected. An MCP server is started
once per session, so sessions that are already open keep their old server and browser until they
restart. Sessions that start (or restart, for example claude --resume) after the change use
pw-pool. Order that works:
- Save a template from the browser you use today and set it as the default (above), so the new browsers are signed in.
- Change the MCP entry to
pw-mcp. - Nothing else. Old sessions continue; new ones get their own browser.
To go back, restore the old MCP entry. Browsers that pw-pool started are reaped after the idle TTL,
or at once with pw-pool stop all. A browser you ran before (for example a shared one on a fixed
CDP port) is not touched by pw-pool and can keep running beside it.
How it works
session A ─▶ pw-mcp ─▶ registry ─▶ Chrome :9300, profiles/A/ ◀─ @playwright/mcp --cdp-endpoint
session B ─▶ pw-mcp ─▶ registry ─▶ Chrome :9301, profiles/B/ ◀─ @playwright/mcp --cdp-endpoint
pw-mcpreplacesnpx @playwright/mcpas the MCP server command. It finds out which session is calling, takes that session's browser from the pool (launching one if needed), and runs the bundled@playwright/mcpagainst it over CDP. Stdio passes straight through.- When the MCP exits, the browser stays up. A resumed session gets the same browser, tabs and all.
- A browser with no open tabs and no active session is stopped at once; one that still has tabs is stopped 1 hour after its session ends (tabs saved). A later start relaunches it on the same profile and reopens the tabs. Unused profiles are deleted after 30 days. An active session holds a lease and is never reaped.
- Nothing raises a window: browsers start with no window, and tabs are opened in the background. The bundled MCP carries a two-line patch for the same reason (see Focus).
No daemon. State is a JSON registry under ~/.pw-pool/, guarded by a lock.
Which session is which
pw-mcp needs a stable key per session. In order:
--key/PW_POOL_KEY— explicit. Any harness can set this.PW_POOL_NAMElabels the window.CLAUDE_CODE_SESSION_ID— Claude Code (2.1.239+) sets it in the MCP server's environment.~/.claude/sessions/<parent pid>.json— Claude Code writes its session id, name and cwd there.- The parent pid — fallback; the browser is deleted when the lease ends.
Same key, same browser. claude --resume keeps the session id, so it gets its browser back.
Templates
pw-pool template save <name> --from <dir> copies the login files of a profile (cookies, local
storage, IndexedDB, saved passwords, preferences — a few MB; no caches). A new session's profile is
seeded from --template <name>, PW_POOL_TEMPLATE, or config.defaultTemplate, once, when it is
created. After that each profile evolves on its own. --fresh forces an empty profile.
Templates and profiles contain live credentials. Keep ~/.pw-pool/ out of repositories. A template is
a point-in-time copy: save it again after signing in to something new.
CLI
pw-pool install [--yes] first-time setup; asks before downloading Chrome
pw-pool ls registered browsers: key, name, port, pid, status, tabs, leases
pw-pool cdp [key] [--ensure] CDP endpoint of a session's browser (default: the calling session)
pw-pool tabs [key]
pw-pool gc [--force] [--dry-run] reap stale leases, idle browsers, old profiles
pw-pool stop <key|all> [--rm] stop a browser (tabs saved); --rm also deletes its profile
pw-pool template save <name> [--from <dir>] | ls | rm <name>
pw-pool config [get <key> | set <key> <json>]
pw-pool doctor
<key> is a full key, a unique prefix, or a session name. pw-pool cdp --ensure lets scripts drive
the same browser as their session's MCP. Every pw-mcp start runs gc; for machines where sessions
are rare, run pw-pool gc from cron or launchd.
Config lives in ~/.pw-pool/config.json (pw-pool config): portRange [9300, 9399],
idleTtlHours 1, profileTtlDays 30, defaultTemplate, sourceProfile, chrome, channel, headless,
sandbox (off, like Playwright's chromiumSandbox), profileTheme, windowCascade, windowSize,
extraChromeArgs, launchTimeoutMs. PW_POOL_HOME moves the whole
state directory; PW_POOL_HEADLESS=1 runs browsers headless (servers, containers).
profileTheme: true tints each browser's toolbar a stable color derived from its key, so several
pool windows are easy to tell apart on screen (macOS Cmd-Tab still shows one icon per instance; this
colors the window itself). A fixed "R,G,B" themes every pool browser the same.
Focus
On macOS, two things activate a Chrome app and take focus from the person using the machine: a
window created at startup, and a tab created in the foreground. pw-pool launches Chrome with
--no-startup-window and opens tabs with CDP's background: true. @playwright/mcp has no option
for this, so scripts/patch-focus.js changes two lines in the bundled copy (browser_tabs new →
background tab, browser_tabs select → no bringToFront). The patch is applied on npm install;
pw-pool doctor verifies it; PW_MCP_FOREGROUND_TABS=1 restores the original behaviour.
One case is outside the patch's reach: when a page itself opens a popup (window.open or a
target="_blank" link on a click), macOS activates the browser to show it, the same as any Chrome.
Browsers are headed by default, matching @playwright/mcp. If that focus-stealing matters on a
shared machine, run headless: pw-pool config set headless true, PW_POOL_HEADLESS=1, or per session
pw-mcp --headless (and --headed to force headed when the default is headless). Headless renders
identically for snapshots and screenshots.
Troubleshooting
- The MCP disconnects ("Connection closed") right after a
browser_evaluate. The result was larger than the client's per-message limit (16 MB in Claude Code), so the client closed the connection. This is not specific to pw-pool. The client restarts the server within seconds andpw-mcpreattaches to the same browser, tabs included; call the tool again and return smaller values. Claude Code keeps the server's log under~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-playwright/. - "Chrome exited during startup" or "did not answer": the error quotes the end of
~/.pw-pool/logs/<key>.chrome.log. Common causes: no display on Linux (useheadlessor Xvfb), a binary that cannot run (pw-pool doctor). - A browser seems to belong to nobody:
pw-pool lsshows leases;!marks a holder that has exited.pw-pool gcclears those;pw-pool stop <key>stops a browser you are sure about.
Development
npm test # unit tests (no browser needed)
npm run test:e2e # real browsers, throwaway pool home: isolation, reattach, concurrency, recovery, templates
npm run test:docker # the same on Linux in a container
The @playwright/mcp version is pinned. To bump it, change the version, run npm install, and fix
scripts/patch-focus.js if the install fails (the bundle changed shape).
Releasing
Publishing uses npm trusted publishing (OIDC from GitHub Actions) — no tokens. One-time setup on
npmjs.com: the package's Settings → Trusted Publisher → this repo's publish.yml workflow. After that,
release by tagging: npm version patch && git push --follow-tags. The workflow runs the tests and
npm publish --provenance. (The first ever publish, before the package exists, is done once locally
with npm publish --access public --auth-type=web.)
License
MIT
推荐服务器
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 模型以安全和受控的方式获取实时的网络信息。