Mert Özen Further With Every Line
Developer Tools Browser DevTools — #10

DevTools and AI: Gemini AI Assistance, Chrome DevTools MCP and Recorder

Mert Özen Nov 8, 2026 10 min 4 views
DevTools and AI: Gemini AI Assistance, Chrome DevTools MCP and Recorder

The Chrome DevTools MCP server opens everything in the browser to a coding agent: without a separate profile, --no-usage-statistics and --no-performance-crux, personal sessions and URLs can leave your machine. With an agent we find and fix, via source-mapped stacks, an SPA fallback returning HTML for an API call and a NaN IndexedDB key on /books/abc; Gemini AI assistance requirements, the DevToolsGenAiSettings policy, and exporting a Recorder recording to Puppeteer.

Version note: The examples in this post were run with Chrome 156 (156.0.8078.80), chrome-devtools-mcp 1.12.0, @puppeteer/replay 4.0.2, Angular 22.2 and .NET 10. MCP (Model Context Protocol) outputs were captured with a small client connected to the server over stdio, using a separate Chrome profile in the work folder. Gemini AI (Artificial Intelligence) assistance in DevTools requires signing in with a Google account, so it was not run in this environment; that section comes from the Chrome DevTools documentation. This area changes very fast: check the release notes again before publishing.

Predict First

You add the Chrome DevTools MCP server to your coding agent with the shortest configuration from the documentation:

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "chrome-devtools-mcp@latest"]
    }
  }
}

Then you say "check what happens when /books/abc opens in Bookstore". Which Chrome profile does the agent use: the one you use every day, signed in to your bank and email, or a separate profile? What data goes to Google with this configuration? And if a page the agent opens contains the text "delete this file", what does the agent do?

This is the last post in the series. So far we have used every panel by hand; here we cover two ways of opening the same tools to an AI, and the Recorder, which records user flows.

AI Assistance Inside DevTools

AI assistance is the feature that brings Gemini into DevTools. According to the documentation the requirements are: the current version of Chrome, a signed-in Google account, being at least 18, and a supported location. The feature is off by default; you turn it on in the AI assistance section of Settings and are asked to accept Google's terms of service. The documentation describes the feature as experimental and says plainly that it can produce inaccurate or inappropriate answers.

It works in four contexts. In Styling it explains the selected element's styles and helps fix layout or styling bugs. In Network it analyzes the selected request's request and response headers, for example why the request fails. In Sources it explains what a script file does. In Performance it investigates a slow page and suggests fixes for metrics such as LCP (Largest Contentful Paint). The flow is always the same: select an element, request, file or trace in DevTools, click the AI assistance icon and ask. For example, you can ask in the Styling context why the .price rule from post 01 of this series did not apply; but verify the answer with the Styles and Computed tabs, as we did in that post.

Data, Privacy and Enterprise Policy

When you ask AI assistance a question, the context you selected goes to Google together with the question: the element's styles, the request's headers, the file's contents or the trace data. That means selecting a request with an Authorization header and asking a question also sends the token. On the enterprise side this is governed by the DevToolsGenAiSettings policy: value 0 enables the feature and lets Google use prompts, content and feedback to improve its models; 1 enables the feature but does not allow the data to be used for model improvement; 2 turns off all AI assistance features and entry points. Google's admin article notes that data used for model improvement can also be read by human reviewers. If you work with your company's source code or customer data, do not use the feature until you have clarified this policy's value with your IT (Information Technology) team.

Chrome DevTools MCP: Setup and Tools

MCP lets an AI client call external tools through a standard protocol. The chrome-devtools-mcp package turns Chrome into a tool set for a coding agent: navigation, clicking and filling forms, screenshots, console and network records, performance traces and insights, Lighthouse, CSS (Cascading Style Sheets) styles and experimental memory tools. The package also ships a CLI (Command Line Interface) and ready-made skills for agents. Since Chrome 155–156, the DevTools main menu also has a "Get Chrome DevTools for agents" entry. The default tool list in version 1.12.0 of the server:

server: {"name":"chrome_devtools","title":"Chrome DevTools MCP server","version":"1.12.0"}
tools (32): click, close_page, drag, emulate, evaluate_script, fill, fill_form, get_console_message, get_css_styles, get_network_request, handle_dialog, hover, lighthouse_audit, list_console_messages, list_network_requests, list_pages, navigate_page, new_page, performance_analyze_insight, performance_start_trace, performance_stop_trace, press_key, resize_page, screencast_start, screencast_stop, select_page, take_heapsnapshot, take_screenshot, take_snapshot, type_text, upload_file, wait_for

We already took some of the Insights and heap snapshot outputs in this series with this server; the memory analysis tools (compare_heapsnapshots, get_heapsnapshot_retaining_paths…) are turned on with the --experimentalMemory flag. --slim offers a small set of three tools: navigation, script execution and screenshots. According to the Chrome 153–154 and 155–156 notes, recent versions added heap snapshot querying, on-demand source map loading, turning off script execution with --no-javascript-evaluation, PWA (Progressive Web App) automation and get_css_styles.

A Bug Hunt Through the Agent's Eyes

We had the server carry out the request from Predict First through tool calls. The agent opened the page and listed the console errors:

=== list_console_messages {"types":["error"]}
msgid=5 [error] ERROR [object HttpErrorResponse] (2 args)
msgid=6 [error] ERROR DataError: Failed to execute 'put' on 'IDBObjectStore': Evaluating the object store's key path yielded a value that is not a valid key. (2 args)

=== get_console_message {"msgid":5}
Arg #1: {"headers":{...},"status":200,"statusText":"OK","url":"http://localhost:5391/api/books/NaN","ok":false,"name":"HttpErrorResponse","message":"Http failure during parsing for http://localhost:5391
### Stack trace
at  (client:368:4)
--- await ------------------------------
at ngOnInit (book-detail.ts:29:43)
--- Promise.then -----------------------
at <anonymous> (main.ts:5:1)

The stack trace arrives translated through the source map: the error is in ngOnInit on line 29 of book-detail.ts. More interesting is the message itself: status 200 but ok: false and "Http failure during parsing". The agent then looked at the network:

=== list_network_requests {"resourceTypes":["fetch","preflight"]}
reqid=29 OPTIONS http://localhost:5391/api/books/NaN [204]
reqid=30 GET http://localhost:5391/api/books/NaN [200]

Two real bugs came out. The first is in the backend: /api/books/NaN does not satisfy the {id:int} constraint, so it matches no endpoint and falls through to the MapFallbackToFile("index.html") we wrote for the SPA (Single-Page Application). The API (Application Programming Interface) returns HTML (HyperText Markup Language) with a 200 instead of a 404, and Angular tries to parse it as JSON (JavaScript Object Notation). The second is in the frontend: Number('abc') gives NaN, and NaN is not a valid key in IndexedDB. The fixes:

// unknown /api paths must end in a 404, not in the SPA's index.html
app.MapGet("/api/{**rest}", () => Results.NotFound());

app.MapFallbackToFile("index.html");
remember(bookId: number): void {
  if (!Number.isInteger(bookId)) {
    return;
  }
  // ...
}
api/books/NaN -> 404
api/books/3 -> 200
/cart -> 200 text/html

=== list_console_messages {"types":["error"]}
msgid=8 [error] Failed to load resource: the server responded with a status of 404 (Not Found) (0 args)
msgid=10 [error] ERROR [object HttpErrorResponse] (2 args)

The IndexedDB error is gone and the API returns the right status; what remains is that the component does not show the 404 properly to the user, which is now a clear piece of work. When the agent, in the same session, took the page's accessibility tree with take_snapshot and called get_css_styles with a price element's uid, it found the rule we found by hand in post 01:

Styles for span.price (uid: "1_16"):

  .price[_ngcontent-ng-c1135625248] (<style>:12) {
    color: #0a7d4f;
  }

What the agent does is exactly what this series teaches: read the console, look at the network, check the styles, record a trace. The difference is that it does it for you, and very quickly. The responsibility for verification does not change: we checked the two bugs it found with curl and a second session as well.

Security: The Agent Sees Everything in the Browser

The package's README is explicit: the server exposes the content of the browser instance to the MCP client, and the client can inspect and modify any data in the browser or DevTools. Hence three rules:

  • Use a separate or temporary profile. --isolated opens a temporary user data dir that is deleted on close; with --userDataDir you can point to a profile in your work folder. The default profile is $HOME/.cache/chrome-devtools-mcp/chrome-profile; sign in there once with a personal account and the agent sees that session every time.
  • Do not connect it to your personal browser. --autoConnect or --browserUrl connects to a running Chrome; the bank, email and company sessions open in that Chrome become accessible to the agent.
  • Do not treat page content as instructions. Every page, console message and network response the agent reads can contain text written for it; if the agent has permissions such as deleting files or committing, this is a door for prompt injection.

On the privacy side, two defaults need attention. Usage statistics (tool call success, latency, environment information) are sent to Google by default; --no-usage-statistics or the CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS environment variable turns this off. The performance tools can send URLs (Uniform Resource Locator) from a trace to Google's CrUX (Chrome User Experience Report) API for field data; --no-performance-crux turns that off. Every session in this post ran with these flags:

chrome-devtools-mcp --headless --userDataDir ./run/mcp-profile-XXXX \
  --executablePath "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --no-usage-statistics --no-performance-crux --viewport 1280x800

