CuratedMCP

Sample Verified Review

chrome-devtools-mcp 1.12.0

This is a real review of Google (ChromeDevTools)'s browser-automation MCP server, published in full so you can see exactly what a maintainer gets for $99. The maintainers did not commission it. Every finding names the file it was read from at the reviewed commit.

Package chrome-devtools-mcp@1.12.0 (npm)

Source commit af28344, Apache-2.0

Reviewed November 10, 2026

Reviewer CuratedMCP

Meets our bar. Verified for v1.12.0.

Risk level recorded on the listing: Network egress, with JavaScript execution in pages and file writes. Three settings deserve a deliberate choice before first use: the persistent browser profile, attaching to a running Chrome, and usage statistics.

Capabilities recorded on the listing

  • •web_fetch: loads any URL through a real Chrome, unless you set --allowedUrlPattern or --blockedUrlPattern
  • •js_exec_in_page: runs caller-provided JavaScript inside pages (evaluate_script), can be switched off
  • •file_read: uploads files from local paths (upload_file), loads scripts and unpacked extensions from disk
  • •file_write: screenshots, traces and network request or response bodies, limited to the MCP client's roots or the temp directory by default
  • •credential_access: returns Cookie and Set-Cookie headers and bodies verbatim; attached to a running Chrome it acts inside your logged-in sessions
  • •telemetry_egress: usage statistics to Google (play.googleapis.com), on by default, documented opt-out

1. Install path

What a user actually gets when they run npx [email protected].

Zero runtime dependencies, no install scripts Good

