playwright-e2e-mcp 0.2.1 → 0.3.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.
- package/README.md +271 -29
- package/dist/cli/ci.d.ts +29 -0
- package/dist/cli/ci.js +145 -0
- package/dist/cli/ci.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +15 -0
- package/dist/server.js +54 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/diagnose-flaky.d.ts +42 -4
- package/dist/tools/diagnose-flaky.js +342 -98
- package/dist/tools/diagnose-flaky.js.map +1 -1
- package/dist/types/index.d.ts +29 -0
- package/dist/utils/attempts-reporter.d.ts +19 -0
- package/dist/utils/attempts-reporter.js +96 -0
- package/dist/utils/attempts-reporter.js.map +1 -0
- package/dist/utils/playwright-runner.js +16 -1
- package/dist/utils/playwright-runner.js.map +1 -1
- package/dist/utils/report-parser.d.ts +1 -0
- package/dist/utils/report-parser.js +1 -1
- package/dist/utils/report-parser.js.map +1 -1
- package/package.json +16 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# playwright-e2e-mcp
|
|
2
2
|
|
|
3
|
-
[](https://github.com/xsignon-secure/E2E/actions/workflows/ci.yml) [](https://github.com/xsignon-secure/E2E/releases) [](https://registry.modelcontextprotocol.io/)
|
|
4
4
|
[](https://m8ven.ai/mcp/trajectiq-ai/e2e?s=readme)
|
|
5
5
|
|
|
6
6
|
An [MCP](https://modelcontextprotocol.io) server that **diagnoses and fixes failing Playwright
|
|
@@ -26,9 +26,13 @@ What it does that a browser-driving MCP or a raw `npx playwright test` does not:
|
|
|
26
26
|
(`getByRole('button', { name: 'Proceed to checkout' })`), re-runs the test and reverts the
|
|
27
27
|
edit if it is still red. When nothing on the page plausibly matches, it says the element is
|
|
28
28
|
missing and does not patch the test to hide a real bug.
|
|
29
|
-
- **Flakiness
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
- **Flakiness with evidence.** `diagnose-flaky` repeats failing tests in one process and
|
|
30
|
+
gives a verdict per test; with `isolate: true` it re-runs them alone to tell a shared-state
|
|
31
|
+
bug that only bites in parallel from a race inside the test. Every run is recorded locally;
|
|
32
|
+
`analyze-history` separates tests that flip (flaky) from ones that started failing
|
|
33
|
+
(regressed) or always fail (broken), and groups failures that share one cause.
|
|
34
|
+
- **In CI too.** A [GitHub Action and `ci` command](#ci-github-action-and-ci-command) post the
|
|
35
|
+
same diagnosis, flaky verdict and fix diffs to the job summary and the PR.
|
|
32
36
|
- **Pages behind a login.** Every page tool accepts a Playwright `storageState`, extra
|
|
33
37
|
headers, and click/fill steps to reach a modal or a later step.
|
|
34
38
|
- **Small on the wire.** In the [benchmark](bench/RESULTS.md), diagnosing and fixing one
|
|
@@ -48,12 +52,12 @@ work side by side in the same client.
|
|
|
48
52
|
`https://playwright-e2e-mcp.vercel.app/api/mcp` returns for a client that sends the
|
|
49
53
|
bearer token (without one, only `list-tests` and `get-failure` are listed):
|
|
50
54
|
|
|
51
|
-

|
|
52
56
|
|
|
53
57
|
**A real test run** — `run-test` served over stdio by `npx -y playwright-e2e-mcp`
|
|
54
58
|
against the bundled `examples/sample-test.spec.ts` (actual output, unedited):
|
|
55
59
|
|
|
56
|
-

|
|
57
61
|
|
|
58
62
|
Images are rendered with `node scripts/gen-demo-images.mjs`: the run-test card is real
|
|
59
63
|
captured output; the endpoint card is an illustration of the authenticated listing.
|
|
@@ -66,9 +70,9 @@ and every other MCP client — pick whichever route fits:
|
|
|
66
70
|
| Route | How |
|
|
67
71
|
| --- | --- |
|
|
68
72
|
| **npm (canonical, fastest)** | `npx -y playwright-e2e-mcp` |
|
|
69
|
-
| **MCP Registry** (registry-aware clients discover it automatically) | `io.github.
|
|
70
|
-
| **Any client, no npm account needed** | `npx -y github:
|
|
71
|
-
| **Claude Desktop, zero Node setup** | double-click the [`.mcpb` extension](https://github.com/
|
|
73
|
+
| **MCP Registry** (registry-aware clients discover it automatically) | `io.github.xsignon-secure/E2E` — [listing](https://registry.modelcontextprotocol.io/) |
|
|
74
|
+
| **Any client, no npm account needed** | `npx -y github:xsignon-secure/E2E#v0.3.0` (pin a release tag) |
|
|
75
|
+
| **Claude Desktop, zero Node setup** | double-click the [`.mcpb` extension](https://github.com/xsignon-secure/E2E/releases) |
|
|
72
76
|
| **Remote-only clients (ChatGPT connectors)** | `https://playwright-e2e-mcp.vercel.app/api/mcp` |
|
|
73
77
|
|
|
74
78
|
One line for the common clients:
|
|
@@ -78,6 +82,9 @@ claude mcp add playwright-e2e -- npx -y playwright-e2e-mcp
|
|
|
78
82
|
code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","playwright-e2e-mcp"]}'
|
|
79
83
|
```
|
|
80
84
|
|
|
85
|
+
Only need the fix loop? `--tools=core` (or `PW_MCP_TOOLS=core`) exposes six tools and
|
|
86
|
+
halves the tool-definition context; see [Configuration](#configuration).
|
|
87
|
+
|
|
81
88
|
Details and per-client config: [Installation](#installation) ·
|
|
82
89
|
[MCP client configuration](#mcp-client-configuration).
|
|
83
90
|
|
|
@@ -283,14 +290,21 @@ and write a red-highlighted diff image for review.
|
|
|
283
290
|
| Argument | Type | Description |
|
|
284
291
|
| --- | --- | --- |
|
|
285
292
|
| `testFiles` | string[] | Tests to diagnose (`file:line` supported). Defaults to the tests that failed in the most recent run |
|
|
286
|
-
| `runs` | number |
|
|
293
|
+
| `runs` | number | Repetitions, `2–10` (default `3`) |
|
|
294
|
+
| `isolate` | boolean | Also tell parallelism bugs from flakiness: repeat fully parallel (`workers` default `4`), then repeat the failing tests with one worker |
|
|
295
|
+
| `separateProcesses` | boolean | Start a fresh Playwright process per repetition instead of one `--repeat-each` process (slower; for flakes that depend on global setup or a cold start) |
|
|
287
296
|
| `browser` / `headed` / `workers` / `config` | — | As with `run-test` |
|
|
288
|
-
| `timeoutMs` | number | Hard wall-clock limit **per
|
|
297
|
+
| `timeoutMs` | number | Hard wall-clock limit **per repetition** (default `120000`); one `--repeat-each` process gets this × `runs` |
|
|
289
298
|
| `projectRoot` | string | Project directory |
|
|
290
299
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
All repetitions run in **one Playwright process** with `--repeat-each` and
|
|
301
|
+
`--retries=0`, so each attempt is honest evidence and the browser and workers
|
|
302
|
+
start once instead of once per run (about 25% faster on the integration fixture,
|
|
303
|
+
more for suites with expensive setup). A small extra reporter records every
|
|
304
|
+
attempt, because Playwright's JSON report keeps only one result per test.
|
|
305
|
+
|
|
306
|
+
The verdict is **per test**: a table of passes, failures, duration spread and
|
|
307
|
+
first error for each test, plus the verdict block for the worst one:
|
|
294
308
|
|
|
295
309
|
- **❌ CONSISTENTLY FAILING** — failed every run (same error → reproducible bug,
|
|
296
310
|
different errors → still broken, just noisy). Fix it; it is not flaky.
|
|
@@ -299,7 +313,17 @@ failure), the count of **distinct normalized error signatures**, and one of:
|
|
|
299
313
|
instability).
|
|
300
314
|
- **✅ NOT REPRODUCING** — passed every re-run; the original failure was one-off.
|
|
301
315
|
|
|
302
|
-
|
|
316
|
+
With `isolate: true` a second table compares each failing test **in parallel**
|
|
317
|
+
and **alone**:
|
|
318
|
+
|
|
319
|
+
| Reading | Meaning |
|
|
320
|
+
| --- | --- |
|
|
321
|
+
| 🔀 fails only in parallel | Passes every run alone: shared state between tests (same account, DB rows, files, ports). Give each worker its own data or run the file serially |
|
|
322
|
+
| ⏱️ flaky even alone | The race is inside the test or the app: missing `await`, asserting before the UI settles |
|
|
323
|
+
| ❌ fails alone too | Not a parallelism problem; a real bug |
|
|
324
|
+
|
|
325
|
+
Each repetition is recorded in the run history, and the last failing run is
|
|
326
|
+
stored, so `analyze-history` and `get-failure` work right afterwards.
|
|
303
327
|
|
|
304
328
|
### `suggest-fix`
|
|
305
329
|
|
|
@@ -367,11 +391,11 @@ Requirements:
|
|
|
367
391
|
|
|
368
392
|
**No npm account needed** — install straight from GitHub (the `prepare` script
|
|
369
393
|
builds `dist/` automatically on install). Pin a release tag: an unpinned
|
|
370
|
-
`github:
|
|
394
|
+
`github:xsignon-secure/E2E` runs whatever is on the default branch at that moment.
|
|
371
395
|
|
|
372
396
|
```bash
|
|
373
|
-
npx -y github:
|
|
374
|
-
npm install -D github:
|
|
397
|
+
npx -y github:xsignon-secure/E2E#v0.3.0
|
|
398
|
+
npm install -D github:xsignon-secure/E2E#v0.3.0 @playwright/test # or as a project dependency
|
|
375
399
|
npx playwright install chromium
|
|
376
400
|
```
|
|
377
401
|
|
|
@@ -379,11 +403,11 @@ Or grab the packaged tarball from the repo's **GitHub Releases** page and instal
|
|
|
379
403
|
it locally:
|
|
380
404
|
|
|
381
405
|
```bash
|
|
382
|
-
npm install -D https://github.com/
|
|
406
|
+
npm install -D https://github.com/xsignon-secure/E2E/releases/download/v0.3.0/playwright-e2e-mcp-0.3.0.tgz
|
|
383
407
|
```
|
|
384
408
|
|
|
385
409
|
Listed in the **official [MCP Registry](https://registry.modelcontextprotocol.io/)** as
|
|
386
|
-
`io.github.
|
|
410
|
+
`io.github.xsignon-secure/E2E` — registry-aware clients discover it there, and every
|
|
387
411
|
`v*` release tag republishes the entry from CI via [`server.json`](server.json).
|
|
388
412
|
|
|
389
413
|
### MCP client configuration
|
|
@@ -395,7 +419,7 @@ Listed in the **official [MCP Registry](https://registry.modelcontextprotocol.io
|
|
|
395
419
|
"mcpServers": {
|
|
396
420
|
"playwright-e2e": {
|
|
397
421
|
"command": "npx",
|
|
398
|
-
"args": ["-y", "github:
|
|
422
|
+
"args": ["-y", "github:xsignon-secure/E2E#v0.3.0"],
|
|
399
423
|
"env": { "PW_MCP_PROJECT_ROOT": "/absolute/path/to/your/project" }
|
|
400
424
|
}
|
|
401
425
|
}
|
|
@@ -409,8 +433,8 @@ when the client launches it somewhere else (e.g. your home directory).
|
|
|
409
433
|
**Codex / VS Code / Copilot CLIs:**
|
|
410
434
|
|
|
411
435
|
```bash
|
|
412
|
-
codex mcp add playwright-e2e -- npx -y github:
|
|
413
|
-
code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:
|
|
436
|
+
codex mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.3.0
|
|
437
|
+
code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:xsignon-secure/E2E#v0.3.0"]}'
|
|
414
438
|
```
|
|
415
439
|
|
|
416
440
|
Codex's defaults fight this server: the first launch clones the repo and runs
|
|
@@ -421,13 +445,13 @@ Codex's defaults fight this server: the first launch clones the repo and runs
|
|
|
421
445
|
```toml
|
|
422
446
|
[mcp_servers.playwright-e2e]
|
|
423
447
|
command = "npx"
|
|
424
|
-
args = ["-y", "github:
|
|
448
|
+
args = ["-y", "github:xsignon-secure/E2E#v0.3.0"]
|
|
425
449
|
startup_timeout_sec = 60
|
|
426
450
|
tool_timeout_sec = 600
|
|
427
451
|
```
|
|
428
452
|
|
|
429
453
|
**Claude Desktop (one-click):** download and double-click the `.mcpb` Desktop
|
|
430
|
-
Extension attached to the [latest release](https://github.com/
|
|
454
|
+
Extension attached to the [latest release](https://github.com/xsignon-secure/E2E/releases) —
|
|
431
455
|
the bundle ships its own dependencies, so no Node setup is required. On install it
|
|
432
456
|
asks you to pick your **project root** (required, no default: choose the project
|
|
433
457
|
folder, not your home directory) and wires it
|
|
@@ -436,7 +460,7 @@ into `PW_MCP_PROJECT_ROOT`, so the tools point at a real project from the first
|
|
|
436
460
|
**Claude Code:**
|
|
437
461
|
|
|
438
462
|
```bash
|
|
439
|
-
claude mcp add playwright-e2e -- npx -y github:
|
|
463
|
+
claude mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.3.0
|
|
440
464
|
```
|
|
441
465
|
|
|
442
466
|
**Gemini CLI / Qwen Code:** paste the `mcpServers` block above into
|
|
@@ -545,11 +569,60 @@ Redeploy after a change: merge to `main`. Vercel's Git integration deploys
|
|
|
545
569
|
every push, so there is no token to manage and no CLI step — watch the
|
|
546
570
|
`Vercel` commit status for the deployment result.
|
|
547
571
|
|
|
572
|
+
## CI: GitHub Action and `ci` command
|
|
573
|
+
|
|
574
|
+
The same diagnosis runs without an agent. `playwright-e2e-mcp ci` runs the
|
|
575
|
+
suite (auto-retry once, so flaky tests are reported as flaky, not failed),
|
|
576
|
+
optionally drafts `suggest-fix` diffs and a flaky verdict for the failures, and
|
|
577
|
+
writes one Markdown report to stdout, to `--output`, and to the GitHub job
|
|
578
|
+
summary when `GITHUB_STEP_SUMMARY` is set. Exit code `0` passed, `1` tests
|
|
579
|
+
failed, `2` the run itself failed.
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
npx -y playwright-e2e-mcp ci --flaky-runs 3 --suggest 2 --output report.md
|
|
583
|
+
npx -y playwright-e2e-mcp ci --help
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
As a GitHub Action, it adds the report to the job summary and keeps one PR
|
|
587
|
+
comment up to date when the run fails:
|
|
588
|
+
|
|
589
|
+
```yaml
|
|
590
|
+
permissions:
|
|
591
|
+
contents: read
|
|
592
|
+
pull-requests: write # only for the PR comment
|
|
593
|
+
steps:
|
|
594
|
+
- uses: actions/checkout@v6
|
|
595
|
+
- uses: actions/setup-node@v6
|
|
596
|
+
with: { node-version: 24 }
|
|
597
|
+
- run: npm ci && npx playwright install --with-deps chromium
|
|
598
|
+
- uses: xsignon-secure/E2E@v0.3.0
|
|
599
|
+
with:
|
|
600
|
+
flaky-runs: 3 # 0 skips the flaky verdict
|
|
601
|
+
suggest: 2 # suggest-fix diffs for the first 2 failures
|
|
602
|
+
# args: --browser chromium tests/checkout
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
Inputs: `project-root`, `args`, `flaky-runs`, `suggest`, `comment`,
|
|
606
|
+
`fail-on-failure`, `version`, `github-token`. Outputs: `exit-code`, `report`.
|
|
607
|
+
|
|
608
|
+
## Docker
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
docker build -t playwright-e2e-mcp .
|
|
612
|
+
docker run -i --rm -v "$PWD:/work" playwright-e2e-mcp # stdio MCP server
|
|
613
|
+
docker run --rm -v "$PWD:/work" playwright-e2e-mcp ci # CI report
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
The image is based on `mcr.microsoft.com/playwright:v1.63.0-noble`, so its
|
|
617
|
+
browsers match Playwright 1.63. Mount your project at `/work`; its own
|
|
618
|
+
`node_modules` provide `@playwright/test`.
|
|
619
|
+
|
|
548
620
|
## Configuration
|
|
549
621
|
|
|
550
622
|
| Environment variable | Default | Purpose |
|
|
551
623
|
| --- | --- | --- |
|
|
552
624
|
| `PW_MCP_PROJECT_ROOT` | server cwd | Default project root for every tool |
|
|
625
|
+
| `PW_MCP_TOOLS` | all | Which tools to expose, as tool names and/or profiles, comma separated (same as the `--tools=` flag). Profiles: `core` (run, status, failure, fix, flaky, list), `triage` (run, status, failure, flaky, history, list), `inspect` (page, selector, visual), `author` (list, page, selector, generate, run). All eleven tool definitions cost about 5.2k tokens of context per request; `core` costs about 2.4k |
|
|
553
626
|
| `PW_MCP_STORAGE_STATE` | — | Default `storageState` file (inside the project) for the page tools |
|
|
554
627
|
| `PW_MCP_HISTORY` | on | `0` stops recording runs to `.playwright-e2e-mcp/history.jsonl` |
|
|
555
628
|
| `PW_MCP_ALLOWED_ROOTS` | — | Extra directories a caller may pass as `projectRoot` (`:`-separated, `;` on Windows). Anything outside these and the default root is rejected |
|
|
@@ -685,6 +758,10 @@ npm test # build + test/run-tests.mjs (unit tests, any Node ≥20)
|
|
|
685
758
|
npm run e2e # build + e2e/run.mjs: live MCP ↔ Playwright integration suite
|
|
686
759
|
npm run mcpb # build + bundle dist/ into playwright-e2e-mcp-<version>.mcpb (+ .sha256)
|
|
687
760
|
npm run mcpb:smoke # ...then install that bundle in a temp dir, launch it and assert the handshake
|
|
761
|
+
npm run mcpb:sign # ...then sign it with MCPB_CERT/MCPB_KEY → <version>.signed.mcpb
|
|
762
|
+
npm run skill:zip # just the archive: dist-skill/playwright-e2e-mcp.zip
|
|
763
|
+
npm run skill:package # the uploadable folder: ../agensi-skill-<version>/ (skill copy, README, zip)
|
|
764
|
+
npm run skill:check # build, then fail if a packaged copy has drifted from skill/
|
|
688
765
|
```
|
|
689
766
|
|
|
690
767
|
Tests cover the report parser (sample Playwright JSON, trace attachments), path utils
|
|
@@ -694,11 +771,15 @@ helpers, the **trace reader** (synthetic trace.zip: error, failed action, DOM sn
|
|
|
694
771
|
`*.network` failed-request parsing, console error/warning events), the **image diff**
|
|
695
772
|
(PNG round-trip, regions, color shift, dimension changes), the **change analyzer**
|
|
696
773
|
(selector extraction, git + mtime paths), the **flaky verdict logic**
|
|
697
|
-
(failure signatures, CONSISTENTLY FAILING / FLAKY / NOT REPRODUCING / NO TESTS RAN
|
|
774
|
+
(failure signatures, CONSISTENTLY FAILING / FLAKY / NOT REPRODUCING / NO TESTS RAN,
|
|
775
|
+
per-test grouping of repeat attempts and the parallel-vs-alone reading), the `ci`
|
|
776
|
+
argument parser and tool profiles,
|
|
698
777
|
the **HTTP bridge** (token, restricted mode, Host allowlist), the **security
|
|
699
778
|
regressions** (sandbox escapes, argument smuggling, symlink writes, code injection,
|
|
700
779
|
SSRF ranges, env scrubbing, decode limits), the `.mcpb` manifest, the `.mcpb` zip
|
|
701
|
-
extractor,
|
|
780
|
+
extractor, the **skill package** (byte-identical rebuilds, a CRLF checkout hashing the
|
|
781
|
+
same, refusal of junk/binary/symlinks, and drift detection between `skill/` and a
|
|
782
|
+
packaged copy), and the MCP config files.
|
|
702
783
|
|
|
703
784
|
### Integration suite (`npm run e2e`)
|
|
704
785
|
|
|
@@ -718,13 +799,174 @@ that only appear end-to-end:
|
|
|
718
799
|
- `get-failure` trace diagnostics: DOM at failure, the 404 network request,
|
|
719
800
|
the `console.error` message, diagnosis and next steps,
|
|
720
801
|
- auto-retry turning a first-run failure into `PASSED (1 flaky)`,
|
|
721
|
-
- `diagnose-flaky` verdict **FLAKY** (2 of 3 runs) with retries disabled,
|
|
802
|
+
- `diagnose-flaky` verdict **FLAKY** (2 of 3 runs) with retries disabled, in one
|
|
803
|
+
`--repeat-each` process, and `isolate` reading a shared-slot test as "fails only in parallel",
|
|
804
|
+
- `--tools=` profiles trimming `tools/list`, and the `ci` command's exit code, report,
|
|
805
|
+
`--output` file and GitHub job summary,
|
|
722
806
|
- `generate-e2e-test` writing its scaffold, plus error paths
|
|
723
807
|
(missing test path, unknown tool, unreachable server).
|
|
724
808
|
|
|
725
809
|
First run needs the browser once: `npx playwright install chromium`.
|
|
726
810
|
CI runs the suite on Ubuntu and Windows (see `.github/workflows/ci.yml`).
|
|
727
811
|
|
|
812
|
+
### Signing the bundle
|
|
813
|
+
|
|
814
|
+
```bash
|
|
815
|
+
MCPB_CERT=~/signing/cert.pem MCPB_KEY=~/signing/key.pem npm run mcpb:sign
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
Signing appends a PKCS#7 signature block to the bundle, so the signed file is
|
|
819
|
+
*the reproducible bundle plus that block*. That ordering is the point: the bytes
|
|
820
|
+
CI proved identical across platforms stay inside the signed file, and
|
|
821
|
+
`mcpb unsign` returns them exactly. `scripts/sign-mcpb.mjs` asserts that round
|
|
822
|
+
trip on every run and deletes its output if it fails, which is what keeps
|
|
823
|
+
`<version>.signed.mcpb` tied to `<version>.mcpb`.
|
|
824
|
+
|
|
825
|
+
The private key is read from a path you pass in (`--cert`/`--key` or
|
|
826
|
+
`MCPB_CERT`/`MCPB_KEY`) and never from the repository — keep it outside version
|
|
827
|
+
control, and back it up: the same key across releases is what makes the signer
|
|
828
|
+
recognisable.
|
|
829
|
+
|
|
830
|
+
What signing does and does not buy you is decided by the certificate, not by
|
|
831
|
+
this script. `mcpb verify` and `mcpb info` accept a signature only when the
|
|
832
|
+
certificate chains to something in the OS trust store, so with a self-signed
|
|
833
|
+
certificate a host still reports **Not signed** — the signature is real
|
|
834
|
+
integrity and key continuity, verifiable by the fingerprint the script prints,
|
|
835
|
+
but not third-party identity. A certificate issued by a public CA, or an
|
|
836
|
+
internal one installed on your machines, is what makes hosts report it as
|
|
837
|
+
signed.
|
|
838
|
+
|
|
839
|
+
### Assembling a release
|
|
840
|
+
|
|
841
|
+
```bash
|
|
842
|
+
npm run mcpb && npm pack # the bundle, then the npm tarball
|
|
843
|
+
npm run release:assemble -- --tag v0.2.3 # sign, checksum and write the notes
|
|
844
|
+
npm run release:publish -- --tag v0.2.3 --assets dist-release/assets \
|
|
845
|
+
--title-file dist-release/RELEASE_TITLE.txt \
|
|
846
|
+
--body-file dist-release/RELEASE_BODY.md --download dist-release/downloaded
|
|
847
|
+
npm run release:verify -- v0.2.3 --dir dist-release/downloaded
|
|
848
|
+
npm run release:publish -- --tag v0.2.3 --publish
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
Pushing a `v*` tag runs exactly that sequence in
|
|
852
|
+
`.github/workflows/release.yml`. The release used to be assembled by hand, and
|
|
853
|
+
the notes were written from what those commands printed: every hash in them was
|
|
854
|
+
a copy, and nothing compared the bundle hash printed there with the bundle that
|
|
855
|
+
shipped.
|
|
856
|
+
|
|
857
|
+
`scripts/assemble-release.mjs` stages the whole release into
|
|
858
|
+
`dist-release/assets/`: the bundle and its sidecar, the **signed** bundle and the
|
|
859
|
+
signing certificate when a key is configured, the npm tarball, the skill package
|
|
860
|
+
built by the same writer as `npm run skill:zip`, and `SHA256SUMS.txt` covering
|
|
861
|
+
every file it staged. It empties that directory first, so a file left over from
|
|
862
|
+
an earlier run cannot be hashed and published as if this run had produced it.
|
|
863
|
+
|
|
864
|
+
The notes are half written, half generated. `release-notes/<tag>.md` holds the
|
|
865
|
+
prose — its H1 becomes the release title and has to name the tag — and the script
|
|
866
|
+
appends the asset table, the reproduction recipe carrying the real bundle hash,
|
|
867
|
+
the signer and fingerprint, and the commit list. The prose is held to the same
|
|
868
|
+
rule: a 64-character hex string in it has to be a hash this release publishes,
|
|
869
|
+
and writing an `### Assets` section of your own fails the assembly rather than
|
|
870
|
+
shipping a second, staler table. See [release-notes/README.md](release-notes/README.md).
|
|
871
|
+
|
|
872
|
+
`scripts/publish-release.mjs` fills the release **as a draft**, uploads the
|
|
873
|
+
assets, downloads every one of them back and compares it byte for byte, and only
|
|
874
|
+
`--publish` makes it public — after `release:verify` has re-derived the release
|
|
875
|
+
from the tag. Re-running is safe: a draft this workflow assembled is refreshed in
|
|
876
|
+
place, while a release it did not assemble, or one already published, is refused
|
|
877
|
+
by name instead of overwritten.
|
|
878
|
+
|
|
879
|
+
Signing is optional and its absence is stated rather than hidden: without the
|
|
880
|
+
`MCPB_KEY` and `MCPB_CERT` repository secrets the release is assembled and
|
|
881
|
+
published **unsigned**, with a notice in the run and a line saying so in the
|
|
882
|
+
notes. Add both — the private key stays out of the repository and out of the logs:
|
|
883
|
+
|
|
884
|
+
```bash
|
|
885
|
+
gh secret set MCPB_KEY --repo xsignon-secure/E2E < ~/signing/key.pem
|
|
886
|
+
gh secret set MCPB_CERT --repo xsignon-secure/E2E < ~/signing/cert.pem
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
Creating the release and uploading its assets needs `contents: write`, which the
|
|
890
|
+
job requests for itself; if it is refused, the run names the setting to change.
|
|
891
|
+
|
|
892
|
+
### Verifying a published release
|
|
893
|
+
|
|
894
|
+
```bash
|
|
895
|
+
git checkout v0.3.0 && npm ci && npm run mcpb
|
|
896
|
+
npm run release:verify -- v0.3.0
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
The release notes promise that the tag rebuilds the published bundle byte for
|
|
900
|
+
byte. `scripts/verify-release.mjs` checks that promise from a checkout of the
|
|
901
|
+
tag: the published bundle against your fresh build, every checksum the release
|
|
902
|
+
publishes (and that nothing shippable is missing from `SHA256SUMS.txt`), a
|
|
903
|
+
**signed** bundle against the bytes its signature wraps, the **skill package**
|
|
904
|
+
against a rebuild from the same tag, and that the published archive still
|
|
905
|
+
extracts with that version's manifest. The skill package is required of a tag
|
|
906
|
+
whose tree carries the publishing workflow; older tags predate it, so there it
|
|
907
|
+
is checked when present and skipped when not, like the signing certificate.
|
|
908
|
+
`.github/workflows/verify-release.yml` runs it on demand for any past tag, and by
|
|
909
|
+
itself for a release published by hand. A release assembled by
|
|
910
|
+
`.github/workflows/release.yml` runs the same check on its own assets *before*
|
|
911
|
+
it is published — GitHub does not raise `release: published` for a release created
|
|
912
|
+
with the repository's own token, so the check is a step there rather than a
|
|
913
|
+
trigger. The `.tgz` is checked for download integrity only: npm
|
|
914
|
+
records the packer's line endings, so a tarball packed locally on another OS is
|
|
915
|
+
legitimately different.
|
|
916
|
+
|
|
917
|
+
### Packaging the agent skill
|
|
918
|
+
|
|
919
|
+
```bash
|
|
920
|
+
npm run skill:package # ../agensi-skill-<version>/, ready to upload
|
|
921
|
+
npm run skill:zip # only the archive: dist-skill/playwright-e2e-mcp.zip
|
|
922
|
+
npm run skill:check # build, then compare every copy
|
|
923
|
+
npm run skill:check -- ../agensi-skill-0.3.0
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
`skill/` is an [Agent Skill](https://agentskills.io/specification) — the
|
|
927
|
+
instructions an agent follows to drive this server — and the marketplace gets
|
|
928
|
+
the same Markdown as a zip with `playwright-e2e-mcp/` at its root.
|
|
929
|
+
`scripts/package-skill.mjs` produces that zip, so the uploaded copy is built
|
|
930
|
+
rather than assembled by hand, and it refuses what the marketplace rejects: a
|
|
931
|
+
missing `SKILL.md`, a non-text file, a symlink, `Thumbs.db`.
|
|
932
|
+
|
|
933
|
+
`skill:package` writes the whole folder a release would otherwise assemble by
|
|
934
|
+
hand — the skill copy, `skill/README.md` and the archive — to
|
|
935
|
+
`../agensi-skill-<version>` (or `--out <dir>`), then verifies it with the same
|
|
936
|
+
comparison `check` uses, so a successful exit means the folder really is the
|
|
937
|
+
skill tree. It is idempotent: a folder that already matches is left untouched.
|
|
938
|
+
A folder that has drifted is refused instead of overwritten, because it may
|
|
939
|
+
already be published — bump `version` for a new package, or pass `--force` to
|
|
940
|
+
replace that one.
|
|
941
|
+
|
|
942
|
+
The archive comes from the same deterministic writer as the `.mcpb`, so the
|
|
943
|
+
same tree always hashes the same, and text payloads are LF-normalised first:
|
|
944
|
+
a CRLF checkout builds the bytes an LF one does. CI runs `skill:check`, generates
|
|
945
|
+
a package folder, and uploads the built zip as an artifact
|
|
946
|
+
(`.github/workflows/ci.yml`).
|
|
947
|
+
|
|
948
|
+
**Every release publishes the package too.** Assembling a release builds it from
|
|
949
|
+
the release tag and attaches it as `<name>-<version>-skill.zip`, and the
|
|
950
|
+
`.github/workflows/release.yml` run downloads that asset back off the draft and
|
|
951
|
+
byte-compares it with the build before anything is published. The marketplace
|
|
952
|
+
upload is that asset, not a folder someone assembled — a deterministic archive
|
|
953
|
+
means "the same build as the tagged release" is an exact statement, and
|
|
954
|
+
`release:verify` checks it again against a rebuild from the tag.
|
|
955
|
+
`.github/workflows/publish-skill-package.yml` stays for the repair path: run it
|
|
956
|
+
by hand to attach or rebuild the package for a release that is missing it.
|
|
957
|
+
|
|
958
|
+
`skill:check` is the other half of that, and the part that matters when a
|
|
959
|
+
package has already been uploaded. It builds twice (the bytes must agree),
|
|
960
|
+
reads the archive back and compares its contents with `skill/` file by file,
|
|
961
|
+
then compares a packaged copy — `../agensi-skill-<version>` by default, or a
|
|
962
|
+
path you pass: the package folder, the bare `playwright-e2e-mcp/` folder, or
|
|
963
|
+
the zip on its own. Comparisons are by content, never by archive bytes, because
|
|
964
|
+
a zip written by a platform `zip` tool carries real timestamps that say nothing
|
|
965
|
+
about whether the Markdown inside it is current. Any file that differs, is
|
|
966
|
+
missing or is extra is named on stderr and the command exits 1 — the repository
|
|
967
|
+
copy and the uploaded copy are the same document, so an edit to either one
|
|
968
|
+
should not be invisible.
|
|
969
|
+
|
|
728
970
|
### Try the example
|
|
729
971
|
|
|
730
972
|
With Playwright installed in your project:
|
package/dist/cli/ci.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `playwright-e2e-mcp ci`: the same diagnosis the MCP tools give an agent,
|
|
3
|
+
* as a plain command for CI. It runs the suite (auto-retry once, so flaky
|
|
4
|
+
* tests are reported as flaky rather than failed), optionally repeats the
|
|
5
|
+
* failures through diagnose-flaky and drafts suggest-fix diffs, and writes
|
|
6
|
+
* one Markdown report: to stdout, to --output, and to the GitHub job
|
|
7
|
+
* summary when GITHUB_STEP_SUMMARY is set.
|
|
8
|
+
*
|
|
9
|
+
* Exit codes: 0 all passed (flaky allowed), 1 tests failed, 2 the run
|
|
10
|
+
* itself failed (no Playwright, config error, timeout) or bad arguments.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CI_USAGE: string;
|
|
13
|
+
export interface CiOptions {
|
|
14
|
+
projectRoot?: string;
|
|
15
|
+
config?: string;
|
|
16
|
+
browser?: 'chromium' | 'firefox' | 'webkit';
|
|
17
|
+
grep?: string;
|
|
18
|
+
workers?: number;
|
|
19
|
+
timeoutMs: number;
|
|
20
|
+
retry: boolean;
|
|
21
|
+
flakyRuns?: number;
|
|
22
|
+
suggest: number;
|
|
23
|
+
output?: string;
|
|
24
|
+
testFiles: string[];
|
|
25
|
+
}
|
|
26
|
+
/** Parse `ci` arguments (everything after the subcommand). Throws on bad input. */
|
|
27
|
+
export declare function parseCiArgs(argv: string[]): CiOptions;
|
|
28
|
+
/** Run the CI flow; returns the exit code. */
|
|
29
|
+
export declare function runCi(argv: string[]): Promise<number>;
|
package/dist/cli/ci.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `playwright-e2e-mcp ci`: the same diagnosis the MCP tools give an agent,
|
|
3
|
+
* as a plain command for CI. It runs the suite (auto-retry once, so flaky
|
|
4
|
+
* tests are reported as flaky rather than failed), optionally repeats the
|
|
5
|
+
* failures through diagnose-flaky and drafts suggest-fix diffs, and writes
|
|
6
|
+
* one Markdown report: to stdout, to --output, and to the GitHub job
|
|
7
|
+
* summary when GITHUB_STEP_SUMMARY is set.
|
|
8
|
+
*
|
|
9
|
+
* Exit codes: 0 all passed (flaky allowed), 1 tests failed, 2 the run
|
|
10
|
+
* itself failed (no Playwright, config error, timeout) or bad arguments.
|
|
11
|
+
*/
|
|
12
|
+
import { appendFile, writeFile } from 'node:fs/promises';
|
|
13
|
+
import { parseArgs } from 'node:util';
|
|
14
|
+
import { createLogger } from '../utils/logger.js';
|
|
15
|
+
import { createToolStore } from '../tools/shared.js';
|
|
16
|
+
import { runTestTool } from '../tools/run-test.js';
|
|
17
|
+
import { diagnoseFlakyTool } from '../tools/diagnose-flaky.js';
|
|
18
|
+
import { suggestFixTool } from '../tools/suggest-fix.js';
|
|
19
|
+
export const CI_USAGE = [
|
|
20
|
+
'Usage: playwright-e2e-mcp ci [options] [test files…]',
|
|
21
|
+
'',
|
|
22
|
+
'Runs the Playwright suite and writes a Markdown diagnosis (stdout, --output,',
|
|
23
|
+
'and $GITHUB_STEP_SUMMARY when set). Exit 0 = passed, 1 = tests failed, 2 = run error.',
|
|
24
|
+
'',
|
|
25
|
+
' --project-root <dir> project directory (default: PW_MCP_PROJECT_ROOT or cwd)',
|
|
26
|
+
' --config <path|n> playwright.config path or 1-based index',
|
|
27
|
+
' --browser <name> chromium | firefox | webkit',
|
|
28
|
+
' --grep <regex> only tests whose title matches',
|
|
29
|
+
' --workers <n> Playwright workers',
|
|
30
|
+
' --timeout <ms> wall-clock limit for the run (default 600000)',
|
|
31
|
+
' --no-retry do not auto-retry failures once',
|
|
32
|
+
' --flaky-runs <n> repeat failing tests n times (2-10) for a flaky verdict',
|
|
33
|
+
' --suggest <n> draft suggest-fix diffs for the first n failures (max 5)',
|
|
34
|
+
' --output <file> also write the report to this file (for a PR comment)',
|
|
35
|
+
'',
|
|
36
|
+
].join('\n');
|
|
37
|
+
function intOption(value, name, min, max) {
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
const n = Number(value);
|
|
41
|
+
if (!Number.isInteger(n) || n < min || n > max)
|
|
42
|
+
throw new Error(`--${name} must be an integer from ${min} to ${max}`);
|
|
43
|
+
return n;
|
|
44
|
+
}
|
|
45
|
+
/** Parse `ci` arguments (everything after the subcommand). Throws on bad input. */
|
|
46
|
+
export function parseCiArgs(argv) {
|
|
47
|
+
const { values, positionals } = parseArgs({
|
|
48
|
+
args: argv,
|
|
49
|
+
allowPositionals: true,
|
|
50
|
+
strict: true,
|
|
51
|
+
options: {
|
|
52
|
+
'project-root': { type: 'string' },
|
|
53
|
+
config: { type: 'string' },
|
|
54
|
+
browser: { type: 'string' },
|
|
55
|
+
grep: { type: 'string' },
|
|
56
|
+
workers: { type: 'string' },
|
|
57
|
+
timeout: { type: 'string' },
|
|
58
|
+
'no-retry': { type: 'boolean' },
|
|
59
|
+
'flaky-runs': { type: 'string' },
|
|
60
|
+
suggest: { type: 'string' },
|
|
61
|
+
output: { type: 'string' },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const browser = values.browser;
|
|
65
|
+
if (browser !== undefined && browser !== 'chromium' && browser !== 'firefox' && browser !== 'webkit') {
|
|
66
|
+
throw new Error('--browser must be chromium, firefox or webkit');
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
projectRoot: values['project-root'],
|
|
70
|
+
config: values.config,
|
|
71
|
+
browser,
|
|
72
|
+
grep: values.grep,
|
|
73
|
+
workers: intOption(values.workers, 'workers', 1, 64),
|
|
74
|
+
timeoutMs: intOption(values.timeout, 'timeout', 1_000, 3_600_000) ?? 600_000,
|
|
75
|
+
retry: values['no-retry'] !== true,
|
|
76
|
+
flakyRuns: intOption(values['flaky-runs'], 'flaky-runs', 2, 10),
|
|
77
|
+
suggest: intOption(values.suggest, 'suggest', 0, 5) ?? 0,
|
|
78
|
+
output: values.output,
|
|
79
|
+
testFiles: positionals,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function text(response) {
|
|
83
|
+
return response.content.map((block) => block.text).join('\n');
|
|
84
|
+
}
|
|
85
|
+
/** Run the CI flow; returns the exit code. */
|
|
86
|
+
export async function runCi(argv) {
|
|
87
|
+
let options;
|
|
88
|
+
try {
|
|
89
|
+
options = parseCiArgs(argv);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
process.stderr.write(`${err.message}\n\n${CI_USAGE}`);
|
|
93
|
+
return 2;
|
|
94
|
+
}
|
|
95
|
+
const projectRoot = options.projectRoot ?? process.env.PW_MCP_PROJECT_ROOT ?? process.cwd();
|
|
96
|
+
const ctx = {
|
|
97
|
+
// Info logs would bury the report in CI output; LOG_LEVEL still wins.
|
|
98
|
+
logger: createLogger({
|
|
99
|
+
level: process.env.LOG_LEVEL || process.env.MCP_LOG_LEVEL ? undefined : 'warn',
|
|
100
|
+
bindings: { name: 'playwright-e2e-mcp', mode: 'ci' },
|
|
101
|
+
}),
|
|
102
|
+
store: createToolStore(),
|
|
103
|
+
projectRoot,
|
|
104
|
+
};
|
|
105
|
+
const sections = [];
|
|
106
|
+
const run = await runTestTool.handler({
|
|
107
|
+
testFiles: options.testFiles.length > 0 ? options.testFiles : undefined,
|
|
108
|
+
grep: options.grep,
|
|
109
|
+
browser: options.browser,
|
|
110
|
+
workers: options.workers,
|
|
111
|
+
timeoutMs: options.timeoutMs,
|
|
112
|
+
retryOnFailure: options.retry,
|
|
113
|
+
config: options.config,
|
|
114
|
+
}, ctx);
|
|
115
|
+
sections.push(text(run));
|
|
116
|
+
const result = ctx.store.lastRun?.result;
|
|
117
|
+
const failures = result?.failures ?? [];
|
|
118
|
+
let code = result === undefined || run.isError ? 2 : result.ok ? 0 : failures.length > 0 ? 1 : 2;
|
|
119
|
+
if (code === 1 && options.suggest > 0) {
|
|
120
|
+
// Before diagnose-flaky, which replaces the last run suggest-fix indexes into.
|
|
121
|
+
const count = Math.min(options.suggest, ctx.store.lastRun?.result.failures.length ?? 0);
|
|
122
|
+
for (let index = 1; index <= count; index += 1) {
|
|
123
|
+
const fix = await suggestFixTool.handler({ index, config: options.config }, ctx);
|
|
124
|
+
sections.push(text(fix).replace(/^## /m, '### '));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (code === 1 && options.flakyRuns) {
|
|
128
|
+
const flaky = await diagnoseFlakyTool.handler({ runs: options.flakyRuns, config: options.config, browser: options.browser }, ctx);
|
|
129
|
+
sections.push(text(flaky).replace(/^## /m, '### '));
|
|
130
|
+
}
|
|
131
|
+
const report = `${sections.join('\n\n---\n\n')}\n\n<sub>Generated by [playwright-e2e-mcp](https://github.com/xsignon-secure/E2E) \`ci\`.</sub>\n`;
|
|
132
|
+
process.stdout.write(report);
|
|
133
|
+
try {
|
|
134
|
+
if (options.output)
|
|
135
|
+
await writeFile(options.output, report, 'utf8');
|
|
136
|
+
if (process.env.GITHUB_STEP_SUMMARY)
|
|
137
|
+
await appendFile(process.env.GITHUB_STEP_SUMMARY, report, 'utf8');
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
process.stderr.write(`could not write the report: ${err.message}\n`);
|
|
141
|
+
code = Math.max(code, 2);
|
|
142
|
+
}
|
|
143
|
+
return code;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=ci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/cli/ci.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
* tests and tooling can construct a server without side effects.
|
|
8
8
|
*/
|
|
9
9
|
import { logger } from './utils/logger.js';
|
|
10
|
-
export { createServer, startServer, SERVER_NAME, SERVER_VERSION } from './server.js';
|
|
10
|
+
export { createServer, startServer, resolveToolSelection, TOOL_PROFILES, SERVER_NAME, SERVER_VERSION } from './server.js';
|
|
11
11
|
export { createMcpHttpHandler, handleNodeRequest, MAX_BODY_BYTES } from './http.js';
|
|
12
12
|
export { logger };
|