playwright-e2e-mcp 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +150 -24
  2. package/dist/cli/ci.js +3 -0
  3. package/dist/cli/ci.js.map +1 -1
  4. package/dist/cli/doctor.d.ts +12 -1
  5. package/dist/cli/doctor.js +34 -4
  6. package/dist/cli/doctor.js.map +1 -1
  7. package/dist/cli/guard.d.ts +11 -0
  8. package/dist/cli/guard.js +80 -0
  9. package/dist/cli/guard.js.map +1 -0
  10. package/dist/cli/upload.d.ts +14 -0
  11. package/dist/cli/upload.js +81 -0
  12. package/dist/cli/upload.js.map +1 -0
  13. package/dist/discovery.d.ts +61 -0
  14. package/dist/discovery.js +108 -0
  15. package/dist/discovery.js.map +1 -0
  16. package/dist/http.d.ts +10 -1
  17. package/dist/http.js +50 -4
  18. package/dist/http.js.map +1 -1
  19. package/dist/index.js +28 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/oauth.d.ts +2 -0
  22. package/dist/oauth.js +1 -1
  23. package/dist/oauth.js.map +1 -1
  24. package/dist/server.d.ts +24 -4
  25. package/dist/server.js +98 -15
  26. package/dist/server.js.map +1 -1
  27. package/dist/skills.d.ts +23 -0
  28. package/dist/skills.js +101 -0
  29. package/dist/skills.js.map +1 -0
  30. package/dist/tools/analyze-history.d.ts +15 -0
  31. package/dist/tools/analyze-history.js +44 -9
  32. package/dist/tools/analyze-history.js.map +1 -1
  33. package/dist/tools/audit-accessibility.d.ts +6 -0
  34. package/dist/tools/audit-performance.d.ts +6 -0
  35. package/dist/tools/check-test-change.d.ts +44 -0
  36. package/dist/tools/check-test-change.js +132 -0
  37. package/dist/tools/check-test-change.js.map +1 -0
  38. package/dist/tools/compare-visual-state.d.ts +6 -0
  39. package/dist/tools/diagnose-flaky.js +5 -1
  40. package/dist/tools/diagnose-flaky.js.map +1 -1
  41. package/dist/tools/generate-e2e-test.d.ts +3 -0
  42. package/dist/tools/generate-e2e-test.js +3 -0
  43. package/dist/tools/generate-e2e-test.js.map +1 -1
  44. package/dist/tools/get-failure.js +3 -1
  45. package/dist/tools/get-failure.js.map +1 -1
  46. package/dist/tools/get-run-status.js +8 -2
  47. package/dist/tools/get-run-status.js.map +1 -1
  48. package/dist/tools/inspect-page.d.ts +6 -0
  49. package/dist/tools/inspect-page.js +3 -1
  50. package/dist/tools/inspect-page.js.map +1 -1
  51. package/dist/tools/list-tests.js +16 -12
  52. package/dist/tools/list-tests.js.map +1 -1
  53. package/dist/tools/probe-script.js +181 -15
  54. package/dist/tools/probe-script.js.map +1 -1
  55. package/dist/tools/quarantine.d.ts +61 -0
  56. package/dist/tools/quarantine.js +133 -0
  57. package/dist/tools/quarantine.js.map +1 -0
  58. package/dist/tools/run-test.d.ts +10 -1
  59. package/dist/tools/run-test.js +38 -6
  60. package/dist/tools/run-test.js.map +1 -1
  61. package/dist/tools/save-login.d.ts +145 -0
  62. package/dist/tools/save-login.js +264 -0
  63. package/dist/tools/save-login.js.map +1 -0
  64. package/dist/tools/shared.d.ts +49 -2
  65. package/dist/tools/shared.js +57 -6
  66. package/dist/tools/shared.js.map +1 -1
  67. package/dist/tools/structured.d.ts +8 -1
  68. package/dist/tools/structured.js +8 -1
  69. package/dist/tools/structured.js.map +1 -1
  70. package/dist/tools/suggest-fix.js +4 -0
  71. package/dist/tools/suggest-fix.js.map +1 -1
  72. package/dist/tools/validate-selector.d.ts +6 -0
  73. package/dist/tools/validate-selector.js +10 -2
  74. package/dist/tools/validate-selector.js.map +1 -1
  75. package/dist/types/index.d.ts +1 -1
  76. package/dist/utils/live-reporter.d.ts +29 -0
  77. package/dist/utils/live-reporter.js +145 -0
  78. package/dist/utils/live-reporter.js.map +1 -0
  79. package/dist/utils/playwright-runner.js +36 -14
  80. package/dist/utils/playwright-runner.js.map +1 -1
  81. package/dist/utils/pro-client.d.ts +29 -0
  82. package/dist/utils/pro-client.js +114 -0
  83. package/dist/utils/pro-client.js.map +1 -0
  84. package/dist/utils/pytest-runner.d.ts +102 -0
  85. package/dist/utils/pytest-runner.js +715 -0
  86. package/dist/utils/pytest-runner.js.map +1 -0
  87. package/dist/utils/quarantine.d.ts +64 -0
  88. package/dist/utils/quarantine.js +106 -0
  89. package/dist/utils/quarantine.js.map +1 -0
  90. package/dist/utils/test-change-guard.d.ts +90 -0
  91. package/dist/utils/test-change-guard.js +516 -0
  92. package/dist/utils/test-change-guard.js.map +1 -0
  93. package/dist/utils/totp.d.ts +26 -0
  94. package/dist/utils/totp.js +84 -0
  95. package/dist/utils/totp.js.map +1 -0
  96. package/dist/utils/update-check.d.ts +50 -0
  97. package/dist/utils/update-check.js +75 -0
  98. package/dist/utils/update-check.js.map +1 -0
  99. package/examples/github-actions/playwright-e2e.yml +80 -0
  100. package/examples/gitlab-ci/playwright-e2e.yml +71 -0
  101. package/package.json +2 -2
  102. package/skill/playwright-e2e-mcp/SKILL.md +45 -7
  103. package/skill/playwright-e2e-mcp/references/setup.md +12 -1
  104. package/skill/playwright-e2e-mcp/references/tools.md +42 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totp.js","sourceRoot":"","sources":["../../src/utils/totp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Asks the npm registry for the latest published version of this package and
