Skip to content

feat(mcp): add compress option to browser_snapshot to collapse repeated ARIA nodes#41396

Closed
Josef-Le wants to merge 1 commit into
microsoft:mainfrom
Josef-Le:feat/browser-snapshot-compress
Closed

feat(mcp): add compress option to browser_snapshot to collapse repeated ARIA nodes#41396
Josef-Le wants to merge 1 commit into
microsoft:mainfrom
Josef-Le:feat/browser-snapshot-compress

Conversation

@Josef-Le

Copy link
Copy Markdown

Closes #41395

Summary

Adds a compress?: boolean parameter to the browser_snapshot MCP tool. When set, a two-pass algorithm collapses repeated structural patterns in the ARIA snapshot YAML — keeping the first 10 occurrences of any pattern that appears more than 100 times — and emits a trailing note explaining how to enumerate the full list via browser_evaluate().

Motivation

On pages with large lists, data grids, or autocomplete menus, browser_snapshot can return thousands of lines. A GitHub issues page with 100 open issues produces ~1 800 lines; a spreadsheet with 500 rows produces ~6 000 lines. The vast majority is structurally identical — only the text and [ref=eN] differ. This wastes tokens and can cause the model to miss important elements buried in the noise.

Algorithm

Two-pass, O(n) time and space:

  1. Pre-scan (safety gate): Normalise every line to a structural signature by stripping [ref=eN], accessible names, and bare numbers. Count (indent, signature) pairs. Only proceed if the maximum count exceeds FIRE_THRESHOLD = 100. This prevents false positives on diverse pages (dashboards, forms, settings pages).

  2. Compression pass: Walk the YAML line by line; keep the first KEEP_N = 10 occurrences of any repeated pattern; collapse the rest along with their descendant subtrees. Lines matching interactive roles (button, input, link, checkbox, menuitem, …) are unconditionally kept.

  3. Trailing note: Informs the model how many lines were removed and suggests browser_evaluate() for full enumeration.

Example

Page with 150 <li> elements:

# before: 152 lines
- list [ref=e2]:
  - listitem [ref=e3]: Item 1
  ... × 150

# after compress: true — 13 lines
- list [ref=e2]:
  - listitem [ref=e3]: Item 1
  ...
  - listitem [ref=e12]: Item 10

[playwright-compress: 140 repeated ARIA nodes collapsed — use browser_evaluate() to enumerate the full list]

Files changed

File Change
packages/playwright-core/src/tools/backend/ariaCompression.ts New — pure compression function, self-contained
packages/playwright-core/src/tools/backend/snapshot.ts Add compress to browser_snapshot zod schema
packages/playwright-core/src/tools/backend/response.ts Wire compress through setIncludeFullSnapshot()
tests/mcp/snapshot-compression.spec.ts 4 tests: happy path, small-list passthrough, interactive-element preservation, compress: false escape hatch

Design notes

  • FIRE_THRESHOLD = 100: a typical sidebar/nav has <20 items; a real pagination list has >100. The gap makes false positives extremely unlikely.
  • KEEP_N = 10: enough for the model to understand the list structure and extract the pattern for browser_evaluate().
  • Explicit opt-in: the model decides when to use compression. It is never forced on, so existing behaviour is fully preserved.
  • Interactive roles always kept: buttons, inputs, links, etc. carry distinct meaning even when visually identical in a list of search results. Collapsing them would silently hide actions.
  • The compression function is a pure transform — no side effects, no I/O — so it can be unit-tested without a browser.

Testing

The 4 tests in tests/mcp/snapshot-compression.spec.ts cover:

  1. compress: true collapses a 150-item list to the first 10 items
  2. compress: false returns the full snapshot unchanged
  3. compress: true does not fire on a 50-item list (below FIRE_THRESHOLD)
  4. compress: true preserves all 150 buttons (interactive-role guard)

Algorithm correctness was also verified with a standalone Node.js harness (18 assertions, all pass) prior to integration.


This PR is opened as a draft pending maintainer triage of issue #41395.

…nodes

Adds a `compress?: boolean` parameter to the `browser_snapshot` MCP tool.
When set, a two-pass algorithm collapses repeated structural patterns in the
ARIA snapshot YAML — keeping the first 10 occurrences of any pattern that
appears more than 100 times — and emits a trailing note explaining how to
enumerate the full list via browser_evaluate().

This targets pages with large lists, data grids, or navigation menus where
the snapshot can grow to thousands of lines. On a 150-item GitHub issues
page the output shrinks from ~1 800 lines to ~80 lines while preserving all
interactive elements (buttons, inputs, links) unconditionally.

Adds ariaCompression.ts with the pure compression function, and four tests
covering the happy path, passthrough on small lists, interactive-element
preservation, and the compress: false escape hatch.
@Josef-Le Josef-Le marked this pull request as ready for review June 21, 2026 08:57
@Josef-Le

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@pavelfeldman

Copy link
Copy Markdown
Member

Closing while discussion takes place in the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(mcp): add compress option to browser_snapshot to collapse repeated ARIA nodes

2 participants