playwright-e2e-mcp 0.4.1 → 0.5.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 (59) hide show
  1. package/README.md +215 -43
  2. package/dist/cli/init.js +3 -2
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/http.d.ts +6 -1
  5. package/dist/http.js +13 -3
  6. package/dist/http.js.map +1 -1
  7. package/dist/oauth.d.ts +34 -0
  8. package/dist/oauth.js +346 -0
  9. package/dist/oauth.js.map +1 -0
  10. package/dist/server.d.ts +2 -2
  11. package/dist/server.js +31 -4
  12. package/dist/server.js.map +1 -1
  13. package/dist/tools/analyze-history.d.ts +12 -1
  14. package/dist/tools/analyze-history.js +89 -5
  15. package/dist/tools/analyze-history.js.map +1 -1
  16. package/dist/tools/audit-accessibility.d.ts +85 -0
  17. package/dist/tools/audit-accessibility.js +4 -1
  18. package/dist/tools/audit-accessibility.js.map +1 -1
  19. package/dist/tools/audit-performance.d.ts +333 -0
  20. package/dist/tools/audit-performance.js +377 -0
  21. package/dist/tools/audit-performance.js.map +1 -0
  22. package/dist/tools/compare-visual-state.d.ts +84 -0
  23. package/dist/tools/generate-e2e-test.d.ts +90 -0
  24. package/dist/tools/generate-e2e-test.js +223 -34
  25. package/dist/tools/generate-e2e-test.js.map +1 -1
  26. package/dist/tools/get-failure.js +2 -1
  27. package/dist/tools/get-failure.js.map +1 -1
  28. package/dist/tools/inspect-page.d.ts +94 -0
  29. package/dist/tools/inspect-page.js +42 -5
  30. package/dist/tools/inspect-page.js.map +1 -1
  31. package/dist/tools/load-report.d.ts +48 -0
  32. package/dist/tools/load-report.js +167 -0
  33. package/dist/tools/load-report.js.map +1 -0
  34. package/dist/tools/probe-script.d.ts +7 -0
  35. package/dist/tools/probe-script.js +256 -7
  36. package/dist/tools/probe-script.js.map +1 -1
  37. package/dist/tools/shared.d.ts +137 -2
  38. package/dist/tools/shared.js +155 -8
  39. package/dist/tools/shared.js.map +1 -1
  40. package/dist/tools/suggest-fix.d.ts +35 -1
  41. package/dist/tools/suggest-fix.js +197 -17
  42. package/dist/tools/suggest-fix.js.map +1 -1
  43. package/dist/tools/validate-selector.d.ts +84 -0
  44. package/dist/tools/validate-selector.js +7 -1
  45. package/dist/tools/validate-selector.js.map +1 -1
  46. package/dist/types/index.d.ts +28 -0
  47. package/dist/utils/project-detector.d.ts +7 -0
  48. package/dist/utils/project-detector.js +11 -0
  49. package/dist/utils/project-detector.js.map +1 -1
  50. package/dist/utils/report-parser.d.ts +28 -3
  51. package/dist/utils/report-parser.js +77 -11
  52. package/dist/utils/report-parser.js.map +1 -1
  53. package/dist/utils/run-history.d.ts +66 -3
  54. package/dist/utils/run-history.js +149 -3
  55. package/dist/utils/run-history.js.map +1 -1
  56. package/package.json +5 -3
  57. package/skill/playwright-e2e-mcp/SKILL.md +71 -15
  58. package/skill/playwright-e2e-mcp/references/setup.md +1 -1
  59. package/skill/playwright-e2e-mcp/references/tools.md +67 -6
package/README.md CHANGED
@@ -40,9 +40,13 @@ run-test ──▶ get-failure ──▶ suggest-fix (apply + re-run) ──▶
40
40
  | 🔍 | "Why did this fail?" | Reads Playwright's trace: the page at the moment of failure, the broken request, the console error. No guessing. |
41
41
  | 🛠️ | "Fix it" | Swaps in a locator proven unique on the page, **re-runs the test**, and undoes the edit if it's still red. If the button is really gone, it tells you it's an app bug instead of hiding it. |
42
42
  | 🎲 | "Is this test flaky?" | Re-runs it many ways (repeated, alone, in random order) and names the exact test and seed that cause the flake. |
43
- | 📈 | "What's been breaking lately?" | Keeps a local run history and separates flaky, newly broken and always-broken tests. |
43
+ | 📈 | "What's been breaking lately?" | Keeps a local run history and separates flaky, newly broken and always-broken tests; shows the slowest tests, stability by day and **the commit where each test went bad**. |
44
+ | ☁️ | "Why did CI fail?" | Loads the CI job's report (or merges sharded blob reports), maps its paths onto your checkout and finds the traces in the downloaded artifact, so the same diagnosis and fixes work on CI failures. |
45
+ | ✍️ | "Write a test for this flow" | Walks the steps on the live page first, writes a spec that replays them with assertions on where the flow landed (URL and accessibility snapshot), and runs it once to prove it passes. |
44
46
  | ♿ | "Check this page for accessibility" | Runs axe-core (WCAG 2.2 AA) and returns each problem with a ready-to-paste locator and regression test. |