3
+ * compares it with the running one. Used by `doctor`, which a person runs on
4
+ * purpose; the MCP server itself never calls this.
5
+ *
6
+ * The request carries nothing but the package name (no project data, no
7
+ * identifiers). It is skipped when PW_MCP_NO_UPDATE_CHECK=1 or when called
8
+ * with `offline`, and any failure (no network, a proxy, a slow registry)
9
+ * resolves to `unknown` instead of throwing.
10
+ */
11
+ export declare const PACKAGE_NAME = "playwright-e2e-mcp";
12
+ export declare const REGISTRY_LATEST_URL = "https://registry.npmjs.org/playwright-e2e-mcp/latest";
13
+ export type UpdateStatus = {
14
+ state: 'current';
15
+ current: string;
16
+ latest: string;
17
+ } | {
18
+ state: 'outdated';
19
+ current: string;
20
+ latest: string;
21
+ } | {
22
+ state: 'ahead';
23
+ current: string;
24
+ latest: string;
25
+ } | {
26
+ state: 'unknown';
27
+ current: string;
28
+ reason: string;
29
+ } | {
30
+ state: 'skipped';
31
+ current: string;
32
+ reason: string;
33
+ };
34
+ /** Compares two x.y.z versions (a pre-release sorts before its release). */
35
+ export declare function compareVersions(a: string, b: string): number;
36
+ export interface UpdateCheckOptions {
37
+ offline?: boolean;
38
+ timeoutMs?: number;
39
+ fetchImpl?: typeof fetch;
40
+ env?: NodeJS.ProcessEnv;
41
+ }
42
+ export declare function checkForUpdate(current: string, options?: UpdateCheckOptions): Promise<UpdateStatus>;
43
+ /**
44
+ * How to upgrade, by the way this copy was installed. `npx -y
45
+ * playwright-e2e-mcp` (npm 10, which ships with Node 22) checks the registry
46
+ * on every launch and picks up a new release by itself, so restarting the MCP
47
+ * client is enough there; a project or global install, a git clone or the
48
+ * Docker image stays on its version until updated.
49
+ */
50
+ export declare const UPGRADE_HINT: string;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Asks the npm registry for the latest published version of this package and
3
+ * compares it with the running one. Used by `doctor`, which a person runs on
4
+ * purpose; the MCP server itself never calls this.
5
+ *
6
+ * The request carries nothing but the package name (no project data, no
7
+ * identifiers). It is skipped when PW_MCP_NO_UPDATE_CHECK=1 or when called
8
+ * with `offline`, and any failure (no network, a proxy, a slow registry)
9
+ * resolves to `unknown` instead of throwing.
10
+ */
11
+ export const PACKAGE_NAME = 'playwright-e2e-mcp';
12
+ export const REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
13
+ /** Compares two x.y.z versions (a pre-release sorts before its release). */
14
+ export function compareVersions(a, b) {
15
+ const parse = (v) => {
16
+ const [core = '', pre = ''] = v.trim().replace(/^v/, '').split('-', 2);
17
+ const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
18
+ while (nums.length < 3)
19
+ nums.push(0);
20
+ return { nums, pre };
21
+ };
22
+ const x = parse(a);
23
+ const y = parse(b);
24
+ for (let i = 0; i < 3; i++) {
25
+ if (x.nums[i] !== y.nums[i])
26
+ return x.nums[i] < y.nums[i] ? -1 : 1;
27
+ }
28
+ if (x.pre === y.pre)
29
+ return 0;
30
+ if (!x.pre)
31
+ return 1;
32
+ if (!y.pre)
33
+ return -1;
34
+ return x.pre < y.pre ? -1 : 1;
35
+ }
36
+ export async function checkForUpdate(current, options = {}) {
37
+ const env = options.env ?? process.env;
38
+ if (options.offline)
39
+ return { state: 'skipped', current, reason: '--offline' };
40
+ if (env.PW_MCP_NO_UPDATE_CHECK === '1' || env.PW_MCP_NO_UPDATE_CHECK === 'true') {
41
+ return { state: 'skipped', current, reason: 'PW_MCP_NO_UPDATE_CHECK is set' };
42
+ }
43
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
44
+ if (typeof fetchImpl !== 'function')
45
+ return { state: 'unknown', current, reason: 'fetch is not available' };
46
+ try {
47
+ const res = await fetchImpl(REGISTRY_LATEST_URL, {
48
+ headers: { accept: 'application/json' },
49
+ signal: AbortSignal.timeout(options.timeoutMs ?? 3000),
50
+ });
51
+ if (!res.ok)
52
+ return { state: 'unknown', current, reason: `npm registry answered ${res.status}` };
53
+ const body = (await res.json());
54
+ const latest = typeof body.version === 'string' ? body.version : '';
55
+ if (!/^\d+\.\d+\.\d+/.test(latest))
56
+ return { state: 'unknown', current, reason: 'npm registry gave no version' };
57
+ const cmp = compareVersions(current, latest);
58
+ return { state: cmp < 0 ? 'outdated' : cmp > 0 ? 'ahead' : 'current', current, latest };
59
+ }
60
+ catch (err) {
61
+ const message = err.name === 'TimeoutError' ? 'npm registry did not answer in time' : err.message.split('\n')[0];
62
+ return { state: 'unknown', current, reason: message };
63
+ }
64
+ }
65
+ /**
66
+ * How to upgrade, by the way this copy was installed. `npx -y
67
+ * playwright-e2e-mcp` (npm 10, which ships with Node 22) checks the registry
68
+ * on every launch and picks up a new release by itself, so restarting the MCP
69
+ * client is enough there; a project or global install, a git clone or the
70
+ * Docker image stays on its version until updated.
71
+ */
72
+ export const UPGRADE_HINT = 'restart your MCP client (npx -y playwright-e2e-mcp fetches the new version itself); ' +
73
+ 'project install: npm install -D playwright-e2e-mcp@latest · global: npm install -g playwright-e2e-mcp@latest · ' +
74
+ 'Docker: docker pull ghcr.io/xsignon-secure/playwright-e2e-mcp:latest · git clone: git pull && npm ci';
75
+ //# sourceMappingURL=update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/utils/update-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ name: Playwright E2E Diagnosis
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main, master]
7
+
8
+ # Permissions required:
9
+ # - contents: read to check out the repository
10
+ # - pull-requests: write to post/update the PR comment report and suggested fixes
11
+ permissions:
12
+ contents: read
13
+ pull-requests: write
14
+
15
+ jobs:
16
+ e2e:
17
+ name: Playwright E2E Tests
18
+ runs-on: ubuntu-latest
19
+ timeout-minutes: 30
20
+
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4
24
+ with:
25
+ persist-credentials: false
26
+
27
+ - name: Set up Node.js
28
+ uses: actions/setup-node@v4
29
+ with:
30
+ node-version: 22
31
+ cache: npm
32
+
33
+ - name: Install dependencies
34
+ run: npm ci
35
+
36
+ - name: Install Playwright browsers and OS dependencies
37
+ run: npx playwright install --with-deps chromium
38
+
39
+ - name: Run Playwright E2E diagnosis action
40
+ id: e2e
41
+ uses: xsignon-secure/E2E@v0.8.0
42
+ with:
43
+ # Directory containing playwright.config.* (default is workspace root)
44
+ project-root: .
45
+
46
+ # Extra arguments passed to playwright-e2e-mcp ci, e.g. "--browser chromium tests/checkout"
47
+ # args: --browser chromium tests/
48
+
49
+ # Repeat failing tests (2-10) to obtain an empirical flaky verdict; 0 skips
50
+ flaky-runs: 3
51
+
52
+ # Draft suggest-fix diffs for the first N failures (0-5)
53
+ suggest: 2
54
+
55
+ # Re-run each failing test with its fix applied and post only verified fixes
56
+ verify-fixes: true
57
+
58
+ # Post verified fixes directly as one-click GitHub suggested changes on the PR
59
+ review: true
60
+
61
+ # Post/edit a single diagnosis summary comment on the PR
62
+ comment: true
63
+
64
+ # Heal guard: block test changes that pass by checking less (deleted assertions, skipped tests, .only)
65
+ # guard: true
66
+
67
+ # Pro Cloud integration (optional, paid): upload run history to Pro Cloud
68
+ # pro-key: ${{ secrets.PW_MCP_PRO_KEY }}
69
+ # pro-url: https://pro.example.com
70
+
71
+ # Fail step when tests fail (default: true)
72
+ fail-on-failure: true
73
+
74
+ - name: Upload diagnosis report
75
+ if: always() && steps.e2e.outputs.report != ''
76
+ uses: actions/upload-artifact@v4
77
+ with:
78
+ name: playwright-e2e-diagnosis-report
79
+ path: ${{ steps.e2e.outputs.report }}
80
+ retention-days: 14
@@ -0,0 +1,71 @@
1
+ # playwright-e2e-mcp on GitLab CI.
2
+ #
3
+ # Copy this into .gitlab-ci.yml (or `include:` it). It does what the GitHub
4
+ # Action does, with GitLab's own pieces:
5
+ # - on a merge request, the heal guard fails the job when a changed test
6
+ # now checks less (an assertion removed, a test skipped, `.only` added);
7
+ # - `ci` runs the suite (auto-retry once, so flaky tests are reported as
8
+ # flaky), repeats failures for a flaky verdict and drafts fixes;
9
+ # - the Markdown report is printed in the job log, kept as an artifact
10
+ # and, when E2E_REPORT_TOKEN is set, posted as a merge request comment.
11
+ #
12
+ # Exit codes of `ci`: 0 passed (flaky allowed), 1 tests failed, 2 the run
13
+ # itself failed (no Playwright, config error, timeout).
14
+
15
+ stages:
16
+ - test
17
+
18
+ playwright-e2e:
19
+ stage: test
20
+ # Microsoft's Playwright image ships Node and the browsers. Use the tag that
21
+ # matches the @playwright/test version in your package-lock.json (the
22
+ # browsers are tied to it), e.g. v1.64.1-noble for 1.64.1.
23
+ image: mcr.microsoft.com/playwright:v1.64.1-noble
24
+ variables:
25
+ # The guard compares with the target branch, so it needs real history.
26
+ GIT_DEPTH: "0"
27
+ npm_config_cache: "$CI_PROJECT_DIR/.npm"
28
+ cache:
29
+ key:
30
+ files:
31
+ - package-lock.json
32
+ paths:
33
+ - .npm/
34
+ rules:
35
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
36
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
37
+ before_script:
38
+ - npm ci --prefer-offline
39
+ script:
40
+ # 1. Heal guard, merge requests only. Add --strict to fail on warnings too.
41
+ - |
42
+ if [ -n "$CI_MERGE_REQUEST_IID" ]; then
43
+ git fetch --quiet origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
44
+ npx -y playwright-e2e-mcp guard --base "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
45
+ fi
46
+ # 2. Run and diagnose the suite. --verify-fixes re-runs each failing test
47
+ # with its drafted fix applied, then restores the file.
48
+ - npx -y playwright-e2e-mcp ci --flaky-runs 3 --suggest 2 --verify-fixes --output e2e-report.md
49
+ after_script:
50
+ # 3. Post the report on the merge request. E2E_REPORT_TOKEN is a project
51
+ # access token with the `api` scope, stored as a masked CI/CD variable.
52
+ # after_script runs even when the tests fail, so the report still lands.
53
+ - |
54
+ if [ -f e2e-report.md ] && [ -n "$CI_MERGE_REQUEST_IID" ] && [ -n "$E2E_REPORT_TOKEN" ]; then
55
+ node -e 'process.stdout.write(JSON.stringify({ body: require("fs").readFileSync("e2e-report.md", "utf8").slice(0, 900000) }))' > e2e-note.json
56
+ curl --silent --show-error --fail --request POST \
57
+ --header "PRIVATE-TOKEN: $E2E_REPORT_TOKEN" \
58
+ --header "Content-Type: application/json" \
59
+ --data @e2e-note.json \
60
+ "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" > /dev/null \
61
+ || echo "Could not post the report on the merge request"
62
+ fi
63
+ artifacts:
64
+ name: "playwright-e2e-$CI_COMMIT_REF_SLUG"
65
+ when: always
66
+ expose_as: "Playwright E2E report"
67
+ paths:
68
+ - e2e-report.md
69
+ - playwright-report/
70
+ - test-results/
71
+ expire_in: 14 days
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "playwright-e2e-mcp",
3
- "version": "0.6.1",
4
- "description": "MCP server and agent skill that run, diagnose and fix failing Playwright tests: CI report diagnosis, trace analysis, verified locator fixes, flaky verdicts, breaking commits, tests written by walking the flow, accessibility and Web Vitals audits.",
3
+ "version": "0.8.0",
4
+ "description": "MCP server and agent skill that run, diagnose and fix failing Playwright tests (TypeScript and pytest): CI report diagnosis, trace analysis, verified locator fixes, flaky verdicts, breaking commits, heal guard, accessibility and Web Vitals audits.",
5
5
  "author": "xsignon-secure (https://github.com/xsignon-secure)",
