文件历史

提交图

17 次代码提交

作者 SHA1 备注 提交日期
Alex Rudenko 9cd734b0a3 refactor: clean up more of the context interface (#2335)
- removed redundant page getters
2026-07-09 13:50:48 +00:00
Antoine Kingue 55c8a541d4 feat(screenshot): add CLI options to cap screenshot size at the source (#1823)
## Summary

Adds **opt-in** CLI flags so operators can cap the size of screenshots
returned by `take_screenshot` before they are embedded in the MCP
response. Refs #879.

The flags address two related symptoms reported when MCP clients display
screenshots inline:

1. **Per-image dimension limit**: hosted LLM APIs commonly reject images
exceeding per-image dimension constraints (typical caps are in the
2000-8000 px range, sometimes scaling down further when many images are
in the same request). This is the exact error reported in #879.
2. **Cumulative request size**: after many captures, the cumulative
base64 payload eventually pushes a request over the per-call body size
limit imposed by the LLM API.

Both can be mitigated at the source by reducing format/quality and
downscaling the capture.

## New flags (all opt-in)

- `--screenshot-format <jpeg|png|webp>`: override the default format
used by `take_screenshot` when the caller does not specify one
- `--screenshot-quality <0-100>`: override the default JPEG/WebP
quality. Ignored for PNG
- `--screenshot-max-width <px>`: downscale screenshots wider than this
before they are returned
- `--screenshot-max-height <px>`: downscale screenshots taller than
this. Combines with `--screenshot-max-width`; the smaller scale wins so
both bounds are respected while preserving aspect ratio

For the exact error in #879, the recipe is `--screenshot-max-width=8000
--screenshot-max-height=8000` (or a smaller value such as `2000` if many
images may end up in the same request, depending on the operator's
chosen API).

## Implementation

- Resizing leverages Puppeteer's `clip.scale` (CDP
`Page.captureScreenshot`), so **no new dependencies**.
- Source dimensions per capture mode:
  - viewport: `page.viewport()`
- full page: `document.documentElement.scrollWidth/scrollHeight` via
`page.evaluate()`
  - element (`uid`): `elementHandle.boundingBox()`
- For element and full-page captures with a downscale clip, the call
routes through `page.screenshot({clip})` so the scale parameter applies.
`captureBeyondViewport` is left to Puppeteer's default (`true` when a
clip is set), preserving correct behavior for elements below the fold
and full-page captures.
- ~150 lines of source code, ~200 lines of new tests.

## Backwards compatibility

**Fully opt-in**: when no flags are set, `take_screenshot` returns the
exact same bytes as before. No behavioral change for existing users.

## Design alignment

- Aligned with the **"Reference over Value"** principle in
`docs/design-principles.md`: the existing 2 MB threshold still routes
oversized screenshots to a temporary file. This change only reduces the
size of the **inline base64 fallback path**, which the principles
document calls out as an acceptable exception when MCP clients display
images natively.
- The MCP server **hardcodes no LLM-specific size limits**. Operators
pick the values that match their client/model combination. This keeps
the maintenance surface here minimal as model limits evolve, and is
intended as a **complement to, not a replacement for**, fixes in the MCP
client itself.

## Addressing concerns raised in #879

> "It's not feasible for us to maintain this. Limits will change when
models change." (@natorion)

The flags are pure parameters; nothing about the upstream LLM is encoded
in the server. When a vendor raises (or lowers) a limit, no code change
is needed here, only the operator's CLI args change.

> "`filePath` / `page_resize` already work as a workaround." (@OrKoN)

`filePath` is great when the call site knows it's about to take a huge
screenshot, but as you noted earlier in the thread, an oversized image
already in the request history keeps causing failures even on subsequent
calls. `page_resize` works but mutates the page being debugged. The
resize in this PR happens **between Puppeteer and the MCP response**, so
the inspected page is untouched and the failure mode is prevented at the
source.

> "Should be fixed client side."

Agreed, this PR is intended as a complement, not a substitute. A
client-side fix (e.g. compaction evicts/downsamples old images) handles
the cumulative case for *any* MCP. A server-side cap handles the
per-call dimension limit for users who hit it before compaction can kick
in. The two address overlapping but distinct failure modes.

Happy to drop or rework any of this if the maintainers prefer a
different shape, for example making the threshold automatic from a
single `--max-image-bytes` knob, or rejecting the PR entirely in favor
of waiting for a client-side fix. Just wanted to put a concrete option
on the table.

## Tests

Added 6 new tests:

- `honors screenshotFormat default from CLI args`
- `keeps "png" as default format when no CLI override is set`
- `downscales viewport screenshot when screenshotMaxWidth is set`
- `downscales using the smaller scale when both max-width and max-height
are set`
- `does not resize when source is smaller than the max bounds`
- `downscales full page screenshot when screenshotMaxWidth is set`

All 627 tests in the suite pass. `npm run typecheck` and `npm run
check-format` are clean.

## Notes for reviewers

- The dimensions compared against `--screenshot-max-width/height` are
**CSS pixels** (`page.viewport()`), not raw bitmap pixels. With
`deviceScaleFactor > 1` (HiDPI emulation) the actual bitmap may still be
larger. Happy to clarify this in the option description if preferred.
- For element captures with a downscale clip, the call routes through
`page.screenshot({clip})` instead of `element.screenshot()`. Same-frame
elements are correct (boundingBox returns main-frame coords). I have
**not** exercised this path against cross-origin iframe elements; let me
know if you'd like a fallback there.
- The PR is currently in **Draft** state pending CLA verification and
any feedback on the framing above.

Refs #879
Closes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/879
2026-06-17 10:40:14 +00:00
Wolfgang Beyer e046c23563 chore: in-page tool output: stash DOM elements and preprocess for serialization (#1877)
Improvements for handling in-page tool responses. In order to
successfully pass an in-page tool response from the page context to the
MCP server, the response needs to be serializable. The code walks the
response object an performs the following changes:

- DOM elements are stashed onto the window object and replaced with an
ID. On the MCP server side this ID is used to map back to the
corresponding UID in the page snapshot generated from the accessibility
tree.
- Circular references are replaced with a string.
- Class instances (which can be complex or non-serializable) are
replaced with a string.
- Functions are replaced with a string.

If the in-page tool response contains DOM elements which are not part of
the page snapshot, a new snapshot is created add the missing elements
are added explicitly.
2026-04-22 14:51:09 +00:00
Alex Rudenko 4cb5a17b57 refactor: remove page passing via context (#1061)
- removes several redundant getters on the context.
- removes passing page instances via context.
2026-02-27 12:08:10 +00:00
Alex Rudenko 40c241bbfc refactor: move dialog handling to McpPage (#1059)
- renamed getSelectedPage to getSelectedPptrPage
- removes getSelectedPptrPage from tool interfaces
- moves dialog handling to McpPage
- makes responses to be optionally McpPage-scoped
2026-02-27 11:49:43 +01:00
Alex Rudenko 302e5a0419 refactor: consistently use McpPage in tools (#1057)
Follow-up to
https://github.com/ChromeDevTools/chrome-devtools-mcp/commit/caf601a32832bb87cfac801a6bbeacb87508412f

The work is not complete and as a follow-up I will handle other Context
methods and moved whatever is relevant to the McpPage. Also, duplicate
getters would go away.
2026-02-27 09:41:08 +00:00
Alex Rudenko 5f694c60ff refactor: improve type safety for page scoped tools (#1051)
I think we should create proper classes for tool definitions soon.

Follow-up for
https://github.com/ChromeDevTools/chrome-devtools-mcp/pull/1022
2026-02-26 14:33:57 +00:00
Simon Zünd 8e90a92780 chore: split withBrowser into withBrowser and withMcpContext (#620)
I split this PR off from my "create one DevTools universe per page" PR
in preparation. This allows tests to re-use browser instances without
creating an `McpContext`.

Drive-by: Move mocked browser/page into utils.ts.
2025-11-28 07:52:52 +01:00
zyzyzyryxy 94752ffade fix: prevent dropping license notices on some files when publishing (#604)
This PR prevents license notices being dropped when creating package for
publication.

This can happen when first import in the file is type-only import that
gets removed during build. When there is no empty line between the
license block comment and such import, the comment is treated as related
to the import and gets removed alongside it.
Adding an empty line between copyright notice and the import fixes the
issue.

Co-authored-by: Piotr Paulski <piotrpaulski@chromium.org>
2025-11-24 12:38:30 +00:00
Alex Rudenko 2eaf2689c3 fix: ignore quality for png (#589)
Fixes https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/588
2025-11-21 06:32:19 +00:00
Nikolay Vitkov 5a062ce373 test: stabilize test locally (#418)
Locally the test `with full page resulting in a large screenshot` would
fail semi consistently.
With what I think is just things not getting loaded fully, so scroll to
the bottom to fix that.
2025-10-20 08:41:08 +00:00
Coquinate 03e02a2d76 feat(screenshot): add WebP format support with quality parameter (#220)
## Summary

This PR adds WebP format support to the screenshot tool, providing
superior compression compared to JPEG while maintaining image quality.

## Problem

Currently, the Chrome DevTools MCP only supports PNG and JPEG formats
for screenshots. This leads to:
- Missing out on WebP's superior compression (25-34% better than JPEG at
equivalent quality)
- Larger file sizes than necessary for AI assistants with image size
limits
- No access to a modern format that offers both better compression and
transparency support
- Bug: `saveTemporaryFile` always saved files with `.png` extension
regardless of the specified format

## Solution

Added WebP as a supported format in the screenshot tool schema and
extended the quality parameter to work with WebP (0-100 range, same as
JPEG). Also fixed the file extension bug in `saveTemporaryFile`.

## Changes

-  Added `webp` to screenshot format enum alongside `png` and `jpeg`
-  Extended quality parameter description to include WebP support
-  Updated `saveTemporaryFile` to properly handle WebP MIME type and
file extension
-  Fixed bug where all screenshots were saved as `.png` regardless of
format
-  Updated type definitions in `ToolDefinition.ts` for WebP support
-  Updated documentation via `npm run docs`

## Testing

Puppeteer 24.22.3 (used by this project) has full WebP support including
quality parameter. Expected compression improvements based on WebP
benchmarks:
- **PNG (baseline):** 128 KB
- **JPEG quality 50:** 84 KB (34% reduction vs PNG)
- **WebP quality 50:** ~60 KB (53% reduction vs PNG, 29% better than
JPEG)
- **WebP quality 75:** ~90 KB (optimal quality/size balance)

All existing tests pass (131/131).

## Impact

This change is **backward compatible** - WebP is an optional format that
doesn't affect existing PNG/JPEG usage. It particularly helps with:
- AI assistants that have image size limits
- Reducing bandwidth when capturing many screenshots  
- Providing transparency support with better compression than PNG
- Offering a modern, universally-supported image format (Chrome,
Firefox, Safari, Edge)

## Example Usage

```javascript
// High quality WebP
await take_screenshot({
  format: 'webp',
  quality: 85,
  fullPage: false
})

// Optimized for size
await take_screenshot({
  format: 'webp',
  quality: 50,  // ~29% smaller than JPEG quality 50
  fullPage: true
})
```

## Checklist

- [x] Code follows conventional commits
- [x] Documentation updated with `npm run docs`
- [x] All tests passing (131/131)
- [x] Backward compatible
- [x] Bug fix included (file extension handling)
- [ ] CLA signed (will complete if needed)

Fixes #[issue-number] (if applicable)

---------

Co-authored-by: aberemia24 <aberemia@gmail.com>
Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
2025-10-01 10:11:04 +02:00
James Doyle f03072698d feat(screenshot): adds ability to output screenshot to a specific pat… (#172)
…h. Closes #152. Closes #153
2025-09-30 19:56:46 +02:00
Nikolay Vitkov 15277541d8 chore: add additional EsLint rule (#147) 2025-09-25 17:20:01 +02:00
Alex Rudenko 91d83c4190 test: fix shell for windows tests (#72) 2025-09-23 09:37:22 +02:00
Alex Rudenko 014a8bc52e feat: validate uids (#37)
- generate snapshot IDs.
- change uid to be a string.
- validate that uid is not coming from a stale snapshot.
2025-09-16 11:54:35 +00:00
Alex Rudenko 31a0bdce26 feat: initial version 2025-09-11 12:46:05 +02:00