XcodeTraceMCP
Integrates with Apple's Xcode Instruments to record, analyze, and compare performance traces for iOS and macOS applications, detecting bottlenecks and providing optimization recommendations.
Provides tools for automated recording of running apps, analysis of Time Profiler, Memory, Network, Energy, Allocations, and Leaks data, regression detection, and trace cleanup using Xcode Instruments.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@XcodeTraceMCPFind why MyApp is slow"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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@latestVerify the local xcrun xctrace setup:
npx -y @xctrace-analyzer/mcp-server@latest --checkClaude 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@latestCheck that Codex registered the server:
codex mcp listOptional 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@latestBuild From Source
git clone https://github.com/jamesrochabrun/XcodeTraceMCP.git
cd XcodeTraceMCP
pnpm install --frozen-lockfile
pnpm verifyFor 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.
Recommended User Experience
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
.tracebundles 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 defaultfullpreset records Time Profiler with Leaks, Allocations, and HTTP Traffic instruments. Usefull-ioswhen profiling iOS/iPadOS and you want Power Profiler too.track_running_app- Attach to a running app, capture a trace, and optionally analyze it immediatelyanalyze_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 outputcompare_traces- Detect Time Profiler regressions between builds; supports optional dSYM symbolication and JSON outputcleanup_traces- Preview or delete generated.tracebundles after inspectionlist_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 |
| Disabled | Launch profiling can execute local programs through | Trusted local sessions where you need true cold-start or launch-time capture. |
| 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. |
|
| Keeps generated traces in a predictable user-level location. | Use a larger local scratch directory or project-specific trace folder. |
| 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. |
| 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. |
|
| 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. |
|
| Redacts common secrets and local user paths in MCP output. | Use |
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@latestMCP 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 Trafficfull-ios: Time Profiler + Leaks + Allocations + HTTP Traffic + Power Profilercpu: Time Profiler onlymemory: Allocations + Leaksnetwork: Time Profiler + HTTP Trafficenergy: 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:
Leaksfor memory leak checksAllocationsfor allocation churnNetworkfor network-only tracesTime Profilerfor 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
userBinaryHintsA 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 viaoutputFormat: "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:
dryRundefaults totrue, so the first call previews what would be deleted.Exact
tracePathscan be deleted withdryRun: falseafter confirmation.Directory cleanup requires
olderThanMinuteswhendryRun: 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 machinelist_devices: shows physical devices and simulators available toxctracecheck_xctrace: verifiesxcrun xctraceavailability 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
Research & Architecture - Deep dive into design decisions
Implementation Options - Why we chose this architecture
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: openedTrack 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 threadCompare 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 verifyTo smoke-test the local Xcode/xctrace installation:
pnpm test:integrationTo inspect the schemas exposed by local traces without committing trace files:
pnpm inspect:trace test-traces/memory.trace test-traces/network.traceTo run the packaged MCP stdio smoke test:
pnpm build
pnpm test:mcp-smokeTo contribute production support:
Fork, clone, and branch from
mainAdd or update real exported XML/HAR fixtures, not committed raw
.tracefilesUpdate the support matrix and docs for any newly supported template/schema
Improve recommendation patterns only when backed by parsed evidence
Add unit tests plus optional local integration validation
Submit a PR
Public npm packages are released from tagged builds after pnpm verify and the MCP stdio smoke test pass.
Release checklist:
Create and control the
@xctrace-analyzernpm organization.Set
NPM_TOKENin the GitHub repository secrets, or switch the release workflow to npm trusted publishing.Push a
vX.Y.Ztag after updating package versions andserver.json.After npm publish succeeds, authenticate with the MCP Registry and run
mcp-publisher publishfrom 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.
This server cannot be installed
Maintenance
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