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:
- Safety Check: Calls
Context.isRunningPerformanceTrace()to ensure only one trace runs concurrently. If a trace is active, the tool returns an error. - State Management: Marks the trace as active via
context.setIsRunningPerformanceTrace(true). - Navigation Handling: Optionally navigates to
about:blankand back to the original URL based on thereloadparameter. - Trace Initiation: Invokes
page.tracing.start({categories})with a curated list of DevTools tracing categories (lines 71-84). - Auto-Stop: If
autoStopis enabled, waits five seconds then calls the internal helperstopTracingAndAppendOutput.
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:
- Verifies the running-trace flag through
Context.isRunningPerformanceTrace(). - If no trace is active, returns silently.
- Invokes
stopTracingAndAppendOutputto 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:
- Retrieves the most recent trace from
context.recordedTraces(). - Calls
response.attachTraceInsight(trace, insightSetId, insightName). - The underlying implementation uses
getInsightOutputfromsrc/trace-processing/parse.tsto look up the insight set by ID, retrieve the concrete insight model, and format it usingDevTools.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:
- Resets the shared
TraceEngineinstance viaengine.resetProcessor(). - Decodes the
Uint8Arrayto a string and parses the JSON. - Normalizes the data to an array of
Eventobjects. - Feeds events to
engine.parse(events). - Extracts
engine.parsedTrace()(aParsedTraceobject). - Returns both the parsed trace and any insight sets (
parsedTrace.insights). - Wraps errors in
TraceParseErrorfor 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:
- Builds a set of unique URLs from the trace metadata.
- Queries the public Chrome UX Report API for each URL.
- Stores the field data in
result.parsedTrace.metadata.cruxFieldData. - 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:
performance_start_trace(withreload: true).- Wait for the page to load.
performance_stop_trace(save astrace.json).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, andperformance_analyze_insight. - Trace capture uses the Chrome DevTools Protocol with a curated category list, enforced by a singleton flag in
McpContextto prevent concurrent traces. - Post-processing occurs in
stopTracingAndAppendOutput, which handles gzip compression, file persistence, CrUX API enrichment, and storage of theTraceResultin session history. - Parsing leverages the bundled DevTools
TraceEngineinsrc/trace-processing/parse.tsto convert rawUint8Arraybuffers into structuredParsedTraceobjects containing insight sets. - Insight extraction uses
DevTools.PerformanceInsightFormatterto convert specific performance metrics (likeLCPBreakdown) 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →