## 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.
Updates the flag for the memory tooling to remove the experimental bit
(keep alias for backwards compatibility).
And updates the SKILLs to reflected the update names and point to the
available tools.
Q: Should it be called `take_heapsnapshot` or `take_heap_snapshot`?
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.
Extracting WebMCP tools into a separate category for better grouping in
the docs. This changes `--experimentalWebmcp` to
`--categoryExperimentalWebmcp` to align with other experimental
categories. Debugging category was not a good fit since the tools
provided by WebMCP are not necessarily used for debugging.
cc @beaufortfrancois
This PR changes the implementation to allow access to tmpdir even if the
client is not configured it explicitly because several tools default to
the tmpdir for outputs. Many clients like gemini-cli/claude do not
configure the tmp dir as a root by default.
This adds a `list_in_page_tools` MCP tool. When called, it dispatches a
`devtoolstooldiscovery` event on the active page. The page announces its
exposing tools by calling the event's `respondWith` method, which causes
the exposed tools to be stashed on the page's `window` object. This list
of in-page tools is then appended to the `list_in_page_tools` response.
Calling the exposed in-page tools from the MCP server will be handled in
a follow-up.
- `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
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>