mcp-accessibility-scanner 3.1.0 → 3.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.
Files changed (86) hide show
  1. package/README.md +42 -13
  2. package/index.d.ts +1 -1
  3. package/lib/browserContextFactory.js +548 -81
  4. package/lib/browserContextFactory.js.map +1 -1
  5. package/lib/browserServerBackend.js +192 -21
  6. package/lib/browserServerBackend.js.map +1 -1
  7. package/lib/browserSessions.js +174 -0
  8. package/lib/browserSessions.js.map +1 -0
  9. package/lib/config.js +52 -9
  10. package/lib/config.js.map +1 -1
  11. package/lib/context.js +143 -10
  12. package/lib/context.js.map +1 -1
  13. package/lib/extension/browserModel.js +166 -13
  14. package/lib/extension/browserModel.js.map +1 -1
  15. package/lib/extension/cdpRelay.js +53 -2
  16. package/lib/extension/cdpRelay.js.map +1 -1
  17. package/lib/extension/extensionContextFactory.js +9 -1
  18. package/lib/extension/extensionContextFactory.js.map +1 -1
  19. package/lib/index.js +5 -1
  20. package/lib/index.js.map +1 -1
  21. package/lib/mcp/http.js +195 -45
  22. package/lib/mcp/http.js.map +1 -1
  23. package/lib/mcp/inProcessTransport.js.map +1 -1
  24. package/lib/mcp/manualPromise.js +1 -0
  25. package/lib/mcp/manualPromise.js.map +1 -1
  26. package/lib/mcp/proxyBackend.js +75 -18
  27. package/lib/mcp/proxyBackend.js.map +1 -1
  28. package/lib/mcp/server.js +70 -41
  29. package/lib/mcp/server.js.map +1 -1
  30. package/lib/mcp/sharedClientSlot.js +134 -0
  31. package/lib/mcp/sharedClientSlot.js.map +1 -0
  32. package/lib/mcp/tool.js +4 -0
  33. package/lib/mcp/tool.js.map +1 -1
  34. package/lib/mcp/toolListChanged.js +1 -0
  35. package/lib/mcp/toolListChanged.js.map +1 -1
  36. package/lib/program.js +70 -9
  37. package/lib/program.js.map +1 -1
  38. package/lib/response.js +8 -0
  39. package/lib/response.js.map +1 -1
  40. package/lib/sessionLog.js +36 -6
  41. package/lib/sessionLog.js.map +1 -1
  42. package/lib/tab.js +37 -8
  43. package/lib/tab.js.map +1 -1
  44. package/lib/tools/auditKeyboard.js +4 -6
  45. package/lib/tools/auditKeyboard.js.map +1 -1
  46. package/lib/tools/auditScreenReader.js +4 -4
  47. package/lib/tools/auditScreenReader.js.map +1 -1
  48. package/lib/tools/auditSite.js +1 -4
  49. package/lib/tools/auditSite.js.map +1 -1
  50. package/lib/tools/axe.js +1 -0
  51. package/lib/tools/axe.js.map +1 -1
  52. package/lib/tools/dialogs.js +4 -6
  53. package/lib/tools/dialogs.js.map +1 -1
  54. package/lib/tools/evaluate.js +2 -0
  55. package/lib/tools/evaluate.js.map +1 -1
  56. package/lib/tools/network.js +13 -102
  57. package/lib/tools/network.js.map +1 -1
  58. package/lib/tools/pdf.js +5 -2
  59. package/lib/tools/pdf.js.map +1 -1
  60. package/lib/tools/scanPageMatrix.js +1 -4
  61. package/lib/tools/scanPageMatrix.js.map +1 -1
  62. package/lib/tools/screenshot.js +6 -2
  63. package/lib/tools/screenshot.js.map +1 -1
  64. package/lib/tools/session.js +53 -0
  65. package/lib/tools/session.js.map +1 -0
  66. package/lib/tools/snapshot.js +1 -4
  67. package/lib/tools/snapshot.js.map +1 -1
  68. package/lib/tools.js +7 -0
  69. package/lib/tools.js.map +1 -1
  70. package/lib/utils/dataUrl.js +1 -0
  71. package/lib/utils/dataUrl.js.map +1 -1
  72. package/lib/utils/fileUtils.js +35 -14
  73. package/lib/utils/fileUtils.js.map +1 -1
  74. package/lib/utils/guid.js +8 -0
  75. package/lib/utils/guid.js.map +1 -1
  76. package/lib/utils/jsSource.js +1 -1
  77. package/lib/utils/jsSource.js.map +1 -1
  78. package/lib/vscode/browserContextFactory.js +4 -0
  79. package/lib/vscode/browserContextFactory.js.map +1 -1
  80. package/lib/vscode/host.js +174 -32
  81. package/lib/vscode/host.js.map +1 -1
  82. package/lib/vscode/main.js +2 -2
  83. package/lib/vscode/main.js.map +1 -1
  84. package/package.json +21 -20
  85. package/lib/mcp/mdb.js +0 -200
  86. package/lib/mcp/mdb.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
 