6
6
  "mcpName": "io.github.xsignon-secure/E2E",
7
7
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: playwright-e2e-mcp
3
- description: Runs, debugs and fixes Playwright end-to-end tests through the playwright-e2e-mcp server, using structured run results grouped by root cause, trace-based failure diagnostics, verified locators, self-healing fixes that re-run and revert if still red, per-test flaky verdicts that separate parallelism, test-order and timing bugs, signed-in page inspection with network mocks and HAR replay, aria snapshots, tests written by walking the flow on the live page, CI report diagnosis, WCAG accessibility audits, Web Vitals performance audits and local run history with the commit that broke each test, plus a guide to writing tests that stay green. Use when the user asks to run Playwright tests, fix a failing or broken e2e test, find out why a CI run failed, find out why a test is flaky or which tests are unstable or slow, repair a selector that no longer matches, write or review a Playwright test, check a page for accessibility, performance or visual regressions.
3
+ description: "Runs, debugs and fixes Playwright end-to-end tests through the playwright-e2e-mcp server: run results grouped by root cause, trace-based failure diagnostics, verified locators, self-healing fixes that re-run and revert if still red, a heal guard that blocks fixes which pass by checking less, per-test flaky verdicts (parallelism, test order, timing), an owned, expiring flaky-test quarantine, saved logins with 2FA codes, signed-in page inspection with network mocks, tests written by walking the flow, CI report diagnosis, accessibility and Web Vitals audits and run history with the commit that broke each test. Use when the user asks to run Playwright tests, fix a failing or broken e2e test, find out why CI failed, find flaky, unstable or slow tests, repair a selector, write or review a Playwright test, log in for tests, or check a page for accessibility, performance or visual regressions."
4
4
  ---
5
5
 
6
6
  # Playwright E2E with playwright-e2e-mcp
@@ -13,7 +13,7 @@ and concrete next steps. It can also propose and apply a verified fix for a brok
13
13
  locator, inspect pages behind a login, run long suites in the background and keep
14
14
  a local history of every run.
15
15
 
16
- This skill is written for playwright-e2e-mcp 0.6.1 and works with 0.2.0 or
16
+ This skill is written for playwright-e2e-mcp 0.8.0 and works with 0.2.0 or
17
17
  newer. If `suggest-fix`, `get-run-status` or `analyze-history` is missing, the
18
18
  server is older than 0.2.0: use the steps that do not need those tools and tell
19
19
  the user to update it. `diagnose-flaky`'s per-test table and `isolate` option
@@ -21,7 +21,12 @@ arrived in 0.3.0; `audit-accessibility`, `diagnose-flaky`'s `order` option and
21
21
  root-cause grouping in `run-test` arrived in 0.4.0; `audit-performance`,
22
22
  `load-report`, network mocks (`routes`), `har`, `browser`, `inspect-page`'s
23
23
  `view: "aria"`, `generate-e2e-test`'s `steps`, the `slow`, `trend` and `commits`
24
- history views and strict-mode fixes in `suggest-fix` arrived in 0.5.0.
24
+ history views and strict-mode fixes in `suggest-fix` arrived in 0.5.0;
25
+ `save-login`, `check-test-change` and `quarantine` arrived in 0.7.0; the
26
+ `switchTab` page step, `blockWrites`, recovery of crashed runs and
27
+ pytest-playwright projects (`run-test`, `get-failure`, `list-tests`) arrived in
28
+ 0.8.0. If `doctor` says a newer version is out, pass its upgrade command on to
29
+ the user.
25
30
 
26
31
  ## Before you start
27
32
 
@@ -29,8 +34,8 @@ history views and strict-mode fixes in `suggest-fix` arrived in 0.5.0.
29
34
  `get-run-status`, `get-failure`, `load-report`, `suggest-fix`, `inspect-page`,
30
35
  `validate-selector`, `list-tests`, `generate-e2e-test`,
31
36
  `compare-visual-state`, `audit-accessibility`, `audit-performance`,
32
- `diagnose-flaky` and
33
- `analyze-history` (your client
37
+ `diagnose-flaky`, `analyze-history`, `audit-tests`, `bisect-failure`,
38
+ `save-login`, `check-test-change` and `quarantine` (your client
34
39
  may prefix them, e.g. `mcp__playwright-e2e__run-test`).
35
40
  2. If they are all missing, stop and tell the user the MCP server is not
36
41
  connected. Point them to `references/setup.md` for the one-line install for
@@ -39,7 +44,7 @@ history views and strict-mode fixes in `suggest-fix` arrived in 0.5.0.
39
44
  `references/writing-tests.md`. Do not fall back to shelling out to `npx playwright test` unless
40
45
  the user asks. If only some are missing, the server may run a smaller tool
41
46
  profile (`--tools=core` exposes `run-test`, `get-run-status`, `get-failure`,
42
- `suggest-fix`, `diagnose-flaky` and `list-tests`); work with what is there and
47
+ `suggest-fix`, `diagnose-flaky`, `check-test-change` and `list-tests`); work with what is there and
43
48
  mention the profile when a task needs a page tool.
