Chrome DevTools MCP Performance Trace Analysis Pipeline: From Start to Insight

The chrome-devtools-mcp performance trace analysis pipeline is a three-stage workflow that captures browser telemetry through performance_start_trace, processes the raw data via performance_stop_trace using the DevTools TraceEngine, and extracts actionable metrics with performance_analyze_insight to generate LLM-ready performance reports.

The chrome-devtools-mcp repository provides a Model-Context-Protocol implementation that allows large language models to control Chrome DevTools programmatically. The performance trace analysis pipeline enables automated capture, parsing, and interpretation of browser performance data through a deterministic sequence of tool calls defined in src/tools/performance.ts and src/trace-processing/parse.ts.

How the Performance Trace Pipeline Works

The pipeline consists of three discrete tools that must be executed in sequence. Each tool is defined in src/tools/performance.ts and interacts with the Chrome DevTools Protocol (CDP) through the bundled DevTools front-end libraries.

Step 1: Starting the Trace with performance_start_trace

The performance_start_trace tool initiates a Chrome tracing session on the currently selected page. The implementation in src/tools/performance.ts (lines 29-71) performs the following operations:

  1. Safety Check: Calls Context.isRunningPerformanceTrace() to ensure only one trace runs concurrently. If a trace is active, the tool returns an error.
  2. State Management: Marks the trace as active via context.setIsRunningPerformanceTrace(true).
  3. Navigation Handling: Optionally navigates to about:blank and back to the original URL based on the reload parameter.
  4. Trace Initiation: Invokes page.tracing.start({categories}) with a curated list of DevTools tracing categories (lines 71-84).
  5. Auto-Stop: If autoStop is enabled, waits five seconds then calls the internal helper stopTracingAndAppendOutput.

Step 2: Stopping and Processing with performance_stop_trace

The performance_stop_trace tool terminates the active tracing session and triggers the processing pipeline. Located in src/tools/performance.ts (lines 15-27), this tool:

  1. Verifies the running-trace flag through Context.isRunningPerformanceTrace().
  2. If no trace is active, returns silently.
  3. Invokes stopTracingAndAppendOutput to handle the heavy lifting of data retrieval and parsing.

Step 3: Extracting Insights with performance_analyze_insight

The performance_analyze_insight tool retrieves specific Performance Insights from the parsed trace data. Implemented in src/tools/performance.ts (lines 40-74), the tool:

  1. Retrieves the most recent trace from context.recordedTraces().
  2. Calls response.attachTraceInsight(trace, insightSetId, insightName).
  3. The underlying implementation uses getInsightOutput from src/trace-processing/parse.ts to look up the insight set by ID, retrieve the concrete insight model, and format it using DevTools.PerformanceInsightFormatter.

Deep Dive: Trace Processing Architecture

The transition from raw binary trace data to structured insights involves several specialized components in src/trace-processing/parse.ts and the shared helper functions in src/tools/performance.ts.

The stopTracingAndAppendOutput Helper

This function in src/tools/performance.ts (lines 77-119) orchestrates the post-processing workflow:

Action Implementation Detail
Stop Tracing await page.tracing.stop() returns a Uint8Array of raw trace events.
File Persistence If filePath ends with .gz, the buffer is compressed using zlib.gzip. The file is saved via Context.saveFile.
Trace Parsing Invokes parseRawTraceBuffer(buffer) to convert raw bytes into a structured TraceResult.
CrUX Enrichment If --performanceCrux is enabled, calls populateCruxData(result) to query the Chrome UX Report API for each URL in the trace.
Result Storage context.storeTraceRecording(result) adds the TraceResult to the session history.
Summary Generation response.attachTraceSummary(result) appends a human-readable summary generated by getTraceSummary.
Cleanup Clears the running-trace flag via context.setIsRunningPerformanceTrace(false).

Parsing Raw Traces with parseRawTraceBuffer

Located in src/trace-processing/parse.ts (lines 27-63), this function interfaces with the DevTools TraceEngine:

  1. Resets the shared TraceEngine instance via engine.resetProcessor().
  2. Decodes the Uint8Array to a string and parses the JSON.
  3. Normalizes the data to an array of Event objects.
  4. Feeds events to engine.parse(events).
  5. Extracts engine.parsedTrace() (a ParsedTrace object).
  6. Returns both the parsed trace and any insight sets (parsedTrace.insights).
  7. Wraps errors in TraceParseError for consistent error handling.

Generating Human-Readable Summaries

The getTraceSummary function in src/trace-processing/parse.ts (lines 73-88) uses DevTools helpers to create markdown output:

const focus = DevTools.AgentFocus.fromParsedTrace(parsedTrace);
const formatter = new DevTools.PerformanceTraceFormatter(focus);
const summaryText = formatter.formatTraceSummary();

