Skip to main content
Glama

performance_start_trace

Read-only

Start recording a performance trace to identify issues and measure Core Web Vitals scores for page optimization.

Instructions

Starts a performance trace recording on the selected page. This can be used to look for performance problems and insights to improve the performance of the page. It will also report Core Web Vital (CWV) scores for the page.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
reloadYesDetermines if, once tracing has started, the page should be automatically reloaded.
autoStopYesDetermines if the trace recording should be automatically stopped.

Implementation Reference

  • The main handler function that checks if a trace is already running, starts Puppeteer tracing with specific categories on the selected page, optionally reloads the page before and after starting, and handles auto-stop by waiting 5 seconds and calling the stop helper.
    handler: async (request, response, context) => {
      if (context.isRunningPerformanceTrace()) {
        response.appendResponseLine(
          'Error: a performance trace is already running. Use performance_stop_trace to stop it. Only one trace can be running at any given time.',
        );
        return;
      }
      context.setIsRunningPerformanceTrace(true);
    
      const page = context.getSelectedPage();
      const pageUrlForTracing = page.url();
    
      if (request.params.reload) {
        // Before starting the recording, navigate to about:blank to clear out any state.
        await page.goto('about:blank', {
          waitUntil: ['networkidle0'],
        });
      }
    
      // Keep in sync with the categories arrays in:
      // https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/timeline/TimelineController.ts
      // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/trace.js
      const categories = [
        '-*',
        'blink.console',
        'blink.user_timing',
        'devtools.timeline',
        'disabled-by-default-devtools.screenshot',
        'disabled-by-default-devtools.timeline',
        'disabled-by-default-devtools.timeline.invalidationTracking',
        'disabled-by-default-devtools.timeline.frame',
        'disabled-by-default-devtools.timeline.stack',
        'disabled-by-default-v8.cpu_profiler',
        'disabled-by-default-v8.cpu_profiler.hires',
        'latencyInfo',
        'loading',
        'disabled-by-default-lighthouse',
        'v8.execute',
        'v8',
      ];
      await page.tracing.start({
        categories,
      });
    
      if (request.params.reload) {
        await page.goto(pageUrlForTracing, {
          waitUntil: ['load'],
        });
      }
    
      if (request.params.autoStop) {
        await new Promise(resolve => setTimeout(resolve, 5_000));
        await stopTracingAndAppendOutput(page, response, context);
      } else {
        response.appendResponseLine(
          `The performance trace is being recorded. Use performance_stop_trace to stop it.`,
        );
      }
    },
  • Zod input schema defining optional boolean parameters 'reload' and 'autoStop' for controlling page reload and automatic stopping of the trace.
    schema: {
      reload: z
        .boolean()
        .describe(
          'Determines if, once tracing has started, the page should be automatically reloaded.',
        ),
      autoStop: z
        .boolean()
        .describe(
          'Determines if the trace recording should be automatically stopped.',
        ),
    },
  • Tool definition and export using defineTool, including name 'performance_start_trace', description, category annotation, schema, and inline handler.
    export const startTrace = defineTool({
      name: 'performance_start_trace',
      description:
        'Starts a performance trace recording on the selected page. This can be used to look for performance problems and insights to improve the performance of the page. It will also report Core Web Vital (CWV) scores for the page.',
      annotations: {
        category: ToolCategories.PERFORMANCE,
        readOnlyHint: true,
      },
      schema: {
        reload: z
          .boolean()
          .describe(
            'Determines if, once tracing has started, the page should be automatically reloaded.',
          ),
        autoStop: z
          .boolean()
          .describe(
            'Determines if the trace recording should be automatically stopped.',
          ),
      },
      handler: async (request, response, context) => {
        if (context.isRunningPerformanceTrace()) {
          response.appendResponseLine(
            'Error: a performance trace is already running. Use performance_stop_trace to stop it. Only one trace can be running at any given time.',
          );
          return;
        }
        context.setIsRunningPerformanceTrace(true);
    
        const page = context.getSelectedPage();
        const pageUrlForTracing = page.url();
    
        if (request.params.reload) {
          // Before starting the recording, navigate to about:blank to clear out any state.
          await page.goto('about:blank', {
            waitUntil: ['networkidle0'],
          });
        }
    
        // Keep in sync with the categories arrays in:
        // https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/timeline/TimelineController.ts
        // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/trace.js
        const categories = [
          '-*',
          'blink.console',
          'blink.user_timing',
          'devtools.timeline',
          'disabled-by-default-devtools.screenshot',
          'disabled-by-default-devtools.timeline',
          'disabled-by-default-devtools.timeline.invalidationTracking',
          'disabled-by-default-devtools.timeline.frame',
          'disabled-by-default-devtools.timeline.stack',
          'disabled-by-default-v8.cpu_profiler',
          'disabled-by-default-v8.cpu_profiler.hires',
          'latencyInfo',
          'loading',
          'disabled-by-default-lighthouse',
          'v8.execute',
          'v8',
        ];
        await page.tracing.start({
          categories,
        });
    
        if (request.params.reload) {
          await page.goto(pageUrlForTracing, {
            waitUntil: ['load'],
          });
        }
    
        if (request.params.autoStop) {
          await new Promise(resolve => setTimeout(resolve, 5_000));
          await stopTracingAndAppendOutput(page, response, context);
        } else {
          response.appendResponseLine(
            `The performance trace is being recorded. Use performance_stop_trace to stop it.`,
          );
        }
      },
    });
  • Helper function called when stopping the trace (auto or manual), parses the trace buffer using trace-processing functions, stores the result if successful, appends summary or error to response, and resets the running trace flag.
    async function stopTracingAndAppendOutput(
      page: Page,
      response: Response,
      context: Context,
    ): Promise<void> {
      try {
        const traceEventsBuffer = await page.tracing.stop();
        const result = await parseRawTraceBuffer(traceEventsBuffer);
        response.appendResponseLine('The performance trace has been stopped.');
        if (traceResultIsSuccess(result)) {
          context.storeTraceRecording(result);
          const traceSummaryText = getTraceSummary(result);
          response.appendResponseLine(traceSummaryText);
        } else {
          response.appendResponseLine(
            'There was an unexpected error parsing the trace:',
          );
          response.appendResponseLine(result.error);
        }
      } catch (e) {
        const errorText = e instanceof Error ? e.message : JSON.stringify(e);
        logger(`Error stopping performance trace: ${errorText}`);
        response.appendResponseLine(
          'An error occurred generating the response for this trace:',
        );
        response.appendResponseLine(errorText);
      } finally {
        context.setIsRunningPerformanceTrace(false);
      }
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds valuable context beyond the readOnlyHint annotation by explaining what the trace records (performance problems, insights, Core Web Vital scores) and the tool's purpose. However, it doesn't disclose important behavioral details like how long traces run, storage implications, performance impact, or what happens to existing traces. With annotations covering the safety aspect, this provides moderate additional value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly concise with three focused sentences that each earn their place: stating the core action, explaining the purpose, and mentioning additional functionality (CWV reporting). It's front-loaded with the primary function and wastes no words on redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (performance tracing with two parameters) and the presence of annotations (readOnlyHint), the description provides adequate context about what the tool does and why. However, without an output schema, it doesn't explain what data is returned or the trace format. For a diagnostic tool, more detail about output expectations would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the input schema already fully documents both parameters (reload and autoStop). The description doesn't add any parameter-specific information beyond what's in the schema. This meets the baseline expectation when schema coverage is complete, but doesn't enhance understanding of parameter usage or interactions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Starts a performance trace recording'), identifies the target resource ('on the selected page'), and distinguishes its purpose from sibling tools like performance_stop_trace (starting vs stopping) and performance_analyze_insight (recording vs analyzing). It provides a clear verb+resource combination with explicit differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context about when to use this tool ('to look for performance problems and insights to improve the performance of the page'), but doesn't explicitly state when NOT to use it or mention alternatives. It distinguishes from performance_stop_trace by implication, but doesn't explicitly guide on choosing between performance-related tools or other diagnostic methods.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SHAY5555-gif/chrome-devtools-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server