44
49
  3. Every tool except `get-run-status` takes an optional `projectRoot`. Leave it
45
50
  out unless the user works in a sub-project; the server defaults to `PW_MCP_PROJECT_ROOT` or its working
@@ -88,6 +93,10 @@ Follow these steps in order. Do not edit code before step 3.
88
93
  - Failed network request (4xx/5xx/no response) right before the failure: the
89
94
  backend is the likely cause; report it.
90
95
  4. **Fix** the spec or the app code, the smallest change that addresses the cause.
96
+ Then call `check-test-change` (0.7.0+; no arguments checks the uncommitted
97
+ changes). If it says **BLOCK**, the fix made the test pass by checking less
98
+ (a deleted assertion, a skip, `.only`): undo that part and fix the cause. Treat
99
+ **WARN** findings as things to justify to the user, not to wave through.
91
100
  5. **Re-run only what failed:** `run-test` with `{ "lastFailed": true }`. Repeat
92
101
  from step 2 until green.
93
102
 
@@ -136,6 +145,26 @@ fresh browser, so a signed-in page shows the login screen unless you pass state:
136
145
  (it must be installed; `audit-performance` stays Chromium-only).
137
146
  - `viewport`: `{ "width": 390, "height": 844 }` for mobile layouts.
138
147
 
148
+ When there is no saved session yet, or it expired, call `save-login` (0.7.0+)
149
+ instead of typing credentials into `actions` every time:
150
+
151
+ ```json
152
+ { "url": "http://localhost:3000/login",
153
+ "actions": [
154
+ { "type": "fill", "locator": "getByLabel('Email')", "value": "qa@example.com" },
155
+ { "type": "fill", "locator": "getByLabel('Password')", "value": "{{env:E2E_PASSWORD}}" },
156
+ { "type": "fill", "locator": "getByLabel('Code')", "value": "{{totp}}" },
157
+ { "type": "click", "locator": "getByRole('button', { name: 'Sign in' })" }],
158
+ "verify": { "url": "/account", "visible": "getByRole('button', { name: 'Sign out' })", "notUrl": "/login" },
159
+ "totpSecretEnv": "E2E_TOTP_SECRET" }
160
+ ```
161
+
162
+ It saves `playwright/.auth/user.json` and reuses it while `verify` passes. Never
163
+ put a password in a tool argument or in chat: ask the user to set it as an
164
+ environment variable for the server (`E2E_*`, `TEST_*`, `LOGIN_*`, or a name
165
+ listed in `PW_MCP_LOGIN_ENV`) and refer to it as `{{env:NAME}}`. `{{totp}}`
166
+ types the current authenticator code from the secret in `totpSecretEnv`.
167
+
139
168
  When a response says the page landed on a login screen, retry with
140
169
  `storageState`. `suggest-fix` takes `storageState` and `headers` too when you heal
141
170
  against a live `url`.
@@ -183,6 +212,14 @@ one verdict **per test** (passes, failures, duration spread, first error):
183
212
  tests that flaked; `fix: true` applies the mechanical rewrites and re-runs them.
184
213
  - **NOT REPRODUCING**: passed every run. Report that the failure was one-off.
185
214
 
215
+ If a FLAKY test cannot be fixed right away and is blocking other work, offer
216
+ `quarantine` (0.7.0+) with `action: "add"`, the test (`index` of the last run's
217
+ failure, or `"file › title"`), an `owner` and a `reason` (an issue link is best).
218
+ It keeps running and being reported, but stops failing the run until the entry
219
+ expires (default 14 days). Ask the user before adding one; never quarantine a
220
+ CONSISTENTLY FAILING test, which is a real failure. `quarantine` with no
221
+ arguments lists the entries and the expired ones.
222
+
186
223
  When a test is FLAKY and the suite runs in parallel, call `diagnose-flaky` again
187
224
  with `isolate: true`. It repeats the tests fully parallel, then repeats the
188
225
  failing ones with one worker, and reads each one:
@@ -244,7 +281,7 @@ with the commit it tested. `analyze-history` views:
244
281
  `selector` for one region) returns the accessibility snapshot and a
245
282
  `toMatchAriaSnapshot` assertion to paste into a spec.
246
283
  - **Set up CI:** when the user wants the same diagnosis on every pull request,
247
- point them to the GitHub Action (`uses: xsignon-secure/E2E@v0.6.1`) or the
284
+ point them to the GitHub Action (`uses: xsignon-secure/E2E@v0.8.0`) or the
248
285
  `npx -y playwright-e2e-mcp ci` command in `references/setup.md`. It writes the
249
286
  run, flaky verdicts and fix diffs to the job summary and one PR comment.
250
287
  - **Accessibility:** `audit-accessibility` with `url` runs axe-core against
@@ -284,6 +321,7 @@ When you finish, tell the user, in this order:
284
321
 
285
322
  - Do not raise timeouts, add retries, add `waitForTimeout`, or delete or
286
323
  `test.skip` a test to make a run green, unless the user explicitly asks.
324
+ `check-test-change` catches these; run it after every test edit.
287
325
  - Do not accept a new visual baseline without the user's confirmation.
288
326
  - Do not pass `allowExpectationUpdate: true` to `suggest-fix` unless the user
289
327
  confirms the new text is intended; a changed expected value can be a real bug.
@@ -82,6 +82,13 @@ Set these in the server's `env` block. None of them are secrets except
82
82
  | `PW_MCP_BLOCK_PRIVATE_URLS` | off for stdio | `1` makes the URL tools refuse loopback, private-network and cloud-metadata addresses |
83
83
  | `PW_MCP_STORAGE_STATE` | none | Default Playwright storageState JSON (inside the project) for the page tools, so signed-in pages open logged in |
84
84
  | `PW_MCP_SHUFFLE_SEEDS` | random | Seeds for `diagnose-flaky`'s `order` pass (comma separated), to replay reported orders |
85
+ | `PW_MCP_LOGIN_ENV` | — | Extra variables `save-login` may type through `{{env:NAME}}`, comma separated (default: only `E2E_*`, `TEST_*`, `PW_*`, `PLAYWRIGHT_*`, `LOGIN_*`) |
86
+ | `PW_MCP_PRO_KEY` / `PW_MCP_PRO_URL` | — | Optional paid Pro: CI runs uploaded with `upload` show up in `analyze-history` (`source: both`). Unset = no network calls |
87
+ | `PW_MCP_BLOCK_WRITES` | off | `1` makes the page tools abort POST, PUT, PATCH and DELETE requests that no mock or HAR answers (0.8.0+) |
88
+ | `PW_MCP_PYTHON` | project venv, then `python3` | The Python used for pytest-playwright projects (0.8.0+) |
89
+ | `PW_MCP_PROTOCOL` | both | `legacy` stops offering the 2026-07-28 MCP revision (0.8.0+) |
90
+ | `PW_MCP_SKILLS` | on | `0` stops serving this skill over the MCP Skills extension (0.8.0+) |
91
+ | `PW_MCP_NO_UPDATE_CHECK` | off | `1` stops `doctor` asking npm whether a newer version is out (0.8.0+) |
85
92
  | `PW_MCP_HISTORY` | on | `0` stops recording runs to `<project>/.playwright-e2e-mcp/history.jsonl` (this turns off `analyze-history`) |
86
93
  | `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` or `silent` |
87
94
  | `PW_MCP_HTTP_TOKEN` | none | HTTP bridge only: bearer token that unlocks all tools |
@@ -112,7 +119,7 @@ Exit code 0 means passed, 1 tests failed, 2 the run itself failed. On GitHub
112
119
  Actions it also writes to the job summary. As an Action:
113
120
 