The resulting summary includes a call tree, network request tables, and descriptions of data formats.

CrUX Data Enrichment

The populateCruxData function in src/tools/performance.ts (lines 121-158) enhances traces with real-world field data:

  1. Builds a set of unique URLs from the trace metadata.
  2. Queries the public Chrome UX Report API for each URL.
  3. Stores the field data in result.parsedTrace.metadata.cruxFieldData.
  4. This data is later incorporated into the trace summary formatter to compare lab vs. field metrics.

Code Examples: Running the Pipeline

Starting a Trace from an LLM Prompt

{
  "tool": "performance_start_trace",
  "params": {
    "reload": true,
    "autoStop": false,
    "filePath": "trace.json.gz"
  }
}

Effect: Navigates to about:blank, starts tracing with the pre-defined categories, then navigates back to the original page.

Stopping the Trace Manually

{
  "tool": "performance_stop_trace",
  "params": {
    "filePath": "trace.json.gz"
  }
}

Effect: The trace is stopped, compressed, saved to trace.json.gz, parsed, CrUX data fetched (if enabled), and a markdown summary is attached to the response.

Getting a Specific Insight

{
  "tool": "performance_analyze_insight",
  "params": {
    "insightSetId": "main",
    "insightName": "LCPBreakdown"
  }
}

Effect: Returns the formatted insight text for the Largest Contentful Paint breakdown of the most recent trace.

Full Pipeline in a Single Prompt

Check the performance of https://example.com

The MCP client will typically issue the following tool calls internally:

  1. performance_start_trace (with reload: true).
  2. Wait for the page to load.
  3. performance_stop_trace (save as trace.json).
  4. performance_analyze_insight (choose an insight from the "Available insight sets" list).

The LLM receives a concise markdown report containing the overall performance summary, call-tree and network tables, and any requested insight details.

Key Source Files

File Role Link
src/tools/performance.ts Defines the three performance tools and the shared helper stopTracingAndAppendOutput. view
src/trace-processing/parse.ts Parses raw trace buffers, extracts insights, and produces human-readable summaries. view
src/third_party/index.ts Re-exports the DevTools front-end libraries (DevTools, zod, etc.) used by the performance pipeline. view
src/ToolDefinition.ts Provides the type-safe defineTool helper and the Response/Context contracts. view
src/McpContext.ts Holds the per-session state (recorded traces, flags, file helpers). view
src/logger.ts Simple logger used throughout the pipeline (e.g., for CrUX errors). view

Summary

  • The chrome-devtools-mcp performance trace analysis pipeline consists of three sequential tools: performance_start_trace, performance_stop_trace, and performance_analyze_insight.
  • Trace capture uses the Chrome DevTools Protocol with a curated category list, enforced by a singleton flag in McpContext to prevent concurrent traces.
  • Post-processing occurs in stopTracingAndAppendOutput, which handles gzip compression, file persistence, CrUX API enrichment, and storage of the TraceResult in session history.
  • Parsing leverages the bundled DevTools TraceEngine in src/trace-processing/parse.ts to convert raw Uint8Array buffers into structured ParsedTrace objects containing insight sets.
  • Insight extraction uses DevTools.PerformanceInsightFormatter to convert specific performance metrics (like LCPBreakdown) into markdown suitable for LLM consumption.

Frequently Asked Questions

What tracing categories does performance_start_trace use?

The tool initializes tracing with a curated list of DevTools categories specified in src/tools/performance.ts (lines 71-84). These categories include essential performance events such as blink, v8, loading, and network timelines, ensuring comprehensive coverage of web performance metrics without overwhelming the trace buffer.

How does the pipeline prevent concurrent trace sessions?

The implementation uses a boolean flag managed by McpContext.isRunningPerformanceTrace() and context.setIsRunningPerformanceTrace(). When performance_start_trace is invoked, it checks this flag in src/tools/performance.ts (lines 29-35) and rejects new requests if a trace is already active, ensuring deterministic resource allocation.

What is the difference between the trace summary and a performance insight?

The trace summary is a comprehensive markdown report generated by getTraceSummary in src/trace-processing/parse.ts (lines 73-88) using DevTools.PerformanceTraceFormatter, containing call trees and network tables. A performance insight is a specific metric extracted via performance_analyze_insight using DevTools.PerformanceInsightFormatter, targeting discrete issues like LCPBreakdown or layout shifts.

How does CrUX enrichment work in the performance pipeline?

When the --performanceCrux flag is enabled, the populateCruxData function in src/tools/performance.ts (lines 121-158) extracts unique URLs from the trace metadata and queries the public Chrome UX Report API. The field data is stored in result.parsedTrace.metadata.cruxFieldData and integrated into the trace summary, enabling comparison between lab results and real-world user experiences.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →