内容
# apple-instruments-mcp
`apple-instruments-mcp` 是一个 Python MCP 服务器,用于通过 `xcrun xctrace` 分析 Apple 平台应用和进程的性能。它允许 MCP 客户端(如 Claude Desktop)记录跟踪,检查现有的 `.trace` 包,并返回简洁的性能报告以及可行的建议。
服务器可以针对 iOS、iPadOS、macOS、tvOS、watchOS、visionOS、模拟器、物理设备和主机进程,当这些目标对已安装的 Xcode/Instruments 工具链可见时。实际的模板和设备支持由 `xcrun xctrace list devices` 和 `xcrun xctrace list templates` 在您的 Mac 上确定。
## 功能
- 使用 `xctrace` 从 MCP 客户端记录新的跟踪。
- 在不重新记录的情况下分析现有的 `.trace` 包。
- 报告启动时间、内存分配、泄漏、CPU 热点和网络活动。
- 按包 ID 或可执行路径启动应用。
- 按进程名称或 PID 附加到正在运行的进程。
- 当 Instruments 模板支持时,记录所有进程。
- 列出可用的设备、模拟器、运行时和 Instruments 模板。
- 返回原始或 JSON 结构的设备/模板列表。
- 使用 `dry_run` 预览生成的 `xctrace` 命令。
- 保留 `.trace` 和 XML 工件以供稍后检查。
- 返回包含主要违规者和建议修复的人类可读摘要。
- 作为标准 stdio MCP 服务器运行。
## 要求
- macOS
- 已安装 Xcode 和 Instruments
- Xcode 命令行工具:`xcode-select --install`
- Python 3.11 或更高版本
- 受支持的目标对 `xctrace` 可见:启动的模拟器、连接的设备、本地 macOS 应用、正在运行的进程或所有进程记录。
物理设备可能需要在 `设置 > 开发者` 中启用 UI 自动化。
## 安装
该软件包发布在 PyPI 上。推荐使用 [`uvx`](https://github.com/astral-sh/uv) 运行它,它会在需要时下载并缓存服务器,而不会污染您的环境:
```bash
uvx apple-instruments-mcp
```
或者,使用 `pipx` 或 `pip` 全球安装:
```bash
pipx install apple-instruments-mcp
# 或
python -m pip install apple-instruments-mcp
```
任一路径都提供 `apple-instruments-mcp` 可执行文件。
## MCP 客户端配置
`apple-instruments-mcp` 是一个标准的 stdio MCP 服务器,因此任何 MCP 兼容的客户端都可以使用 — Claude Desktop、Claude Code、Codex CLI、Kiro、Cursor、Cline、Continue、Windsurf、Zed 或任何其他支持 MCP 的客户端。
最简单的配置使用 `uvx`,因此客户端会在需要时启动服务器,而无需单独的安装步骤。适用于 Claude Desktop 的示例(`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"apple-instruments": {
"command": "uvx",
"args": ["apple-instruments-mcp"]
}
}
}
```
要固定特定版本,请将参数替换为 `apple-instruments-mcp@1.2.1`。
适用于 Claude Code:
```bash
claude mcp add apple-instruments -- uvx apple-instruments-mcp
```
如果您更喜欢全局安装(`pipx` 或 `pip`),请将客户端指向生成的二进制文件:
```json
{
"mcpServers": {
"apple-instruments": {
"command": "apple-instruments-mcp"
}
}
}
```
其他客户端(Codex CLI、Kiro、Cursor、Cline、Continue、Windsurf、Zed)接受相同的 `command` / `args` 形状,具体取决于其自身的 MCP 服务器配置 - 请查看客户端的文档以获取确切的文件路径。在保存后重启客户端。
## 示例提示
```text
运行 xctrace 医生并告诉我当前是否可以记录。
列出此 Mac 上可用的设备和 Instruments 模板。
在模拟器上使用完整预设分析 com.example.app 15 秒。
记录 com.example.app 在 iPhone 模拟器上的启动跟踪并显示启动违规者。
启动 /Applications/MyMacApp.app 并使用 Time Profiler 显示 CPU 热点方法。
分析 com.example.app 的时间配置文件,然后放大 8000ms–12000ms 窗口并标记主线程停顿超过 200ms。
分析发布构建并使用 ~/Build/MyApp.dSYM 符号化原始地址。
将 Allocations 附加到正在运行的进程 MyMacApp 30 秒。
将 Time Profiler 附加到 PID 1234。
使用 Time Profiler 记录所有进程 10 秒。
分析 com.example.app 的网络活动并标记慢速请求。
分析 ~/Desktop/launch.trace 中现有的跟踪。
比较 ~/Desktop/baseline.trace 和 ~/Desktop/candidate.trace 的启动回归。
```
## 工具
| 工具 | Instruments 模板 | 描述 |
| --- | --- | --- |
| `doctor` | - | 一次性健康检查:xctrace 版本/路径、在线/离线设备数量、CoreSimulator 访问、模板/仪器和针对楔形或沙盒失败的目标诊断。 |
| `list_devices` | - | 列出对 `xctrace` 可见的设备、模拟器、运行时和主机目标。 |
| `list_devices_structured` | - | 以 JSON 形式返回设备/运行时列表。 |
| `list_templates` | - | 列出此 Mac 上安装的 Instruments 模板。 |
| `list_templates_structured` | - | 以 JSON 形式返回模板列表。 |
| `profile_preset` | `cpu` / `memory` / `network` / `full` | 记录一组仪器,然后报告每个产生数据的系列。`full` 涵盖 CPU + 分配 + 泄漏 + 网络,单次运行。 |
| `profile_ios_app` | 按 `profile_type` 选择 | 在模拟器/设备上分析 iOS、iPadOS、tvOS、watchOS 或 visionOS 应用的性能。 |
| `profile_mac_app` | 按 `profile_type` 选择 | 分析 macOS `.app` 或可执行文件的性能。 |
| `profile_process` | 按 `profile_type` 选择 | 分析正在运行的进程的性能。 |
| `profile_all_processes` | 按 `profile_type` 选择 | 分析主机或选定设备上的所有进程的性能。 |
| `analyze_launch` | 应用启动 | 记录并分析应用启动时间。 |
| `analyze_launch_trace` | 应用启动 | 分析现有的应用启动 `.trace`。 |
| `analyze_allocations` | 分配 | 记录内存分配并报告实时堆/VM 总数以及顶级分配类别。 |
| `analyze_allocations_trace` | 分配 | 分析现有的分配 `.trace`。 |
| `analyze_leaks` | 泄漏 | 记录泄漏跟踪,并在可用时报告导出的泄漏详细信息。 |
| `analyze_leaks_trace` | 泄漏 | 分析现有的泄漏 `.trace`,当泄漏详细信息可导出时。 |
| `analyze_time_profiler` | 时间分析器 | 记录 CPU 样本并报告热点方法。支持 `scope_start_ms`/`scope_end_ms` 窗口,主线程挂起检测,用户二进制过滤和 `dsym_path` 符号化发布构建帧。 |
| `analyze_time_profiler_trace` | 时间分析器 | 分析现有的时间分析器 `.trace`。与 `analyze_time_profiler` 具有相同的范围/挂起/用户二进制/DSYM 选项。 |
| `analyze_network` | 网络 | 记录网络请求、延迟、传输大小和状态码。 |
| `analyze_network_trace` | 网络 | 分析现有的网络 `.trace`。 |
| `compare_launch_traces` | 应用启动 | 比较两个应用启动跟踪并报告启动差异。 |
| `compare_memory_traces` | 分配 | 比较两个分配跟踪并报告内存差异。 |
| `compare_cpu_traces` | 时间分析器 | 比较两个时间分析器跟踪并报告 CPU 差异。 |
| `build_xctrace_command` | 任意 | 返回针对目标的精确 `xcrun xctrace record` 命令,而不执行它。 |
## 记录目标
记录工具接受确切的一种目标模式:
- `bundle_id`:应用包 ID,例如 `com.example.app`。与 `device_id` 一起用于 iOS、iPadOS、tvOS、watchOS 和 visionOS 模拟器/设备启动。
- `launch_path`:可执行路径或 `.app` 路径。用于 macOS 应用和命令行工具。
- `process_name`:按名称附加到正在运行的进程。
- `pid`:按进程 ID 附加到正在运行的进程。
- `all_processes`:当选定的模板支持时,记录所有进程。
附加的记录参数:
- `device_id`:`list_devices` 的可选模拟器 UUID 或物理设备标识符。省略它用于主机 macOS 分析。
- `launch_args`:启动路径后传递的可选 shell 样式参数。
- `time_limit_seconds`:记录持续时间,从 5 到 120 秒。默认为 20。
- `dry_run`:返回生成的 `xctrace` 命令而不记录。
- `keep_trace`:保留运行目录和生成的 `.trace`/XML 工件,包括失败时,并包含它们的路径在报告中。
- `output_dir`:生成的工件的可选父目录。每个运行在其中创建一个专用子目录。
示例:
```json
{ "bundle_id": "com.example.app", "device_id": "SIMULATOR-UUID" }
{ "launch_path": "/Applications/MyMacApp.app" }
{ "launch_path": "/usr/bin/python3", "launch_args": "--version" }
{ "process_name": "MyMacApp" }
{ "pid": 1234 }
{ "all_processes": true }
{ "launch_path": "/Applications/MyMacApp.app", "dry_run": true }
{ "bundle_id": "com.example.app", "device_id": "SIMULATOR-UUID", "keep_trace": true, "output_dir": "~/Desktop/traces" }
```
`profile_*` 工具是围绕通用 `analyze_*` 工具的更高级别的包装器。当您知道目标形状时,请优先使用它们:
```json
{ "profile_type": "launch", "bundle_id": "com.example.app", "device_id": "SIMULATOR-UUID" }
{ "profile_type": "time_profiler", "launch_path": "/Applications/MyMacApp.app" }
{ "profile_type": "allocations", "process_name": "MyMacApp" }
{ "profile_type": "time_profiler", "pid": 1234 }
{ "profile_type": "time_profiler" }
```
支持的 `profile_type` 值有 `launch`、`allocations`、`leaks`、`time_profiler` 和 `network`。
## 自定义阈值
通用 `analyze_*` 和 `analyze_*_trace` 工具公开了特定于解析器的阈值。当默认值对于设备类别、平台、工作负载或 CI 预算过于严格或宽松时,请使用这些阈值。
启动:
- `launch_good_ms`
- `launch_critical_ms`
- `offender_warning_ms`
- `offender_critical_ms`
分配:
- `memory_warning_mb`
- `memory_critical_mb`
- `memory_cache_warning_mb`
泄漏:
- `leak_critical_count`
时间分析器:
- `total_good_ms` - 标准化 CPU 负载的良好阈值,以 CPU 活动毫秒/墙上秒为单位。
- `total_critical_ms` - 相同标准化 CPU 负载指标的临界阈值。默认值 100/500 对应于大约 10%/50% 的单个核心占用。
- `method_warning_ms`
- `method_critical_ms`
网络:
- `request_warning_ms`
- `request_critical_ms`
- `slow_request_critical_count`
- `transfer_warning_mb`
示例:
```json
{
"bundle_id": "com.example.app",
"device_id": "SIMULATOR-UUID",
"launch_good_ms": 700,
"launch_critical_ms": 1500,
"offender_warning_ms": 150,
"offender_critical_ms": 500
}
```
## 跟踪分析参数
跟踪分析工具接受:
- `trace_path`:现有 `.trace` 包的绝对路径。
- `bundle_id`:生成的报告中使用的可选目标名称。
跟踪比较工具接受:
- `baseline_trace_path`:基线 `.trace` 包的绝对路径。
- `candidate_trace_path`:候选 `.trace` 包的绝对路径。
- `bundle_id`:生成的报告中使用的可选目标名称。
示例:
```json
{
"baseline_trace_path": "~/Desktop/baseline.trace",
"candidate_trace_path": "~/Desktop/candidate.trace",
"bundle_id": "com.example.app"
}
```
## 示例报告
```markdown
# 应用启动分析 - com.example.app
警告:启动时间 1240ms - 高于 400ms。用户可能会注意到延迟。
**总计:** 1240ms
## 阶段
- **pre-main(dyld + 静态初始化):** 434ms(35%)
- **post-main(AppDelegate + UI):** 806ms(65%)
## 顶级违规者
严重:`-[DatabaseManager setup]` [post-main]
自身:**540ms** | 总计:540ms | 43%
建议:将数据库初始化移至后台队列或使用延迟加载。
警告:`+[AnalyticsSDK configure:]` [post-main]
自身:**210ms** | 总计:210ms | 17%
建议:在渲染第一个帧后延迟分析 SDK 初始化。
## 建议
- 修复 1 个关键违规者 - 每个添加 300ms+ 启动。
- 目标:总启动时间低于 400ms。
```
## 注意
- 记录工具创建的临时 `.trace` 包在每次运行后都会被清理。
- 失败的记录仅在其包含非空工件时保留部分 `.trace`;空和零字节包会被删除。
- 服务器仅终止其通过其看护程序启动的 `xctrace` 子进程。它不会扫描 Mac 上运行的不相关 `xctrace` 会话。
- 记录拆卸在请求的时间限制后有 15 秒的宽限期。已知断开输出立即中止,而不是留下 `xctrace` 子进程楔形。
- 所有分析都基于 `xcrun xctrace export` 导出的 XML。
- 报告包含一个“分析质量”部分,当成功的 XML 导出为空或包含没有识别的数据时,会显示为空或“导出错误”,并且不会对选定的解析器运行解析器。失败的导出报告为“分析不完整”,在“导出错误”下,并且不会对缺少或部分 XML 的解析器运行解析器。
- 如果您已经有一个跟踪,请使用 `_trace` 工具避免再次记录。
## 解析器状态
每个解析器都连接到特定的 `xctrace export --xpath` 查询。工具链已针对真实 `.trace` 包进行了端到端验证,验证结果如下:
| 模板 | xpath / schema | 状态 |
| --- | --- | --- |
| 时间分析器 | `time-profile` | ✅ 已针对真实跟踪验证 |
| 应用启动 | `time-profile`(CPU 样本,过滤空闲叶子) | ✅ 已针对真实跟踪验证 |
| 分配 | `tracks/track[@name="Allocations"]/details/detail[@name="Statistics"]` | ✅ 已针对真实跟踪验证 |
| 泄漏 | `tracks/track[@name="Leaks"]/details/detail[@name="Leaks"]` | ✅ 已针对真实跟踪验证 |
| 网络 | `network-connection-detected`(基于 socket 级的回落) | ✅ 已针对真实物理设备跟踪验证;HTTP/HAR 行可能缺失,如果 Instruments 不导出 URLSession 任务详细信息 |
### 应用启动注意事项
应用启动解析器使用与时间分析器相同的 `time-profile` 架构,并通过符号启发式将帧分为 pre-main(dyld / 静态初始化 / Swift 运行时)vs post-main(AppDelegate / UIApplication / Cocoa 方法)分类。两点需要注意:
- `total_launch_ms` 是 **CPU 活动** 启动时间,而不是壁上时钟。 xctrace 不暴露干净的“应用程序变为活动”标记,我们可以读取。
- 样本的叶子帧是已知内核等待(`mach_msg2_trap`、`start_wqthread` `semaphore_wait_trap` 等)被丢弃,匹配 Instruments 的默认“隐藏系统库”行为。否则,如果启动后跟踪长时间空闲,worker 线程会因等待而主导总计。