Skip to main content
Glama

Xcode Instruments Trace Analyzer (MCP)

https://github.com/user-attachments/assets/e92cbd43-cd6c-4ec9-9392-d0d2408a648d

Intelligent performance analysis for Xcode Instruments traces, powered by AI via Model Context Protocol.

Ask Claude to record and analyze Xcode Instruments traces, detect Time Profiler regressions, and get actionable optimization recommendations through a local MCP server.

This project is an Instruments companion, not a full replacement for Instruments.app. It automates the parts Apple exposes through xcrun xctrace: recording, TOC/XML/HAR export, symbolication, parsing, reports, regression checks, and safe trace cleanup. Recording tools open the saved .trace in Instruments.app by default so areas that are not present in the trace or not exportable can be verified in the GUI. When a template or Instruments view is not exportable, the server reports that limitation instead of inventing data.


Installation

Claude Code

claude mcp add --transport stdio --scope user xctrace-analyzer -- npx -y @xctrace-analyzer/mcp-server@latest

Verify the local xcrun xctrace setup:

npx -y @xctrace-analyzer/mcp-server@latest --check

Claude Desktop

Add this to ~/Library/Application Support/Claude/claude_desktop_config.json, then restart Claude Desktop:

{
  "mcpServers": {
    "xctrace-analyzer": {
      "command": "npx",
      "args": ["-y", "@xctrace-analyzer/mcp-server@latest"]
    }
  }
}

Codex CLI

codex mcp add xctrace-analyzer -- npx -y @xctrace-analyzer/mcp-server@latest

Check that Codex registered the server:

codex mcp list

Optional Environment Settings

Claude Desktop-style MCP configs can pass security settings through env:

{
  "mcpServers": {
    "xctrace-analyzer": {
      "command": "npx",
      "args": ["-y", "@xctrace-analyzer/mcp-server@latest"],
      "env": {
        "XCTRACE_ANALYZER_TRACE_ROOT": "/Users/you/Library/Application Support/xctrace-analyzer/traces",
        "XCTRACE_ANALYZER_ALLOW_LAUNCH": "1"
      }
    }
  }
}

Codex can pass the same settings with --env:

codex mcp add xctrace-analyzer \
  --env XCTRACE_ANALYZER_TRACE_ROOT="/Users/you/Library/Application Support/xctrace-analyzer/traces" \
  --env XCTRACE_ANALYZER_ALLOW_LAUNCH=1 \
  -- npx -y @xctrace-analyzer/mcp-server@latest

Build From Source

git clone https://github.com/jamesrochabrun/XcodeTraceMCP.git
cd XcodeTraceMCP
pnpm install --frozen-lockfile
pnpm verify

For local source installs, point your MCP client at packages/mcp-server/dist/index.js.


Avoiding Recording Interruptions

Trace recording runs as a single uninterrupted xcrun xctrace session. If your assistant pauses mid-recording to ask for tool approval, the capture window can drift or the run may need to be restarted. To keep recordings clean, before starting a profile:

  • Claude Code: switch to auto permission mode (Shift+Tab or /permissions) so MCP tool calls are not gated by approval prompts during recording.

  • Codex: enable auto-review so recording is not interrupted by approval gates.

Re-enable interactive approvals afterward if you prefer a stricter mode for the rest of your session.


For clients that support skills, register the bundled skill at skills/xctrace-profiler. npm installs also include the same skill at node_modules/@xctrace-analyzer/mcp-server/skills/xctrace-profiler. Once the skill is available, users can start from normal language:

Profile this app.

Useful prompts:

Find why this app is slow.
Profile this app for hangs and tell me which of my code is responsible.
Check this build for leaks and allocation churn.
Analyze network activity.
Launch this app and profile startup hangs.
I will launch MyApp; record it for 60 seconds when it appears.
Analyze this trace.
Compare these two traces.
Clean up profiling traces when we are done.

The skill is the user-facing planner. It chooses the target, selects the recording or analysis workflow, records or analyzes with outputFormat: "both" when diagnostics matter, can wait for a manually launched app and attach to the first valid PID without a second prompt, can rerun analyze_trace with timeRangeMs around a hang so the final answer names app-owned code from ## Top User-Code Frames, and offers cleanup_traces once the saved trace is no longer needed.

Use the raw MCP tools directly only when building another integration, test, or scripted workflow.


Usage

You: Profile this app.

Claude: I'll choose the profiling workflow, record or analyze the trace, and report the app-owned code responsible.

That's it. Claude can now profile apps, analyze traces, detect regressions, and suggest optimizations.


What It Does

Profile Running Apps

You: Profile the running app MyApp for 60 seconds with the full preset
Claude: [Records one combined xctrace session and reports CPU, leaks, allocations, and network findings]

Analyze Existing Traces

You: Analyze /path/to/app.trace
Claude: [Identifies Time Profiler bottlenecks and Memory, Network, Energy, Allocations, or Leaks findings when those instruments are present]

Detect Regressions

You: Compare baseline.trace with current.trace
Claude: [Shows performance delta, regressions, improvements]

List Available Tools

You: What Instruments templates are available?
Claude: [Lists all templates on your system]

Features

  • ๐Ÿ” Automatic bottleneck detection - Finds slow functions, calculates impact

  • ๐ŸŽฅ Automated recording - Attach to a running app, capture a trace, open it in Instruments.app by default, and analyze it in one MCP call

  • ๐Ÿงญ Multi-instrument analysis - Auto-detects Memory, Network, Energy, Allocations, and Leaks data

  • ๐ŸงŠ Hang-focused workflow - Captures hang events, scopes follow-up analysis to the hang window, and attributes samples to app code

  • ๐Ÿ“Š Regression analysis - Compare builds to catch performance issues

  • ๐Ÿ’ก Smart recommendations - Pattern-based suggestions with Swift code examples

  • ๐Ÿค– Natural language interface - Just ask Claude in plain English

  • ๐Ÿงพ Honest diagnostics - Reports support status, export attempts, and non-exportable data

  • ๐Ÿงน Safe trace cleanup - Preview or delete .trace bundles after the user is done inspecting them

Supported Scope

This repository is a local MCP server distributed through npm/npx and usable from source. profile_running_app can attach to a process, launch a target, or record all processes with one combined xcrun xctrace record session, save the .trace, open it in Instruments.app by default, and analyze it. track_running_app records one specific template and also opens the saved trace by default. Recorded traces are retained so users can inspect them in Instruments.app; cleanup_traces previews or deletes .trace bundles after the user confirms they are no longer needed. analyze_trace auto-detects Time Profiler, Memory, Network, Energy, Allocations, and Leaks data exported by xcrun xctrace; each area is reported as available, partial, not exportable, or not present in the trace. If a GUI track such as Leaks is visible in Instruments.app but xcrun export --toc exposes no exportable table schema, the report marks that family as not_exportable, not as "no issues." Existing traces can be scoped with timeRangeMs to answer "what ran during this hang window?" without re-recording, and Top User-Code Frames attribute Time Profiler samples to app binaries instead of system frames. If Time Profiler export or parsing fails, the report says it failed to parse instead of presenting zero-thread CPU data as a valid result. compare_traces remains focused on Time Profiler regressions. Full Instruments.app GUI parity remains out of scope.


Architecture

Monorepo with two packages:

@xctrace-analyzer/core

Reusable TypeScript library for trace analysis.

import { analyzeTraceFile } from '@xctrace-analyzer/core';

const analysis = await analyzeTraceFile('/path/to/trace.trace');
console.log(analysis.bottlenecks);
console.log(analysis.recommendations);

@xctrace-analyzer/mcp-server

MCP server exposing the core library to AI assistants.

Tools:

  • profile_running_app - Run one combined profiling recording against a running app and return one report. For macOS, the default full preset records Time Profiler with Leaks, Allocations, and HTTP Traffic instruments. Use full-ios when profiling iOS/iPadOS and you want Power Profiler too.

  • track_running_app - Attach to a running app, capture a trace, and optionally analyze it immediately

  • analyze_trace - Analyze Time Profiler bottlenecks plus supported Memory, Network, Energy, Allocations, and Leaks data; supports optional dSYM symbolication, time-window scoping, user-code frame attribution, and JSON output

  • compare_traces - Detect Time Profiler regressions between builds; supports optional dSYM symbolication and JSON output

  • cleanup_traces - Preview or delete generated .trace bundles after inspection

  • list_templates, list_devices, check_xctrace

Security Defaults

The MCP server keeps normal attach profiling and existing trace analysis available by default. These settings do not remove Time Profiler, Leaks, Allocations, HTTP Traffic, or other Instruments from normal recordings. They only restrict operations that can execute local programs, capture unrelated app activity, write arbitrary paths, delete arbitrary traces, or print sensitive details in reports.

Option

Default

Why it matters

When to enable

XCTRACE_ANALYZER_ALLOW_LAUNCH=1

Disabled

Launch profiling can execute local programs through xcrun xctrace --launch; this is useful for startup profiling but equivalent to granting the MCP server permission to run the requested app or command.

Trusted local sessions where you need true cold-start or launch-time capture.

XCTRACE_ANALYZER_ALLOW_ALL_PROCESSES=1

Disabled

All-process traces can include activity from unrelated apps and background services, not just the target under investigation.

System-wide investigations where the user explicitly accepts broader capture.

XCTRACE_ANALYZER_TRACE_ROOT=/path/to/traces

~/Library/Application Support/xctrace-analyzer/traces

Keeps generated traces in a predictable user-level location.

Use a larger local scratch directory or project-specific trace folder.

XCTRACE_ANALYZER_ALLOW_EXTERNAL_OUTPUT=1

Disabled

Prevents writes outside the trace root, including launch stdin/stdout redirection paths.

Trusted automation that must save traces or launch streams to a known external directory.

XCTRACE_ANALYZER_ALLOW_EXTERNAL_CLEANUP=1

Disabled

Prevents destructive cleanup outside the trace root, except exact traces recorded by the current server instance.

Trusted maintenance scripts after a dry-run preview.

XCTRACE_ANALYZER_MAX_DURATION_SECONDS=300

300

Bounds trace size and recording time so an accidental request does not capture indefinitely or produce huge exports.

Longer repros where the user expects larger traces.

XCTRACE_ANALYZER_REDACTION=balanced

balanced

Redacts common secrets and local user paths in MCP output. strict also redacts hosts; off preserves full local details.

Use strict for shared reports; use off only in trusted local debugging.

For startup profiling without enabling launch mode, start the app manually and attach by exact PID as soon as it appears. For trusted local startup profiling, start the MCP server with launch enabled:

XCTRACE_ANALYZER_ALLOW_LAUNCH=1 npx -y @xctrace-analyzer/mcp-server@latest

MCP Tool Reference

profile_running_app

Best default tool when a user says "start profiling", "record performance", or "give me a full report" for an app that is already running.

It performs one xcrun xctrace record call. For the macOS full preset, it uses Time Profiler as the base template and adds Leaks, Allocations, and HTTP Traffic as Instruments. A durationSeconds value of 60 means one 60-second recording, plus save/export/analyze time.

Report sections include:

  • Summary, trace path, process, preset, recording strategy, and whether Instruments.app opened

  • Support matrix and export diagnostics

  • CPU / Time Profiler bottlenecks

  • Main-thread hang events; severe hangs are reported as critical findings even if no CPU function crosses the Time Profiler bottleneck threshold

  • Top User-Code Frames for app-attributed CPU work

  • Time Profiler parse-failure callouts when CPU samples could not be parsed

  • Leaks findings when exportable

  • Allocation metrics and churn findings when exportable

  • Network request metrics and failures when HAR/CFNetwork data is exportable

  • Prioritized recommendations aggregated across all findings

Presets:

  • full: Time Profiler + Leaks + Allocations + HTTP Traffic

  • full-ios: Time Profiler + Leaks + Allocations + HTTP Traffic + Power Profiler

  • cpu: Time Profiler only

  • memory: Allocations + Leaks

  • network: Time Profiler + HTTP Traffic

  • energy: Power Profiler only; intended for iOS/iPadOS targets

profile_running_app opens the saved trace in Instruments.app by default after recording. Pass openInInstruments: false for CI or headless automation. The report keeps the trace path visible and reminds agents to use cleanup_traces after the user is done with the trace.

track_running_app

Use this when the user wants a specific Instruments template rather than a full preset. It records one trace with the requested template, then optionally analyzes it. It supports attach, launch, and all-processes targets; processName remains the attach shorthand.

track_running_app opens the saved trace in Instruments.app by default after recording. Pass openInInstruments: false for CI or headless automation. The report keeps the trace path visible and reminds agents to use cleanup_traces after the user is done with the trace.

Common templates:

  • Leaks for memory leak checks

  • Allocations for allocation churn

  • Network for network-only traces

  • Time Profiler for CPU sampling

analyze_trace

Use this for an existing .trace file. The parser reads xcrun xctrace export --toc, exports supported schemas, and normalizes results into one analysis model.

It can report:

  • Time Profiler bottlenecks, hot functions, and recommendations

  • Additional Memory, Network, Energy, Allocations, and Leaks sections when Xcode exposes usable tables

  • Clear status when a family is available, partial, not exportable, or not present in the trace

  • Scoped Time Profiler samples and hang events with timeRangeMs: { startMs, endMs }

  • Top User-Code Frames, using trace process metadata plus optional userBinaryHints

  • A Time Profiler parse-failure message when CPU samples could not be parsed; this is an analyzer/export issue, not evidence of zero CPU work

  • Machine-readable JSON via outputFormat: "json" or Markdown plus JSON via outputFormat: "both"

Example scoped follow-up after a hang starts near 2 seconds and lasts about 5 seconds:

{
  "tracePath": "/path/to/app.trace",
  "timeRangeMs": { "startMs": 2000, "endMs": 7000 },
  "userBinaryHints": ["MyApp"],
  "outputFormat": "both"
}

compare_traces

Use this for Time Profiler regression checks between a baseline and current trace. It compares total time and function-level deltas, then can mark the MCP call as an error when failOnRegression is true.

cleanup_traces

Use this after a profiling session when the user has finished inspecting the saved .trace in Instruments.app. The tool only acts on paths ending in .trace.

Safe defaults:

  • dryRun defaults to true, so the first call previews what would be deleted.

  • Exact tracePaths can be deleted with dryRun: false after confirmation.

  • Directory cleanup requires olderThanMinutes when dryRun: false; this avoids accidentally deleting every trace in a folder.

Example after a report:

{
  "tracePaths": ["/path/to/MyApp-full.trace"],
  "dryRun": false
}

Discovery And Health Tools

  • list_templates: shows Instruments templates available on the machine

  • list_devices: shows physical devices and simulators available to xctrace

  • check_xctrace: verifies xcrun xctrace availability and reports the installed version


Requirements

  • macOS with Xcode Command Line Tools

  • Node.js 18+

  • pnpm only for source development

  • Claude Desktop, Claude Code (Web/CLI), or another MCP-compatible client


Documentation


Examples

Profile a running app

You: Start profiling MyApp for 60 seconds and report all issues

Claude:
# Profiling Report

- Process: MyApp
- Preset: full
- Recording strategy: combined
- Duration: 60s
- Base template: Time Profiler
- Instruments: Leaks, Allocations, HTTP Traffic

## Summary
- Overall status: critical issues found
- Traces recorded: 1/1
- Traces analyzed: 1/1

## CPU / Time Profiler
Top bottlenecks and slow functions.

## Leaks
Leak count, leaked bytes, and leak findings.

## Allocations
Allocation volume and churn findings.

## Network
Requests, failures, bytes transferred, and hosts.

For iOS/iPadOS, use the `full-ios` preset to include Energy / Power data.

Record a manual launch

You: I will launch MyApp; record it for 60 seconds when it appears.

Claude:
I'm watching for MyApp now; launch it when ready.

# Profiling Report

- Target: MyApp PID 12345, attached immediately after launch
- Duration: 60s
- Preset: full
- Trace: ~/Library/Application Support/xctrace-analyzer/traces/MyApp-full-...trace
- Instruments.app: opened

Track a running app for leaks

You: Track MyApp for leaks for 60 seconds on the iPhone 16 Pro Simulator

Claude:
# Running App Trace Report

- Process: MyApp
- Template: Leaks
- Duration: 60s
- Device: iPhone 16 Pro Simulator
- Trace: ~/Library/Application Support/xctrace-analyzer/traces/MyApp-Leaks-2026-05-02T16-30-00-000Z.trace

## Additional Instrument Analysis
### Leaks Analysis
3 leaks were detected.

Analyze a trace

You: Check the performance of my latest build at ~/traces/v2.0.trace

Claude:
๐Ÿ“Š Analysis Summary: Total time 5.2s across 3 threads.

๐ŸŒ Bottlenecks:
1. ImageProcessor.resize() - 450ms (critical)
2. JSONDecoder.decode() - 120ms (high)

๐Ÿ’ก Recommendations:
- Implement NSCache for image caching (save ~400ms)
- Move JSON parsing to background thread

Compare builds

You: Compare baseline.trace with current.trace and tell me if we regressed

Claude:
โš ๏ธ Performance regressed by 15% (+0.65s)

Regressions:
๐Ÿ”ด NetworkClient.parseJSON() - 50ms โ†’ 85ms (+70%)

Improvements:
โœ… DatabaseManager.fetch() - 200ms โ†’ 120ms (-40%)

The NetworkClient regression is concerning. Should I investigate?

Contributing

Contributions welcome.

Before sending changes, run:

pnpm verify

To smoke-test the local Xcode/xctrace installation:

pnpm test:integration

To inspect the schemas exposed by local traces without committing trace files:

pnpm inspect:trace test-traces/memory.trace test-traces/network.trace

To run the packaged MCP stdio smoke test:

pnpm build
pnpm test:mcp-smoke

To contribute production support:

  1. Fork, clone, and branch from main

  2. Add or update real exported XML/HAR fixtures, not committed raw .trace files

  3. Update the support matrix and docs for any newly supported template/schema

  4. Improve recommendation patterns only when backed by parsed evidence

  5. Add unit tests plus optional local integration validation

  6. Submit a PR

Public npm packages are released from tagged builds after pnpm verify and the MCP stdio smoke test pass.

Release checklist:

  1. Create and control the @xctrace-analyzer npm organization.

  2. Set NPM_TOKEN in the GitHub repository secrets, or switch the release workflow to npm trusted publishing.

  3. Push a vX.Y.Z tag after updating package versions and server.json.

  4. After npm publish succeeds, authenticate with the MCP Registry and run mcp-publisher publish from the repo root.


License

MIT


Built by research-first approach. See MCP_RESEARCH_AND_ARCHITECTURE.md for the full story of how this was designed.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

โ€“Maintainers
โ€“Response time
0dRelease cycle
2Releases (12mo)

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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/jamesrochabrun/XcodeTraceMCP'

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