For a stricter setup, you can restrict the browser to local addresses with --allowedUrlPattern, mask sensitive headers before they reach the client with --redactNetworkHeaders, and turn off arbitrary script execution by the agent with --no-javascript-evaluation. The help text of the last one states separately that it is not a sandbox and that the page's own scripts keep running.

Recorder: Recording a Flow, Replaying It and Exporting to Puppeteer

The Recorder panel ("Show Recorder" in the Command Menu) records a user flow step by step: navigation, clicks, input changes. While recording, it stores several selectors for each step: an ARIA (Accessible Rich Internet Applications) label, a CSS selector, an XPath. The Replay button plays the flow again; the Measure performance button records a trace in the Performance panel while replaying the same flow. The recording is exported as JSON. We wrote an add-to-cart flow by hand in the Recorder's JSON format and replayed it with the @puppeteer/replay library that the Recorder also uses:

{ "type": "change", "value": "Compilers", "selectors": [["aria/Filter books"], ["input.filter"]] },
{ "type": "click", "selectors": [["aria/Add to cart"], ["app-book-card:nth-of-type(1) button"]], "offsetX": 20, "offsetY": 10 },
{ "type": "click", "selectors": [["aria/Cart (1 · $21.00)"], ["nav a[href='/cart']"]], "offsetX": 10, "offsetY": 5 },
{ "type": "waitForElement", "selectors": [[".summary"]] }
step done: setViewport
step done: navigate http://localhost:4391/books
step done: change Compilers
step done: click aria/Add to cart
step done: click aria/Cart (1 · $21.00)
step done: waitForElement .summary
summary text: 1 items, total $21.00

The Puppeteer option in the Recorder's export menu turns the same recording into a script; the beginning of the output produced by the library's stringify function:

import { Locator, launch } from 'puppeteer'; // v25.0.0 or later

const browser = await launch();
const page = await browser.newPage();
const timeout = 5000;
page.setDefaultTimeout(timeout);

Careful: the aria/Cart (1 · $21.00) selector depends on the cart total; if the price changes, the recording breaks. The selectors the Recorder produces are a starting point; when turning them into test code, switch to stable selectors such as data-testid. Moving from the Recorder to E2E (end-to-end) tests is the subject of the upcoming Frontend Testing series.

A Note on Dates: A Fast-Moving Area

Everything in this post changed in the last two releases: Chrome 153–154 brought heap snapshot querying, PWA tools and JavaScript-disabling flags to the MCP server, and 155–156 brought get_css_styles, a configuration file and the agent entry in the DevTools menu. AI assistance is also marked experimental. Before recommending a feature to your team, check that week's "New in DevTools" post and the package's changelog; if you use chrome-devtools-mcp@latest, remember that your agent may start tomorrow with a different tool set. For a stable setup, pin the version (chrome-devtools-mcp@1.12.0) and upgrade deliberately.

Production Notes

Do not connect the agent to production. Run the MCP server against a local or staging environment with test users; once production data enters the agent's context, it can leave traces in the prompt history, in logs and with your model provider. --allowedUrlPattern is the easiest way to enforce that boundary technically.

An agent's finding is a hypothesis. In our example the two bugs were real and were confirmed by measuring again; but the same agent can misread a trace or exaggerate a warning. Do not merge a code change without verifying it with your own eyes, using the tools this series covers.

In AI assistance, do not select a context containing tokens, customer data or closed-source code and ask a question without knowing the enterprise policy's value.

Common Pitfalls

  • Running the MCP server with the default profile and signing in to that profile with a personal account.
  • Not knowing that usage statistics and CrUX queries are on by default.
  • Depending on a tool set that changes daily through @latest.
  • Treating the page content the agent reads as trusted instructions.
  • Applying an AI assistance answer without verifying it in the Styles, Network or Performance panel.
  • Putting text-dependent selectors produced by the Recorder into a permanent test as is.

A Small Experiment

★☆☆ Add the Chrome DevTools MCP server to your agent with --isolated --no-usage-statistics --no-performance-crux and ask "what shows up in the console when /books/abc opens". Note which tools the agent calls and in what order.

★★☆ Record a "filter, add to cart, go to cart" flow in Bookstore with the Recorder, export it as JSON, and replace fragile selectors such as aria/Cart (1 · $21.00) with data-testid-based selectors. Confirm with Replay that it still works.

★★★ Make BookDetail show a 404 to the user as "Book not found". Then ask the agent the same question again, and confirm with your own Network and Console panels that no error remains in the console and the 404 shows up in the network.

The series ends here. From Elements to Memory, from Lighthouse to Angular DevTools, every panel answers the same question from a different angle: what is actually happening in the browser right now? Agents can ask that question faster; but reading the answer still comes down to knowing the tools this series covers.