## Summary
validatePath() in McpContext returned immediately, with no restriction
at all, whenever roots() returned undefined. roots() only returns
undefined when the connecting MCP client never negotiates the optional
roots capability during initialize, which any minimal client can trigger
simply by omitting it from its declared capabilities.
Since roots() already always appends the OS temp directory to whatever
explicit roots are configured, this change makes it return that same
default (temp directory only) instead of undefined when no roots have
been set. This removes the early return in validatePath() entirely, so
path validation now runs unconditionally rather than being conditional
on whether the connecting client happened to negotiate a capability it
was never required to declare per the MCP spec.
Any filePath-accepting tool (take_screenshot, saveFile, and the
performance/Lighthouse export tools that route through the same check)
had its only path-traversal guard silently disabled for the lifetime of
a connection whenever the client omitted the optional roots capability.
Since this server is designed to let an LLM drive a browser, and browsed
page content is not trusted input, this meant a client that simply
doesn't implement roots (a plausible, non-adversarial default for
lightweight or custom MCP clients) removed the only boundary preventing
the connected agent from writing to any path the process can reach.
Added a test that exercises the actual default state of roots (never
calling setRoots()) directly, since the existing tests always call
setRoots(), even with an empty array, before validating. Verified
locally with a minimal MCP client that declares no capabilities: before
this change, take_screenshot with a filePath outside any root wrote a
real file to an arbitrary path with no error; after this change, the
same call is rejected with the existing Access denied error. Also
verified that a client that does declare roots is unaffected, and that
writes to the OS temp directory continue to succeed with no roots
negotiated, matching prior behavior for that path.
## Support for Network Blocklists and Allowlists
(`--blocked-url-pattern` & `--allowed-url-pattern` arguments)
This PR adds support for CLI options to restrict network access in the
browser session via URL patterns.
### Key Features & How It Works
- **Pattern Matching:** Utilizes the [URLPattern
Standard](https://urlpattern.spec.whatwg.org/) for pattern matching.
- **Target Detachment:** Silently detaches from targets (pages/tabs)
whose URLs match blocked patterns (or do not match allowed patterns)
upon connection.
- **Runtime Blocking:** Prevents navigations and blocks runtime requests
(such as fetch/XHR and subresources) if they violate the pattern rules.
- **Mutual Exclusivity:** `--blocked-url-pattern` and
`--allowed-url-pattern` conflict with each other and cannot be
configured simultaneously.
- **Browser Requirements:**
- **`--allowed-url-pattern`**: Requires **Chrome 149+**.
- **`--blocked-url-pattern`**: Works on Chrome versions older than 149,
but **Chrome 149+ is highly recommended**.
### Important Limitations & Side Effects
- **Network Emulation/Throttling Conflict:** Network throttling is
disabled when a network blocklist/allowlist is configured, to avoid
conflicting with Puppeteer's underlying blocking mechanisms.
- Using the `emulate` tool to modify `networkConditions` (e.g. setting
to `Offline`) will throw an error: *`Network throttling is not supported
when network blocking (allowlist/blocklist) is configured.`*
- Other emulation settings (e.g., `cpuThrottlingRate`, `geolocation`,
`viewport`) are unaffected and remain fully functional.
---
### Configuration Examples
#### 1. Blocking specific domains or endpoints (Blocklist)
Add the `--blocked-url-pattern` options to the `args` list in your MCP
settings file:
```json
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--blocked-url-pattern=*://*.blocked-example.com/*",
"--blocked-url-pattern=*://*.another-blocked-example.com/*"
]
}
}
}
```
#### 2. Restricting access to authorized domains (Allowlist)
Add the `--allowed-url-pattern` options to restrict the browser to
permitted hosts (requires Chrome 149+):
```json
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--allowed-url-pattern=https://*.allowed-example.com/*",
"--allowed-url-pattern=https://*.another-allowed-example.com/*"
]
}
}
}
```
---------
Co-authored-by: Natallia Harshunova <nharshunova@chromium.org>
Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
Enables "third-party developer tools" feature. This allows the inspected
web page to expose tools which provide debugging information to Chrome
DevTools for Agents.
Third-party developer tools enable web applications to expose internal
state, component hierarchies, or specific debug data that cannot be
deduced through static analysis. This allows Chrome DevTools for Agents
to provide richer, more actionable context to AI agents during debugging
sessions.
2 additional tools are enabled in Chrome DevTools for Agents for
interacting with third-party developer tools:
`list_3p_developer_tools()` and `execute_3p_developer_tool`.
Code changes in this PR:
- Rename "in-page tools" to "third-party developer tools"
- Unhide
- Make available in CLI
- Add documentation
This PR moves the checks for CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS and
CI env vars to parseArguments making sure it is correctly applied by the
daemon and in tests. It also updates the tests to set explicit
CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS as it might not always be
inherited. This change is likely to affect the metrics collected and
might explain some fluctuations we observed.
This PR adds a CLI flag to enable redacting network headers in the same
way they are redacted in DevTools. Note that sometimes it might prevent
the agent from properly analysing network issues. Pass
`--redact-headers=false` to revert to the previous behavior.
- `chrome-devtools-mcp.js` is the `npx chrome-devtools-mcp`
- `chrome-devtools.js` is the new CLI
- `-cli-options.js` is the corresponding options
- all these files are in the bin folder to indicate they are executable
We upgrade the performance trace tools to include real-user experience
data from the Chrome User Experience Report (CrUX).
https://developer.chrome.com/docs/cruxhttps://developer.chrome.com/docs/crux/methodology
### Deets
* When a trace is stopped, the server now extracts the primary
navigation URLs from the trace (determined by insightSets).
* It calls the public CrUX API to fetch field metrics (LCP, INP, CLS)
for each unique URL/Origin.
* The formatting of crux data is handled by upstream TraceFormatter, but
it looks like this:
```md
Metrics (field / real users):
- LCP: 2595 ms (scope: url)
- LCP breakdown:
- TTFB: 1273 ms (scope: url)
- Load delay: 86 ms (scope: url)
- Load duration: 451 ms (scope: url)
- Render delay: 786 ms (scope: url)
- INP: 140 ms (scope: url)
- CLS: 0.06 (scope: url)
- The above data is from CrUX–Chrome User Experience Report. It's how the page performs for real users.
- The values shown above are the p75 measure of all real Chrome users
- The scope indicates if the data came from the entire origin, or a specific url
- Lab metrics describe how this specific page load performed, while field metrics are an aggregation of results from real-world users. Best practice is to prioritize metrics that are bad in field data. Lab metrics may be better or worse than fields metrics depending on the developer's machine, network, or the actions performed while tracing.
```
**Privacy Considerations:**
* Updates the server README to inform users that performance analysis tools may send trace URLs to the Google CrUX API.
* Adds a notification message to the server startup logs regarding the CrUX API interaction.
Doc: go/crux-in-bifrost
Fixes b/446630695
---------
Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
Co-authored-by: Alex Rudenko <OrKoN@users.noreply.github.com>
## **Usage statistics**
Google collects usage statistics (such as tool invocation success rates,
latency, and environment information) to improve the reliability and
performance of Chrome DevTools MCP.
Data collection is **enabled by default**. You can opt-out by passing
the `--no-usage-statistics` flag when starting the server:
```json
"args": ["-y", "chrome-devtools-mcp@latest", "--no-usage-statistics"]
```
Google handles this data in accordance with the [Google Privacy
Policy](https://policies.google.com/privacy).
Google's collection of usage statistics for Chrome DevTools MCP is
independent from the Chrome browser's usage statistics. Opting out of
Chrome metrics does not automatically opt you out of this tool, and
vice-versa.
The code determining statistics that are collected is in here
https://github.com/ChromeDevTools/chrome-devtools-mcp/tree/main/src/telemetry.
This PR initiates the implementation of clearcut telemetry. It
introduces the CLI configuration required to opt-out of usage
statistics, along with the necessary transparency disclaimers for the
user. It's hidden by default during development & while we get the
launch approvals.
**Implementation Roadmap:**
This is the first in a series of PRs designed to implement the telemetry
system:
1. **CLI & Opt-out Mechanism (This PR):**
* Adds the `--usage-statistics` flag (hidden, default `false` for now).
* Adds transparency logging to specify data collection when enabled.
2. **Logger Scaffolding & Integration:**
* Implement `ClearcutLogger` and integrate it into `main.ts`.
* Add hooks for `logServerStart` and `logToolInvocation`.
* Introduce `ClearcutSender` as an abstraction layer for transport
logic.
3. **Persistence Layer:**
* Implement local state management to reliably track "First Time
Installation" and "Daily Active" metrics.
* Implement sending the daily active and first time installation event
based on this local state.
4. **Watchdog Process Architecture:**
* Move `ClearcutSender` execution to a dedicated watchdog process to
ensure reliable event transmission even during abrupt server shutdowns.
5. **Transport, Batching & Retries:**
* Finalize `ClearcutSender` with actual HTTP transport logic, including
event batching, respecting `next_request_wait_millis` and retries.
Related Issue -
https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/430
### Description
When Chrome is launched via Puppeteer, it automatically adds a set of
default flags like `--enable-automation --disable-extensions
--disable-component-extensions-with-background-pages.`
Currently, there is no way to opt out of these defaults, which makes
certain use cases difficult or impossible to support. this PR adds a way
to selectively ignore specific default Chrome launch flags applied by
Puppeteer using its
[ignoreDefaultArgs](https://pptr.dev/api/puppeteer.launchoptions#ignoredefaultargs)
property.
```json
{
"name": "chrome-devtools-mcp",
"version": "latest",
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--ignore-default-chrome-arg='--enable-automation'",
"--ignore-default-chrome-arg='--disable-extensions'"
]
}
}
}
```
**Feedback appreciated** @OrKoN
This PR adds a new connection mode called `--auto-connect`. To activate
it, add the `--auto-connect` flag to the chrome-devtools-mcp server
configuration. With this, chrome-devtools-mcp will automatically connect
to the running Chrome instance by looking up the port and the URL in the
user data dir for the specified `--channel` (by default, `stable`).
Requires Chrome M145.
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>
This PR introduces a feature to disable some of the MCP server tool
categories to tailor it to specific use cases.
For example,
```
npx chrome-devtools-mcp@latest --no-category-emulation Disable tools in the emulation category
npx chrome-devtools-mcp@latest --no-category-performance Disable tools in the performance category
npx chrome-devtools-mcp@latest --no-category-network Disable tools in the network category
```
## Summary
Add support for connecting to Chrome via WebSocket endpoint with custom
headers, enabling authenticated remote debugging scenarios and providing
an alternative to the HTTP-based connection method.
## What's New
This PR introduces two new CLI arguments:
- **`--wsEndpoint` / `-w`**: Connect directly to Chrome using a
WebSocket URL
- Example: `ws://127.0.0.1:9222/devtools/browser/<id>`
- Alternative to `--browserUrl` (mutually exclusive)
- **`--wsHeaders`**: Pass custom headers for WebSocket connections (JSON
format)
- Example: `'{"Authorization":"Bearer token"}'`
- Only works with `--wsEndpoint`
## Use Cases
- **Authenticated remote debugging**: Use API keys, tokens, or custom
auth headers
- **Secured instances**: Connect to browser instances requiring
authentication