metal-gpu-trace
A server for measuring and comparing how Wine or macOS programs use the GPU on Apple silicon (and native programs on Windows), from recording traces to diagnosing translation-layer overhead.
Record:
perf_recordcaptures FPS, GPU ms/frame, frame pacing and memory for a program (Wine, native, or a downloaded test workload), optionally with Metal GPU Counters.Record a running program:
perf_attachprofiles an already-running game by pid or name.Batch experiments:
perf_baseline_recordrepeats a run to build a reference,perf_abcompares two environments A B B A, andperf_sweepruns one value at a time (dim, api, size, env var) with trend fitting.Compare and judge:
perf_runs,perf_compare,perf_check,perf_gate(budget pass/fail),perf_baseline, andperf_historyfor trends across runs.Diagnose:
perf_diagnoseflags too many short encoders and GPU idle time typical of DXMT, Mullion or MoltenVK.Visualize/export:
perf_panelwrites a self-contained HTML panel andperf_export_tracewrites a Chrome/Perfetto trace.Raw trace reading:
trace_tables,trace_count,trace_querypage through kept.tracetables;capture_summaryandcapture_recordsread.gputracecaptures without Xcode.Reference data:
gpu_familyreturns Apple's published facts for Apple7–Apple10 and named chips.Test programs and tools:
workload_list/workload_fetchdownload hashed benchmark binaries, andpresentmon_installsets up PresentMon on Windows.
Provides access to Apple GPU family facts (Apple7 to Apple10, chips, feature limits) and supports GPU profiling on Apple silicon via Instruments' Metal System Trace and Metal .gputrace captures.
Enables recording and profiling of native macOS programs' GPU usage on Apple silicon, including GPU time per frame, frame pacing, FPS, and memory.
Enables recording and profiling of Windows programs running under Wine on Apple silicon, with settings for the Wine directory, prefix, and environment.
Click on "Deploy 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., "@metal-gpu-tracerecord 30s of my Wine game and show GPU time per frame and FPS"
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.
metal-gpu-trace
Measure how a Wine or macOS program uses the GPU on an Apple silicon Mac, from the command line or through an AI
coding agent: GPU time per frame, frame pacing, FPS and memory, recorded with Instruments' Metal System Trace; whether
a translation layer (DXMT, Mullion, MoltenVK) splits the work into too many short encoders; Metal
.gputrace captures read without Xcode; and Apple's published facts on each GPU family to read the numbers against.
Python 3.9+ standard library, zsh, and Xcode (for xctrace). MIT license. Español.
File | What it does |
| Records a program for N seconds with Metal System Trace and writes |
| Summarizes an existing |
| Reads a Metal |
| Apple7 to Apple10: chips, what each family adds, limits that differ, with Apple's sources. |
| An MCP server over all of the above. |
| Self-check without Instruments: |
Recording
PERF_OUT=~/perf-runs zsh perf_record.sh game-d3d12 30 /path/to/wine ~/.wine /path/to/game game.exe
PERF_OUT=~/perf-runs zsh perf_record.sh app-metal 30 native - /path/to/app ./appArguments: label, seconds, a Wine directory holding bin/wine (or native), the Wine prefix, the working directory,
the program and its arguments. Without PERF_OUT, runs go to ./perf-runs. Reading the trace afterwards takes about
a minute on an M1 Pro (87 s for a 10 s recording); through the MCP server the whole call times out after 10 s per
recorded second plus 120 s, and an overrun recording leaves no files behind. One recording runs at a time; keep other GPU work off the Mac while it records.
Under Wine, give it 30 s: Wine's start-up takes part of the recording. A recording with under 100 frames is too short to compare.
Related MCP server: XcodeTraceMCP
Disk use
Each recording keeps a JSON summary and three CSVs, about 2 MB for 10 s (most of it the Metal memory samples). The
.trace (tens to hundreds of MB) is deleted unless KEEP_TRACE=1. KEEP_RUNS=N keeps only the newest N recordings. PERF_MEMORY=0 skips the Metal memory table, the slowest to read:
the summary then has no metal_memory_mib and there is no memory CSV (41 % faster to summarize a 626 MB trace).
The MCP tools perf_record and perf_baseline_record offer the same as memory=false.
MCP server
Install
The server runs with uvx from PyPI, with nothing to clone
(brew install uv installs it). Recording also needs Xcode installed (xcrun xctrace version prints a version).
uvx metal-gpu-traceThis is the command each client below runs. Desktop apps do not see Homebrew's PATH: give them the full path that
which uvx prints (/opt/homebrew/bin/uvx on Apple silicon). uvx keeps the version it first downloaded; run
the command once with --refresh after uvx to get the latest. uvx metal-gpu-trace@0.4.0 pins a version.
The server reads these environment variables:
Variable | What it sets |
| Where recordings go. Give an absolute path: the default, |
| The Wine directory (holding |
| The Wine prefix used when the call names none; |
| More directories the tools may read, separated by |
|
|
|
|
| Keeps only the newest N recordings. |
|
|
| Instruments added to the Metal System Trace template, separated by |
Claude Code
claude mcp add --scope user metal-trace -e METAL_TRACE_OUT=$HOME/perf-runs -e METAL_TRACE_WINE=/path/to/wine \
-- uvx metal-gpu-trace
claude mcp listclaude mcp list shows metal-trace as connected. --scope user makes it available in every project; leave it out
to add it to the current project only.
Windows
On Windows the server records native programs (perf_record_windows.py); no Wine and no Metal. METAL_TRACE_WINE is not needed: perf_record and perf_attach use native. METAL_TRACE_READ is separated by ;.
Frames come from Intel's PresentMon console application (MIT): one row per Present() of the process, with MsBetweenPresents and the GPU time MsGPUTime. Download PresentMon-<version>-x64.exe from its releases, check its SHA-256 against the one GitHub shows, and call the presentmon_install tool, or put it in %LOCALAPPDATA%\metal-gpu-trace or on PATH, or point PRESENTMON_EXE at it. The user must be an administrator or in the "Performance Log Users" group. Without PresentMon the summary falls back to DWM composition intervals (gpu.source is dwm-composition): they cover the whole desktop, miss games in exclusive full screen, and carry no GPU time. With neither a frame log, PresentMon nor DWM samples, a recording fails; it never invents frames.
What cannot be measured is null, not zero: the 1% low needs 100 frames and the 0.1% low 1000; stutter rate and jitter need two frames; thermal_throttling_detected needs GPU times; a drawstress log holds one mean per line, so its summary (gpu.frame_times) has no frame-level percentiles, stutter or jitter. DWM keeps only intervals between consecutive composed frames and drops a jump of several frames. perf_diagnose calls a large working set with uneven frame times MEMORY_PRESSURE_SUSPECTED: a suspicion, since memory bandwidth is not measured.
winget install --id=astral-sh.uv -e
claude mcp add --scope user metal-trace -e METAL_TRACE_OUT=%USERPROFILE%\perf-runs -- uvx metal-gpu-trace
claude mcp listTo run from a clone instead of PyPI (needs Python 3.9 or newer):
claude mcp add --scope user metal-trace -e METAL_TRACE_OUT=%USERPROFILE%\perf-runs -- python C:\path\to\metal-gpu-trace\metal_trace_mcp.pyIn JSON clients use "command": "uvx" (or the full path where uvx prints) and Windows paths with doubled backslashes. Claude Desktop reads %APPDATA%\Claude\claude_desktop_config.json. Run the Windows tests with python -m pytest test_perf_record_windows.py.
Claude Desktop, Cursor and other JSON clients
These apps do not expand ~ or $HOME: write absolute paths.
{
"mcpServers": {
"metal-trace": {
"command": "/opt/homebrew/bin/uvx",
"args": ["metal-gpu-trace"],
"env": {
"METAL_TRACE_OUT": "/absolute/path/to/perf-runs",
"METAL_TRACE_WINE": "/absolute/path/to/wine"
}
}
}
}Client | File |
Claude Desktop |
|
Cursor |
|
VS Code |
|
Codex CLI
In ~/.codex/config.toml:
[mcp_servers.metal-trace]
command = "/opt/homebrew/bin/uvx"
args = ["metal-gpu-trace"]
env = { METAL_TRACE_OUT = "/absolute/path/to/perf-runs", METAL_TRACE_WINE = "/absolute/path/to/wine" }Tools
Tool | Reads or records |
| Records a program and returns its summary; when it ends it stops every program of its Wine prefix, or every process named like a native program. |
| Records a program that is already running, by pid or name, and leaves it running |
| Lists recordings, newest first, one page at a time, whether each kept its |
| Compares two recordings: headline numbers, encoders, GPU idle time and each encoder label's GPU ms per frame, largest change first; flags those under 100 frames. |
| Saves several equal recordings as a named reference and returns the range each number spans across them and |
| Records the same program |
| Records the same program with two environments ( |
| Records the same program once per value of one variable ( |
| Judges a recording against a reference: |
| Checks a recording against budgets you set (FPS and 1% low floors; stutter, p95 GPU ms, hitch and Metal MiB ceilings) and returns pass or fail with each limit and value; a missing number fails |
| Follows FPS, 1% low, GPU ms, stutter, hitches and Metal MiB across the runs whose name starts with a prefix, oldest first, with the change from first to last |
| Writes |
| Writes a recording's GPU frames as |
| Says whether a recording splits its GPU work into too many short encoders, as translation layers do, with encoders and command buffers per frame, the labels with the most GPU time and the GPU's idle time |
| Lists the tables of a kept |
| Counts the rows of several tables of a kept |
| One page of rows of one table, optionally one process |
| Summarizes a |
| One page of a |
| Apple's facts for a family or chip ( |
| Windows only: downloads PresentMon, checks its pinned SHA-256 and keeps it in |
| Lists the test programs |
| Downloads a test program once, checks its SHA-256 and keeps it in |
perf_record takes workload, api (mtl, mtl-x64, vk, d3d11 or d3d12), dim, size and example instead of
program, to record a fetched test program (workload_list says what each has). mtl-x64 is native Metal built for
x86_64 and run under Rosetta, like Wine's programs; size ("1920x1080") sets drawstress's window. The first workload is bgfx's
17-drawstress (BSD-2, 9.3 MB),
built from source by .github/workflows/workloads.yml: a grid of cubes, dim³ draws per frame, with its shaders
inside the program. The compare-layer prompt (/metal-trace:compare-layer drawstress d3d12 in Claude Code) records it
in native Metal and under the Wine in METAL_TRACE_WINE, then runs perf_diagnose and perf_compare.
The second workload, bgfx-examples (25 MiB), holds nine bgfx examples, each a different load (many cubes, textures,
render-target chains, a G-buffer, compute, reflective shadow maps, post-processing, draws the GPU decides):
perf_record(workload="bgfx-examples", api="d3d12", example="21-deferred"). Two macOS levers change the Mac under a
recording: memory_free_pct (20 to 60) holds the whole Mac at that percentage of RAM free (memory_pressure), and
background runs the program under taskpolicy -b, a hard throttle. A small GPU-bound program does not feel the first
(drawstress stayed at 728 FPS and its resident memory fell); the second slows it several times over. Repeat a run that
uses either.
Reading the numbers across runs
A summary says where it ran and what the GPU did:
machine(chip, cores, RAM, macOS,screen_locked),gpu_activity(utilization of the device, renderer and tiler, split scenes, GPU recoveries: it covers the whole GPU, not only the program),resource_allocations(allocation events per frame, by type; a running total, not memory in use) andcommand_buffer_errors.A locked Mac session leaves native Metal windows unpaced: 3 000 to 4 000 FPS against 120 with vsync, on the same examples. Record with the Mac unlocked;
perf_comparereturnsscreenwhen one run was recorded locked and the other not.GPU ms per frame follow the GPU's performance state: a run paced at 120 FPS sits in Minimum and takes more ms for the same work (21-deferred: 1.75 ms paced, 0.27 ms unpaced).
perf_comparereturnsgpu_statewhen two runs sat in different states, andperf_diagnosereturnsdisplay_synced_hzwhen the FPS sits on a display rate. Compare runs paced alike: native Metal and D3D12 under Wine with Mullion, both at 120 FPS, do compare.
api=vk runs the same program through Vulkan on MoltenVK. MoltenVK is not shipped: set METAL_TRACE_MOLTENVK to a
directory (no spaces) holding an arm64 libMoltenVK.dylib, such as the one in a Vulkan SDK or brew install molten-vk.
The run's layer names MoltenVK with the library's SHA-256, so perf_compare against a native Metal run says it
compares two layers. In one measurement at dim=20, 10 s each: native Metal 2 encoders per frame; MoltenVK 13, 91 % of
them short, and the GPU idle 89 % of the time (perf_diagnose: too_many_short_encoders true). One pair of runs, not a
benchmark.
api=vk is native only. drawstress.exe --vk under Wine needs a Wine built with Vulkan: the Wine of DXMT and Apple's
Game Porting Toolkit were tried and both log Wine was built without Vulkan support, so the recording holds no GPU
frames. CrossOver's Wine has Vulkan but runs only inside one of its bottles, which was not tried.
The same facts are MCP resources: metal-trace://gpu-families (all) and metal-trace://gpu-families/apple7 to Each saved run is a resource too: metal-trace://runs/<run> reads its summary.
apple10. They restate Apple's Metal Feature Set Tables
of 21 May 2026, MTLGPUFamily and the
M3 tech talk; check a device with supportsFamily.
How it follows the MCP specification and Claude Code's limits:
stdout carries only MCP messages; each tool call logs one line to stderr (
METAL_TRACE_LOG=offsilences it), with no arguments or paths.Lists come in pages (
offset,limit, default 50, at most 500) withtotalandnext_offset; a result over 40 000 characters is refused with a hint to ask for a smaller page.Files are read only inside
METAL_TRACE_OUTand the directories inMETAL_TRACE_READ(separated by:).Failures come back as
isErrorresults that say what to do, without stack traces or local paths. Summaries cut absolute paths to file names, so they can be shared.Every
xctracecall has a timeout.
HTTP
METAL_TRACE_TOKEN=<secret of 16+ characters> metal-gpu-trace --http [--port N] serves the same tools at
POST http://127.0.0.1:8765/mcp (Streamable HTTP, one JSON reply per request), for a client on the same Mac that cannot
start a stdio server. Every request needs Authorization: Bearer <token>. It listens on 127.0.0.1 only, refuses a
request whose Host or Origin is not localhost or 127.0.0.1 (DNS rebinding), and does not start without the token. Cancel
a running call with notifications/cancelled from another connection. There is no progress stream over HTTP, and no
remote access: reach another Mac through an SSH tunnel (ssh -L 8765:127.0.0.1:8765 mac), not by opening the port.
Windows tests on a real machine
GitHub's windows-latest has no GPU and no desktop session, so PresentMon and DWM recordings are only tested on a real
Windows machine. windows/winbridge-run-tests.ps1 updates a checkout there and runs test_perf_record_windows.py; it is
written as a WinBridge task (fixed name, script pinned by SHA-256, no
arguments). To register it, copy it to the laptop, set $repo to the checkout's path, take its hash there with
Get-FileHash <file> -Algorithm SHA256 (Git may have changed the line endings, so the hash of the copy in this repo is
not the one to use), and add a [tasks.<name>] table with script and sha256 to the agent's TOML.
CI gate
metal-gpu-trace check RUN BASELINE [--margin-pct N] runs perf_check without a client and prints one JSON line
(verdict, reasons, hints). Exit code 0: same or improved; 1: regressed; 2: could not be judged (no such run or
reference, or under 100 frames). Runs are read from METAL_TRACE_OUT. Recording needs Instruments, so the job runs on
a self-hosted macOS runner:
jobs:
perf:
runs-on: [self-hosted, macOS, ARM64]
steps:
- run: zsh perf_record.sh pr native - . ./app
- run: metal-gpu-trace check "$(ls -t ~/perf-runs/pr_*.json | head -1 | xargs basename -s .json)" main-refCredits
The record layout of a
.gputracecommand stream follows tmc/gputrace (MIT); no code is copied. The call ids were matched against Xcode's command list on macOS 27.0.1.GPU family facts: Apple's documents linked above, restated, not quoted.
Available Tools
23 toolscapture_recordsARead-only
Returns one page of the records of a .gputrace command stream, with their Metal call names when known.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | rows per page, default 50, at most 500 | |
| offset | No | first row, default 0 | |
| capture | Yes | path of a .gputrace bundle saved from Xcode, inside METAL_TRACE_OUT or METAL_TRACE_READ |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | |
| total | Yes | |
| offset | Yes | |
| next_offset | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description still adds real behavioral context beyond the annotations: results are paginated ('one page'), call names are best-effort ('when known'), and the operation is scoped to a single capture rather than global state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the pagination constraint and then the record contents. No filler, nothing repeated from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the required capture path is fully described in the schema. What is missing is orientation relative to siblings (trace_count for total rows, trace_query for filtering), which matters for a paged reader in a crowded toolset.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so limit, offset, and the capture path constraint (METAL_TRACE_OUT / METAL_TRACE_READ) are already documented. The description's 'one page' phrasing reinforces the paging model but adds no syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb-and-resource pair: it returns one page of records from a .gputrace command stream, and notes Metal call names are included when known. That is clear enough to distinguish it from the surrounding perf_* tools, though it never explicitly contrasts with trace_query or trace_tables, which operate on similar row data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the tool reads a capture's records, so callers infer it applies after a capture exists. There is no explicit when-to-use guidance, no statement of when to prefer trace_query/trace_tables, and no note that trace_count should be consulted first to page correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
capture_summaryBRead-only
Reads a Metal .gputrace capture without Xcode: command buffers, encoders, draws, debug groups, and the 100 most frequent call ids out of calls_total.
| Name | Required | Description | Default |
|---|---|---|---|
| capture | Yes | path of a .gputrace bundle saved from Xcode, inside METAL_TRACE_OUT or METAL_TRACE_READ |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds one genuinely useful behavioral trait — that only the 100 most frequent call ids are returned out of calls_total, i.e. the output is truncated — but says nothing about error behavior, cost, or how much of the trace is actually parsed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the key scope ('without Xcode') and the contents appear immediately. The trailing enumeration is dense but each item earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, and annotations cover the read-only profile; with a single fully documented parameter the definition is nearly complete. The remaining gap is sibling disambiguation against capture_records, which matters given the crowded tool list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema description coverage is 100%; the schema already explains that 'capture' is a path to a .gputrace bundle inside METAL_TRACE_OUT or METAL_TRACE_READ. The description adds nothing about the parameter beyond the resource type, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (Reads) and resource (Metal .gputrace capture) and enumerates exactly what the summary contains: command buffers, encoders, draws, debug groups, top-100 call ids. It does not, however, contrast itself with the sibling capture_records, so an agent must infer which capture-reading tool to pick.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'without Xcode' hints at the lightweight/headless use case, but there is no explicit when-to-use, no when-not-to-use, and no reference to the obvious alternative capture_records. The agent gets no routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gpu_familyARead-only
Apple's published facts for one GPU family, by family ("Apple7") or chip ("M1 Pro"): its chips, what it adds, its limits, plus the limits shared by all families and the footnotes. Source URLs are in the result.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | a family (Apple7 to Apple10) or a chip (M1 Pro, M2, M4 Max, A17 Pro) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false. The description adds provenance by noting source URLs are in the result and clarifies that shared limits and footnotes are included, but it does not mention error behavior or caching.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the resource and scope. The colon list is dense but each item clarifies the returned facts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Low-complexity read-only lookup with a fully described parameter, annotations, and output schema. The description covers scope, result contents, and provenance, leaving no material gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter already documents family/chip examples. The description repeats the same valid input forms but adds no formatting or edge-case guidance beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States it returns Apple's published facts for one GPU family and enumerates result contents: chips, additions, limits, shared limits, and footnotes. It does not explicitly differentiate from sibling perf/trace tools, though those are unrelated categories.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies use for looking up GPU family/chip facts and gives example names such as Apple7 and M1 Pro. It never states when to use this instead of related performance tools or what happens for unsupported names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_abADestructive
Records the same program with two environments in the order A B B A (repeated rounds times, so drift hits both
sides equally) and says per metric whether B is better, worse or the same as A, with every value behind it.
env_a and env_b are NAME=VALUE pairs separated by spaces; empty means none. Runs are named name-a1, name-b1, ...
Each recording takes its seconds plus about a minute to read back. skip_s leaves out the first seconds of every
recording (the start-up) when the verdicts are drawn, as perf_compare does; the recordings are whole.
| Name | Required | Description | Default |
|---|---|---|---|
| api | No | with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine) | |
| dim | No | with workload drawstress: side of the cube grid, dim^3 draws per frame | |
| args | No | program arguments as in a shell, quotes included | |
| name | Yes | name for the runs: letters, digits, '.', '_', '-' | |
| size | No | with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080 | |
| wine | No | Wine directory holding bin/wine, or native | |
| env_a | Yes | NAME=VALUE pairs for side A, the reference (empty: none) | |
| env_b | Yes | NAME=VALUE pairs for side B, the change under test (empty: none) | |
| memory | No | default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak | |
| prefix | No | Wine prefix, default WINEPREFIX or ~/.wine; ignored with native | |
| rounds | No | A B B A rounds, default 1 (4 recordings), at most 5 | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them | |
| example | No | with a workload that lists examples in workload_list: the one to run | |
| program | No | path of the .exe, or of the macOS binary with wine=native | |
| seconds | No | recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine | |
| workdir | No | directory the program starts in, default the program's own | |
| counters | No | default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second | |
| workload | No | a test program from workload_list, fetched with workload_fetch, instead of program | |
| background | No | macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run | |
| memory_free_pct | No | macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses the repeated recording sequence, run-name pattern, substantial read-back time per recording, and the important fact that skip_s changes verdict calculations without truncating the recordings. It does not explain what behavior motivates destructiveHint=true or discuss overwrite and cleanup behavior, which prevents a top score.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description front-loads the purpose and experimental design, then efficiently covers environment syntax, artifacts, runtime cost, and skip_s behavior. Each sentence supplies distinct, useful information without unnecessary background or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Together with the fully documented input schema and existing output schema, the description provides enough context to configure the experiment and understand its cost and analysis behavior. The main remaining gaps are explicit sibling-tool routing and explanation of the destructive or system-side-effect profile signaled by the annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds useful operational meaning. It clarifies space-separated env_a/env_b encoding, concrete run naming, how seconds affects elapsed time, how rounds repeats the sequence, and the analysis-only effect of skip_s.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific action and scope: record one program under two environments in A B B A order and report per-metric B-versus-A verdicts with supporting values. This clearly conveys the combined recording-and-comparison purpose, but it does not explicitly differentiate the tool from perf_record, perf_compare, or perf_sweep.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The drift-balancing rationale makes the intended context—controlled A/B performance comparisons—clear, and the runtime estimate helps when deciding how many recordings or rounds to request. It lacks explicit selection guidance, such as when to use perf_compare on existing runs or perf_sweep for broader comparisons, and gives no when-not conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_attachA
Records a program that is already running, by pid or by a name in its command line (Game.exe under Wine),
for seconds and returns the same summary as perf_record; the program keeps running. For games started by
Steam, CrossOver, NotProton or any launcher: start the game or its benchmark there first.
| Name | Required | Description | Default |
|---|---|---|---|
| label | Yes | name for the run: letters, digits, '.', '_', '-' | |
| process | Yes | pid, or a name in the program's command line such as Game.exe | |
| seconds | No | recording length, default 20; the export afterwards takes several minutes under Wine |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and non-idempotent, so the safety profile is covered. The description adds genuinely new behavior: the target keeps running afterwards, the result matches perf_record's summary, and the post-run export takes minutes under Wine. It omits failure modes such as what happens when the pid/name is not found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core behavior and scope, then the launcher caveat. Slightly run-on across line breaks but no filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists and the description references it by equivalence ('same summary as perf_record'), so return values need no explanation. Given a non-destructive attach tool with full schema coverage, only error/not-found behavior and permission needs are missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented, including the default of 20 for `seconds`. The description's 'Game.exe under Wine' example reinforces the `process` semantics but does not add syntax or matching rules beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Records a program that is already running') and adds the scope constraint 'by pid or by a name in its command line', which cleanly separates it from perf_record, the sibling that presumably launches its own target. An agent can tell the two apart without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it: for programs that are already running, and for games launched by Steam/CrossOver/NotProton where the agent must start the game in the launcher first. It stops short of naming perf_record as the alternative for not-yet-running programs, leaving that inference to the reader.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_baselineAIdempotent
Names a reference for perf_check, or lists them. With name and runs (names from perf_runs, several runs of the
same program recorded with no change between them), it saves copies of their summaries as the reference name,
replacing a previous one, and returns the range each number spans across them: that range, not one run, is what
perf_check judges against, since repeated runs differ by a few percent, and spread_pct, each range's width in %
of its midpoint: the noise of this program on this machine, which a change must exceed. With name alone it shows that reference;
with nothing it lists them. With skip_s the reference keeps each run without its first skip_s seconds (the
start-up, as perf_compare's skip_s) and perf_check applies the same cut to the run it judges, so both are
steady-state; the runs need their per-frame files for that.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | reference name: letters, digits, '.', '_', '-'; alone, shows that reference | |
| runs | No | run names from perf_runs to save as this reference, ideally 3 or more equal runs; replaces a previous one | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them; perf_check applies the same cut to the run it judges |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, but the description adds material facts the annotations don't carry: the call overwrites a previous reference of the same name, and skip_s requires the runs' per-frame files to exist. The overwrite ('replacing a previous one') sits awkwardly with destructiveHint=false, though it is a reversible upsert rather than a true contradiction. The explanation of what the returned numbers mean (ranges, spread_pct as machine noise) also goes beyond the flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every clause carries information — nothing is filler — but the prose is a dense run-on with parenthetical tangents and elided articles, and the three-mode dispatch is buried mid-sentence rather than front-loaded as a list. It is efficient in content but weak in structure, and a re-read is needed to extract the branching logic.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value description isn't required; the description instead covers mode selection, overwrite behavior, the skip_s precondition, and how perf_check consumes the result. The remaining gap is sibling positioning against perf_baseline_record, which matters in a family of 20+ perf tools with overlapping names.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns the extra point by adding meaning the schema doesn't: runs should be 'several runs of the same program recorded with no change between them', ideally 3+, and skip_s is coupled to per-frame file availability and mirrored by perf_check. That cross-parameter, cross-tool semantics is real added value rather than restatement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause states a specific verb and resource — it names or lists baselines used as references for perf_check — and the three modes (name+runs, name alone, nothing) are each spelled out, so an agent can tell what the tool does. It loses a point because the near-identically named sibling perf_baseline_record is never mentioned, leaving ambiguity about which of the two to pick.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is dispatched explicitly by argument shape: 'With name and runs... it saves copies', 'With name alone it shows that reference; with nothing it lists them' — a genuine when-to-use map. It also states the upstream dependency (runs come from perf_runs) and that the named reference is what perf_check judges against. It gives no exclusions and never contrasts itself with the sibling perf_baseline_record.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_baseline_recordADestructive
Records the same program count times in a row with perf_record's arguments and saves the runs as the
reference name for perf_check, returning the range each number spans across them. Runs are named
name-1, name-2, ... Each recording takes its seconds plus about a minute to read back. skip_s as in
perf_baseline: the reference leaves out each run's start-up.
| Name | Required | Description | Default |
|---|---|---|---|
| api | No | with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine) | |
| dim | No | with workload drawstress: side of the cube grid, dim^3 draws per frame | |
| env | No | NAME=VALUE pairs separated by spaces, set in the program's environment | |
| args | No | program arguments as in a shell, quotes included | |
| name | Yes | reference name: letters, digits, '.', '_', '-' | |
| size | No | with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080 | |
| wine | No | Wine directory holding bin/wine, or native | |
| count | No | equal recordings to make, default 3 | |
| memory | No | default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak | |
| prefix | No | Wine prefix, default WINEPREFIX or ~/.wine; ignored with native | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them; perf_check applies the same cut to the run it judges | |
| example | No | with a workload that lists examples in workload_list: the one to run | |
| program | No | path of the .exe, or of the macOS binary with wine=native | |
| seconds | No | recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine | |
| workdir | No | directory the program starts in, default the program's own | |
| counters | No | default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second | |
| workload | No | a test program from workload_list, fetched with workload_fetch, instead of program | |
| background | No | macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run | |
| memory_free_pct | No | macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, so the safety bar is lower; the description still adds real cost and side-effect context — each recording costs its `seconds` plus about a minute of read-back, and run objects are created under fixed names. It does not say what happens when a reference with that `name` already exists, which is the one mutation detail an agent would want.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four dense sentences, front-loaded with the write-and-name behavior before cost details. Nearly every clause carries information, though the read-back timing remark is slightly buried mid-paragraph rather than separated as a cost caveat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 19-parameter destructive recording tool with a full output schema, the description covers the action, the artifact naming convention, the relationship to perf_check, and the run-time cost. Return values need not be explained because an output schema exists, and the remaining gap (overwrite semantics) is narrow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 19 parameters thoroughly. The description reinforces `count` (equal recordings, default 3) and the skip_s cut, including that perf_check applies the same cut, but adds little syntax or meaning the schema lacks; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: record the same program `count` times, save as reference `name` for perf_check, and return the per-metric range. It explicitly contrasts with perf_record (whose arguments it reuses) and perf_baseline (whose skip_s convention it follows), plus names the artifact naming scheme (`name`-1, `name`-2), so an agent can distinguish it from every sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is clearly implied and partly explicit: the reference is built for perf_check, and repeated recording exists to get the range each number spans. It borrows context from perf_baseline and perf_record rather than stating outright when to pick one of those instead, so there is no explicit exclusion, but the routing signal is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_checkARead-only
Judges a recording against a reference saved with perf_baseline: regressed when FPS falls under the
reference's lowest FPS by more than margin_pct, GPU ms per frame rises over its highest by more than margin_pct,
or encoders or command buffers per frame exceed its highest; improved when a number leaves the range the other
way and none regressed; same otherwise. Frame pacing, short encoders and GPU idle time are reported by the
comparison but do not decide: they vary too much between equal runs. A run from Windows against a Metal
reference (or the reverse) is judged on FPS alone. A reference saved with skip_s judges the run without its first
skip_s seconds too (skipped_s says so). Returns the reasons and perf_compare's
full comparison against the reference's first run.
| Name | Required | Description | Default |
|---|---|---|---|
| run | Yes | a run name from perf_runs | |
| baseline | Yes | a reference name from perf_baseline | |
| margin_pct | No | how far outside the reference's range FPS or GPU ms per frame may fall before counting, default 3 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description goes far beyond by disclosing the exact verdict logic, that frame pacing, short encoders and GPU idle time are reported but never decide, that cross-OS comparisons fall back to FPS alone, and that a skip_s reference trims the run's first skip_s seconds (reported as skipped_s). It also says what is returned: the reasons plus perf_compare's full comparison against the reference's first run.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first clause and the rules follow in a logical order, with the caveats (non-deciding metrics, cross-OS, skip_s) after the core logic. It is a dense single block of prose, but each sentence carries distinct behavioral information rather than restating the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no further explanation, and the description still names the shape of the verdict and returned reasons. For a tool that compares recordings across platforms and time windows, the description covers the decision rules, the exceptions, and the baseline prerequisite without gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both required params and margin_pct are already documented in the schema. The description adds real meaning for margin_pct by explaining it applies to both the FPS floor and the GPU-ms-per-frame ceiling, but it adds nothing for run or baseline beyond what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Judges a recording against a reference saved with perf_baseline', then enumerates the exact decision rules (FPS under the reference's lowest by more than margin_pct, GPU ms per frame over its highest, encoder/command-buffer counts). It also distinguishes itself from perf_baseline (which saves the reference) and from perf_compare (whose full comparison it returns).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Makes clear the prerequisite (a reference created by perf_baseline) and the conditions under which a run is judged regressed, improved, or same, including the cross-platform Windows/Metal special case. What it does not do is explicitly route the agent away from perf_compare or perf_gate when a raw comparison or a pass/fail gate is wanted, leaving that inference to the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_compareARead-only
Compares two saved recordings (names from perf_runs), a the reference and b the run after a change: the
headline numbers (FPS, GPU ms, frame pacing, memory), then what changed in the GPU work and where: encoders and
command buffers per frame, the share of encoders under short_us, the GPU's idle time, and each encoder label's
count and GPU ms per frame, largest change first. layer says whether both ran on the same translation layer:
with different layers it compares layers, not one change. A Windows run against a Metal run has measure: the
GPU ms and Metal memory differ in kind and the encoders exist only in Metal, so use FPS, its lows, stutter and
jitter. Recordings with under 100 frames are flagged: too short to compare. With markdown true the result also has
markdown: the same numbers as tables for a PR comment. skip_s leaves out the first seconds of each recording,
where shaders compile and resources load: the GPU numbers, hitches and Metal memory are recomputed from the
per-frame files without them, and skipped_s says it; thermal state, process memory and encoders stay whole-run.
screen appears when one run was recorded with the screen locked and the other not: FPS is then not comparable.
| Name | Required | Description | Default |
|---|---|---|---|
| a | Yes | run name from perf_runs: the reference, such as the run before a change | |
| b | Yes | run name from perf_runs: the run to compare against a | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them | |
| markdown | No | also return the numbers as Markdown tables, default false | |
| short_us | No | an encoder under this GPU time counts as short: 10, 25 (default), 50, 100, 250, 500 or 1000 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint and openWorldHint=false; the description goes well beyond by disclosing the diagnostic flags it emits (layer, measure, screen, skipped_s), the short-recording threshold that alters the comparison, and exactly which metrics are recomputed under skip_s versus which remain whole-run. That level of disclosure about conditional result semantics is unusual and directly useful for interpreting output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence front-loads the purpose and headline metrics, and subsequent clauses each carry a distinct conditional fact rather than filler. It is dense to the point of being hard to scan (no lists, minor typos like 'a the reference'), but almost no sentence could be deleted without losing a conditional rule.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only comparison tool with an output schema and two required name parameters, the description covers source of names, comparison semantics, the three cases where the comparison is not apples-to-apples, and the effect of each optional parameter. Nothing an agent needs in order to call it correctly or interpret a flag is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema for skip_s: thermal state, process memory and encoders stay whole-run while GPU numbers, hitches and Metal memory are recomputed, and skipped_s reports the exclusion. It also ties markdown output to a concrete use (PR comment) and restates short_us's role only lightly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: compares two saved recordings from perf_runs, with 'a' as the reference and 'b' as the post-change run, and it enumerates what is compared (FPS, GPU ms, frame pacing, memory, encoder counts, GPU idle). An agent can distinguish this from perf_runs (listing) and from capture tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit conditional guidance: recordings under 100 frames are flagged as not comparable, different translation layers mean layer-vs-layer comparison, a Windows-vs-Metal pair should be judged on FPS/lows/stutter/jitter, and a locked-vs-unlocked screen makes FPS non-comparable. It lacks routing against nearby siblings such as perf_ab, perf_gate or perf_check, so the alternative-selection guidance is strong on data conditions but absent on tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_diagnoseARead-only
Says whether a saved recording splits its GPU work into too many short encoders, the pattern of translation layers such as DXMT, Mullion or MoltenVK, with the numbers behind it: encoders and command buffers per frame, the share of short encoders, the labels with the most GPU time and the GPU's idle time. Read the idle time together with the FPS: a program waiting for vsync idles too. Defaults come from bgfx 17-drawstress on an M1 Pro: 7 encoders per frame and 50% under 25 us under Mullion, 2 and 2% in native Metal.
| Name | Required | Description | Default |
|---|---|---|---|
| run | Yes | a run name from perf_runs | |
| short_us | No | an encoder under this GPU time counts as short: 10, 25 (default), 50, 100, 250, 500 or 1000 | |
| short_share | No | share of short encoders from which the verdict is yes, default 0.25 | |
| min_encoders | No | encoders per frame (median) from which the verdict can be yes, default 4 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered; the description adds genuine context by disclosing the verdict's decision basis (short-encoder share, encoders per frame), reference values from bgfx 17-drawstress on an M1 Pro under Mullion vs native Metal, and an important interpretation caveat that idle time must be read alongside FPS because a vsync-bound program also idles.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The verdict and evidence list are front-loaded in the first sentence, with the interpretation caveat and the reference numbers following. It is dense but every sentence carries decision-relevant information; the M1 Pro benchmark sentence is long but functions as calibration rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate return values, and it correctly focuses on the decision logic, interpretation caveat and reference thresholds. For a four-parameter read-only diagnostic tool this is close to sufficient, missing only explicit routing versus sibling diagnostics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description earns extra credit by giving concrete calibration values (7 encoders/frame and 50% short under Mullion versus 2 and 2% in native Metal) that tell the agent what magnitudes of short_us, short_share and min_encoders are meaningful. It does not restate the per-parameter defaults that the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verdict ('says whether a saved recording splits its GPU work into too many short encoders') plus the secondary axis it inspects (translation layers like DXMT/Mullion/MoltenVK) and the evidence it returns. An agent knows exactly what question this tool answers. It stops short of naming a sibling (e.g. perf_compare or perf_check) to draw the boundary explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: the tool takes a run name from perf_runs, so it operates on already-recorded data, and the vsync/idle-time note tells the agent how to interpret results. But there is no explicit when-to-use versus perf_compare, perf_check or perf_baseline, nor any stated prerequisite beyond the run parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_export_traceAIdempotent
Writes a recording's GPU frames as a Chrome trace file, <run>.chrome-trace in the runs directory, that
ui.perfetto.dev and chrome://tracing open: one slice per GPU frame, from its start for its GPU time (the sum of
its encoders' time, so a frame with parallel encoders can show shorter than it took), with the compute, fragment
and vertex split as arguments. Returns the file name and the number of frames.
| Name | Required | Description | Default |
|---|---|---|---|
| run | Yes | a run name from perf_runs |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=true and openWorldHint=false, so the safety profile is covered; the description adds real value beyond that by naming the output path/filename pattern and disclosing a subtle caveat that a frame's GPU time can be shorter than its wall time when encoders run in parallel. It stops short of stating overwrite behavior for a pre-existing trace file, which would complete the picture.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that opens with the action and artifact before descending into slice semantics. It is dense but nearly every clause carries information; the trailing phrase 'with the compute, fragment and vertex split as arguments' is the weakest and slightly ambiguous part.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with an output schema and full annotations, the description covers the output location, format compatibility, and the meaning of the trace contents. Only the runs-directory location and existing-file overwrite semantics are left unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter and schema description coverage is 100%, with the schema itself explaining that 'run' is 'a run name from perf_runs'. The description adds no further syntax or format detail, so the schema is doing all the work and baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Writes') plus a precise resource ('a recording's GPU frames as a Chrome trace file') and names the exact artifact produced. An agent can immediately distinguish this file-producing export from sibling query tools like trace_query, trace_tables, and capture_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the mention that ui.perfetto.dev and chrome://tracing can open the output hints that this is for visual inspection, but the description never says when to prefer this over trace_query or capture_summary, nor when not to use it. No prerequisites (e.g. that a run must already be recorded) are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_gateARead-only
Checks a recording against budgets and says pass or fail: a floor for FPS and the 1% low, a ceiling for the stutter rate, the p95 GPU ms per frame, the hitch count and the peak Metal MiB. Give at least one. A number the recording lacks fails its budget (value null): a gate must not pass on missing data. Returns each budget with its limit, the value and whether it held. Use it as a bar a change must clear, where perf_check judges against equal runs. skip_s leaves out the first seconds of the recording (the start-up), as perf_compare does.
| Name | Required | Description | Default |
|---|---|---|---|
| run | Yes | a run name from perf_runs | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them | |
| fps_min | No | the FPS must be at least this | |
| hitches_max | No | the number of hitches at most this | |
| metal_mib_max | No | the peak Metal memory in MiB at most this | |
| gpu_ms_p95_max | No | the p95 GPU ms per frame at most this | |
| fps_1pct_low_min | No | the 1% low FPS must be at least this | |
| stutter_rate_pct_max | No | the share of stutter frames, in %, at most this |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered structurally. The description adds genuinely useful semantics beyond that: missing data fails its budget rather than passing, and skip_s causes GPU numbers, hitches and Metal memory to be recomputed. Return shape is described but an output schema already exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The pass/fail purpose and the missing-data rule are front-loaded, which is good. However the budget enumeration and the skip_s note are crammed into a run-on block, and the skip_s sentence at the end repeats territory the schema already covers.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an eight-parameter read-only gate with a full schema and an output schema, the description covers the non-derivable parts: the at-least-one requirement, the fail-closed policy on missing data, and the sibling routing. Nothing an agent needs to invoke it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter, which sets the baseline at 3. The description contributes the cross-parameter rule ('Give at least one') and the null-fails-on-missing-data semantics for the budget params, but the skip_s explanation largely restates the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Checks a recording against budgets and says pass or fail') and immediately enumerates the exact budget dimensions (FPS floor, 1% low, stutter rate ceiling, p95 GPU ms, hitch count, peak Metal MiB). It also explicitly contrasts itself with a sibling: 'where perf_check judges against equal runs.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete when-to-use rule ('a bar a change must clear') and names the alternative tool with the condition that selects it (perf_check for equal-run comparison). It also states a hard invocation constraint ('Give at least one' budget) that would otherwise cause a confusing error.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_historyARead-only
Lists the recordings whose name starts with prefix, oldest first, with their FPS, 1% low, GPU ms, stutter,
hitches and peak Metal MiB, and the change from the first to the last: how a number moved over a series of runs, such as
one recording per version of a translation layer. Read a trend as real only when it exceeds the spread_pct that
perf_baseline reports for equal runs. Runs from Windows and Metal in one series are flagged: their GPU ms and
memory do not compare. skip_s leaves out the first seconds of each recording (the start-up), as perf_compare does.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | newest runs to keep, default 50 | |
| prefix | Yes | the start of the run names to follow: letters, digits, '.', '_', '-' | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint, so the description carries the real behavioral load and does so: it states the sort order ('oldest first'), the cross-platform comparability caveat ('Runs from Windows and Metal in one series are flagged: their GPU ms and memory do not compare'), and the noise-floor interpretation rule. These are non-obvious traits an agent could not infer from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Verb and resource are front-loaded and nearly every clause carries information (ordering, metrics, delta, noise threshold, platform caveat, skip semantics). It is a single dense paragraph whose parentheticals ('the start-up', the translation-layer example) border on redundant given the schema, but nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description still covers ordering, comparability caveats, and the interpretation rule that an agent would otherwise miss. The remaining gap is the limit/sort interaction (capped at the newest N but reported oldest-first), which affects how a caller reasons about truncation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description largely mirrors it — skip_s as 'the start-up' seconds with recomputed metrics is already spelled out in the schema, and prefix semantics are already there. The one genuinely additive phrase is ordering ('oldest first'), which is not a parameter but interacts with limit ('newest runs to keep, default 50'); the description does not explain that tension.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ('Lists the recordings whose name starts with `prefix`') and then names the exact output content (FPS, 1% low, GPU ms, stutter, hitches, peak Metal MiB) plus the first-to-last delta. It also frames the intended shape of the series ('one recording per version of a translation layer'), which separates it from one-off tools like perf_compare or perf_baseline that it explicitly references.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage context — following a number across a series of runs — and an interpretive rule ('Read a trend as real only when it exceeds the spread_pct that perf_baseline reports for equal runs'), which is real when-to-use guidance. What it lacks is an explicit exclusion: it never says when an agent should choose perf_compare or perf_ab instead of this tool, only that skip_s behaves 'as perf_compare does'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_panelAIdempotent
Writes one HTML file, <name>.panel.html in the runs directory, that shows one or two recordings in a
browser without a server: GPU time per frame with the hitches marked, the numbers (FPS and its lows, frame
time, jitter, stutter, memory, thermal state), Metal memory over time and, for two runs, A against B. The file
holds the data itself, no path, and loads nothing from the network; the viewer can hide and reorder the
widgets and export the layout as JSON. preset fps is the timeline, numbers and memory; compare (two runs)
puts A against B first. skip_s leaves out the first seconds of each recording (the start-up), as perf_compare does.
layout (tab ids in the order to show) is saved as panel.json in the runs directory and becomes the default tab
order of every panel, the live one too, until the viewer changes it in the browser; ids left out are hidden but
can be switched back on; tabs are summary, ab, frames, encoders, counters, memory and data, and a panel.json
you wrote yourself, or copied from the panel's Layout JSON, works the same.
Returns the file name, the runs, the frames shown and the file's bytes.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | name for the panel file: letters, digits, '.', '_', '-' | |
| runs | Yes | one or two run names from perf_runs; with two, the first is A, the reference | |
| layout | No | tabs to show, in order: summary, ab, frames, encoders, counters, memory, data; saved as panel.json in the runs directory as the default for every panel | |
| preset | No | fps (default) or compare (needs two runs) | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses the real behavioral traits: a file is written into the runs directory, the file is self-contained and loads nothing from the network, and — most importantly — the `layout` argument is persisted as panel.json and becomes the default tab order for every panel, including the live one, until a viewer changes it. That global side effect is exactly the kind of context annotations cannot carry. It stops short of saying what happens on name collision or overwrite of an existing panel.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content is front-loaded on the artifact, which is right, but the body is a dense run-on with stacked clauses ('The file holds the data itself, no path, and loads nothing from the network') and buries the significant layout/persistence side effect mid-paragraph. Several fragments ('no path', 'A against B') cost parsing effort without adding precision.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a five-parameter write tool it covers everything an agent needs: required inputs, file destination and naming, all preset and layout consequences, and even the return payload (file name, runs, frames shown, byte size) which is also backed by an output schema. Nothing material is missing given the annotation and schema richness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3; the prose adds genuine meaning on top by giving the tab id vocabulary (summary, ab, frames, encoders, counters, memory, data), the semantics of omitted ids (hidden but switchable back on), the persistence behavior of layout, and the fact that a hand-written or copied panel.json works identically. skip_s and preset meanings largely restate the schema rather than extend it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a concrete verb and artifact: 'Writes one HTML file, `<name>.panel.html` in the runs directory', then enumerates exactly what the artifact shows (GPU time per frame with hitches, FPS/lows/jitter/stutter/memory/thermal, Metal memory, A vs B). It also anchors itself to siblings by name ('as perf_compare does', runs 'from perf_runs'), so an agent can separate this from perf_ab/perf_compare without reading schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear what the output is for (viewing one or two recordings in a browser without a server) and explains which preset fits which case ('compare' needs two runs), but it never states when an agent should choose this over perf_compare, perf_ab or the live panel. Usage is implied from the artifact type rather than routed explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_recordADestructive
Records program (an .exe under Wine, or a macOS binary with wine="native"), or a test program fetched with
workload_fetch (workload, api, dim), for seconds with Metal System Trace and returns its summary: GPU ms per
frame, frame intervals, FPS, Metal and resident memory (memory=false skips the Metal memory table, the slowest
to read). When it ends it stops every program of that Wine prefix (wineserver -k), or every process named like
the program with native. counters=true also records Metal GPU Counters (gpu_counters in the summary: the units the
GPU waited on, its utilization, occupancy and memory bandwidth); it adds about 40 s of read-back per recorded second.
| Name | Required | Description | Default |
|---|---|---|---|
| api | No | with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine) | |
| dim | No | with workload drawstress: side of the cube grid, dim^3 draws per frame | |
| env | No | NAME=VALUE pairs separated by spaces, set in the program's environment | |
| args | No | program arguments as in a shell, quotes included | |
| size | No | with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080 | |
| wine | No | Wine directory holding bin/wine, or native | |
| label | Yes | name for the run: letters, digits, '.', '_', '-' | |
| memory | No | default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak | |
| prefix | No | Wine prefix, default WINEPREFIX or ~/.wine; ignored with native | |
| example | No | with a workload that lists examples in workload_list: the one to run | |
| program | No | path of the .exe, or of the macOS binary with wine=native | |
| seconds | No | recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine | |
| workdir | No | directory the program starts in, default the program's own | |
| counters | No | default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second | |
| workload | No | a test program from workload_list, fetched with workload_fetch, instead of program | |
| background | No | macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run | |
| memory_free_pct | No | macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Critical behavior beyond the annotations is spelled out: at the end it kills every program in the Wine prefix (wineserver -k) or every process named like the program with native — exactly the destructiveHint in concrete terms. It also quantifies costs and risks: counters adds ~40 s read-back per recorded second, memory=false is ~40% faster, background throttling is 18-280x, memory_free_pct can freeze the Mac, and the export takes minutes under Wine.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action and its return value are front-loaded in the first sentence, with caveats following. It is dense and long-sentenced but nearly every clause carries operational information; only the memory=false phrasing is repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-parameter, destructive, long-running recording tool with an output schema, the description covers prerequisites (workload_fetch/list), side effects (process killing), timing implications, and platform caveats. Nothing an agent needs to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter, and much of the description's parameter talk (memory=false, counters=true, wine=native, seconds=30) restates it. The added value is mainly the program/workload mutual exclusivity and the consequence of the kill behavior tied to the wine choice, which is a modest increment over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Records' a program or a fetched workload under Metal System Trace) and enumerates what the summary contains (GPU ms/frame, frame intervals, FPS, memory). It also draws the program-vs-workload boundary that separates it from workload_fetch/workload_list and the non-recording siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete guidance on selecting inputs: pass `program` for a local .exe/binary or `workload` for a test program from workload_list, set wine=native for macOS binaries, use 30 s under Wine because start-up eats into the recording. It does not explicitly say when to prefer perf_attach, perf_ab, or perf_sweep instead, so routing among siblings is left partly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_runsARead-only
Lists the saved recordings, newest first, with frames, FPS, GPU ms per frame, memory peaks and the translation layer each ran on (fingerprint and Wine, or native).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | rows per page, default 50, at most 500 | |
| offset | No | first row, default 0 |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | |
| total | Yes | |
| offset | Yes | |
| next_offset | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered for free. The description contributes two genuinely new facts: result ordering ('newest first') and which metrics are surfaced per row; however, enumerated row fields are largely redundant with the existing output schema, and pagination/truncation behavior is never mentioned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the verb and resource plus the ordering guarantee, then the payload. Nothing is padding and nothing essential is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A read-only, two-param list tool with a full output schema and complete annotation coverage needs little more than this, and the description covers scope, ordering and payload. The only real gap is whether more pages exist beyond the returned window and how callers should page through large result sets.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both `limit` (default 50, max 500) and `offset` (default 0) are already fully documented with defaults and bounds. The description adds nothing about paging strategy or ordering interaction with offset, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource ('Lists the saved recordings') and enumerates what each row contains (frames, FPS, GPU ms/frame, memory peaks, translation layer), so there's no ambiguity about what the tool returns as opposed to perf_record or perf_compare. It stops short of naming a sibling it is not, which keeps it at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by 'Lists the saved recordings' – an agent can infer this is the read-only inventory tool, but the description never says when to reach for it over perf_baseline, capture_records or perf_compare, nor any exclusions. No explicit when/when-not guidance is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
perf_sweepADestructive
Records the same program once per value of one variable (dim, example, api, size, or env:NAME for an environment
variable) and returns, per value, the median of FPS, 1 % low, GPU ms per frame and stutter, and with 3 or more
numeric values the straight line GPU ms per frame follows (fixed ms plus ms per draw for dim, per unit otherwise)
with its r2. With rounds above 1 the values run in opposite order every other round, so drift hits all alike.
Runs are named name--r; each takes its seconds plus about a minute to read back.
| Name | Required | Description | Default |
|---|---|---|---|
| api | No | with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine) | |
| dim | No | with workload drawstress: side of the cube grid, dim^3 draws per frame | |
| env | No | NAME=VALUE pairs separated by spaces, set in the program's environment | |
| args | No | program arguments as in a shell, quotes included | |
| name | Yes | name for the runs: letters, digits, '.', '_', '-' | |
| size | No | with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080 | |
| wine | No | Wine directory holding bin/wine, or native | |
| memory | No | default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak | |
| prefix | No | Wine prefix, default WINEPREFIX or ~/.wine; ignored with native | |
| rounds | No | rounds, default 1, at most 5 and at most 24 recordings in all; every other round runs the values in reverse | |
| skip_s | No | seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them | |
| values | Yes | 2 to 8 values of the variable, such as [10, 20, 30] for dim | |
| example | No | with a workload that lists examples in workload_list: the one to run | |
| program | No | path of the .exe, or of the macOS binary with wine=native | |
| seconds | No | recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine | |
| workdir | No | directory the program starts in, default the program's own | |
| counters | No | default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second | |
| variable | Yes | what changes between runs: dim, example, api, size, or env:NAME for an environment variable | |
| workload | No | a test program from workload_list, fetched with workload_fetch, instead of program | |
| background | No | macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run | |
| memory_free_pct | No | macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations only declare destructive/not-idempotent; the description goes well beyond them by disclosing real cost ('each takes its seconds plus about a minute to read back'), a hard budget ('at most 5 and at most 24 recordings in all'), the interleaved reverse-order scheduling used to spread drift, and the naming scheme of every run created. These are exactly the traits an agent needs before committing an expensive mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in one long sentence, but that sentence crams in return-value detail (FPS, 1 % low, GPU ms, stutter, slope and r2) that an output schema already covers, and the phrasing is compressed to the point of ambiguity ('1 % low', 'the straight line GPU ms per frame follows'). Useful content, but not tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 21-parameter, destructive, long-running sweep the description supplies the critical operational facts: time cost, recording budget, ordering strategy, artifact naming and the memory=false speed trade-off. With an output schema present, return-value explanation is optional, and only the sibling-routing advice is genuinely absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters are already documented and the baseline is 3. The description adds only marginal meaning beyond the schema — chiefly the run-naming template tying `name` to values and rounds, and the reversal semantics of `rounds` — while most parameter behavior lives in the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause states a specific verb and resource: 'Records the same program once per value of one variable', which immediately separates it from a single-run tool like perf_record. The enumerated variable space (dim, example, api, size, env:NAME) and the per-value aggregation make the sweep semantics unmistakable, though no sibling is named explicitly to complete the contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied by the parameter-space enumeration and by notes like 'with rounds above 1...' and 'with 3 or more numeric values', so an agent can infer when the tool fits. However, nothing states when to choose perf_sweep over perf_ab, perf_compare or perf_baseline, and no prerequisites (e.g. needing workload_fetch first) appear in the description itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
presentmon_installAIdempotent
Windows only: downloads Intel's PresentMon console application (MIT) from its GitHub release, checks its SHA-256 against the one this package pins, and keeps it in %LOCALAPPDATA%\metal-gpu-trace, where perf_record and perf_attach find it; later calls reuse it. It needs administrator rights or the Performance Log Users group to run.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations: names the network source (GitHub release), discloses SHA-256 verification against a pinned hash, gives the on-disk location (%LOCALAPPDATA%\metal-gpu-trace), and states the privilege requirement (admin or Performance Log Users group). This is exactly the auth/network/artifact context annotations cannot convey, and it is consistent with readOnlyHint=false/openWorldHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the platform constraint and packs platform, source, verification, destination, reuse semantics, and privileges into three dense sentences with no filler. Slightly long and run-on in the first sentence, but every clause carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, rich annotations, and an output schema to carry return values, the description supplies everything else an agent needs: OS constraint, network dependency, integrity check, install path, idempotency, and privilege prerequisite.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: downloads Intel's PresentMon console app from its GitHub release and installs it locally. The 'Windows only' qualifier and repeated references to perf_record/perf_attach make it clearly distinguishable from every sibling, which are all consumers rather than installers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the tool is what perf_record and perf_attach depend on and that later calls reuse the installed copy, so an agent knows to install before recording. It lacks an explicit 'skip this if already installed / use X instead' clause, but idempotentHint and 'later calls reuse it' cover the main decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trace_countARead-only
Counts the rows of several tables of a kept .trace, in all and per process, so a recording's useful tables show before reading them: a table with 0 rows needs another instrument or Xcode, not a bigger page.
| Name | Required | Description | Default |
|---|---|---|---|
| trace | Yes | a run name from perf_runs whose trace_kept is true, or the path of a .trace | |
| tables | No | table names from trace_tables; default the tables that matter for a translation layer |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context — counts are aggregated both globally and per process, and zero counts mean a different tool/Xcode is needed — but says nothing about cost, trace size limits, or failure modes when a trace is missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the verb and object, and the rationale clause earns its place by explaining what the counts are for. Only minor cost is the slightly convoluted trailing clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Two well-described params, an output schema that carries the return shape, and annotations covering safety — the description supplies the one thing structured fields can't: the interpretive rule that zero rows means a different instrument. Complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%: the trace param already documents the run-name-or-path forms and tables already points at trace_tables with its default. The description adds no parameter-level detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: counts rows of tables in a kept .trace, both overall and per process. The triage framing ("so a recording's useful tables show before reading them") makes it distinguishable from the table-listing and querying siblings, though it never names them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"so a recording's useful tables show before reading them" plus the 0-row guidance gives a clear posture: run this as a cheap pre-check before querying, and treat zero-row tables as a signal to switch instruments rather than retry with a larger page. No explicit exclusion or named alternative (trace_query) is given, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trace_queryARead-only
Returns one page of rows of one table of a .trace as {column: value}, optionally only one process's rows.
| Name | Required | Description | Default |
|---|---|---|---|
| pid | No | keep only this process's rows | |
| limit | No | rows per page, default 50, at most 500 | |
| trace | Yes | a run name from perf_runs whose trace_kept is true, or the path of a .trace | |
| offset | No | first row, default 0 | |
| schema | Yes | a table name that trace_tables lists, such as metal-gpu-intervals |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | |
| total | Yes | |
| offset | Yes | |
| next_offset | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered; the description adds genuinely new behavior: results are paginated ('one page'), shaped as {column: value}, and can be scoped to a single process. It stops short of disclosing what happens with an invalid table name or an offset past the end of the data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the core behavior (paged row read from one table of a trace) comes first and the optional pid narrowing follows. Nothing could be removed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and all five parameters are documented in the schema. For a read-only paginated query tool the coverage is nearly complete; only error/edge-case behavior and the trace_tables dependency are unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with limit defaults/maximum, offset default, pid filtering, and the trace_kept/table-name constraints all documented in the schema itself. The description only restates the pid filter ('optionally only one process's rows') and the paging concept, adding little beyond the structured fields, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: returns one page of rows from one table of a .trace, plus the return shape ({column: value}) and the optional pid narrowing. It implicitly separates itself from trace_tables (which lists tables) and trace_count (which counts), but never names those siblings, so an agent must infer the division of labor.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says what the tool returns but never states when to reach for it versus trace_tables, trace_count, or capture_records. There is no mention of the prerequisite that 'schema' must first come from trace_tables, and no guidance on paging strategy (e.g. advancing offset until a short page). Usage is only inferable from the wording.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trace_tablesARead-only
Lists the data tables (schemas) a .trace recording holds; recordings keep their .trace only with KEEP_TRACE=1.
| Name | Required | Description | Default |
|---|---|---|---|
| trace | Yes | a run name from perf_runs whose trace_kept is true, or the path of a .trace |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds a meaningful behavioral caveat: recordings retain their .trace only when KEEP_TRACE=1, which affects whether this tool can be used at all. It stops short of saying what happens when the trace is absent or not kept.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is a single front-loaded sentence with no wasted wording. The KEEP_TRACE=1 clause is relevant but slightly terse and could be mistaken for a condition on this tool rather than on trace retention.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with an output schema, annotations, and full parameter coverage, the description is complete enough to call it correctly. The main missing piece is explicit sibling routing, but the core behavior and trace-retention caveat are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter description already explains that the trace argument can be a run name with trace_kept=true or a .trace path. The tool description does not add format or validation details beyond that. Baseline 3 is appropriate when the schema covers the single parameter thoroughly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it lists the data tables (schemas) contained in a .trace recording. This distinguishes it from query/count siblings by output type, though it does not name those siblings explicitly. The purpose is clear without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer this is a discovery step before querying a trace, but the description gives no explicit when-to-use guidance or comparison to trace_query or trace_count. The KEEP_TRACE=1 note is a retention prerequisite rather than routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workload_fetchAIdempotent
Downloads a test program from this project's GitHub releases once, checks its SHA-256 against the one this package pins, and keeps it in ~/Library/Caches/metal-gpu-trace; later calls reuse it. The programs are built from source by the project's workloads workflow.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | a workload name from workload_list, such as drawstress |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the description's job is mostly to add context. It does: network fetch from GitHub, SHA-256 integrity verification against a pinned hash, and a specific cache path in ~/Library/Caches/metal-gpu-trace. It omits what happens on checksum mismatch or offline failure, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the action and integrity check, followed by cache location and reuse semantics. The provenance sentence about the workloads workflow justifies trust in the binary rather than padding, and no sentence is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With rich annotations and an output schema present, the description covers the essential mechanics: source, verification, cache location, and idempotent reuse. The remaining gap is failure behavior (checksum mismatch, no network), which matters for an open-world download but is a modest omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single `name` parameter is documented in the schema with an example and a pointer to workload_list. The description itself adds no parameter guidance, so the baseline of 3 is appropriate given the schema carries the load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action and resource: downloading a test program from the project's GitHub releases, verifying its SHA-256, and caching it locally. An agent can distinguish this from read-only siblings like workload_list or perf_run because the caching and download behavior is stated. It stops short of explicitly directing agents to workload_list for valid names, which would sharpen differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'later calls reuse it' implies the tool is safely re-invoked and that a first call seeds the cache, which is useful implied guidance. However, there is no explicit when-to-use instruction (e.g. 'call before perf_run if the workload is not cached') and no stated alternatives or exclusions relative to workload_list or presentmon_install.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workload_listARead-only
Lists the test programs workload_fetch can download, such as bgfx's drawstress: what each measures, its size, license and APIs, and whether it is already downloaded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds useful context about what is enumerated, including the 'whether it is already downloaded' state, which tells the agent results reflect local state rather than a static catalog. No mention of caching or freshness, keeping it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the resource first and the informative payload (measures, size, license, APIs, download status) following. No filler or restated title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return structure need not be explained; the description still summarizes the fields, and for a zero-parameter read-only list tool nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the baseline there is nothing for the description to disambiguate. Schema coverage is 100% and the description correctly implies a parameterless call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists the test programs workload_fetch can download') and even gives a concrete example (bgfx's drawstress). It clearly positions itself as the enumeration counterpart to the sibling workload_fetch, so an agent can distinguish them without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
By tying the listing to 'programs workload_fetch can download,' it implicitly tells the agent to call this first to discover valid workload names before fetching. It does not explicitly state when-not to use it or name alternatives beyond workload_fetch, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.18.0- Added
perf_ab - Changed
perf_baseline1 field changed- added
Input schema / properties / skip_sAdded value: +{ + "description": "seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them; perf_check applies the same cut to the run it judges", + "type": "number" +}
- Changed
perf_baseline_record8 fields changed- changed
Input schema / properties / api / descriptionPrevious value: -"with workload: mtl (native Metal), d3d11 or d3d12 (under wine)"New value: +"with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine)" - added
Input schema / properties / backgroundAdded value: +{ + "description": "macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run", + "type": "boolean" +} - added
Input schema / properties / countersAdded value: +{ + "description": "default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second", + "type": "boolean" +} - added
Input schema / properties / envAdded value: +{ + "description": "NAME=VALUE pairs separated by spaces, set in the program's environment", + "type": "string" +} - added
Input schema / properties / exampleAdded value: +{ + "description": "with a workload that lists examples in workload_list: the one to run", + "type": "string" +} - added
Input schema / properties / memory_free_pctAdded value: +{ + "description": "macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac", + "type": "integer" +} - added
Input schema / properties / sizeAdded value: +{ + "description": "with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080", + "type": "string" +} - added
Input schema / properties / skip_sAdded value: +{ + "description": "seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them; perf_check applies the same cut to the run it judges", + "type": "number" +}
- Changed
perf_compare1 field changed- added
Input schema / properties / skip_sAdded value: +{ + "description": "seconds to leave out at the start of each recording, where shaders compile and resources load; 0 (default) keeps all. The GPU numbers, hitches and Metal memory are recomputed without them", + "type": "number" +}
- Added
perf_gate - Added
perf_history - Added
perf_panel - Changed
perf_record7 fields changed- changed
Input schema / properties / api / descriptionPrevious value: -"with workload: mtl (native Metal), d3d11 or d3d12 (under wine)"New value: +"with workload: mtl (native Metal), mtl-x64 (Metal built for x86_64, run under Rosetta like Wine), vk (Vulkan through MoltenVK: set METAL_TRACE_MOLTENVK), d3d11 or d3d12 (under wine)" - added
Input schema / properties / backgroundAdded value: +{ + "description": "macOS only, default false; true runs the program under taskpolicy -b, which throttles it hard and unevenly (drawstress: 18 to 280 times slower): repeat the run", + "type": "boolean" +} - added
Input schema / properties / countersAdded value: +{ + "description": "default false; true also records Metal GPU Counters (gpu_counters in the summary); not under Windows; adds about 40 s of read-back per recorded second", + "type": "boolean" +} - added
Input schema / properties / envAdded value: +{ + "description": "NAME=VALUE pairs separated by spaces, set in the program's environment", + "type": "string" +} - added
Input schema / properties / exampleAdded value: +{ + "description": "with a workload that lists examples in workload_list: the one to run", + "type": "string" +} - added
Input schema / properties / memory_free_pctAdded value: +{ + "description": "macOS only, 20 to 60: holds the whole Mac at this percentage of RAM free while recording (memory_pressure), to see how the program behaves short of memory; lower can freeze the Mac", + "type": "integer" +} - added
Input schema / properties / sizeAdded value: +{ + "description": "with a workload that has size_variables (drawstress): the window size, WIDTHxHEIGHT such as 1920x1080", + "type": "string" +}
- Added
perf_sweep
18 tool updates
v0.10.1- Changed
capture_records1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "next_offset": { + "type": [ + "integer", + "null" + ] + }, + "offset": { + "type": "integer" + }, + "rows": { + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "total", + "offset", + "rows", + "next_offset" + ], + "type": "object" +}
- Changed
capture_summary1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
gpu_family1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_attach2 fields changed- changed
Input schema / properties / seconds / descriptionPrevious value: -"recording length, default 20; the export afterwards takes about a minute"New value: +"recording length, default 20; the export afterwards takes several minutes under Wine" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_baseline1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_baseline_record3 fields changed- added
Input schema / properties / memoryAdded value: +{ + "description": "default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak", + "type": "boolean" +} - changed
Input schema / properties / seconds / descriptionPrevious value: -"recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes about a minute"New value: +"recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_check1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_compare2 fields changed- added
Input schema / properties / markdownAdded value: +{ + "description": "also return the numbers as Markdown tables, default false", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_diagnose1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Added
perf_export_trace - Changed
perf_record3 fields changed- added
Input schema / properties / memoryAdded value: +{ + "description": "default true; false skips the Metal memory table, the slowest to read (about 40 % faster summary): no metal_mib_peak", + "type": "boolean" +} - changed
Input schema / properties / seconds / descriptionPrevious value: -"recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes about a minute"New value: +"recording length, default 20; use 30 under Wine, whose start-up takes part of it; the export afterwards takes several minutes under Wine" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
perf_runs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "next_offset": { + "type": [ + "integer", + "null" + ] + }, + "offset": { + "type": "integer" + }, + "rows": { + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "total", + "offset", + "rows", + "next_offset" + ], + "type": "object" +}
- Added
presentmon_install - Changed
trace_count1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
trace_query1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "next_offset": { + "type": [ + "integer", + "null" + ] + }, + "offset": { + "type": "integer" + }, + "rows": { + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "total", + "offset", + "rows", + "next_offset" + ], + "type": "object" +}
- Changed
trace_tables1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
workload_fetch1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
workload_list1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
14 tool updates
v0.7.1- Changed
capture_records1 field changed- added
Input schema / properties / capture / descriptionAdded value: +"path of a .gputrace bundle saved from Xcode, inside METAL_TRACE_OUT or METAL_TRACE_READ"
- Changed
capture_summary1 field changed- added
Input schema / properties / capture / descriptionAdded value: +"path of a .gputrace bundle saved from Xcode, inside METAL_TRACE_OUT or METAL_TRACE_READ"
- Added
perf_attach - Added
perf_baseline - Added
perf_baseline_record - Added
perf_check - Changed
perf_compare3 fields changed- added
Input schema / properties / a / descriptionAdded value: +"run name from perf_runs: the reference, such as the run before a change" - added
Input schema / properties / b / descriptionAdded value: +"run name from perf_runs: the run to compare against a" - added
Input schema / properties / short_usAdded value: +{ + "description": "an encoder under this GPU time counts as short: 10, 25 (default), 50, 100, 250, 500 or 1000", + "type": "integer" +}
- Added
perf_diagnose - Changed
perf_record6 fields changed- added
Input schema / properties / apiAdded value: +{ + "description": "with workload: mtl (native Metal), d3d11 or d3d12 (under wine)", + "type": "string" +} - added
Input schema / properties / dimAdded value: +{ + "description": "with workload drawstress: side of the cube grid, dim^3 draws per frame", + "type": "integer" +} - added
Input schema / properties / prefix / descriptionAdded value: +"Wine prefix, default WINEPREFIX or ~/.wine; ignored with native" - added
Input schema / properties / workdir / descriptionAdded value: +"directory the program starts in, default the program's own" - added
Input schema / properties / workloadAdded value: +{ + "description": "a test program from workload_list, fetched with workload_fetch, instead of program", + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "label", - "program" -]New value: +[ + "label" +]
- Added
trace_count - Changed
trace_query3 fields changed- added
Input schema / properties / pid / descriptionAdded value: +"keep only this process's rows" - added
Input schema / properties / schema / descriptionAdded value: +"a table name that trace_tables lists, such as metal-gpu-intervals" - added
Input schema / properties / trace / descriptionAdded value: +"a run name from perf_runs whose trace_kept is true, or the path of a .trace"
- Changed
trace_tables1 field changed- added
Input schema / properties / trace / descriptionAdded value: +"a run name from perf_runs whose trace_kept is true, or the path of a .trace"
- Added
workload_fetch - Added
workload_list
8 tool updates
v0.2.0- First observed
capture_records - First observed
capture_summary - First observed
gpu_family - First observed
perf_compare - First observed
perf_record - First observed
perf_runs - First observed
trace_query - First observed
trace_tables
TDQS
Scored across 23 tools
Despite many perf_* tools, each has a clearly distinct role: record, attach, sweep, A/B compare, baseline, check, gate, history, diagnose, panel, export, and run listing. Similar-sounding pairs like perf_baseline versus perf_baseline_record are differentiated by whether they consume existing runs or record new ones. The trace and capture tools are also cleanly separated by operation and artifact type.
The set follows a consistent snake_case convention with useful domain prefixes such as perf_, trace_, capture_, workload_, and gpu_. Names are not strictly verb_noun throughout—there are noun-style names like perf_runs, perf_history, and perf_panel—but the grouping is readable and predictable. Minor deviations do not impede tool selection.
At 23 tools the surface is large, but this is a broad GPU profiling suite covering recording, comparison, baselines, gates, traces, captures, workload setup, and environment inspection. Each tool appears to earn its place, though the count is slightly heavy and could be streamlined. It is not an extreme mismatch for the stated scope.
The tool set covers the main lifecycle: fetching workloads, recording or attaching, saving baselines, comparing, checking, gating, diagnosing, visualizing, exporting traces, and inspecting raw trace/capture data. The main noticeable gap is management of saved artifacts, such as deleting or renaming recordings and baselines. That is a minor omission rather than a blocker for core profiling workflows.
Maintenance
Related MCP Connectors
GPU compute-asset identity registry: resolve device identity, verify history, buy official reports.
GPU fabric tools: NCCL benchmark analysis, degradation cost, cluster compatibility, XportL facts.
Estimated game fps for any GPU or Apple Silicon chip, with the limiter and tweaks.
Live GPU prices, VRAM requirements and local LLM hardware planning from VRAMGlass.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables GPU profiling and performance analysis via NVIDIA Nsight Systems, allowing agents to profile binaries and aggregate statistics for kernels, memory copies, and NVTX ranges. It supports advanced analysis through interval tree construction and structural queries on profiling reports.5MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to record, analyze, and compare Xcode Instruments traces, detect performance bottlenecks and regressions, and provide optimization recommendations.44MIT
- AlicenseAqualityCmaintenanceEnables AI agents to profile iOS/macOS apps using Xcode Instruments, automate simulator interactions, and get structured performance data for optimization.3726 npm20MIT
- AlicenseAqualityBmaintenanceEnables coding agents to profile and disassemble GPU kernels, benchmark and compare candidate rewrites against baselines, and run an autonomous speedrun loop that verifies and records results.1032 PyPIApache 2.0