The published tarball (378 files, 15 MB) declares no dependencies; Puppeteer, Lighthouse and the other libraries are bundled into build/. There are no preinstall, install or postinstall hooks, so nothing runs at install time. Resolving the package with npm produced one package and npm audit reported zero vulnerabilities.

  • package.json in the tarball: dependencies {} and no install hooks (the repo's prepare script does not run for consumers)
  • npm audit --omit=dev on a lockfile resolved for [email protected]: 0 vulnerabilities

Bundling moves third-party code out of npm's view Worth knowing

Because dependencies are vendored into the bundle, your own npm audit will never flag a vulnerable Puppeteer or Lighthouse version inside this package. Rely on the project's release cadence instead. The bundle ships a THIRD_PARTY_NOTICES file and the repo tests it.

  • scripts: bundle, test:notices in the repo's package.json
  • build/ in the tarball

Daily update check calls the npm registry Worth knowing

On start, at most once every 24 hours, the server spawns a detached process that runs npm config get registry and fetches <registry>/chrome-devtools-mcp/latest. It writes a small timestamp file under your home directory to rate-limit itself. The README documents this and the opt-out.

  • src/utils/check-for-updates.ts: 24-hour mtime check, spawn with detached: true
  • src/bin/check-latest-version.ts: execSync('npm config get registry'), fetch(`${registry}/chrome-devtools-mcp/latest`)
  • Opt-out: CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS (README, Update checks)

2. Credentials and secrets

How the server handles keys, cookies, sessions and anything else it could leak.

No secrets of its own; the browser profile is the secret Your decision

The server takes no API keys. What it holds is a Chrome profile. By default it launches Chrome with a persistent profile at $HOME/.cache/chrome-devtools-mcp/chrome-profile, so logins and cookies survive between sessions and are available to whichever agent starts it next. --isolated uses a temporary profile that is deleted on exit. Decide which you want before the first run.

  • src/BrowserManager.ts #launch(): userDataDir defaults to path.join(os.homedir(), '.cache', 'chrome-devtools-mcp', 'chrome-profile') unless --isolated or --userDataDir
  • src/config/browser-options.ts: isolated (default false), userDataDir

Attaching to your running Chrome hands the agent your live sessions Your decision

--browserUrl, --wsEndpoint and --autoConnect connect to an already running Chrome instead of launching one. That is the documented way to debug a real session, and it means every tool call runs inside your logged-in accounts. Treat it as giving the model your browser.

  • src/config/browser-options.ts: autoConnect ('automatically connects to a browser (Chrome 144+) running locally'), browserUrl, wsEndpoint
  • src/BrowserManager.ts #connect()

Network tools return cookies and bodies verbatim Worth knowing

get_network_request is designed to inspect headers, and its own description says so: request headers including Cookie, response headers including Set-Cookie. Request and response bodies can be returned inline or written to a file you name. There is no redaction, which is correct for a debugging tool and worth knowing when the model's context is logged anywhere.

  • src/tools/network.ts: get_network_request description; requestFilePath and responseFilePath parameters

Extra headers, including bearer tokens, come from your config Worth knowing

The CLI accepts extraHttpHeaders as a JSON string, with an Authorization bearer token given as the example. Anything you put there sits in plain text in your MCP client config, the same as any other server's environment block.

  • src/config/cli-options.ts: extraHttpHeaders

3. What it can do

61 tools. 28 are annotated read-only, 36 are not. These are the ones that change state outside the page.

Arbitrary JavaScript in any page, with a documented off switch Worth knowing

evaluate_script runs caller-provided JavaScript in the target page, inline or from a local file, and navigate_page accepts an initScript. --no-javascript-evaluation disables these entry points and blocks javascript:, data: and vbscript: URLs. The flag's own help is candid that this is not a sandbox: scripts on pages still run, and --experimentalDevtools reopens a path through the DevTools console.

  • src/tools/script.ts: evaluate_script, readOnlyHint: false
  • src/config/mcp-options.ts: javascriptEvaluation (default true) and its description

File writes are fenced to the client's roots Good

Screenshots, traces and saved bodies go to a path the model names, but the server resolves every path against the MCP client's negotiated roots, falling back to the temp directory when the client negotiates none. Writing outside them is refused unless the operator starts the server with --allowUnrestrictedPaths (default false). Symlinks are resolved before the check.

  • src/McpContext.ts: root resolution with fs.realpath, 'Access denied' on paths outside roots
  • src/config/mcp-options.ts: allowUnrestrictedPaths (default false)

Local file reads and extension loading are explicit tools Worth knowing

upload_file sends files from local paths into a page's file input. install_extension loads an unpacked extension from an absolute local path (not from a URL). Both are listed in SECURITY.md as intentional features rather than bugs.

  • src/tools/input.ts: upload_file (filePaths)
  • src/tools/extensions.ts: install_extension ('Absolute path to the unpacked extension folder')
  • SECURITY.md, Scope

URL allow and block lists exist Good

--blockedUrlPattern and --allowedUrlPattern restrict where the browser may go, including subresources, using the URL Pattern standard. The allow list needs Chrome 149 or newer. For an agent that should only touch your staging site, this is the control to set.

  • src/config/puppeteer-options.ts: blockedUrlPattern, allowedUrlPattern (reloadable)

Usage statistics are on by default, and the payload is small Your decision

Telemetry goes to Google's Clearcut endpoint. We read what it sends: tool name, a per-process random session id (rotated, never written to disk), app version, OS type, error codes, and tool parameters reduced to shape only: strings become a bucketed length, arrays a count, enums and booleans their value; uid, reqid and msgid are never sent. No URLs, selectors, page content or persistent machine identifier. The local state file holds two timestamps. The flag help and README disclose the collection and the opt-outs; the first-run notice goes to stderr, which many MCP clients hide, so most users will not see it.

  • src/telemetry/watchdog/ClearcutSender.ts: https://play.googleapis.com/log?format=json_proto; session_id = crypto.randomUUID()
  • src/telemetry/transformation.ts: sanitizeParams, PARAM_BLOCKLIST = {uid, reqid, msgid}, bucketize(string length)
  • src/telemetry/persistence.ts: LocalState { lastActive, lastToolCall } in telemetry_state.json
  • src/config/mcp-options.ts: usageStatistics default true; README 'Usage statistics'; opt-outs --no-usage-statistics, CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS, CI

4. Tool descriptions

Do the descriptions the model reads match what the code does, and do they try to steer the model?

Descriptions match behaviour Good

We compared the descriptions of the tools that touch files, the network, extensions and scripts with their handlers. Each says what the code does, including the uncomfortable parts (cookies in get_network_request, local paths in upload_file). No hidden instructions, no external URLs the model is told to visit, no claims the code does not back up.

  • src/tools/*.ts, all 61 description strings scanned for directive language

One steering phrase, harmless Worth knowing

fill_form tells the model to ALWAYS prefer it over repeated fill or click calls. That is efficiency advice about the server's own tools, not an instruction about the user's data, and we do not count it against the server.

  • src/tools/input.ts: fill_form description

Prompt injection is named, and placed on the client Worth knowing

SECURITY.md states that web content is returned to the model as-is and that the calling agent is responsible for validating tool calls and parameters. That is the honest position for a browser tool. It also means this server should be paired with a client that treats page text as untrusted.

  • SECURITY.md, Scope and Trusted host environment

If you install it

What we would suggest to the maintainers

None of these change the verdict. They are the kind of notes a paying maintainer gets in the findings email, and can fix before we take a second look at no extra charge.

Scope and method

Want this for your server?

Same four checks, same written findings, within 3 business days. $99 one-time, $49 with Maintainer Pro. If it meets the bar, your listing shows verified with its risk level and capabilities.