2
2
  # MCP Accessibility Scanner 🔍
3
3
 
4
+ [![MCP Toplist](https://mcptoplist.com/badge/io.github.JustasMonkev%2Fmcp-accessibility-scanner.svg)](https://mcptoplist.com/server/io.github.JustasMonkev%2Fmcp-accessibility-scanner)
5
+
4
6
  ## Star History
5
7
  [![Star History Chart](https://api.star-history.com/svg?repos=justasmonkev%2Fmcp-accessibility-scanner&type=Date)](https://api.star-history.com/svg?repos=justasmonkev%2Fmcp-accessibility-scanner&type=Date)
6
8
 
@@ -224,6 +226,7 @@ Create a `config.json` file with the following options:
224
226
  - `timeouts.settle`: How long to wait after every action before responding (default: `500`). An action that finishes quietly is first watched for up to 100ms (or the settle delay, whichever is shorter) so scheduled network work can still be awaited before the settle delay.
225
227
  - `network.allowedOrigins`: List of origins to allow (blocks all others if specified)
226
228
  - `network.blockedOrigins`: List of origins to block
229
+ - `outputDir`: Directory for output files — reports, screenshots, traces, and session logs (CLI: `--output-dir`, env: `PLAYWRIGHT_MCP_OUTPUT_DIR`). Defaults to a fresh directory under the system temp folder, resolved once per server run so all of a run's artifacts land together. The output location is always server configuration; the deprecated MCP roots capability (client workspace folders) is no longer consulted.
227
230
 
228
231
  CLI equivalents are also available: `--cdp-launch-command`, `--cdp-launch-args`, `--cdp-launch-cwd`, `--cdp-launch-port`, `--cdp-launch-startup-timeout`, `--cdp-endpoint`, `--cdp-header` (repeat for multiple headers, e.g. `--cdp-header "Authorization: Bearer <token>"`), and `--cdp-timeout`. The CDP headers and timeout can also be set via the `PLAYWRIGHT_MCP_CDP_HEADERS` (one `Name: Value` entry per line) and `PLAYWRIGHT_MCP_CDP_TIMEOUT` environment variables.
229
232
 
@@ -231,7 +234,11 @@ Use `--timeout-settle` or `PLAYWRIGHT_MCP_TIMEOUT_SETTLE` to override the post-a
231
234
 
232
235
  #### HTTP Heartbeat
233
236
 
234
- When the server runs with `--port`, it sends MCP heartbeat pings for Streamable HTTP sessions. Set `PLAYWRIGHT_MCP_PING_TIMEOUT_MS` to override the default `5000` ms timeout. Set it to `0` or any negative value to disable heartbeat pings for clients or proxies that do not answer server-initiated pings.
237
+ When the server runs with `--port`, it sends MCP heartbeat pings for Streamable HTTP sessions. Set `PLAYWRIGHT_MCP_PING_TIMEOUT_MS` to override the default `5000` ms timeout. Set it to `0` or any negative value to disable heartbeat pings for clients or proxies that do not answer server-initiated pings. A client that answers `ping` with a JSON-RPC "method not found" error (as clients on the MCP 2026-07-28 revision do) is treated as alive: the server stops heartbeating that session instead of closing it. Only an unanswered ping (timeout) or a transport failure closes the session.
238
+
239
+ #### Clients without the initialize handshake
240
+
241
+ Clients on the MCP 2026-07-28 revision no longer send the `initialize` handshake. With `--port`, requests carrying the revision's per-request `_meta` envelope are served natively on the 2026-07-28 protocol: `server/discover` is answered (so clients negotiating with `versionNegotiation: 'auto'` or a `2026-07-28` pin connect directly), results carry `resultType` and the SEP-2549 cache fields — the tool list is advertised as cacheable for one hour with `cacheScope: "private"` — and the SEP-2243 standard headers (`MCP-Protocol-Version`, `Mcp-Method`, `Mcp-Name`) are validated against the request body. Older handshake-free clients (2025-era requests without the envelope) are served statelessly as before. In both cases requests receive no heartbeat pings, and in the modes where the server creates browser contexts itself each request runs against a fresh default browser session: with the default persistent profile the per-request default context runs in its own disposable profile (like an explicit browser session), so parallel handshake-free requests do not contend for the stable profile — and the stable profile's sign-in state is not visible to them — while `--isolated`, remote endpoints and isolated CDP modes mint a fresh context per request anyway. Modes that reuse one live browser context are the exception: `--extension` (and a `browser_connect` or VS Code session switched to a connected-browser provider) and CDP attach without `--isolated` serve every handshake-free request from the same shared context, so its tabs, cookies and storage persist across requests — the same sharing that makes these modes refuse `browser_session_open` (in `--vscode` serving the session tools are the exception: they are host-scoped and keep running against the default provider even while switched — see [Browser Session Tools](#browser-session-tools)). With a pinned `--cdp-launch-port`, only one launched application can be served at a time, so a second handshake-free request arriving while another request's browser context is still live is rejected with a clear error instead of silently attaching to the first request's application. With `--user-data-dir`, each handshake-free request launches a browser in the one configured profile: the profile's state persists across requests, and parallel requests contend for its browser lock and can fail with "Browser is already in use". Elsewhere, browser state that must persist across handshake-free requests belongs in an explicit browser session — a `browserSessionId` handle minted by `browser_session_open` in one request resolves in later ones (see [Browser Session Tools](#browser-session-tools)). Clients that do send `initialize` keep the classic `Mcp-Session-Id` session behavior unchanged. When several such stateful clients are connected at once in the default persistent-profile mode, the first client's default context holds the stable profile — concurrent clients' default contexts run in their own disposable profiles (without the stable profile's sign-in state) until it is freed, instead of failing with "Browser is already in use".
235
242
 
236
243
  ## Auditing pages behind a login
237
244
 
@@ -248,14 +255,14 @@ Every tool shares one browser context, and `audit_site` crawls in a temporary ta
248
255
  4. audit_site — the crawl inherits the session you just created
249
256
  ```
250
257
 
251
- This works out of the box in every mode, including the default persistent-profile mode. With the default profile the session also survives across server restarts, so you usually only sign in once.
258
+ This works out of the box in every mode, including the default persistent-profile mode. With the default profile the session also survives across server restarts, so you usually only sign in once. The default profile is keyed to the server's working directory, so each workspace's server keeps its own sign-in state — servers launched for different workspaces neither share cookies nor contend for the same profile.
252
259
 
253
260
  ### Storage state route (repeatable, CI-friendly)
254
261
 
255
262
  Record a session once with Playwright's codegen, then hand the file to the server:
256
263
 
257
264
  ```bash
258
- npx playwright@1.62.1 codegen --save-storage=auth.json https://example.com/login
265
+ npx playwright@1.63.0-alpha-2026-08-22 codegen --save-storage=auth.json https://example.com/login
259
266
  ```
260
267
 
261
268
  Sign in in the opened browser, then close it — `auth.json` now holds the cookies and local storage.
@@ -322,7 +329,7 @@ Performs a comprehensive accessibility scan on the current page using Axe-core.
322
329
  - `annotateScreenshot` (default `false`): capture an annotated screenshot of the violations
323
330
 
324
331
  **Annotated screenshots:**
325
- When `annotateScreenshot` is `true`, each violating element is outlined and labelled with the rule ids it failed, a full-page PNG is written to the MCP output directory (`scan-page-annotated-{timestamp}.png`) and returned as a resource link, and the markers are then removed so the page is left exactly as it was. The markers are drawn in an out-of-flow overlay clipped to each element's own box, so they never reflow the page. The overlay uses a fresh id per scan, is placed in the browser's top layer so it stays visible over an open dialog, popover or fullscreen element, and compensates for a CSS `zoom` or a scaled ancestor so markers line up with what is rendered.
332
+ When `annotateScreenshot` is `true`, each violating element is outlined and labelled with the rule ids it failed, a full-page PNG is written to the MCP output directory (`scan-page-annotated-{timestamp}-{token}.png`) and returned as a resource link, and the markers are then removed so the page is left exactly as it was. The markers are drawn in an out-of-flow overlay clipped to each element's own box, so they never reflow the page. The overlay uses a fresh id per scan, is placed in the browser's top layer so it stays visible over an open dialog, popover or fullscreen element, and compensates for a CSS `zoom` or a scaled ancestor so markers line up with what is rendered.
326
333
  An element that fails several rules gets one box listing every rule id, and elements inside open shadow roots are marked by walking the shadow path Axe reports.
327
334
  Running animations are paused before the elements are measured and resumed after the capture, so a moving target keeps its marker. The markers themselves live in a shadow root under an overlay whose own styles are `!important`, so page CSS cannot restyle or hide what the report counts, and each rule label sits outside the clipped box so it stays readable on an element smaller than its own label.
328
335
  At most 50 elements are annotated per scan. The result text always reports how many nodes were marked out of the total, plus how many were left out because they exceeded the limit, were hidden, zero-size or off-canvas (a full-page screenshot is clipped to the document box), or were inside an iframe (cross-frame selectors cannot be resolved from the top document).
@@ -373,7 +380,7 @@ A frame you scoped out yourself is not reported: with `excludeSelectors: ["ifram
373
380
  Crawls and scans multiple internal pages, then aggregates violations across the site.
374
381
  - Default strategy: link-based BFS from the current URL
375
382
  - Supports `links`, `nav`, `sitemap`, and `provided` URL strategies
376
- - Always writes a JSON report (default filename: `audit-site-{timestamp}.json`)
383
+ - Always writes a JSON report (default filename: `audit-site-{timestamp}-{token}.json`)
377
384
  - Warns and records `sessionLosses` if the crawl loses cookies it started with — see [Auditing pages behind a login](#auditing-pages-behind-a-login)
378
385
 
379
386
  **Example flow:**
@@ -387,7 +394,7 @@ Crawls and scans multiple internal pages, then aggregates violations across the
387
394
  Runs Axe scans on the same page across viewport/media/zoom variants and compares deltas against baseline.
388
395
  - Default variants: baseline, mobile, desktop, forced-colors, reduced-motion, zoom-200
389
396
  - Supports custom variants and optional reload between variants
390
- - Always writes a JSON report (default filename: `scan-matrix-{timestamp}.json`)
397
+ - Always writes a JSON report (default filename: `scan-matrix-{timestamp}-{token}.json`)
391
398
  - JSON report and structured result schema `v2` set baseline deltas to `null` when either scan left frames unscanned, because their coverage is not comparable
392
399
 
393
400
  **Example flow:**
@@ -403,7 +410,7 @@ Audits real keyboard focus behavior by pressing Tab (and optional Shift+Tab) wit
403
410
  - Checks target size against WCAG 2.2 SC 2.5.8 (`checkTargetSize`, default on)
404
411
  - Checks that focus is not entirely obscured, WCAG 2.2 SC 2.4.11 (`checkFocusObscured`, default on)
405
412
  - Optional issue screenshots (`screenshotOnIssue`)
406
- - Always writes a JSON report (default filename: `audit-keyboard-{timestamp}.json`)
413
+ - Always writes a JSON report (default filename: `audit-keyboard-{timestamp}-{token}.json`)
407
414
 
408
415
  **Limits of the WCAG 2.2 checks** — these are heuristics, not a conformance verdict:
409
416
  - Target size only inspects elements the tab order actually reaches, so pointer-only targets are never measured.
@@ -455,7 +462,7 @@ Audits what a screen reader actually announces, using the browser's own accessib
455
462
  - Findings for names overlap with axe rules such as `link-name`, `button-name` and `image-alt`; this tool adds the quality checks (generic names, file names, label-in-name, duplicates) that axe cannot make.
456
463
  - It reports the page as currently rendered. Content behind a collapsed panel or another viewport is judged in that state.
457
464
 
458
- **Bounds:** `maxElements` (default 400) caps how many *screen-reader-reachable* accessibility tree elements are analyzed. The snapshot also refs `aria-hidden` subtrees, which no check reports, so measuring continues past them until the budget is filled with reachable elements (up to a hard ceiling of twice `maxElements` measured, so a page built mostly of hidden refs stays bounded). `maxFindingsPerCheck` (default 20) caps the findings listed per check. Both truncations are stated in the summary and the JSON report, and the full counts are always reported. Always writes a JSON report (default filename: `audit-screen-reader-{timestamp}.json`).
465
+ **Bounds:** `maxElements` (default 400) caps how many *screen-reader-reachable* accessibility tree elements are analyzed. The snapshot also refs `aria-hidden` subtrees, which no check reports, so measuring continues past them until the budget is filled with reachable elements (up to a hard ceiling of twice `maxElements` measured, so a page built mostly of hidden refs stays bounded). `maxFindingsPerCheck` (default 20) caps the findings listed per check. Both truncations are stated in the summary and the JSON report, and the full counts are always reported. Always writes a JSON report (default filename: `audit-screen-reader-{timestamp}-{token}.json`).
459
466
 
460
467
  **Example flow:**
461
468
  ```text
@@ -487,6 +494,7 @@ Set default operation timeout for existing tabs.
487
494
  #### `browser_snapshot`
488
495
  Capture accessibility snapshot of the current page (better than screenshot for analysis).
489
496
  Large `data:` URL payloads in snapshot output are truncated to their media type prefix.
497
+ AI snapshots mark a visually present subtree excluded from accessibility queries with `[aria-hidden]` on its boundary element. Descendants are not marked again.
490
498
  - Parameters: `compress` (optional boolean, default false)
491
499
  - When true, repeated non-interactive ARIA snapshot nodes are collapsed in the rendered response when a repeated structural pattern appears more than 100 times. The first 10 examples of each collapsed pattern are kept.
492
500
  - Use `browser_evaluate()` to retrieve the full uncompressed list when needed.
@@ -547,7 +555,7 @@ Take a screenshot of the current page.
547
555
 
548
556
  #### `browser_pdf_save`
549
557
  Save page as PDF.
550
- - Parameters: `filename` (optional, defaults to `page-{timestamp}.pdf`)
558
+ - Parameters: `filename` (optional, defaults to `page-{timestamp}-{token}.pdf`)
551
559
 
552
560
  This tool requires `--caps pdf` in the CLI.
553
561
 
@@ -570,6 +578,29 @@ Resize the browser window.
570
578
  Manage browser tabs in one tool.
571
579
  - Parameters: `action` (`list`, `new`, `close`, `select`) and optional `index` (for `close` and `select`).
572
580
 
581
+ ### Browser Session Tools
582
+
583
+ Following the MCP 2026-07-28 stateless prescription, browser state can be named by an explicit server-minted handle instead of living implicitly in the connection. Every browser tool except the two session tools accepts an optional `browserSessionId` argument; when it is omitted, the tool runs in the default session and behaves exactly as before.
584
+
585
+ #### `browser_session_open`
586
+ Opens a separate browser session — its own browser context with its own tabs, cookies and storage — and returns its opaque handle (`bs_...`) both in the result text and as `structuredContent.browserSessionId`. Pass that handle as the `browserSessionId` argument of other browser tools to run them in this session.
587
+
588
+ How the separate context is provided depends on the mode:
589
+
590
+ - **Default persistent-profile mode**: each session runs in its own fresh, disposable profile (removed when the session closes or expires); only the default session uses the stable persistent profile, whose sign-in state keeps surviving restarts. This is required — one profile directory can back only one running browser at a time.
591
+ - **`--isolated`, remote endpoints, and CDP/`--cdp-launch` with `--isolated`**: each session gets its own fresh browser context. In `--cdp-launch` mode each context launches its own instance of the configured application on its own free port — which is why combining `--cdp-launch-port` with `--isolated` also rejects `browser_session_open`: a pinned port can serve only one launched instance, so a second session would silently attach to the first session's application. A second concurrent browser context on the pinned port (e.g. from a parallel client) is likewise rejected with an error rather than attaching to the first context's application.
592
+ - **Modes that reuse one live browser context** — CDP attach or `--cdp-launch` without `--isolated`, `--extension`, the VS Code bridge, and servers created with a custom context getter — cannot create a separate context, so `browser_session_open` is rejected with an explanation instead of handing out a handle that would share the same tabs, cookies and storage as everything else. The same applies in the default mode when `--user-data-dir` pins all browsing to one user-supplied profile.
593
+
594
+ In `--vscode` serving, browser sessions are host-scoped: `browser_session_open`, `browser_session_close`, and every call carrying a `browserSessionId` always run against the default provider's session registry at the host, regardless of any `browser_connect` provider switch. A handle opened before a switch keeps working (and can be closed) while the proxy is switched to a VS Code-connected browser, and a session opened while switched is created by the default provider — the VS Code-connected browser itself reuses one live context and cannot host separate sessions. Only session-less tool calls follow the switch.
595
+
596
+ #### `browser_session_close`
597
+ Closes a session opened with `browser_session_open` and releases its browser resources.
598
+ - Parameters: `browserSessionId` (the handle to close)
599
+
600
+ Closing is refused with a tool error while a tool call is still running in that session — a close that disposed the browser mid-call would fail the running tool; wait for it to finish and retry.
601
+
602
+ Sessions that stay idle expire automatically after 30 minutes; the timer is refreshed on every use and while a tool is running in the session (overlapping calls each count, so the session survives until the last one finishes), so a long `audit_site` crawl is never expired mid-run. Set `PLAYWRIGHT_MCP_BROWSER_SESSION_TTL_MS` to override the idle TTL in milliseconds (`0` or a negative value disables expiry). Passing an unknown or expired handle produces a tool error pointing back to `browser_session_open`; the error deliberately does not list other open sessions' handles, since handles are bearer tokens that route tool calls into their sessions. With `--save-session`, logged tool calls record the `browserSessionId` they were routed with, and recorded user actions from an explicit session carry the same `browserSessionId` in their logged args, so entries from different sessions stay distinguishable (default-session entries stay untagged).
603
+
573
604
  ### Information & Monitoring Tools
574
605
 
575
606
  #### `browser_console_messages`
@@ -582,13 +613,11 @@ Large `data:` URL payloads in request URLs are truncated to their media type pre
582
613
  When there is at least one request, a closing line points at `browser_network_request`.
583
614
 
584
615
  #### `browser_network_request`
585
- Returns the request headers, request body, response headers and response body of one request from the `browser_network_requests` listing.
616
+ Returns credential-redacted request/response headers and body metadata for one request from the `browser_network_requests` listing.
586
617
  - Parameters: `index` (the number shown in the listing, starting at 1)
587
618
  - The listing is cleared by `browser_navigate` and when the tab closes; other navigations (link clicks, form submits, `history` calls) leave it in place and keep appending. Re-run `browser_network_requests` to get current indexes.
588
619
  - Credential-bearing headers (`authorization`, `proxy-authorization`, `cookie`, `set-cookie`, `x-api-key`, `x-auth-token`) are reported as `<redacted, N characters>`, so their presence and size stay visible but the secret never reaches the transcript. All other headers are reported in full, one line each.
589
- - Binary request and response bodies are reported as `<binary data, N bytes, mime/type>` rather than dumped. The type decides: `text/*`, `+json`/`+xml` suffixes and known textual types are text; `image/`, `audio/`, `video/`, `font/`, `model/` and known binary types are binary; anything else (`multipart/form-data`, custom types, a missing type) is decided by inspecting the bytes.
590
- - Textual bodies are decoded using the charset in `content-type`, and are truncated at 20000 characters with a trailing note. The cap applies to the request body and the response body separately, so one call can return up to two truncated bodies.
591
- - Bodies are wrapped in a code fence, so page-controlled content cannot forge the report's own section headings.
620
+ - Request and response body contents are never returned because they can contain submitted credentials or private API data. Non-empty bodies are reported as `<redacted, N bytes, mime/type>`; empty bodies remain `<empty>`.
592
621
  - A request that failed after its response arrived reports both the status and the failure.
593
622
  - Sections that could not be read are reported in place (`<headers unavailable: ...>`, `<body unavailable: ...>`) rather than failing the whole call; reads are bounded by the default timeout, so a still-streaming response cannot hang the tool.
594
623
 
package/index.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
17
+ import type { Server } from '@modelcontextprotocol/server';
18
18
  import type { Config } from './config.js';
19
19
  import type { BrowserContext } from 'playwright';
20
20