45
- | 🔐 | "Test the page after login" | Works behind sign-in with saved sessions, headers and click/fill steps. |
47
+ | ⚡ | "Why is this page slow?" | Measures Web Vitals (LCP, CLS, INP, TBT) on desktop or a throttled phone, names the slow element and the elements that jump, and hands back a budget test. |
48
+ | 🧪 | "Show me the error state" | Mocks API responses (500s, empty lists, slow calls) so the AI can inspect, audit or measure states that are hard to reach. |
49
+ | 🔐 | "Test the page after login" | Works behind sign-in with saved sessions, headers and click/fill steps, in Chromium, Firefox or WebKit, and can record or replay network traffic from a HAR file. |
46
50
  | 🤖 | "Do it in CI" | A [GitHub Action and `ci` command](#ci-github-action-and-ci-command) post the diagnosis, flaky verdict and fix diffs on your PR. |
47
51
 
48
52
  **Why it stands out**
@@ -55,6 +59,14 @@ run-test ──▶ get-failure ──▶ suggest-fix (apply + re-run) ──▶
55
59
  (locators, waiting, auth, test data, mocking, flake patterns, review checklist).
56
60
  - **Ready in one line.** `npx -y playwright-e2e-mcp init` sets up Claude Code, Cursor and VS Code.
57
61
 
62
+ ### Free and open source, for good
63
+
64
+ - **MIT licensed.** Use it, change it, ship it in commercial work; no fees, no paid tier, no feature held back.
65
+ - **No account, no API key, no sign-up.** `npx -y playwright-e2e-mcp init` is the whole setup.
66
+ - **No telemetry.** It never phones home; your tests, traces and run history stay on your machine.
67
+ - **Free dependencies only:** the MCP SDK (Apache-2.0), zod (MIT), axe-core (MPL-2.0) and the Playwright your project already has (Apache-2.0).
68
+ - **Free to host yourself**, too: the HTTP bridge deploys to a free Vercel account (see [Hosted endpoint](#hosted-endpoint-chatgpt--remote-clients)).
69
+
58
70
  <details>
59
71
  <summary><b>The technical details</b></summary>
60
72
 
@@ -75,8 +87,16 @@ run-test ──▶ get-failure ──▶ suggest-fix (apply + re-run) ──▶
75
87
  flaky, regressed and broken tests from the local run record.
76
88
  - **Accessibility.** `audit-accessibility` runs axe-core against WCAG 2.2 AA on any page,
77
89
  signed in or after steps, with offending elements as verified locators.
78
- - **Pages behind a login.** Every page tool accepts a Playwright `storageState`, extra
79
- headers, and click/fill steps to reach a modal or a later step.
90
+ - **Performance.** `audit-performance` measures lab Web Vitals (LCP, CLS, TBT, FCP, TTFB, and
91
+ INP for the interactions in `actions`), optionally as a throttled phone and as the median of
92
+ several runs, rates them against Google's thresholds or your budgets, and names the LCP
93
+ element and the elements that shifted as verified locators.
94
+ - **Ambiguous locators.** When a locator suddenly matches two elements (strict mode
95
+ violation), `suggest-fix` takes the unique locator Playwright reports for the intended
96
+ match: the exact-name one, or the one you pick.
97
+ - **Pages behind a login, in any state.** Every page tool accepts a Playwright
98
+ `storageState`, extra headers, click/fill steps to reach a modal or a later step, and
99
+ network mocks to force error, empty and slow states.
80
100
 
81
101
  </details>
82
102
 
@@ -131,7 +151,7 @@ npx -y playwright-e2e-mcp init # --client all | cursor,vscode … ·
131
151
  | **Skill only, any agent** | `npx skills add xsignon-secure/E2E` |
132
152
  | **npm (canonical, fastest)** | `npx -y playwright-e2e-mcp` |
133
153
  | **MCP Registry** (registry-aware clients discover it automatically) | `io.github.xsignon-secure/E2E` — [listing](https://registry.modelcontextprotocol.io/) |
134
- | **Any client, no npm account needed** | `npx -y github:xsignon-secure/E2E#v0.4.1` (pin a release tag) |
154
+ | **Any client, no npm account needed** | `npx -y github:xsignon-secure/E2E#v0.5.0` (pin a release tag) |
135
155
  | **Claude Desktop, zero Node setup** | double-click the [`.mcpb` extension](https://github.com/xsignon-secure/E2E/releases) |
136
156
  | **Remote-only clients (ChatGPT connectors)** | `https://playwright-e2e-mcp.vercel.app/api/mcp` |
137
157
 
@@ -143,7 +163,7 @@ code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","playwrigh
143
163
  ```
144
164
 
145
165
  Only need the fix loop? `--tools=core` (or `PW_MCP_TOOLS=core`) exposes six tools and
146
- halves the tool-definition context; see [Configuration](#configuration).
166
+ cuts the tool-definition context by about three quarters; see [Configuration](#configuration).
147
167
 
148
168
  Details and per-client config: [Installation](#installation) ·
149
169
  [MCP client configuration](#mcp-client-configuration).
@@ -157,30 +177,53 @@ Details and per-client config: [Installation](#installation) ·
157
177
  | `run-test` | Run Playwright tests and return stats, failures, diagnostics and hints; reports progress, and `background: true` returns a run id for long suites |
158
178
  | `get-run-status` | Progress or final result of a background run; can wait for it or cancel it |
159
179
  | `get-failure` | Deep analysis of one failure: stack, expected/actual, **DOM snapshot at failure (from the Playwright trace)**, failed requests, console errors, next steps |
160
- | `suggest-fix` | Patch a failure: a drifted locator is replaced with one **proven unique** on the DOM at failure, changed copy gets the new expected text; `apply: true` writes it, re-runs the test and reverts if still red |
161
- | `inspect-page` | Open a URL headlessly (optionally signed in, after steps) and return elements with **verified Playwright locators**, CSS selectors, visibility, text and console output |
180
+ | `load-report` | Load a run from CI: a JSON report or a folder of sharded blob reports; CI paths are mapped onto the checkout and traces found in the unpacked artifact, so `get-failure`, `suggest-fix` and `diagnose-flaky` work on it, and the run joins the history with its commit |
181
+ | `suggest-fix` | Patch a failure: a drifted locator is replaced with one **proven unique** on the DOM at failure, an ambiguous one (strict mode violation) gets the unique locator of the intended match, changed copy gets the new expected text; `apply: true` writes it, re-runs the test and reverts if still red |
182
+ | `inspect-page` | Open a URL headlessly (optionally signed in, after steps) and return elements with **verified Playwright locators**, CSS selectors, visibility, text and console output, or the **accessibility snapshot with a ready `toMatchAriaSnapshot` assertion** |
162
183
  | `list-tests` | List available tests (`file`, `line`, full title, projects) with filtering |
163
184
  | `validate-selector` | Check a CSS selector, Playwright selector or **locator expression** against a live page: validity, match count, and a sturdier verified locator for each match |
164
- | `generate-e2e-test` | Scaffold a Playwright test from a description using the project's **real** selectors and verified locators from the live page |
185
+ | `generate-e2e-test` | Scaffold a Playwright test from a description using the project's **real** selectors and verified locators from the live page, or **walk a flow** step by step on the live page and write a spec that is run once to prove it passes |
165
186
  | `compare-visual-state` | Visual regression: screenshot before/after a change and report *what* moved and how colors shifted |
166
187
  | `audit-accessibility` | Run axe-core (WCAG 2.2 AA by default) on a page, signed in or after steps, and return violations worst first with **verified locators** for the offending elements and a regression check |
188
+ | `audit-performance` | Measure lab **Web Vitals** (LCP, CLS, TBT, FCP, TTFB, INP during steps), optionally as a throttled phone and the median of several runs; rate them or check budgets, name the LCP and shifting elements as verified locators, list heavy and render-blocking requests, and return a budget test |
167
189
  | `diagnose-flaky` | Run a failing test 2–10 times **with retries disabled** and return an evidence verdict: `CONSISTENTLY FAILING`, `FLAKY` or `NOT REPRODUCING`; tells parallelism and **test-order** bugs from races |
168
- | `analyze-history` | Rank flaky, regressed and broken tests from the local run history, group failures by cause, or show one test's timeline |
190
+ | `analyze-history` | Rank flaky, regressed and broken tests from the local run history, group failures by cause, list the slowest tests, show stability by day, name **the commit where each test went bad**, or show one test's timeline |
169
191
 
170
192
  Two **prompts** package the main workflows for clients that show them as slash commands:
171
193
  `fix-failing-test` (optional `test`) and `triage-flaky-tests`.
172
194
 
173
195
  ### Page state: signed-in pages, headers and steps
174
196
 
175
- `inspect-page`, `validate-selector` and `compare-visual-state` accept the same page-state
176
- arguments (`suggest-fix` accepts `storageState` and `headers` for a live `url`):
197
+ `inspect-page`, `validate-selector`, `compare-visual-state`, `audit-accessibility` and
198
+ `audit-performance` accept the same page-state arguments (`suggest-fix` accepts
199
+ `storageState` and `headers` for a live `url`):
177
200
 
178
201
  | Argument | Type | Description |
179
202
  | --- | --- | --- |
180
203
  | `storageState` | string | Path inside the project to a Playwright storageState JSON (cookies + localStorage), e.g. `playwright/.auth/user.json` from your setup project. Defaults to `PW_MCP_STORAGE_STATE` |
181
204
  | `headers` | object | Extra HTTP headers for every request, e.g. `{ "Authorization": "Bearer …" }` |
182
205
  | `actions` | array | Up to 20 steps run after load: `{ "type": "click" \| "dblclick" \| "hover" \| "fill" \| "press" \| "check" \| "uncheck" \| "select" \| "wait" \| "goto", "locator"?, "value"?, "url"?, "ms"? }`. Locators use Playwright syntax, e.g. `getByRole('button', { name: 'Open settings' })` |
206
+ | `routes` | array | Up to 20 network mocks applied before the page loads, first match wins: `{ "url": "**/api/cart", "method"?, "status"?, "json"? \| "body"?, "contentType"?, "headers"?, "abort"?, "delayMs"? }`. `json`, `body` or `status` fulfils the request, `abort: true` fails it, and `delayMs` alone slows the real request |
183
207
  | `viewport` | object | `{ "width": 390, "height": 844 }` (default 1280×720) |
208
+ | `har` | object | `{ "path": "tests/fixtures/cart.har", "mode"?: "replay" \| "record", "url"?: "**/api/**", "notFound"?: "abort" \| "fallback" }`. `replay` (default) answers matching requests from the file, `record` saves the page's traffic to it. The file and its folder must be inside the project. `routes` mocks still win over the HAR |
209
+ | `browser` | `chromium` \| `firefox` \| `webkit` | Browser engine (default `chromium`; the engine must be installed with `npx playwright install`). `audit-performance` is Chromium-only, and WebKit is refused while private addresses are blocked |
210
+
211
+ Mocks make states that are hard to reach easy to inspect, audit or measure: the error
212
+ banner after a 500, the empty list, the spinner of a slow API, the page without a
213
+ third-party script. The response says how many requests each mock handled and flags a mock
214
+ that matched nothing, which usually means a wrong glob:
215
+
216
+ ```json
217
+ "routes": [
218
+ { "url": "**/api/cart", "json": { "items": [] } },
219
+ { "url": "**/api/checkout", "method": "POST", "status": 500, "body": "boom" },
220
+ { "url": "**/googletagmanager.com/**", "abort": true }
221
+ ]
222
+ ```
223
+
224
+ A HAR makes a page repeatable: record it once against a working backend
225
+ (`"mode": "record"`), then replay it so the page renders the same data offline or in CI.
226
+ The same file works in a spec with `page.routeFromHAR()`.
184
227
 
185
228
  A failing step reports which one failed and how many ran. When the page lands on a login
186
229
  screen, the response says so and suggests `storageState`.
@@ -256,7 +299,7 @@ numbered next steps (re-run this single test by `file:line`, headed/debug mode,
256
299
  | Argument | Type | Description |
257
300
  | --- | --- | --- |
258
301
  | `url` | string | Full http(s) URL to open (required) |
259
- | `view` | `elements` \| `locators` | `locators` returns a compact map of interactive elements with verified locators (cheapest); `elements` (default) the DOM inventory |
302
+ | `view` | `elements` \| `locators` \| `aria` | `locators` returns a compact map of interactive elements with verified locators (cheapest); `aria` the accessibility snapshot of the page (or of `selector`) with a ready `toMatchAriaSnapshot` assertion; `elements` (default) the DOM inventory |
260
303
  | `projectRoot` | string | Project whose Playwright launches the browser |
261
304
  | `selector` | string | Inspect matches of this selector instead of the whole DOM |
262
305
  | `waitFor` | string | Wait for a selector (CSS or `text=…`) before inspecting |
@@ -264,7 +307,7 @@ numbered next steps (re-run this single test by `file:line`, headed/debug mode,
264
307
  | `includeHtml` | boolean | Include the rendered HTML (capped) |
265
308
  | `maxHtmlChars` | number | HTML cap, default `20000` |
266
309
  | `timeoutMs` | number | Overall limit, default `45000` |
267
- | `storageState` / `headers` / `actions` / `viewport` | — | [Page state](#page-state-signed-in-pages-headers-and-steps) |
310
+ | `storageState` / `headers` / `actions` / `routes` / `har` / `browser` / `viewport` | — | [Page state](#page-state-signed-in-pages-headers-and-steps) |
268
311
 
269
312
  Each element comes with Playwright locators that were **checked on the page** to resolve to
270
313
  exactly that element, best first (role + accessible name, test id, label, placeholder, text,
@@ -276,6 +319,16 @@ captured, errors first. A locator map looks like:
276
319
  2. `getByLabel('Search')` — searchbox "Search"
277
320
  ```
278
321
 
322
+ `view: "aria"` returns the page's structure as Playwright sees it, and the assertion that
323
+ locks it in a test:
324
+
325
+ ```ts
326
+ await expect(page.locator("#cart")).toMatchAriaSnapshot(`
327
+ - list:
328
+ - listitem: Real item
329
+ `);
330
+ ```
331
+
279
332
  ### `list-tests`
280
333
 
281
334
  | Argument | Type | Description |
@@ -318,9 +371,35 @@ advice, or `❌ INVALID` with the parse error.
318
371
  | `write` | boolean | Write the file to disk (default `true`) |
319
372
  | `overwrite` | boolean | Replace an existing spec at the target path; only specs this tool generated can be replaced |
320
373
  | `liveInspect` | boolean | Cross-check selectors against the live page (default on when a URL is known) |
374
+ | `steps` | array | **Walk the flow**: up to 30 steps in the [`actions`](#page-state-signed-in-pages-headers-and-steps) format, run on the live page before anything is written |
375
+ | `assertScope` | string | With `steps`: CSS scope of the end-state accessibility snapshot (default `body`) |
376
+ | `storageState` | string | With `steps`: signed-in session for the walk; the spec uses it too (`test.use`) |
377
+ | `verify` / `project` / `timeoutMs` | — | With `steps`: run the written spec once (default `true`), in this Playwright project |
321
378
  | `projectRoot` / `config` | string | As with the other tools |
322
379
 
323
- Reads the agent's recent changes (`git status`, falling back to `git diff HEAD~1`,
380
+ **With `steps`**, the tool walks the flow on the live page first. If a step's locator does
381
+ not work, it stops there, writes nothing and says which step failed. Otherwise it writes a
382
+ spec that replays the steps, asserts the URL path and the accessibility snapshot where the
383
+ flow landed (headings only when the snapshot is long), and runs it once:
384
+
385
+ ```ts
386
+ test('rename in settings', async ({ page }) => {
387
+ await page.goto('http://localhost:3000/account');
388
+ await page.getByRole('button', { name: 'Open settings' }).click();
389
+ await page.getByLabel('Nickname').fill('Ada');
390
+
391
+ // End state
392
+ await expect(page.locator("dialog")).toMatchAriaSnapshot(`
393
+ - dialog:
394
+ - heading "Settings" [level=2]
395
+ - text: Nickname
396
+ - textbox "Nickname": Ada
397
+ - button "Save settings"
398
+ `);
399
+ });
400
+ ```
401
+
402
+ **Without `steps`**, it reads the agent's recent changes (`git status`, falling back to `git diff HEAD~1`,
324
403
  then recent mtimes), extracts the locators those files actually declare
325
404
  (`data-testid`, `getByRole`, `aria-label`, `placeholder`, `id`, `name`, element text),
326
405
  ranks verified-live selectors first, writes a spec built from them, and reports each
@@ -433,6 +512,47 @@ Example output:
433
512
 
434
513
  It ends with an `@axe-core/playwright` check for the spec, so the page stays fixed.
435
514
 
515
+ ### `audit-performance`
516
+
517
+ | Argument | Type | Description |
518
+ | --- | --- | --- |
519
+ | `url` | string | Page to measure (required) |
520
+ | `throttle` | `none` \| `mobile` | `mobile` is Lighthouse's phone preset: 412×823 touch viewport, 4x CPU slowdown, slow 4G. Default `none` (desktop, unthrottled) |
521
+ | `cpuSlowdown` | number | Override the CPU slowdown factor (1–20) |
522
+ | `runs` | number | Load the page 1–5 times and report the median (default `1`); the LCP range is shown |
523
+ | `budgets` | object | `{ lcpMs, cls, inpMs, tbtMs, fcpMs, ttfbMs, transferKb, requests }`, any subset. With budgets the verdict is pass/fail; without, metrics are rated against Google's thresholds |
524
+ | `settleMs` | number | Keep observing after load for late images and shifts (default `1500`) |
525
+ | `waitFor` / `waitUntil` / `timeoutMs` | — | As with `inspect-page` (`waitUntil` default `load`, `timeoutMs` per run, default `60000`) |
526
+ | `storageState` / `headers` / `actions` / `routes` / `viewport` | — | [Page state](#page-state-signed-in-pages-headers-and-steps). Clicks and key presses in `actions` are measured as interactions (INP) |
527
+
528
+ The metrics come from the browser's own performance entries (the same ones Lighthouse and
529
+ the `web-vitals` library read) and the bytes from the DevTools protocol, so cross-origin
530
+ sizes count too. Example output:
531
+
532
+ ```
533
+ ## ⚡ 3 of 6 metrics need work (CLS, INP, TBT)
534
+
535
+ | Metric | Value | Rating |
536
+ | --- | --- | --- |
537
+ | LCP · largest contentful paint | 412 ms | 🟢 good |
538
+ | CLS · cumulative layout shift | 0.109 | 🟠 needs improvement |
539
+ | INP · slowest interaction (lab) | 360 ms | 🟠 needs improvement |
540
+ | TBT · total blocking time | 306 ms | 🟠 needs improvement |
541
+
542
+ ### What to fix
543
+ - **CLS 0.109**: these moved: `getByRole('img', { name: 'Summer sale' })`, `getByRole('button', { name: 'Add to cart' })`. Reserve their space (…)
544
+ - **TBT 306 ms** from 2 long task(s), the longest 404 ms: split or defer JavaScript.
545
+ - **INP 360 ms** on pointerdown on button: the handler blocks the next paint; yield (…)
546
+
547
+ ### Network
548
+ **Transfer:** 302 kB in 4 requests · DOM: 13 nodes · JS heap: 10.0 MB
549
+ **Render-blocking:**
550
+ - stylesheet `http://localhost:4173/style.css` · 324 ms
551
+ ```
552
+
553
+ It ends with a Playwright test that asserts LCP and CLS stay within budget. These are lab
554
+ numbers from one headless Chromium; field data (CrUX, RUM) can differ.
555
+
436
556
  ### `suggest-fix`
437
557
 
438
558
  | Argument | Type | Description |
@@ -441,12 +561,18 @@ It ends with an `@axe-core/playwright` check for the spec, so the page stays fix
441
561
  | `apply` | boolean | Write the fix into the spec (default `false`: return the diff only) |
442
562
  | `verify` | boolean | After applying, re-run the test and revert the file if it still fails (default `true`) |
443
563
  | `allowExpectationUpdate` | boolean | Allow applying a changed expected text/value (default `false`, since it can hide a real regression) |
564
+ | `candidate` | number | For a strict mode violation, which of the listed matches the test meant (1-based) |
444
565
  | `url` | string | Heal against this live page instead of the DOM snapshot in the failure trace |
445
566
  | `storageState` / `headers` | — | For `url`, as in [Page state](#page-state-signed-in-pages-headers-and-steps) |
446
567
  | `config` / `timeoutMs` / `projectRoot` | — | As with `run-test` |
447
568
 
448
- Two kinds of fix:
569
+ Three kinds of fix:
449
570
 
571
+ - **Ambiguous locator.** A strict mode violation ("resolved to 2 elements") lists each match
572
+ with the unique locator Playwright computed for it. When the broken locator matched by
573
+ substring (`name: 'Save'` hitting *Save* and *Save draft*), the exact-name match is picked
574
+ with `high` confidence. When the matches are equal (the same *Home* link in the header and
575
+ the footer), they are listed and you choose with `candidate`.
450
576
  - **Locator drift.** The broken locator is read from the error, its words are matched
451
577
  (with synonyms such as *btn → button*, *checkout → proceed to checkout*) against every
452
578
  element in the DOM at failure, and the best match's verified-unique locator replaces it.
@@ -476,17 +602,38 @@ the full `run-test` result, which also becomes the last run for `get-failure` an
476
602
 
477
603
  | Argument | Type | Description |
478
604
  | --- | --- | --- |
479
- | `view` | `flaky` \| `patterns` \| `test` | `flaky` (default) ranks unstable tests; `patterns` groups failures by kind and normalized error; `test` shows one test's timeline |
605
+ | `view` | `flaky` \| `patterns` \| `slow` \| `trend` \| `commits` \| `test` | `flaky` (default) ranks unstable tests; `patterns` groups failures by kind and normalized error; `slow` lists tests by median duration and flags ones that got slower; `trend` shows failed and flaky executions per day; `commits` names the first bad commit of each failing or flaky test; `test` shows one test's timeline |
480
606
  | `test` | string | Substring of a test's file or title (filters every view) |
481
607
  | `lastRuns` | number | How many recent runs to analyze (default `30`) |
482
608
  | `limit` | number | Max rows (default `15`) |
483
609
 
484
- Every `run-test`, `diagnose-flaky` and `suggest-fix` run appends a line to
610
+ Every `run-test`, `diagnose-flaky`, `suggest-fix` and `load-report` run appends a line to
485
611
  `<project>/.playwright-e2e-mcp/history.jsonl` (the folder carries its own `.gitignore`;
486
612
  nothing leaves the machine; `PW_MCP_HISTORY=0` turns it off). The flaky view separates
487
613
  tests that flip between pass and fail, tests that started failing and stayed red
488
614
  (regressed), and tests that failed every run (broken), each with a `PFFP~` timeline.
489
615
 
616
+ Each run records the commit it tested (from git locally, from the report's metadata for CI
617
+ runs). The `commits` view uses that to say where a test went bad: the first failing or flaky
618
+ run after its last streak of passes, with the last good commit and a `git diff` to compare
619
+ them.
620
+
621
+ ### `load-report`
622
+
623
+ | Argument | Type | Description |
624
+ | --- | --- | --- |
625
+ | `report` | string | A Playwright JSON report inside the project (e.g. `ci-artifacts/results.json`), or a folder of blob-report zips from sharded jobs (merged with the project's `playwright merge-reports`) (required) |
626
+ | `traceDirs` | string[] | Folders inside the project where the job's `test-results` artifact was unpacked (default: the report's folder and its parent) |
627
+ | `commit` / `branch` | string | Override what the report's metadata says (Playwright records it with `captureGitInfo` or on CI) |
628
+ | `record` | boolean | Add the run to the history (default `true`) |
629
+ | `timeoutMs` | number | Limit for merging blob reports (default `120000`) |
630
+
631
+ Download the artifacts first, for example with
632
+ `gh run download <run-id> -n playwright-report -D ci-artifacts`. The CI machine's absolute
633
+ paths are mapped onto your checkout, so failures point at local files and get-failure can
634
+ open each trace. The run becomes the last run, so the usual loop works on it: `get-failure`,
635
+ then `suggest-fix` (which re-runs the fix locally), or `diagnose-flaky`.
636
+
490
637
  ---
491
638
 
492
639
  ## Installation
@@ -502,8 +649,8 @@ builds `dist/` automatically on install). Pin a release tag: an unpinned
502
649
  `github:xsignon-secure/E2E` runs whatever is on the default branch at that moment.
503
650
 
504
651
  ```bash
505
- npx -y github:xsignon-secure/E2E#v0.4.1
506
- npm install -D github:xsignon-secure/E2E#v0.4.1 @playwright/test # or as a project dependency
652
+ npx -y github:xsignon-secure/E2E#v0.5.0
653
+ npm install -D github:xsignon-secure/E2E#v0.5.0 @playwright/test # or as a project dependency
507
654
  npx playwright install chromium
508
655
  ```
509
656
 
@@ -511,7 +658,7 @@ Or grab the packaged tarball from the repo's **GitHub Releases** page and instal
511
658
  it locally:
512
659
 
513
660
  ```bash
514
- npm install -D https://github.com/xsignon-secure/E2E/releases/download/v0.4.1/playwright-e2e-mcp-0.4.1.tgz
661
+ npm install -D https://github.com/xsignon-secure/E2E/releases/download/v0.5.0/playwright-e2e-mcp-0.5.0.tgz
515
662
  ```
516
663
 
517
664
  Listed in the **official [MCP Registry](https://registry.modelcontextprotocol.io/)** as
@@ -527,22 +674,24 @@ Listed in the **official [MCP Registry](https://registry.modelcontextprotocol.io
527
674
  "mcpServers": {
528
675
  "playwright-e2e": {
529
676
  "command": "npx",
530
- "args": ["-y", "github:xsignon-secure/E2E#v0.4.1"],
677
+ "args": ["-y", "github:xsignon-secure/E2E#v0.5.0"],
531
678
  "env": { "PW_MCP_PROJECT_ROOT": "/absolute/path/to/your/project" }
532
679
  }
533
680
  }
534
681
  }
535
682
  ```
536
683
 
537
- **Claude Desktop / Cursor / Windsurf:** add the same block to their MCP config file.
684
+ **Claude Desktop / Cursor / Windsurf / Cline:** add the same block to their MCP config file
685
+ (Cline: *MCP Servers → Configure*). **Zed** and other clients that take a command: run `npx`
686
+ with the arguments `-y playwright-e2e-mcp`.
538
687
  The server uses its working directory as the project root; set `PW_MCP_PROJECT_ROOT`
539
688
  when the client launches it somewhere else (e.g. your home directory).
540
689
 
541
690
  **Codex / VS Code / Copilot CLIs:**
542
691
 
543
692
  ```bash
544
- codex mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.4.1
545
- code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:xsignon-secure/E2E#v0.4.1"]}'
693
+ codex mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.5.0
694
+ code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:xsignon-secure/E2E#v0.5.0"]}'
546
695
  ```
547
696
 
548
697
  Codex's defaults fight this server: the first launch clones the repo and runs
@@ -553,7 +702,7 @@ Codex's defaults fight this server: the first launch clones the repo and runs
553
702
  ```toml
554
703
  [mcp_servers.playwright-e2e]
555
704
  command = "npx"
556
- args = ["-y", "github:xsignon-secure/E2E#v0.4.1"]
705
+ args = ["-y", "github:xsignon-secure/E2E#v0.5.0"]
557
706
  startup_timeout_sec = 60
558
707
  tool_timeout_sec = 600
559
708
  ```
@@ -568,7 +717,7 @@ into `PW_MCP_PROJECT_ROOT`, so the tools point at a real project from the first
568
717
  **Claude Code:**
569
718
 
570
719
  ```bash
571
- claude mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.4.1
720
+ claude mcp add playwright-e2e -- npx -y github:xsignon-secure/E2E#v0.5.0
572
721
  ```
573
722
 
574
723
  **Gemini CLI / Qwen Code:** paste the `mcpServers` block above into
@@ -609,7 +758,7 @@ Streamable HTTP bridge for exactly that case:
609
758
  | --- | --- |
610
759
  | **Endpoint** | `https://playwright-e2e-mcp.vercel.app/api/mcp` |
611
760
  | **Transport** | MCP Streamable HTTP (`POST` JSON in, JSON or SSE out) |
612
- | **Auth** | bearer token (`PW_MCP_HTTP_TOKEN`). The deployment at this URL requires it; a bridge started without the variable serves only the read-only tools |
761
+ | **Auth** | bearer token (`PW_MCP_HTTP_TOKEN`), or OAuth sign-in with that token as the access key (for claude.ai connectors). The deployment at this URL requires one of them; a bridge started without the variable serves only the read-only tools |
613
762
  | **Source** | [`api/mcp.ts`](api/mcp.ts) → [`src/http.ts`](src/http.ts) |
614
763
 
615
764
  The bridge runs the *same* `createServer()` as the stdio transport; the SDK
@@ -617,11 +766,16 @@ serves every request with a fresh server instance, which is what a serverless
617
766
  function wants. `test/http-bridge.test.mjs` drives the real Node adapter over
618
767
  `node:http` so a broken bridge fails in CI, not in ChatGPT.
619
768
 
620
- **This deployment is token-protected.** `https://playwright-e2e-mcp.vercel.app`
621
- has `PW_MCP_HTTP_TOKEN` set, so a request without `Authorization: Bearer <token>`
622
- — including a ChatGPT connector created with authentication *None* — gets
623
- `401 {"error":"unauthorized"}`. Ask the operator for the token, or run your own
624
- bridge (below).
769
+ **This demo deployment is token-protected.** `https://playwright-e2e-mcp.vercel.app`
770
+ runs on the maintainer's account and has `PW_MCP_HTTP_TOKEN` set, so a request
771
+ without `Authorization: Bearer <token>` (or an OAuth sign-in with it) gets
772
+ `401 {"error":"unauthorized"}`. Nothing is held back: the same bridge is free to
773
+ host yourself on a free Vercel account, with your own token:
774
+
775
+ [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fxsignon-secure%2FE2E&env=PW_MCP_HTTP_TOKEN&envDescription=A%20random%20secret%20of%2016%2B%20characters%3B%20clients%20send%20it%20as%20a%20bearer%20token%20or%20type%20it%20to%20sign%20in&project-name=playwright-e2e-mcp)
776
+
777
+ A serverless function has no browser, so for running and fixing your own tests
778
+ the free local install (`npx -y playwright-e2e-mcp init`) is the better route.
625
779
 
626
780
  **Open vs. token-protected.** With `PW_MCP_HTTP_TOKEN` set (at least 16
627
781
  characters; use a random value) every tool is served to clients that send
@@ -643,6 +797,20 @@ deployment choose the connector's **API key** authentication and send
643
797
  `Authorization: Bearer <token>` — or point the connector at your own deployment
644
798
  with `PW_MCP_HTTP_TOKEN` unset.
645
799
 
800
+ **Add it to claude.ai (or Claude Desktop's connectors):** Settings → Connectors →
801
+ *Add custom connector* → paste the endpoint above and leave the OAuth fields
802
+ empty. Claude registers itself and opens a sign-in page; type the deployment's
803
+ access key (the value of `PW_MCP_HTTP_TOKEN`) and press **Allow access**. The
804
+ bridge is its own small OAuth 2.1 server (discovery, dynamic client
805
+ registration, authorization code with PKCE S256, refresh tokens) and keeps no
806
+ state: client ids, codes and tokens are signed with a key derived from
807
+ `PW_MCP_HTTP_TOKEN`, access tokens last an hour and refresh tokens 30 days, and
808
+ changing `PW_MCP_HTTP_TOKEN` signs every connected client out. The sign-in page
809
+ shows which site will receive access, so only type the key when that is the
810
+ app you are connecting. Source: [`src/oauth.ts`](src/oauth.ts); the
811
+ `/.well-known/oauth-*` and `/oauth/*` paths reach the function through the
812
+ rewrites in [`vercel.json`](vercel.json).
813
+
646
814
  To self-host the open, read-only variant, deploy this repo with
647
815
  `PW_MCP_HTTP_TOKEN` unset; nothing else changes.
648
816
 
@@ -659,9 +827,10 @@ codex mcp add playwright-e2e-remote --url https://playwright-e2e-mcp.vercel.app/
659
827
  **What to expect:** `list-tests` works and reports the specs bundled with the
660
828
  deployment. Even with a token, tools that spawn a browser (`run-test`,
661
829
  `inspect-page`, `validate-selector`, `diagnose-flaky`, …) cannot download
662
- Chromium in a serverless function, so they return their normal `NO_PLAYWRIGHT`
663
- hint. Use the stdio install for real runs; the hosted endpoint is for discovery
664
- and for clients that cannot run local processes.
830
+ Chromium in a serverless function, so they return `NO_PLAYWRIGHT` with a note
831
+ that points to the local install. Use the stdio install for real runs; the
832
+ hosted endpoint is for discovery and for clients that cannot run local
833
+ processes.
665
834
 
666
835
  ```bash
667
836
  # verify the handshake without any client (the live deployment needs the token;
@@ -703,7 +872,7 @@ steps:
703
872
  - uses: actions/setup-node@v6
704
873
  with: { node-version: 24 }
705
874
  - run: npm ci && npx playwright install --with-deps chromium
706
- - uses: xsignon-secure/E2E@v0.4.1
875
+ - uses: xsignon-secure/E2E@v0.5.0
707
876
  with:
708
877
  flaky-runs: 3 # 0 skips the flaky verdict
709
878
  suggest: 2 # suggest-fix diffs for the first 2 failures
@@ -730,7 +899,7 @@ browsers match Playwright 1.63. Mount your project at `/work`; its own
730
899
  | Environment variable | Default | Purpose |
731
900
  | --- | --- | --- |
732
901
  | `PW_MCP_PROJECT_ROOT` | server cwd | Default project root for every tool |
733
- | `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, accessibility, visual), `author` (list, page, selector, generate, run). All twelve tool definitions cost about 5.5k tokens of context per request; `core` costs about 2.2k |
902
+ | `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, CI report, flaky, history, list), `inspect` (page, selector, accessibility, performance, visual), `author` (list, page, selector, generate, run). All fourteen tool definitions cost about 9k tokens of context per request; `core` costs about 2.3k |
734
903
  | `PW_MCP_STORAGE_STATE` | — | Default `storageState` file (inside the project) for the page tools |
735
904
  | `PW_MCP_SHUFFLE_SEEDS` | random | Comma-separated seeds for `diagnose-flaky`'s `order` pass, to replay the orders a diagnosis reported |
736
905
  | `PW_MCP_HISTORY` | on | `0` stops recording runs to `.playwright-e2e-mcp/history.jsonl` |
@@ -848,7 +1017,7 @@ picks the right locator from the snapshot on the first try, which the server doe
848
1017
  src/
849
1018
  ├── index.ts # bin entry point (--version/--help, main-module guard)
850
1019
  ├── server.ts # McpServer setup, tool registration, shutdown handling
851
- ├── tools/ # the twelve tools, the probe script + shared plumbing
1020
+ ├── tools/ # the fourteen tools, the probe script + shared plumbing
852
1021
  ├── prompts.ts # fix-failing-test, triage-flaky-tests
853
1022
  ├── utils/ # playwright-runner, report-parser, project-detector, path-utils,
854
1023
  │ # logger, trace-reader (trace.zip → DOM/network/console),
@@ -897,10 +1066,13 @@ server over stdio against a live fixture app and a Playwright project under
897
1066
  `e2e/fixture/`, then drives it exactly like an MCP client and asserts ~40 behaviours
898
1067
  that only appear end-to-end:
899
1068
 
900
- - initialize handshake, 12 tools, 2 prompts, spec tool annotations and object input schemas,
1069
+ - initialize handshake, 14 tools, 2 prompts, spec tool annotations and object input schemas,
901
1070
  - verified locators, locator validation, signed-in pages (`storageState`) and page steps,
902
1071
  - background runs with progress, run history views, and `suggest-fix` healing a drifted
903
- locator and verifying it with a re-run (and refusing when the element is missing),
1072
+ locator and an ambiguous one, verifying each with a re-run (and refusing when the
1073
+ element is missing),
1074
+ - Web Vitals with budgets and phone throttling, and network mocks that force error and
1075
+ empty states,
904
1076
  - live DOM inspection, CSS selector validation (matches, zero matches, engine
905
1077
  syntax, parse errors), dead-server detection,
906
1078
  - visual regression: baseline → unchanged compare → `blue → red` diff detection,
@@ -1001,8 +1173,8 @@ job requests for itself; if it is refused, the run names the setting to change.
1001
1173
  ### Verifying a published release
1002
1174
 
1003
1175
  ```bash
1004
- git checkout v0.4.1 && npm ci && npm run mcpb
1005
- npm run release:verify -- v0.4.1
1176
+ git checkout v0.5.0 && npm ci && npm run mcpb
1177
+ npm run release:verify -- v0.5.0
1006
1178
  ```
1007
1179
 
1008
1180
  The release notes promise that the tag rebuilds the published bundle byte for
package/dist/cli/init.js CHANGED
@@ -42,7 +42,7 @@ export function parseInitArgs(argv, cwd = process.cwd()) {
42
42
  args: argv,
43
43
  strict: true,
44
44
  options: {
45
- client: { type: 'string' },
45
+ client: { type: 'string', multiple: true },
46
46
  'project-root': { type: 'string' },
47
47
  tools: { type: 'string' },
48
48
  'no-skill': { type: 'boolean' },
@@ -51,7 +51,8 @@ export function parseInitArgs(argv, cwd = process.cwd()) {
51
51
  });
52
52
  let clients;
53
53
  if (values.client !== undefined) {
54
- const names = values.client.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
54
+ // `--client gemini --client codex` and `--client gemini,codex` mean the same.
55
+ const names = values.client.join(',').split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
55
56
  if (names.includes('all'))
56
57
  clients = [...CLIENTS];
57
58
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;AAG9F,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,0CAA0C;IAC1C,EAAE;IACF,gFAAgF;IAChF,+DAA+D;IAC/D,EAAE;IACF,kFAAkF;IAClF,qFAAqF;IACrF,4EAA4E;IAC5E,2DAA2D;IAC3D,mFAAmF;IACnF,yDAAyD;IACzD,kEAAkE;IAClE,EAAE;IACF,qEAAqE;IACrE,oFAAoF;IACpF,8EAA8E;IAC9E,uEAAuE;IACvE,0CAA0C;IAC1C,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAUb,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAC3B,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE;YACP,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC1C,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAClC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;YAC/B,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;SAC/B;KACF,CAAC,CAAC;IACH,IAAI,OAA6B,CAAC;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,8EAA8E;QAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpG,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;aAC7C,CAAC;YACJ,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAE,OAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACjF,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC;YAC/G,CAAC;YACD,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAa,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC;QAC7D,OAAO;QACP,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjF,IAAI,GAAG,CAAC,SAAS,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,GAAG,CAAC,SAAS,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAI,GAAG,CAAC,QAAQ,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB,EAAE,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AACjG,CAAC;AAUD,gFAAgF;AAChF,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAW,EAAE,KAA8B,EAAE,MAAc;IACzF,IAAI,IAAI,GAA4B,EAAE,CAAC;IACvC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBACzG,IAAI,GAAG,MAAiC,CAAC;YAC3C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAoB,GAAa,CAAC,OAAO,mBAAmB,EAAE,CAAC;YAChH,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,OAAO,GACX,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,GAAI,OAAmC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvH,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;IAC7B,IAAI,OAAO,IAAI,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC9F,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACvI,CAAC;AAED,sEAAsE;AACtE,SAAS,SAAS,CAAC,IAAY,EAAE,IAAc;IAC7C,MAAM,KAAK,GAAG,gBAAgB,WAAW,GAAG,CAAC;IAC7C,MAAM,KAAK,GAAG,GAAG,KAAK,8BAA8B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACvG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1F,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC/E,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/F,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,EAAE,EAAE,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAoB,EAAE,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;IACjC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACvC,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;gBACxG,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC5F,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC/G,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjG,MAAM;YACR,KAAK,OAAO;gBACV,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBACxE,MAAM;YACR,KAAK,UAAU;gBACb,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;gBAChH,MAAM;QACV,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/F,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,UAAU,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAwB,EAAE,WAAW,GAAG,eAAe,EAAE;IACjF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;YAAE,SAAS;QACzE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAc,EAAE,GAAG,GAA2B,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;IACzG,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,SAAU,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACzC,GAAG,CAAC,UAAU,CAAC,CAAC;QAChB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,0EAA0E,CAAC,CAAC;QAChF,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO;gBAAE,CAAC,CAAC,MAAM,GAAG,WAAW,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClH,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/F,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACvD,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,gFAAgF,CAAC,CAAC;IACtF,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAClE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/dist/http.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * verified locally before it is deployed.
11
11
  *
12
12
  * The stdio transport in server.ts is untouched; this is an additional way to
13
- * reach the same twelve tools.
13
+ * reach the same fourteen tools.
14
14
  */
15
15
  import type { IncomingMessage, ServerResponse } from 'node:http';
16
16
  import type { McpHttpHandler } from '@modelcontextprotocol/server';
@@ -31,6 +31,11 @@ export interface McpHttpHandlerOptions {
31
31
  * deployment's own Vercel hostnames are accepted.
32
32
  */
33
33
  allowedHosts?: string[];
34
+ /**
35
+ * Path the MCP endpoint is served on, advertised as the OAuth protected
36
+ * resource. Defaults to `/api/mcp`, where the Vercel function lives.
37
+ */
38
+ mcpPath?: string;
34
39
  }
35
40
  /** Tokens shorter than this are refused: they can be guessed. */
36
41
  export declare const MIN_TOKEN_LENGTH = 16;
package/dist/http.js CHANGED
@@ -10,10 +10,11 @@
10
10
  * verified locally before it is deployed.
11
11
  *
12
12
  * The stdio transport in server.ts is untouched; this is an additional way to
13
- * reach the same twelve tools.
13
+ * reach the same fourteen tools.
14
14
  */
15
15
  import { createHash, timingSafeEqual } from 'node:crypto';
16
16
  import { createMcpHandler, hostHeaderValidationResponse } from '@modelcontextprotocol/server';
17
+ import { createOAuthServer } from './oauth.js';
17
18
  import { createServer, READ_ONLY_TOOLS } from './server.js';
18
19
  import { setMaxChildren, setScrubChildEnv } from './utils/playwright-runner.js';
19
20
  import { setBlockPrivateUrls } from './utils/url-policy.js';
@@ -74,6 +75,9 @@ export function createMcpHttpHandler(options = {}) {
74
75
  if (!token) {
75
76
  logger.warn('PW_MCP_HTTP_TOKEN is not set; serving read-only tools only', { tools: READ_ONLY_TOOLS });
76
77
  }
78
+ // With a token, OAuth clients (claude.ai connectors) sign in by typing it
79
+ // on the authorize page; without one the endpoint is open and needs none.
80
+ const oauth = token ? createOAuthServer({ token, mcpPath: options.mcpPath ?? '/api/mcp' }) : undefined;
77
81
  const inner = createMcpHandler((context) => createServer({
78
82
  ...(token ? {} : { tools: READ_ONLY_TOOLS, restricted: true }),
79
83
  // Lets tools stop their children when the HTTP client disconnects.
@@ -90,8 +94,14 @@ export function createMcpHttpHandler(options = {}) {
90
94
  if (rejected)
91
95
  return rejected;
92
96
  }
93
- if (token && !tokenMatches(request.headers.get('authorization'), token)) {
94
- return jsonResponse(401, { error: 'unauthorized' }, { 'www-authenticate': 'Bearer' });
97
+ if (oauth) {
98
+ const oauthResponse = await oauth.handle(request);
99
+ if (oauthResponse)
100
+ return oauthResponse;
101
+ const authorization = request.headers.get('authorization');
102
+ if (!tokenMatches(authorization, token) && !oauth.verifyAccessToken(authorization)) {
103
+ return jsonResponse(401, { error: 'unauthorized' }, { 'www-authenticate': oauth.challenge(request) });
104
+ }
95
105
  }
96
106
  return inner.fetch(request, requestOptions);
97
107
  },