114
121
  ```yaml
115
- - uses: xsignon-secure/E2E@v0.6.1
122
+ - uses: xsignon-secure/E2E@v0.8.0
116
123
  with:
117
124
  flaky-runs: 3
118
125
  suggest: 2
@@ -120,3 +127,7 @@ Actions it also writes to the job summary. As an Action:
120
127
 
121
128
  It keeps one PR comment up to date when the run fails (needs
122
129
  `pull-requests: write`).
130
+
131
+ From 0.7.0, `npx -y playwright-e2e-mcp guard --base origin/main` (or the
132
+ Action's `guard: true` input) fails the job when a changed test was made to
133
+ pass by checking less, and `ci` honours `playwright-quarantine.json`.
@@ -68,7 +68,7 @@ becomes the last run for `get-failure`, `suggest-fix` and `diagnose-flaky`.
68
68
  | `view` | `elements` \| `locators` \| `aria` | `locators`: compact map of interactive elements with verified locators; `aria` (0.5.0+): accessibility snapshot of the page or of `selector`, with a `toMatchAriaSnapshot` assertion |
69
69
  | `storageState` | string | Playwright storageState JSON inside the project (signed-in session); defaults to `PW_MCP_STORAGE_STATE` |
70
70
  | `headers` | object | Extra HTTP headers |
71
- | `actions` | array | Up to 20 steps after load: `{ type: click\|dblclick\|fill\|press\|check\|uncheck\|select\|hover\|wait\|goto, locator?, value?, url?, ms? }`. Locators may start with `frameLocator('#frame')` or use `.contentFrame()` for iframes (0.6.1+) |
71
+ | `actions` | array | Up to 20 steps after load: `{ type: click\|dblclick\|fill\|press\|check\|uncheck\|select\|hover\|wait\|goto, locator?, value?, url?, ms? }`. Locators may start with `frameLocator('#frame')` or use `.contentFrame()` for iframes (0.6.1+). `{ type: 'switchTab', value?: 'last'\|'first'\|'2'\|text in URL or title }` moves to a popup or new tab (0.8.0+) |
72
72
  | `actionTimeoutMs` | number | How long each action waits for its element (0.6.1+, default 10000) |
73
73
  | `routes` | array | Up to 20 network mocks before load, first match wins: `{ url (glob), method?, status?, json? \| body?, contentType?, headers?, abort?, delayMs? }` (0.5.0+). The result reports hits per mock |
74
74
  | `har` | object | `{ path, mode?: replay\|record, url?, notFound?: abort\|fallback }` (0.5.0+): replay requests from a HAR inside the project, or record the traffic to one. `routes` still win |
@@ -278,3 +278,44 @@ mechanically. Files rank by findings weighted by their flaky rate in the history
278
278
  Runs in a temporary git worktree with the current `node_modules` linked in;
279
279
  untestable commits are skipped. `status` is `found`, `ambiguous`, `max-steps`,
280
280
  `not-failing` (passes at bad) or `good-fails`.
281
+
282
+ ## save-login (0.7.0+)
283
+
284
+ | Argument | Type | Notes |
285
+ | --- | --- | --- |
286
+ | `url` | string | Login page (required) |
287
+ | `actions` | array | Login steps as in `inspect-page`; fill values may use `{{env:NAME}}` and `{{totp}}` |
288
+ | `verify` | object | `url` (page to check, e.g. `/account`), `visible` (locator only a signed-in user sees), `notUrl` (bad if the URL contains it, e.g. `/login`) |
289
+ | `name` / `path` | string | Saved to `playwright/.auth/<name>.json` (default `user`) or `path` |
290
+ | `totpSecretEnv` | string | Variable holding the authenticator secret (base32 or `otpauth://`) |
291
+ | `reuse` | boolean | Keep a saved session that still passes `verify` (default true) |
292
+
293
+ `status` is `saved`, `valid` (reused, nothing typed) or `failed` (no file written).
294
+ Only `E2E_*`, `TEST_*`, `PW_*`, `PLAYWRIGHT_*`, `LOGIN_*` and names in
295
+ `PW_MCP_LOGIN_ENV` can be read through `{{env:…}}`.
296
+
297
+ ## check-test-change (0.7.0+)
298
+
299
+ | Argument | Type | Notes |
300
+ | --- | --- | --- |
301
+ | `base` | string | Git ref (default `HEAD`: the uncommitted changes; `origin/main` for the branch) |
302
+ | `files` | string[] | Only these files |
303
+ | `file` + `after` | string | Check a proposed full file content before writing it |
304
+
305
+ `status` is `OK`, `WARN` or `BLOCK`; `ok` is false only on BLOCK. BLOCK: fewer
306
+ assertions in a test, a removed or skipped test, `.only`, a deleted spec. WARN:
307
+ `expect.soft`, a weaker matcher, `waitForTimeout`, `force: true`, a swallowed
308
+ error, a raised timeout, retries or screenshot tolerance.
309
+
310
+ ## quarantine (0.7.0+)
311
+
312
+ | Argument | Type | Notes |
313
+ | --- | --- | --- |
314
+ | `action` | string | `list` (default), `add`, `remove` |
315
+ | `test` | string | `'file › title'`; or `file` + `title`; or `index` (last run's failure) |
316
+ | `owner` / `reason` | string | Required for `add` |
317
+ | `days` | number | 1–90, default 14 |
318
+
319
+ Stored in `playwright-quarantine.json` (commit it). A quarantined, unexpired
320
+ failure is listed under 🧊 and does not fail `run-test` or `ci`; `run.quarantined`
321
+ counts them. Expired entries block again.