[playwright-e2e-mcp logo: a heartbeat line that ends in a green check]
playwright-e2e-mcp
The test doctor for AI agents.
Your Playwright test fails. Your AI finds out why, fixes it, and proves the fix works, or tells you it's a real bug.
[npm] [npm downloads] [CI] [MCP Registry] [License: MIT] [100% free]
[Install in Cursor]
[Install in VS Code]
[Add to Claude Desktop]
[An agent runs the failing checkout test, suggest-fix proposes a locator proven on the page at failure, and the applied fix is re-run and verified green]
⭐ If it saves you a debugging session, a star helps other Playwright users find it.
Quick start ·
Features ·
Tools ·
Tool reference ·
GitHub Action ·
Benchmark ·
Changelog
An MCP server and agent skill that gives Claude, Cursor,
VS Code Copilot, Codex, Gemini and any other MCP client a full Playwright toolkit: a test
runner, a failure detective and a fixer that checks its own work. Browser MCPs let an
AI click around a page. This one lets it keep your test suite green, for TypeScript and
Python suites, on your laptop and in CI. Free, MIT, no account.
❌ Without it / ✅ With it
Without it, your agent sees Timeout 5000ms exceeded waiting for getByTestId('checkout'),
guesses a new selector, edits the test and hopes. Or it "fixes" the test by deleting the
assertion that caught a real bug.
With it, your agent reads the page as it was when the test failed (from the Playwright
trace), swaps in a locator proven unique on that page, re-runs the test and keeps the edit only
if it passes. When the button is really gone, it says so: that's an app bug, not a test to patch.
And a heal guard blocks any "fix" that went green by checking less.
⚡ Quick start
Run this in your project root. It adds the server to every MCP client config it finds (Claude
Code, Cursor, VS Code, Gemini CLI, Codex), installs the agent skill and leaves your other servers
alone:
Then restart your client and ask:
Or let your agent install it. Paste this into any coding agent:
Install the playwright-e2e-mcp server and skill by following
https://raw.githubusercontent.com/xsignon-secure/E2E/main/llms-install.md
Or add the standard config by hand (works in most clients):
Needs: Node.js 22+, and a project with @playwright/test and a browser
(npx playwright install chromium) or with pytest-playwright.
The server uses its working directory as the project root; if your client starts it elsewhere,
add "env": { "PW_MCP_PROJECT_ROOT": "/path/to/your/project" }.
Claude Code
Server and skill, as a plugin:
Or the server only:
Claude Desktop
Download the .mcpb extension from the latest release
and double-click it. It ships its own dependencies, so no Node setup is needed. On install it
asks for your project root: choose the project folder, not your home directory.
You can also add the standard config to claude_desktop_config.json.
Cursor
Click Install in Cursor,
or go to Settings → MCP → Add new MCP server and paste the standard config. For one
project only, put it in .cursor/mcp.json.
Only fixing failing tests? Install the core tools only: the seven-tool fix loop
(--tools=core), about 2.3k tokens of tool definitions instead of 12.1k.
VS Code / GitHub Copilot
Click the Install in VS Code button above, or run:
Codex
A Playwright run with retries can take longer than Codex's default 60 s tool timeout. Raise
the timeouts in ~/.codex/config.toml:
Gemini CLI / Qwen Code
Server and skill, as an extension:
Or paste the standard config into .gemini/settings.json (Qwen Code: .qwen/settings.json).
Windsurf, Cline, Zed, Freebuff and other clients
Add the standard config to the client's MCP config file (Cline: MCP Servers → Configure).
Clients that take a command, such as Zed, run npx with the arguments -y playwright-e2e-mcp.
Freebuff / Codebuff: drop an mcp.json with the standard config into your project's .agents/
folder. This repo ships one in .agents/mcp.json; Freebuff asks you to trust
a repository's .agents/ on first run.
ChatGPT, claude.ai and other remote-only clients
Some clients only accept a remote HTTPS server. This repo ships a Streamable HTTP bridge you
can host for free on Vercel, with OAuth sign-in for claude.ai connectors (dynamic registration
and Client ID Metadata Documents). See Hosted endpoint. On Vercel the
page tools (inspect a page, check selectors, accessibility and Web Vitals audits) run on a
bundled Chromium against public URLs. Running and fixing your own tests needs your project, so
use the local install for that.
Other ways to install: skill only, Docker, registry, tarball
Updating
npx -y playwright-e2e-mcp doctor tells you whether a newer version is out and prints the
command for your setup. Upgrade notes for each release are on the
releases page.
💬 What you can ask
✨ What you get
🩺 A fix loop that proves itself
- Fixes are verified, not guessed.
suggest-fix picks a locator proven unique on the DOM at
failure, writes it, re-runs the test and reverts if it's still red. Strict-mode violations get
the locator of the intended match; changed copy gets the new expected text.
- Honest about real bugs. When the element is really gone, it refuses to patch the test and
reports an app bug.
- Heal guard.
check-test-change (and playwright-e2e-mcp guard in CI) blocks a "fix" that
went green by deleting an assertion, skipping the test, adding .only, swallowing the error or
moving an assertion under an if, and warns on weaker matchers, hard waits, forced clicks,
early returns and raised timeouts. runtime: true also runs the old and new version and blocks
a test that now executes fewer assertions, which catches what no code scan can. Works for
pytest-playwright files too.
- Asks before it writes. Applying a fix, writing a test, quarantining or replacing a visual
baseline shows you the exact diff and waits for your yes in clients that support MCP
questions (
PW_MCP_CONFIRM_WRITES).
🔬 Flaky tests, history and the breaking commit
- Flaky verdicts with evidence.
diagnose-flaky tells a race from shared state from a
test-order dependency, and gives the seed that replays it.
- Quarantine with an owner and an expiry. The test keeps running and being reported; it stops
blocking the build until the date you set.
- Memory of every run.
analyze-history ranks flaky, regressed, broken and slow tests and
names the commit where each went bad. Share one history across every CI job and laptop with the
free, self-hosted history server (one docker run, dashboard included).
bisect-failure finds the first bad commit without touching your checkout.
audit-tests finds flake risks in the test code (hard waits, one-shot assertions, missing
awaits, fragile selectors, clicks right after goto on a server-rendered app), ranks them by
real flakiness and applies the safe rewrites with a verifying run.
⚡ Hydration races and stale mocks
- The "too fast" click. On Next.js, Nuxt, Remix, Astro and other server-rendered apps the HTML
is clickable before JavaScript attaches its handlers, so a test clicks, the step passes and
nothing happens.
inspect-page names the framework and measures how long controls were on
screen before hydration; get-failure and diagnose-flaky flag a click made while the page's
scripts were still downloading and hydration errors in the console; each comes with the wait
to add.
- Mocks that drifted from the API.
check-mocks (and playwright-e2e-mcp mocks in CI) finds
every route.fulfill JSON body and routeFromHAR recording, calls the real endpoint (GET only)
and reports the fields the mock relies on that the API no longer sends, changed types, new
nulls and removed endpoints, so a green suite stops hiding a broken contract.
🔗 CI runs by URL, remote browsers, Python fixes and AI chat UIs
-
Paste the CI run, skip the download. Give load-report a GitHub Actions run or GitLab job
URL. It fetches the report and traces with your own GITHUB_TOKEN / GITLAB_TOKEN, maps them
onto your checkout, and get-failure and suggest-fix work on that run.
-
Any browser, anywhere. The page tools take connect: a Playwright server
(npx playwright run-server), a browser grid or device cloud, or a Chrome over CDP. Keys stay
in the environment as {{env:…}}, never in chat, and only go to hosts you named in
PW_MCP_CONNECT or PW_MCP_CONNECT_HOSTS.
-
Fixes for pytest suites. suggest-fix now patches test_*.py files in Python syntax and
re-runs the test with pytest before keeping the change:
-
AI chat and streaming UIs. The agent skill shows how to test answers that stream in: mock
the model's stream, wait for the "done" signal instead of the text, and check shape rather than
exact wording against a live model.
🤖 CI that comments with working fixes
- GitHub Action that writes the diagnosis to the job summary, keeps one PR comment up to date
and posts each verified fix as a suggested change reviewers apply with one click.
- CI templates for GitHub Actions, GitLab, Azure DevOps, CircleCI, Bitbucket and AWS CodeBuild, and a plain
ci command for anything else.
- Diagnose CI locally:
load-report maps a CI job's report and traces onto your checkout.
🌐 Page tools with locators that already work
inspect-page returns a compact map of verified Playwright locators (about 570 tokens
for a storefront page, against 2,300 for a Playwright MCP snapshot), or the full DOM inventory,
or the accessibility snapshot with a ready toMatchAriaSnapshot assertion.
- Reaches the hard screens: saved logins, headers, click and fill steps, popups and new tabs,
API mocks (500s, empty lists, slow calls), HAR record and replay, phone and tablet presets,
Chromium, Firefox, WebKit, Chrome and Edge.
- Look without changing anything:
blockWrites stops POST, PUT, PATCH and DELETE requests
from reaching a real backend, and blockResources skips images, fonts and trackers for faster,
private page checks. offline: true cuts the network after load to test offline states.
- Accessibility, Web Vitals and visual diffs that return locators and ready tests, not just a score.
🚀 Built for agents in 2026
- Lean on context. Start with
--tools=auto (about 2.4k tokens of tool definitions instead of
12.1k) and the agent loads the page, audit or history tools when it needs them, or pick a
profile: core, triage, inspect, author.
- Interactive test report in MCP Apps clients (Claude, ChatGPT, Cursor): filter failures, see
expected vs. received, re-run or "Ask to fix" in one click.
- Current MCP: the stateless 2026-07-28 revision (2025 clients still work), structured results
with output schemas, tool annotations for accurate safety prompts, the skill served over the
Skills extension, and a Server Card for discovery.
- Everywhere you work: npm, Claude Code plugin, Claude Desktop bundle, Gemini CLI extension,
Docker image on GHCR, and an HTTP bridge with OAuth for remote-only clients.
🧰 Tools
With --tools=auto, a load-tools tool turns on more tools mid-session. Two prompts,
fix-failing-test and triage-flaky-tests, package the main workflows as slash commands. Every
argument and example output is in the tool reference.
Typical workflow
run-test { "testFiles": ["tests/checkout.spec.ts"] }, or { "background": true }
for a long suite and get-run-status { "waitSeconds": 30 } until it finishes. For a
failure from CI, call load-report with the run URL
{ "report": "https://github.com/acme/shop/actions/runs/123" } (needs GITHUB_TOKEN; GitLab
job URLs need GITLAB_TOKEN), or with the artifacts you downloaded
{ "report": "ci-artifacts/results.json" }.
get-failure { "index": 1 } to read the code frame, expected/actual, the DOM
snapshot at failure, the failed network requests and the page's console errors.
suggest-fix { "index": 1 } for a locator or copy change: review the diff, then
{ "index": 1, "apply": true } to write it and verify with a re-run. If it reports the
element is missing, fix the app, not the test.
- For anything it cannot patch:
inspect-page { "url": "…" } (add storageState or
actions to reach the right screen), then validate-selector to prove the new locator
before editing.
- If a failure looks intermittent:
diagnose-flaky { "runs": 3 } for fresh evidence,
and analyze-history { "view": "commits" } to see where it went bad.
- Re-run only what failed with
run-test { "lastFailed": true } until green.
To write a new test, call generate-e2e-test with a description and the steps of the flow;
it walks them on the live page, writes the spec and runs it once.
🤖 CI: GitHub Action, GitLab and any CI
The same diagnosis runs without an agent. On a pull request the Action re-runs each failing test
with its suggested fix and posts the fixes that pass as suggested changes on the failing
lines, so a reviewer applies one with the Commit suggestion button:
- Ready-to-copy workflows: GitHub Actions
(artifact upload, heal guard, history server), GitLab CI
(heal guard on merge requests and a merge request comment),
Azure DevOps,
CircleCI,
Bitbucket Pipelines and
AWS CodeBuild (heal guard on pull requests, reports as artifacts).
- Any other CI (Jenkins, Buildkite, TeamCity):
npx -y playwright-e2e-mcp ci --flaky-runs 3 --suggest 2 --output report.md.
Exit code 0 passed, 1 tests failed, 2 the run itself failed. Quarantined, unexpired
failures don't fail it.
- Heal guard without the Action:
npx -y playwright-e2e-mcp guard --base origin/main
(exit 1 on BLOCK; --strict fails on warnings too).
- Mock drift check:
npx -y playwright-e2e-mcp mocks --base-url https://staging.example.com
against a preview or staging deploy (exit 1 on drift; --map gives wildcard routes a real URL,
--header "Authorization: Bearer $TOKEN" signs the calls).
- Team history across machines: run the free history server and
give the Action
history-url and history-token; every CI run lands in one history that
analyze-history on your laptop and the server's dashboard both read.
Action inputs: project-root, args, flaky-runs, suggest, comment, review,
verify-fixes, guard, history-token, history-url, fail-on-failure, version,
github-token. Outputs: exit-code, report, guard.
🐍 Python projects (pytest-playwright)
When the project has no Node Playwright but has pytest settings (pytest.ini, pyproject.toml,
setup.cfg, tox.ini) or a conftest.py, the tools run python -m pytest instead.
What works for Python
run-test runs the suite, a file, tests/test_cart.py::TestCart::test_add or
tests/test_cart.py:42 (the test at that line). grep becomes -k, browser becomes
--browser, retries uses pytest-rerunfailures. Failures that finished are kept even when
the run is killed.
get-failure shows the message, the code frame, expected vs actual and, from the trace
pytest-playwright keeps (--tracing retain-on-failure is added for you), the failed action,
the DOM at failure, network and console.
list-tests, analyze-history, quarantine and the ci command work as for Node.
check-test-change (the heal guard) reads test_*.py files: deleted asserts and
expects, @pytest.mark.skip / xfail, try: … except: pass around an assertion, weaker
matchers, wait_for_timeout, force=True. check-mocks reads route.fulfill(json=…),
body=json.dumps(…) and body='{…}'.
suggest-fix patches .py files too: the new locator is written in Python syntax
(get_by_role("button", name="Buy")) and verified with a pytest re-run. It checks the locator on
the DOM at failure with Node Playwright, like the page tools.
diagnose-flaky repeats pytest tests (one pytest process per run) for the same per-test
verdicts. isolate: true runs them in parallel with pytest-xdist (-n) first, then alone.
order needs Playwright's shuffle and is Node only.
audit-tests reads test_*.py / *_test.py with Python rules: wait_for_timeout,
time.sleep, one-shot assert loc.is_visible() (rewritten to expect(loc).to_be_visible()
with fix: true), un-awaited calls in async def tests, force=True, networkidle,
query_selector, layout selectors, timeout=0.
generate-e2e-test writes tests/generated/test_<name>.py with Python locators. With
steps it walks the flow, writes the module and runs it once with pytest. The start URL comes
from pageUrl or base_url in your pytest config (pytest-base-url).
- The page tools and
suggest-fix drive the browser with Node Playwright. A Python project needs
nothing extra: the server brings its own playwright-core. If it reports a missing browser,
run the command it gives once (npx -y playwright@<version> install chromium).
Results come from a small pytest plugin the server loads with -p from its temp folder; nothing
is installed in your project. It uses your Python: PW_MCP_PYTHON, else .venv, venv or env
in the project, else python3 / python.
⚙️ Configuration
Pick your tools. --tools= (or PW_MCP_TOOLS) takes profiles and tool names:
auto (core loop plus load-tools, about 2.4k tokens), core (the seven-tool fix loop, about
2.3k), triage, inspect, author, or all twenty (about 12.1k, the default).
Environment variables
Logs always go to stderr; stdout is reserved for the MCP protocol. Unrecognized values
fall back to the default, so a typo in LOG_LEVEL logs at info and one in LOG_FORMAT
logs as text rather than silencing the server.
📊 Benchmark
bench/token-benchmark.mjs breaks a checkout button's test id on a
storefront page and fixes it two ways: with this server (run-test → suggest-fix → apply) and
with Playwright MCP plus a shell (playwright test, browser_navigate + browser_snapshot, edit,
re-run). Latest result (full output):
Tokens are characters ÷ 4 and count what the model reads (each tool's name, description and input
schema). Tool definitions are sent with every request, so with all 20 tools loaded they outweigh
the saving on the work itself: use --tools=core when you only fix failing tests, or
--tools=auto to start at 2,427 tokens and load more on request. The Playwright MCP route is a
lower bound: it assumes the agent picks the right locator from the snapshot on the first try,
which the server does for it here. Run 2026-11-01 with Playwright 1.64.1; re-run with
npm run build && node bench/token-benchmark.mjs.
A real run-test result
A real run-test call served over stdio by npx -y playwright-e2e-mcp against the bundled
examples/sample-test.spec.ts (actual output, unedited):
[run-test result: 4 passed, 0 failed, 5.1s]
🤝 Works alongside your browser MCP
Microsoft's Playwright MCP, Chrome DevTools MCP and similar servers are great for driving a page
step by step. This server doesn't replace them or Playwright's own Test Agents in VS Code. Use a
browser MCP to explore, and this one to run, diagnose and fix the suite, with fixes that are
verified, a guard against fixes that cheat, flaky verdicts with evidence and the commit that broke
a test.
💚 Free and open source
- MIT licensed. Use it, change it, ship it in commercial work. No paid tier, no feature held
back, including the team history server, which you host yourself.
- No account, no API key, no sign-up.
npx -y playwright-e2e-mcp init is the whole setup.
- No telemetry. It never phones home. Your tests, traces and run history stay on your machine
unless you point it at your own history server. The only other requests are
doctor asking npm
for the latest version number when you run it (--offline skips it), load-report downloading
a CI run's artifacts when you give it a run URL, and a remote browser you name with connect.
- Free dependencies only: the MCP SDK (Apache-2.0), zod (MIT), axe-core (MPL-2.0) and
playwright-core (Apache-2.0). Test runs use the Playwright your project already has.
🆕 Recent releases
- 0.15: pytest-playwright suites get
diagnose-flaky (with pytest-xdist for isolate),
audit-tests (Python flake rules and expect(...) rewrites) and generate-e2e-test
(writes and verifies test_*.py). -n runs no longer count each pytest result twice.
- 0.14.1: security fix: behind a reverse proxy the sign-in limit can no longer be dodged
with a forged
X-Forwarded-For; {{env:…}} secrets in an agent-chosen connect URL only go
to hosts you named. CI templates for Azure DevOps, CircleCI, Bitbucket and AWS CodeBuild, and
check-mocks reads JSON bodies written as strings (body='{"id": 1}').
- 0.14:
run-test changed: true (only tests affected by your changes), suggest-fix
verifyAllProjects (keep a fix only if every browser passes), mask for dynamic regions in
compare-visual-state, blockResources and offline for page tools, and a guard when the
server starts in your home folder.
- 0.13.1: security fix:
load-report only sends GITHUB_TOKEN / GITLAB_TOKEN to github.com,
gitlab.com and hosts in PW_MCP_CI_HOSTS, never along a redirect. Page tools and suggest-fix
now work in pytest projects installed from npm or Docker (the server ships playwright-core).
- 0.13:
load-report takes a GitHub Actions or GitLab run URL, remote browsers and device
clouds with connect, suggest-fix patches pytest files, guidance for testing AI chat and
streaming UIs.
- 0.12: hydration-race detection,
check-mocks for mocks that drifted from the API, heal
guard that checks at run time and reads pytest files.
- 0.11: compact
inspect-page (571 tokens instead of 3,600), --tools=auto to load tools on
request, smaller tool definitions.
- 0.10: asks before changing your files, interactive test report in MCP Apps clients, Client
ID Metadata Document sign-in for the hosted endpoint.
- 0.9: the team history server is free, self-hosted and in this repo.
- 0.8: pytest-playwright suites, popups and new tabs,
blockWrites, MCP 2026-07-28, update check in doctor.
- 0.7: saved logins with 2FA, heal guard, flaky-test quarantine.
All release notes
📚 More documentation
- Tool reference: every argument, example outputs, edge cases handled
- Hosted endpoint: the HTTP bridge for ChatGPT and claude.ai connectors
- History server: shared CI run history with a dashboard, self-hosted
- Architecture: how the server is built and the design decisions behind it
- Security: the security model and how to report a vulnerability
- Development: building, tests, Docker, signing and releasing
🙌 Contributing
Issues, ideas and pull requests are welcome. Start with a
good first issue, read
CONTRIBUTING.md and the code of conduct.
License
MIT. If this saves you a debugging session, a ⭐ on the repo helps other Playwright
users find it.