perfetto-mcp-rs
perfetto-mcp-rs
English | 简体中文
一个用于通过 LLM 分析 Perfetto 追踪文件的 MCP 服务器。将 Claude Code(或任何 MCP 客户端)指向 Perfetto 追踪文件(.pftrace / .perfetto-trace / .bin 等 —— 支持内容嗅探),并使用 PerfettoSQL 进行查询。
由 trace_processor_shell 提供支持 —— 首次运行时自动下载,无需手动安装 Perfetto。
最适合与支持多轮工具调用的智能体 MCP 客户端(Claude Code、Codex、Claude Desktop、Cursor)配合使用。非智能体客户端虽然也能看到相同的工具,但无法遵循引导 LLM 完成典型 load_trace → list_tables → list_table_structure → execute_sql 流程的错误消息提示。
引导智能体使用正确的 PerfettoSQL 标准库模块 —— 分析 SQL 始终由智能体自行生成。
快速安装
macOS / Linux (Homebrew, 推荐):
brew tap tooluse-labs/tap
brew install perfetto-mcp-rs
# brew prints caveats; run the printed line to register with Claude Code / Codex:
perfetto-mcp-rs install --binary-path "$(brew --prefix)/bin/perfetto-mcp-rs"Rust 开发者 (cargo install):
cargo install --locked perfetto-mcp-rs
perfetto-mcp-rs install --binary-path "$(which perfetto-mcp-rs)"Linux / macOS / Windows (Git Bash, MSYS2, Cygwin) — 直接脚本:
curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.sh | shWindows (PowerShell):
irm https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.ps1 | iex上述安装程序会将预构建的二进制文件放入 ~/.local/bin(Windows 上为 %USERPROFILE%\.local\bin),并在需要时将其添加到您的用户 PATH 中。如果安装了 Claude Code 和/或 Codex,它还会自动进行注册。重启 Claude Code 或开启新的 Codex 会话即可生效。
Claude 作用域: 默认注册为 --scope user(可在任何目录下使用)。如需项目级安装,请设置 SCOPE=local(或 project)并在该项目目录下运行脚本:
SCOPE=local bash -c 'curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.sh | sh'PowerShell 等效命令:$env:SCOPE = 'local'; irm ... | iex。Codex 没有作用域概念,会忽略此变量。
支持的平台:linux amd64/arm64, macOS amd64/arm64, Windows amd64。如果您不想运行脚本,可以直接从 发布页面 获取二进制文件。发布资源命名为 perfetto-mcp-rs-<platform>(例如 perfetto-mcp-rs-linux-amd64);在调用 install 时重命名或显式指定下载的文件,并在 Unix 系统上先标记为可执行文件 (chmod +x) —— 子命令会拒绝非可执行路径,以避免写入损坏的 MCP 条目。示例:
# Linux amd64 example — adjust the asset name for your platform.
curl -fsSL -o perfetto-mcp-rs \
https://github.com/tooluse-labs/perfetto-mcp-rs/releases/latest/download/perfetto-mcp-rs-linux-amd64
chmod +x perfetto-mcp-rs
./perfetto-mcp-rs install --scope user --binary-path "$PWD/perfetto-mcp-rs"Related MCP server: arcana-mcp
升级
重新运行相同的安装命令 —— 它会拉取最新版本,安全地覆盖现有二进制文件(支持 Windows 文件锁定重试),并幂等地重新向 Claude Code / Codex 注册 MCP 服务器。
使用 --version 标志锁定特定版本:
curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.sh | sh -s -- --version v0.7.0VERSION 环境变量也有效,但必须紧接在 sh 之前(POSIX VAR=value cmd 仅作用于下一条命令 —— VERSION=v0.7.0 curl ... | sh 会将 VERSION 作用于 curl,而不是管道后的 sh):
curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.sh | VERSION=v0.7.0 shPowerShell —— 在同一行设置 $env:VERSION,因为 iex 在当前会话中运行:
$env:VERSION = 'v0.7.0'; irm https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/install.ps1 | iex没有自动更新守护进程 —— 升级是显式的。
检查更新
perfetto-mcp-rs check-update如果已是最新(或领先于发布版本 —— 本地开发构建),则退出码为 0;如果存在更新版本,则为 2;网络或解析错误则为 1。适用于 shell 提示符集成和 CI 预检查。
卸载
每个平台都有对称的单行命令。从 Claude Code 和 Codex 中注销,删除二进制文件,并删除缓存的 trace_processor_shell。幂等 —— 如果某些步骤已手动完成,再次运行也是安全的。
Linux / macOS / Windows (Git Bash, MSYS2, Cygwin):
curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/uninstall.sh | shWindows (PowerShell) — 请先关闭 Claude Code、Codex 或任何其他正在使用该 .exe 的程序:
irm https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/uninstall.ps1 | iex作用域安装 (local / project): claude 按项目目录存储本地/项目条目,因此卸载必须使用相同的 SCOPE 并在该目录下运行。省略此步骤会留下作用域内的 Claude 条目,而包装器仍会删除二进制文件和缓存:
# Ran `SCOPE=local bash install.sh` in ~/work/foo earlier? Then:
cd ~/work/foo
SCOPE=local bash -c 'curl -fsSL https://raw.githubusercontent.com/tooluse-labs/perfetto-mcp-rs/main/uninstall.sh | sh'PowerShell 等效命令:cd <original-project-dir>; $env:SCOPE = 'local'; irm ... | iex。
$INSTALL_DIR(默认 ~/.local/bin)不会从您的 PATH 中移除:
Linux / macOS — 安装程序仅打印
PATH提示;如果您将其添加到了 shell rc 文件中,请手动删除该行。Windows — 安装程序将
$INSTALL_DIR写入您的用户 PATH (HKCU\Environment);如果您想删除它,请通过“系统属性”→“环境变量”进行操作。
其他工具可能仍依赖此目录,这就是卸载时将其保留的原因。
工具
工具 | 用途 |
| 打开 Perfetto 追踪文件(任何 trace_processor 可读格式: |
| 列出已加载追踪中的表/视图,可选 GLOB 过滤器 |
| 显示表的列名和类型 |
| 运行 PerfettoSQL 查询,返回列式 JSON |
| 列出追踪中的进程(pid, 名称, 开始/结束时间戳) |
| 列出进程名称下的线程(最多 2000 个) |
| 最严重的卡顿帧及其原因、子原因、delay_since_last_frame(Chrome 追踪) |
| 页面加载:URL, FCP, LCP, DCL, 加载耗时(毫秒)(Chrome 追踪) |
| 按持续时间排序的主线程任务(含 cpu_pct,使用 is_main_thread)(Chrome 追踪) |
| 浏览器启动事件和首次可见内容时间(Chrome 追踪) |
| 按持续时间排名的 Web 内容交互(点击、轻触、INP)(Chrome 追踪) |
| 列出可用的 PerfettoSQL 标准库模块及使用示例(无需追踪文件) |
典型流程取决于追踪类型:
Chrome 追踪:
load_trace→ 专用chrome_*工具(chrome_scroll_jank_summary,chrome_page_load_summary,chrome_main_thread_hotspots,chrome_startup_summary,chrome_web_content_interactions) →execute_sql以对返回的行进行更深入的分析。其他追踪:
load_trace→list_tables/list_table_structure以进行模式发现 →execute_sql进行查询。当标准库模块可能涵盖您的分析时(Android,通用模块如slices.with_context),可辅助调用list_stdlib_modules。
示例
向 Claude Code 或 Codex 询问类似以下内容:
加载
~/traces/scroll_jank.pftrace并告诉我最主要的滚动卡顿原因。
Claude 将调用 load_trace,然后发出类似以下的查询:
INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3;
SELECT cause_of_jank, COUNT(*) AS n
FROM chrome_janky_frames
GROUP BY cause_of_jank
ORDER BY n DESC;手动 MCP 客户端配置
如果安装程序的自动注册不适用于您的客户端:
Codex:
codex mcp add perfetto-mcp-rs -- /absolute/path/to/perfetto-mcp-rs基于 JSON 的客户端 (例如 Claude Code, Claude Desktop, Cursor):
{
"mcpServers": {
"perfetto-mcp-rs": {
"command": "/absolute/path/to/perfetto-mcp-rs"
}
}
}配置
变量 | 作用 |
| 指向现有 |
| 覆盖 |
| 覆盖 HTTP 状态/查询超时时间(毫秒) |
|
|
CLI 标志:
标志 | 默认值 | 描述 |
| 3 | 最大缓存的 |
| 20000 | 等待生成的 |
| 30000 |
|
从源码构建
需要 Rust 工具链和 protoc(Protocol Buffers 编译器):
# Ubuntu/Debian
sudo apt install -y protobuf-compiler
# macOS
brew install protobuf
# Windows
choco install protoc然后:
git clone https://github.com/tooluse-labs/perfetto-mcp-rs
cd perfetto-mcp-rs
cargo build --release
# Binary at target/release/perfetto-mcp-rs开发
cargo test # unit tests
cargo clippy # lint
cargo fmt # format许可证
采用 Apache License, Version 2.0 或 MIT license 双重许可。贡献均在相同条款下接受。
Available Tools
17 toolschrome_main_thread_hotspotsARead-onlyIdempotent
Top Chrome main-thread tasks by wall duration: id, ts, name, task_type, thread_name, process_name, upid, pid, nullable machine_id, dur_ms, overlap_dur_ms, full_task_cpu_pct/full_task_thread_dur_ms, overlap_cpu_pct/overlap_thread_dur_ms; legacy cpu_pct/thread_dur_ms are full-task. Uses chrome.tasks, thread.is_main_thread = 1, and Chrome's Cr*Main fallback. Pass a returned id to slice_descendants_breakdown for child-slice breakdowns.
Use when: investigating responsiveness, scroll/load stalls, CPU vs wall time, or one renderer.
Don't use for: non-Chrome traces (will error). For background (non-main) thread tasks, drop to execute_sql against chrome.tasks directly.
Parameters (all optional):
process_name/pid/machine_id/upid: scope to one process/type. Preferupid; addmachine_idto disambiguate multi-machinepids. All filters AND.page_load_id/navigation_id/phase: scope to a page-load window. IDs matchchrome_page_loads.idand.navigation_idrespectively and are mutually exclusive.phase:navigation_to_fcp,navigation_to_load,dcl_to_fcp,fcp_to_load. If an id is set withoutphase, defaults tonavigation_to_fcp; phase-only uses the latest page load.start_ts_ns/end_ts_ns: raw trace timestamp bounds in nanoseconds (end_ts_nsexclusive); aliasesstart_ts/end_tsare accepted; intersect page-load windows.overlap_dur_msis clipped to that window.min_dur_ms: minimum full-task duration, or clipped overlap duration when a window is set. Defaults to 16 ms. Pass 0 for all positive-overlap tasks.limit: max rows (default 100, capped at 5000). Must be > 0 if set.max_string_len: optional cap for returned string cells. Unset preserves full strings for precision. Must be > 0 if set.
Output: metadata-first JSON preserving columns / rows; truncated=true means an extra-row probe found more rows; string_truncated=true means cell text was shortened.
Empty result: no detected main-thread tasks exceeded min_dur_ms at the selected process/window threshold, or the trace uses non-standard main-thread names outside the Cr*Main fallback.
| Name | Required | Description | Default |
|---|---|---|---|
| pid | No | Optional pid filter — the OS-level process ID (visible in Task Manager). Get pid from `list_processes`. ANDs with the other filters when set. Note: pids can be recycled within a long trace; prefer `upid` when precision matters. Accepts both numbers and numeric strings. | |
| upid | No | Optional upid filter — the trace-internal Unique Process ID assigned by trace_processor (also from `list_processes`). Always uniquely identifies one process within a trace, even if the OS recycled its pid. Use this to disambiguate same-named or pid-recycled processes; ANDs with the other filters when set. Accepts both numbers and numeric strings. | |
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000 to match `execute_sql`. Lower values keep responses short; higher values surface long tails of mid-duration tasks. Accepts both numbers and numeric strings. | |
| phase | No | Optional page-load phase window. If set without `page_load_id` or `navigation_id`, uses the latest page load in the trace. Values: navigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| end_ts_ns | No | Optional raw trace timestamp upper bound in nanoseconds, exclusive. This uses the same unit as the returned `ts` column. ANDs with any page-load window. | |
| machine_id | No | Optional machine id filter for multi-machine traces when the trace schema has `process.machine_id`. ANDs with pid/process filters and disambiguates same pid values on different machines. Accepts numbers and numeric strings. | |
| min_dur_ms | No | Optional minimum task duration in milliseconds. Defaults to 16 ms (one 60 Hz frame budget). Pass 0 to see ALL main-thread tasks; raise to e.g. 33 (30 Hz) or 100 to focus on the worst stutters. Must be a finite non-negative number. Accepts both numbers and numeric strings. | |
| start_ts_ns | No | Optional raw trace timestamp lower bound in nanoseconds. This uses the same unit as the returned `ts` column. ANDs with any page-load window. | |
| page_load_id | No | Optional page-load id used to scope tasks to one navigation phase. Matches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| process_name | No | Optional process-name filter (e.g. "Renderer", "Browser", "GPU Process"). Useful to scope to one process type without picking a specific instance. | |
| navigation_id | No | Optional Chrome navigation id used to scope tasks to one navigation phase. Matches `chrome_page_loads.navigation_id`. Mutually exclusive with `page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds detailed behavioral context: query sources, fallback for main-thread detection, default min_dur_ms of 16ms, output format with truncation flags, and empty result semantics. No contradiction with annotations.
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 is long but well-structured with sections for usage, parameter groups, output format, and empty result. Every sentence adds value for a complex tool, though slight verbosity could be trimmed. Still appropriate for the complexity.
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 13 parameters, no output schema, and rich annotations, the description covers all aspects: usage context, parameter details, output format (columns/rows, metadata, truncation), and empty result explanation. It is fully complete for an agent to use 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 description coverage is 100% (baseline 3), but the description adds substantial meaning beyond the schema: explains defaults, mutual exclusivity of page_load_id/navigation_id, AND logic for filters, and relationships like `phase` defaults. This is exceptionally thorough parameter documentation.
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 clearly states it retrieves 'Top Chrome main-thread tasks by wall duration', lists columns, and distinguishes from sibling tools like `execute_sql` and `slice_descendants_breakdown`. The purpose is specific and differentiated.
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 provides explicit 'Use when' (responsiveness, stutters) and 'Don't use for' (non-Chrome traces, background threads) guidance, and suggests alternatives like `execute_sql` for non-main-thread tasks. This is excellent usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_page_load_resource_hotspotsARead-onlyIdempotent
Rank URL-bearing Chrome resource/request slices in a page-load/raw window. Returns timing, overlap, process/thread/machine_id, URL. Use after chrome_page_load_resource_summary to drill into slow URL slices. Filters: page_load/window, min_dur_ms default 50, limit, max_string_len. slice_duration_status='incomplete_duration' means dur=-1; overlap is measured to window end or trace_end().
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set. | |
| phase | No | Optional page-load phase window. If set without `page_load_id` or `navigation_id`, uses the latest page load in the trace. Values: navigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| end_ts_ns | No | Optional raw trace timestamp upper bound in nanoseconds, exclusive. This uses the same unit as the returned `ts` column. ANDs with any page-load window. | |
| min_dur_ms | No | Optional minimum resource-like slice duration in milliseconds. Defaults to 50 ms. Pass 0 to see all matching resource slices. | |
| start_ts_ns | No | Optional raw trace timestamp lower bound in nanoseconds. This uses the same unit as the returned `ts` column. ANDs with any page-load window. | |
| page_load_id | No | Optional page-load id used to scope resources to one navigation phase. Matches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| navigation_id | No | Optional Chrome navigation id used to scope resources to one navigation phase. Matches `chrome_page_loads.navigation_id`. Mutually exclusive with `page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate the tool is read-only and idempotent. The description adds useful behavioral details about the slice_duration_status meaning and overlap measurement, complementing the annotations without contradiction.
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 is three sentences, front-loaded with the core purpose, followed by usage guidance and a note on parameters and status. No wasted words, very efficient.
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?
The description covers purpose, return fields, usage context, key filters, and a behavioral nuance. Given no output schema, it provides enough context for the agent to understand the tool's role and basic output, though more explicit output structure could help.
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% with detailed parameter descriptions. The description summarizes key filters and defaults, adding high-level grouping but not significantly new meaning 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?
The description clearly states the tool ranks URL-bearing resource slices in a page-load/raw window. It specifies the verb 'rank', the resource, and the context, and distinguishes from sister tool chrome_page_load_resource_summary by indicating it is used to drill into slow slices after that 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?
The description explicitly says to use the tool after chrome_page_load_resource_summary to drill into slow URL slices, providing clear sequencing. It also lists key filters, though it does not explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_page_load_resource_pipelineARead-onlyIdempotent
Drill into one Chrome page-load resource URL and join lifecycle/request spans with script/style/layout signals. Use after chrome_page_load_resource_summary with example_slice_id or url_substring. Returns timing facts, match evidence, resource ends, primary/detail slice evidence (detail is not a root-cause claim), URL/ancestor-correlated resource result source/hit, machine-id sets, incomplete count, and evidence_boundary. Parameters: URL seed required; optional window filters, url_grouping, limit default 30, max_string_len.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 30 and is capped at 5000. Must be > 0 when set. | |
| phase | No | Optional page-load phase window. If set without `page_load_id` or `navigation_id`, uses the latest page load in the trace. Values: navigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| end_ts_ns | No | Optional raw trace timestamp upper bound in nanoseconds, exclusive. ANDs with any page-load window. | |
| start_ts_ns | No | Optional raw trace timestamp lower bound in nanoseconds. ANDs with any page-load window. | |
| page_load_id | No | Optional page-load id used to scope resources/scripts to one navigation phase. Matches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| url_grouping | No | URL grouping strategy. Defaults to full URL; use without_query to merge signed/nonce query variants of the same endpoint. | |
| navigation_id | No | Optional Chrome navigation id used to scope resources/scripts to one navigation phase. Matches `chrome_page_loads.navigation_id`. Mutually exclusive with `page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| url_substring | No | Optional URL substring to drill into, e.g. "main.js" or "qianwen-web-desktop/2.3.401/js/main.js". Matches against URL-bearing resource and script slices with SQL INSTR, not LIKE wildcards. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. | |
| example_slice_id | No | Optional resource-summary/hotspot `example_slice_id`; when provided the tool derives that slice's URL and drills into matching URL rows. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description lists return fields (timing facts, match evidence, etc.) and notes that detail is not a root-cause claim, adding transparency beyond annotations that already mark readOnly and idempotent. No contradictions.
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?
Description is a single paragraph with multiple sentences, front-loaded with purpose and usage. Could be more concise but avoids unnecessary fluff.
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 11 parameters and no output schema, the description covers what the tool returns and key parameter guidance. It provides sufficient context for an agent to invoke correctly, though some return details could be more structured.
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 fully documents parameters. The description provides a summary but no additional meaning beyond the schema. Minor confusion about 'URL seed' not matching parameter names.
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?
Description clearly states the tool drills into a Chrome page-load resource URL and joins lifecycle/request spans with signals. It specifies the verb 'drill' and the resource, and distinguishes from siblings by positioning as a deeper analysis after chrome_page_load_resource_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?
Explicitly advises using after chrome_page_load_resource_summary with example_slice_id or url_substring, providing clear context and alternatives. No further when-not-to-use needed given the specificity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_page_load_resource_summaryARead-onlyIdempotent
URL-level Chrome resource/request summary for a page-load/raw window. Returns URL key, process/machine/priority sets, span, max/summed overlap, primary/detail slice evidence (detail is not a root-cause claim), navigation/renderer relation including target_renderer_source, example_slice_id, incomplete_duration_slice_count. Use before chrome_page_load_resource_hotspots; rank by max overlap.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 25 and is capped at 5000. Must be > 0 when set. | |
| phase | No | Optional page-load phase window. If set without `page_load_id` or `navigation_id`, uses the latest page load in the trace. Values: navigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| end_ts_ns | No | Optional raw trace timestamp upper bound in nanoseconds, exclusive. ANDs with any page-load window. | |
| start_ts_ns | No | Optional raw trace timestamp lower bound in nanoseconds. ANDs with any page-load window. | |
| page_load_id | No | Optional page-load id used to scope resources to one navigation phase. Matches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| url_grouping | No | URL grouping strategy. Defaults to full URL; use without_query to merge signed/nonce query variants of the same endpoint. | |
| navigation_id | No | Optional Chrome navigation id used to scope resources to one navigation phase. Matches `chrome_page_loads.navigation_id`. Mutually exclusive with `page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. | |
| min_overlap_ms | No | Optional minimum per-URL max overlap in milliseconds. Defaults to 50 ms. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, idempotentHint, non-destructive. Description adds behavioral context: lists output fields, clarifies 'detail is not a root-cause claim', explains navigation/renderer relation. It goes beyond annotations but could mention more about result interpretation or caveats.
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?
Description is moderately sized (3 sentences) and front-loaded with purpose. Could slightly improve structure (e.g., list fields separately), but effectively conveys essential information without redundancy.
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 10 parameters, no output schema, and annotations covering safety, the description is fairly complete. It lists output fields and usage hints. However, without output schema, it could elaborate on fields like max/summed overlap and incomplete_duration_slice_count.
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?
Input schema has 100% parameter description coverage, so the description does not need to add parameter meaning. It does not provide additional context beyond the schema, maintaining baseline score.
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?
Description clearly states it provides a URL-level resource summary for a page-load or raw window, using specific verbs and resource. It distinguishes itself from siblings by noting it should be used before chrome_page_load_resource_hotspots.
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 'Use before chrome_page_load_resource_hotspots; rank by max overlap', giving clear ordering guidance. However, it does not detail when to avoid this tool or contrast with other similar tools like chrome_page_load_summary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_page_load_script_hotspotsARead-onlyIdempotent
Rank renderer main-thread script groups in a Chrome page-load/raw window: URL/name/process/thread/machine_id, wall/CPU totals, style/layout ms, example_slice_id. Read-only.
Use when: slow FCP/load needs post-resource JS attribution; expand example_slice_id with slice_descendants_breakdown.
Parameters: optional process filters (process_name/pid/machine_id/upid), page-load/window filters shared with chrome_main_thread_hotspots, min_total_ms (default 20), limit, max_string_len. Empty result: no matching script groups.
| Name | Required | Description | Default |
|---|---|---|---|
| pid | No | Optional OS pid filter. Accepts both numbers and numeric strings. | |
| upid | No | Optional trace-internal upid filter. Prefer this when distinguishing same-named Renderer processes. Accepts numbers and numeric strings. | |
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set. | |
| phase | No | Optional page-load phase window. If set without `page_load_id` or `navigation_id`, uses the latest page load in the trace. Values: navigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| end_ts_ns | No | Optional raw trace timestamp upper bound in nanoseconds, exclusive. This uses the same unit as trace `slice.ts`. ANDs with any page-load window. | |
| machine_id | No | Optional machine id filter for multi-machine traces when the trace schema has `process.machine_id`. Accepts numbers and numeric strings. | |
| start_ts_ns | No | Optional raw trace timestamp lower bound in nanoseconds. This uses the same unit as trace `slice.ts`. ANDs with any page-load window. | |
| min_total_ms | No | Optional minimum aggregated wall time per grouped script hotspot. Defaults to 20 ms. Pass 0 to see every matching group. | |
| page_load_id | No | Optional page-load id used to scope scripts to one navigation phase. Matches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| process_name | No | Optional process-name filter (e.g. "Renderer"). Useful to scope one process type without picking a specific instance. | |
| navigation_id | No | Optional Chrome navigation id used to scope scripts to one navigation phase. Matches `chrome_page_loads.navigation_id`. Mutually exclusive with `page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds that it is 'Read-only' and describes the ranking behavior with optional filters, plus mentions empty result meaning. Provides useful operational context beyond safety profile.
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 is two paragraphs with core purpose front-loaded, then usage and parameter guidance. It is efficient without being overly verbose. Every sentence adds value, though the parameter list is somewhat redundant with 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?
Given 13 parameters and no output schema, the description explains output fields (URL, name, totals, etc.) and links to sibling for expansion. It provides sufficient context for a read-only analysis tool, covering what results look like and how to use them.
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. Description repeats some default values (min_total_ms=20) and lists filter types but adds little new detail beyond the schema. Mentions 'Empty result: no matching script groups' which is a minor addition.
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 clearly states the tool ranks renderer main-thread script groups in a Chrome page-load/raw window, listing specific output fields like URL, name, wall/CPU totals. It distinguishes itself by mentioning 'post-resource JS attribution' and referencing the sibling tool for expansion.
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 'Use when: slow FCP/load needs post-resource JS attribution' and guides to expand `example_slice_id` with `slice_descendants_breakdown`. It also notes that parameters are shared with `chrome_main_thread_hotspots`. Lacks explicit when-not-to-use compared to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_page_load_summaryARead-onlyIdempotent
Summarize each page navigation in a Chrome trace: navigation id, URL, raw boundary timestamps, FCP / LCP / DCL / load timings in ms. Read-only.
Use when: comparing page-load timings across navigations, finding slow loads, baselining web-vitals before/after a change. Prefer over hand-joining chrome.page_loads — schema is already correct.
Don't use for: non-Chrome traces (will error). For sub-event timings inside one navigation, drop to execute_sql against the chrome.page_loads module.
Parameters: optional limit (default 100, capped at 5000) and max_string_len. Operates on the loaded trace.
Output: metadata-first JSON; row_count exact; truncated=true means more rows exist; string_truncated=true means shortened text.
Empty result: no navigations occurred during capture (e.g. trace started after the page was already loaded).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set; accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned Chrome-tool rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description adds context beyond annotations: states read-only, describes output format (metadata-first JSON), mentions row_count and truncated flags, and explains empty result behavior. Annotations already indicate readOnlyHint, but description enriches transparency.
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?
Concise with 5-6 sentences, each serving a purpose: purpose, read-only, usage, don't-use, parameters, output, empty result. No fluff.
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 tool with three optional parameters and no output schema, the description covers output structure, edge cases, and usage context thoroughly. Sufficient for an agent to decide and invoke 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% and includes descriptions for all three parameters. Description reinforces limit (default 100, capped 5000) and max_string_len role. Trace_id is omitted from description but schema covers it well, so value added is moderate.
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 clearly states the tool summarizes page navigations in a Chrome trace, enumerating specific timings (FCP, LCP, DCL, load). It distinguishes itself from sibling tools like chrome_page_load_resource_hotspots by focusing on top-level navigation 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?
Explicitly provides when to use (comparing timings), when not to use (non-Chrome traces), and an alternative (execute_sql for sub-event timings). Also recommends preferring this over manual joins.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_scroll_jank_summaryARead-onlyIdempotent
Summarize the worst scroll jank frames in a Chrome trace: cause_of_jank, sub_cause_of_jank, delay_since_last_frame, event_latency_id, scroll_id, vsync_interval. One row per janky frame, sorted by delay_since_last_frame DESC. Read-only.
Use when: investigating jank reports, finding scroll regressions, ranking jank causes. Prefer over hand-rolling SQL on chrome.scroll_jank.scroll_jank_v3 — same data, less code.
Don't use for: non-Chrome traces (will error). For custom filters, use execute_sql against the same view.
Parameters: optional limit (default 100, capped at 5000) and max_string_len. Operates on the loaded trace.
Output: metadata-first JSON; row_count exact; truncated=true means more rows exist; string_truncated=true means shortened text.
Empty result: no janky frames detected (clean trace) or no scrolls occurred during capture.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set; accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned Chrome-tool rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, which the description reinforces ('Read-only'). It adds details like operating on the loaded trace, empty result meaning (clean trace or no scrolls), and output metadata (row_count, truncated flags). No contradictions.
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?
Concise yet comprehensive, using clear sections and bullet-like lists. Every sentence adds value, and the structure is front-loaded with key info. No wasted words.
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 tool with 3 parameters and no output schema, the description thoroughly explains output format, metadata, and edge cases (empty results, truncation). It fully compensates for lack of output schema.
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 description adds context beyond the schema, such as default limit (100), cap (5000), and max_string_len purpose. This elevates it above the baseline 3.
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 clearly states the tool summarizes the worst scroll jank frames from a Chrome trace, listing specific output columns. It distinguishes itself from siblings like `execute_sql` and other Chrome summary tools, providing a specific verb+resource.
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?
Explicit guidance on when to use (investigating jank, finding regressions) and when not to (non-Chrome traces). Also suggests an alternative (`execute_sql`) for custom filters, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_startup_summaryARead-onlyIdempotent
Summarize Chrome browser startup events: id, name, launch_cause, startup_duration_ms (first_visible_content_ts - startup_begin_ts), browser_upid. Read-only.
Use when: measuring time-to-first-visible-content for cold starts, comparing launch causes (NEW_WINDOW vs CMD_LINE vs RESTORE_SESSION), regressing startup performance.
Don't use for: non-Chrome traces (will error). Browser-process work during steady state is covered by chrome_main_thread_hotspots.
Parameters: optional limit (default 100, capped at 5000) and max_string_len. Operates on the loaded trace.
Output: metadata-first JSON; row_count exact; truncated=true means more rows exist; string_truncated=true means shortened text.
Empty result: trace started after the browser was already running (most cases — startup is captured only when tracing began before launch).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set; accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned Chrome-tool rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations set readOnlyHint=true and idempotentHint=true; the description adds operational details: limit cap (5000), output metadata (row_count, truncated flags), and explains the empty result scenario (trace started after browser launch).
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 is well-structured with separate paragraphs for purpose, usage, parameters, output, and edge cases. Every sentence is informative with no redundancy.
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 the tool's complexity and no output schema, the description fully covers input parameters, output metadata, empty result handling, and trace scope, making it complete for an AI agent to decide to use the tool.
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?
100% schema coverage means the schema already describes all three parameters with their types, defaults, and constraints. The description mentions limit and max_string_len but adds no additional semantic value beyond what the schema provides.
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 uses a specific verb ('Summarize') and resource ('Chrome browser startup events'), lists the fields returned, and explicitly distinguishes from sibling tools like chrome_main_thread_hotspots for steady-state analysis.
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?
Provides explicit use cases (cold start measurement, launch cause comparison, regression analysis) and clear contraindications (non-Chrome traces, steady-state work handled by chrome_main_thread_hotspots).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chrome_web_content_interactionsARead-onlyIdempotent
Rank Chrome web content interactions by total_duration_ms: id, ts, total_duration_ms, longest_event_dur_ms, interaction_type, renderer_upid. Read-only.
Use when: INP analysis, reproducing user-felt latency, finding slow click/tap/keyboard handlers.
Don't use for: non-Chrome traces (will error). For interactions filtered by interaction_type, drop to execute_sql against chrome.web_content_interactions.
Parameters: optional limit (default 100, capped at 5000) and max_string_len. Operates on the loaded trace.
Output: metadata-first JSON; row_count exact; truncated=true means more rows exist; string_truncated=true means shortened text.
Empty result: no interactions captured (trace started before user input or interaction tracking was disabled in tracing config).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Must be > 0 when set; accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned Chrome-tool rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description details output format (metadata-first JSON, row_count, truncated, string_truncated) and explains empty results (no interactions captured). No contradictions with annotations.
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 is moderately long but well-structured with sections for output columns, usage, parameters, and output behavior. It front-loads key information but could be slightly more succinct.
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 output schema, the description explains output format and status flags adequately. It covers trace_id implicitly by stating 'operates on the loaded trace,' and explains empty results. Slightly more detail on trace_id parameter could be added.
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?
Description adds minimal value for limit (default/cap) and max_string_len, but schema already covers all three parameters with 100% coverage. The description notes the limit default and cap, confirming schema info.
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 clearly states it ranks Chrome web content interactions by duration, listing specific columns (id, ts, total_duration_ms, etc.) and explicitly marks itself as read-only. It distinguishes from siblings by noting that filtered interactions can be obtained via execute_sql on the same table.
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?
Provides explicit use cases (INP analysis, reproducing user-felt latency, finding slow handlers) and exclusions (non-Chrome traces will error). Also offers an alternative approach for filtering by interaction_type, which helps an agent choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_sqlARead-onlyIdempotent
Run a PerfettoSQL query against the loaded trace and return rows as columnar JSON. Read-only against trace data; SQLite operates in-memory per session. Aggregates are strongly preferred over raw row data; results are capped at 5000 rows.
Use when: composing analyses not covered by the dedicated tools — custom aggregations, joins across stdlib modules, or queries against base tables (slice, thread, process, sched).
Don't use for: questions the dedicated chrome_* tools answer — they return the same data with the JOIN shape already correct. Don't hand-roll slice scans with LIKE '%x%' patterns when a stdlib module covers the data; INCLUDE PERFETTO MODULE chrome.tasks is faster and the joins are pre-baked.
Parameters: sql is a single PerfettoSQL statement (the INCLUDE PERFETTO MODULE foo; and SELECT ... can be in the same call). Optional output shaping (head/limit, columns_only, summary, include_row_count, max_string_len) only changes what this tool returns; it does not rewrite the SQL. Blob cells render as blob:hex:<hex>. String results may be redacted by the server privacy policy before they are returned, preserving diagnostic structure while masking sensitive URL/header/cookie/path values. Requires load_trace to have run first.
Empty rows means the query matched nothing — distinct from a SQL error, which is returned as an error string with a hint pointing at the most likely cause (missing module, missing column, missing table).
Reference docs (fetch when you need exact column names or function signatures): https://perfetto.dev/docs/analysis/stdlib-docs (24 stdlib packages — chrome / android / sched / slices / linux / wattson / v8 / ...; use per-package anchors like #package-chrome), https://perfetto.dev/docs/analysis/perfetto-sql-syntax (syntax).
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | SQL query to execute (PerfettoSQL syntax). | |
| head | No | Agent-friendly alias for `limit`: return only the first N decoded rows. This trims returned rows only; it does not rewrite the SQL. Mutually exclusive with `limit`. Accepts both numbers and numeric strings. | |
| limit | No | Optional output row cap. This trims returned rows only; it does not rewrite or limit the SQL that trace_processor executes. Mutually exclusive with `head`. Accepts both numbers and numeric strings. | |
| summary | No | Return column names, row-count metadata, and a small sample of rows. Defaults to 10 sample rows unless `head` or `limit` is provided. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| columns_only | No | Return only column names and row-count metadata; omit row values. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Accepts both numbers and numeric strings. Must be > 0 when set. | |
| include_row_count | No | Include decoded row-count metadata with a row-returning shaped response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only, idempotent, and non-destructive. The description adds important behavioral details: aggregates preferred over raw rows, 5000 row cap, blob rendering as hex, string redaction by server privacy policy, and error handling with hints. No contradiction with annotations.
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 is comprehensive but well-structured: core action first, then usage guidelines, then parameter details, error handling, and references. It is front-loaded with the essential purpose. While long, each sentence adds necessary information for an agent to use the tool correctly.
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 8 parameters, no output schema, and the tool's complexity (query language, error modes, privacy redaction), the description covers all key behaviors, constraints, and edge cases. It also provides links to external documentation for details on SQL syntax and stdlib modules.
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 parameters are already documented. The description adds value by explaining that `head`/`limit` only trim output, not rewrite SQL; that `sql` can include `INCLUDE PERFETTO MODULE`; and that `summary` defaults to 10 samples. This exceeds the baseline expectation.
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 clearly states the tool runs a PerfettoSQL query against a loaded trace and returns rows as columnar JSON. It distinguishes itself from sibling tools by explicitly noting that dedicated `chrome_*` tools exist for specific analyses and should be used instead.
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?
Provides explicit guidance on when to use (composing custom analyses not covered by dedicated tools) and when not to use (for questions answered by `chrome_*` tools or when stdlib modules suffice). Names alternatives like `chrome_*` tools and stdlib modules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_processesARead-onlyIdempotent
List every process captured in the trace: upid (trace-internal id), pid, machine_id, name, start_ts, end_ts. Read-only.
Use when: entry point for Android and Linux trace analysis, or picking the right pid/upid to feed into list_threads_in_process or chrome_main_thread_hotspots.
Don't use for: Chrome traces — the dedicated chrome_* tools answer most common questions without process-level navigation.
Parameters: none — operates on the loaded trace.
Empty result: rare; would mean the trace captured no process metadata at all.
Errors when: no trace is loaded — call load_trace first.
| Name | Required | Description | Default |
|---|---|---|---|
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant context beyond annotations: it states the tool is read-only (consistent), explains what data is returned, describes rare outcomes (empty result), and documents error conditions (no trace loaded). Annotations already mark it as read-only and non-destructive.
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 is well-structured with clear sections and front-loaded information. It could be slightly more concise by removing 'Read-only.' since annotations already convey that, but overall it efficiently delivers value.
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 output schema, the description thoroughly covers return fields, edge cases, and error scenarios. It fully prepares the agent to use the tool correctly and understand its results.
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 description claims 'Parameters: none — operates on the loaded trace', but the input schema includes an optional 'trace_id' parameter. This is a direct contradiction between description and schema, misleading the agent about available parameters. Despite 100% schema coverage, the description undercuts clarity.
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 clearly states 'List every process captured in the trace' and enumerates the fields returned. This explicitly identifies the tool's function and scope, distinguishing it from siblings that focus on specific Chrome analyses.
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?
Explicit guidance on when to use (entry point for Android/Linux, picking pid) and when not to (Chrome traces), with specific alternative tools mentioned (chrome_* tools).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_stdlib_modulesARead-onlyIdempotent
List curated PerfettoSQL stdlib modules as JSON entries with domain, module, views, description, and usage. Use when choosing an INCLUDE PERFETTO MODULE ... target; no trace has to be loaded.
Optional filters: domain (chrome, android, generic), query (case-insensitive search over module/view/description), and limit. For longer guidance, read resource://perfetto-mcp/stdlib-quickref.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max entries to return. Must be > 0 when set; accepts both numbers and numeric strings. | |
| query | No | Optional case-insensitive search over module name, view names, and description. | |
| domain | No | Optional domain filter. Valid values: "chrome", "android", "generic". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true. Description adds important context: no trace required, result format (JSON with fields), and optional filters. No contradictions.
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 precise sentences. First sentence states core function and output. Second sentence adds usage context and optional filters. No redundant 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?
No output schema, but description explains output format. Covers optional filters and points to a resource for longer guidance. Adequate for selection and 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 description coverage is 100%, and the description enhances each parameter: valid domain values, case-insensitive search scope for query, and constraint for limit. Provides meaning beyond bare 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?
Description clearly states the tool lists curated PerfettoSQL stdlib modules with specific fields, and its purpose is for choosing an INCLUDE PERFETTO MODULE target. It distinguishes from siblings which are specific analysis tools.
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 (choosing INCLUDE PERFETTO MODULE target) and notes that no trace needs to be loaded. Optional filters are mentioned, but no explicit alternatives or when-not-to-use are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesARead-onlyIdempotent
List tables and views in the loaded trace. Read-only.
Use when: exploring an unfamiliar trace or verifying a table exists before writing SQL. Underlying SQL engine is SQLite, so the catalog tables common in other SQL engines aren't present — this MCP tool is the schema introspection path.
Don't use for: queries against known stdlib modules — go straight to execute_sql with INCLUDE PERFETTO MODULE. Don't reference this tool name inside SQL; it's a separate MCP tool, not a SQL function — call it via the tool API.
Parameters: optional pattern — SQLite GLOB filter (e.g. chrome_* for chrome stdlib views, slice* for the slice table family). Without it, internal stdlib tables (_*) are hidden.
Empty result: no tables matched. For stdlib views, run execute_sql with INCLUDE PERFETTO MODULE ... first; otherwise retry an explicit pattern for internal tables.
Errors when: no trace is loaded — call load_trace first.
| Name | Required | Description | Default |
|---|---|---|---|
| pattern | No | Optional GLOB pattern to filter table names (e.g. "chrome_*"). | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint, and openWorldHint. Adds value by explaining SQLite engine, behavior of pattern parameter hiding internal tables, empty result handling, and error when no trace loaded. No contradictions.
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?
Description is well-structured with clear sections (Use when, Don't use for, Parameters, Empty result, Errors). Every sentence adds value, no fluff. Appropriately sized for the tool's complexity.
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?
Despite no output schema, the description covers return behavior (empty result) and error conditions (no trace loaded). It also explains the underlying SQL engine limitation, making the tool's role clear in the larger system.
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. Description adds meaningful details: pattern is a GLOB filter with examples, trace_id is optional and defaults to active trace. This provides context beyond the schema descriptions.
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 clearly states 'List tables and views in the loaded trace. Read-only.' It uses a specific verb and resource, and distinguishes itself from siblings like execute_sql and list_stdlib_modules.
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 when to use (exploring unfamiliar trace) and when not to use (known stdlib modules, avoid calling tool name in SQL). Mentions alternative execute_sql with INCLUDE PERFETTO MODULE.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_table_structureARead-onlyIdempotent
Show the columns of a table or view: name, type, nullability, primary_key flag.
Use when: writing or debugging a query — call this immediately after a no such column error to inspect the actual schema rather than guessing. Both stdlib views and base tables have fixed schemas; don't infer columns by analogy across them.
Don't use for: this is a separate MCP tool, not a SQL function — don't write SELECT * FROM list_table_structure inside execute_sql.
Parameters: table_name (string) — the exact table or view name as it appears in list_tables output. Case-sensitive; does not accept GLOB patterns or partial matches. Also accepts the alias name (v0.11.3+).
Errors when: the table doesn't exist or has no columns. Call list_tables first; stdlib views may need an INCLUDE first.
| Name | Required | Description | Default |
|---|---|---|---|
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| table_name | Yes | Name of the table to describe. Also accepted as `name` for callers who model schema discovery around a generic "name" field. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate safe read-only operation. The description adds behavioral details: case-sensitivity, alias support, error conditions, and the need to call list_tables first. This provides useful context beyond annotations.
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?
Description is compact and well-structured: summary, when/not to use, parameter details, error info. Every sentence earns its place with no redundancy.
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?
Despite no output schema, the description adequately explains what is returned (columns attributes) and handles error conditions. It also provides prerequisite guidance (call list_tables) and version info for alias, making it complete for the tool's complexity.
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?
Input schema covers 100% of parameters, but the description adds extra meaning: case-sensitive, no pattern matching, accepts alias 'name'. This exceeds the baseline of 3 for high coverage.
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 clearly states it shows columns of a table/view with specific attributes (name, type, nullability, primary_key). This distinguishes it from sibling tools like list_tables and execute_sql.
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 tells when to use (after 'no such column' error) and when not to use (not a SQL function). Provides alternative actions like calling list_tables first and noting stdlib views may need INCLUDE.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_threads_in_processARead-onlyIdempotent
List threads in one process or same-named process set: tid, thread_name, pid, upid, machine_id. Limit 2000, cap 5000.
Use when: drilling into a process from list_processes.
Don't use for: ALL trace threads — use execute_sql on thread.
Parameters: pass either upid (trace-internal id, precise — prefer when multiple processes share a name like 'Renderer') or process_name (exact match). upid wins when both are set. Optional limit and offset page large result sets; both accept numbers or numeric strings.
Output: exact row_count, returned_rows, truncated/has_more; rows are ordered by pid/tid. process_counts reports per-upid counts for same-name fan-out.
Empty result: returned as an error pointing at list_processes for available candidates.
When truncated=true, increase offset or drill down with upid.
| Name | Required | Description | Default |
|---|---|---|---|
| upid | No | Process upid (the trace-internal unique id from `list_processes`). Takes precedence over `process_name` when both are set — useful for disambiguating same-named processes (e.g. multiple Renderer instances). Accepts both numbers and numeric strings. | |
| limit | No | Optional max rows to return. Defaults to 2000, capped at 5000. Accepts both numbers and numeric strings. Must be > 0 when set. | |
| offset | No | Optional row offset for pagination. Defaults to 0. Accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| process_name | No | Process name to match exactly (e.g. "com.android.chrome", "/system/bin/init"). Either this or `upid` must be provided. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate safe read-only behavior (readOnlyHint, idempotentHint, destructiveHint false). The description adds details on pagination (truncated, has_more), ordering, empty result error pointing to list_processes, and process_counts for same-name fan-out.
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?
Well-structured with clear sections and bullet points. Front-loaded with essential info. Slightly lengthy but every sentence adds value. Could be slightly more concise but overall effective.
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?
Comprehensive coverage given 5 parameters, no output schema, but rich annotations. Includes usage context, parameter details, behavioral traits (pagination, ordering, empty results), and error handling.
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?
With 100% schema coverage, baseline is 3. The description adds significant value by explaining parameter trade-offs (upid vs process_name), precedence, accepted types (numeric strings), and pagination usage, exceeding schema documentation.
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 clearly states the tool lists threads for a specific process or same-named process set, specifying output fields (tid, thread_name, pid, upid, machine_id) and limits. It distinguishes itself from siblings like list_processes and execute_sql.
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?
Explicit 'Use when' and 'Don't use for' sections with direct references to list_processes and execute_sql, providing clear context and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_traceAIdempotent
Load one or more local Perfetto trace files and return routing summaries plus trace_id handles. Other tools use the active trace by default; pass trace_id to analyze a specific loaded trace after loading more.
Use when: starting any analysis session — call this first.
Don't use for: live capture or streaming URLs; paths must be complete local trace files.
Parameters: pass path for one trace or paths for a batch. Calling again makes the last loaded path the active default; cached trace processors make repeat loads cheap unless the file fingerprint changed.
Errors when: the file doesn't exist, isn't a valid Perfetto trace, trace_processor fails to parse it, or the binary cannot be downloaded.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Absolute path to a Perfetto trace file (.pftrace, .perfetto-trace, .bin, or any other trace_processor-readable format — content-sniffed, not by extension). | |
| paths | No | Absolute paths to multiple Perfetto trace files. Use this to load all comparison targets in one call; the response returns one `trace_id` per path. Mutually exclusive with `path`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotent and non-destructive. Description adds valuable context: caching behavior ('cached trace processors make repeat loads cheap'), active default trace management, and error conditions. No contradiction with annotations.
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-loaded with action and output, then uses clear sections for usage, parameters, and errors. Every sentence adds value; no fluff or redundancy.
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?
Covers return value (routing summaries + trace_ids), error conditions, and behavior with multiple calls. Without an output schema, the description is sufficiently complete for an agent, though more detail on the return structure could help.
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% with descriptions for path and paths. The description adds usage nuance (one vs batch, active default) and caching behavior, which provides extra value beyond the schema. However, the schema already covers format and mutual exclusivity.
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 clearly states the tool loads Perfetto trace files and provides trace_id handles, distinguishing it from sibling analysis tools which consume loaded traces. The verb 'load' and resource 'local Perfetto trace files' are specific.
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?
Explicit 'Use when' and 'Don't use for' sections guide the agent to call this first for analysis sessions and avoid live capture. It also explains how other tools use the active trace and how to pass trace_id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slice_descendants_breakdownARead-onlyIdempotent
Recursive child-slice expansion under known slice.id roots, aggregated as a bounded breakdown per (depth, name) group. Use to drill into a long task — after chrome_main_thread_hotspots or execute_sql returns a slice id — without hand-writing WITH RECURSIVE CTEs over slice.parent_id. Required: slice_ids. Optional bounds: min_dur_ms, max_depth, limit, include_args, max_string_len. The response echoes summary_scope, applied_filters, and missing_root_ids (missing root slice ids). Returned columns: root_id, depth, name, slice_count, inclusive_total_ms (do not sum across depths), self_ms (direct-child time subtracted, clamped at zero), max_ms, first_ts_ns (raw nanoseconds, not ms), example_slice_id (longest-duration descendant per group), and optionally example_args. incomplete_descendant_count counts dur<0 descendants excluded from duration aggregates.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional max rows to return. Defaults to 100 and is capped at 5000. Accepts both numbers and numeric strings. | |
| trace_id | No | Optional trace id returned by `load_trace`. Omit to use the active trace. | |
| max_depth | No | Optional maximum descendant depth. Defaults to 8. Must be > 0 when set; accepts both numbers and numeric strings. | |
| slice_ids | Yes | Root slice ids to expand. The root slices themselves are omitted from the summary; returned rows aggregate matching descendants under each root. Accepts numbers or numeric strings. | |
| min_dur_ms | No | Optional descendant minimum duration in milliseconds. Defaults to 1 ms. Must be finite and non-negative; accepts both numbers and numeric strings. | |
| include_args | No | Include an example args summary for one representative slice per group. | |
| max_string_len | No | Optional per-string-cell character cap applied to returned rows only. Unset preserves full strings for precision; accepts both numbers and numeric strings. Must be > 0 when set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate read-only and idempotent. The description adds significant behavioral detail: echoes summary_scope, applied_filters, missing_root_ids; explains each column (e.g., do not sum inclusive_total_ms across depths, self_ms clamped at zero, first_ts_ns in raw nanoseconds, incomplete_descendant_count excludes dur<0). Root slices are omitted from summary. These details go beyond annotations.
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 is a single dense paragraph but front-loads the purpose and efficiently covers all aspects. Could be slightly improved with bullet points for the list of parameters and return columns, but it is not overly verbose and every sentence adds value.
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?
No output schema, so the description fully documents the return structure: columns, their meanings, and special handling like clamping and incomplete counts. It also covers optional parameters and the summary metadata. Given the complexity of recursive expansion and many columns, this is complete.
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%, but the description enriches each parameter with defaults and context: limit defaults to 100 capped at 5000, max_depth defaults to 8 and must be >0, min_dur_ms defaults to 1 ms, include_args boolean, max_string_len must be >0 if set. It also notes that slice_ids accepts numbers or numeric strings and trace_id can be omitted for active trace.
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 clearly states the tool performs recursive child-slice expansion under given slice.id roots, aggregated per (depth, name) group. It distinguishes from siblings like chrome_main_thread_hotspots and execute_sql by specifying its use case: drilling into long tasks after those tools return a slice id.
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 when to use: after chrome_main_thread_hotspots or execute_sql returns a slice id, and that it avoids writing recursive CTEs. Does not explicitly list when not to use, but the context is clear given the required parameter and sibling tools.
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.
16 tool updates
v0.17.1- Changed
chrome_main_thread_hotspots1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_page_load_resource_hotspots1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_page_load_resource_pipeline1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_page_load_resource_summary1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_page_load_script_hotspots1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_page_load_summary1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_scroll_jank_summary1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_startup_summary1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
chrome_web_content_interactions1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
execute_sql1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
list_processes1 field changed- added
Input schema / propertiesAdded value: +{ + "trace_id": { + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" + } +}
- Changed
list_table_structure1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
list_tables1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
list_threads_in_process1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
- Changed
load_trace4 fields changed- added
Input schema / properties / path / defaultAdded value: +null - added
Input schema / properties / path / nullableAdded value: +true - added
Input schema / properties / pathsAdded value: +{ + "default": [], + "description": "Absolute paths to multiple Perfetto trace files. Use this to load all\ncomparison targets in one call; the response returns one `trace_id` per\npath. Mutually exclusive with `path`.", + "items": { + "type": "string" + }, + "type": "array" +} - removed
Input schema / requiredRemoved value: -[ - "path" -]
- Changed
slice_descendants_breakdown1 field changed- added
Input schema / properties / trace_idAdded value: +{ + "default": null, + "description": "Optional trace id returned by `load_trace`. Omit to use the active trace.", + "nullable": true, + "type": "string" +}
8 tool updates
v0.16.2- Changed
chrome_main_thread_hotspots1 field changed- added
Input schema / properties / machine_idAdded value: +{ + "default": null, + "description": "Optional machine id filter for multi-machine traces when the trace\nschema has `process.machine_id`. ANDs with pid/process filters and\ndisambiguates same pid values on different machines. Accepts numbers\nand numeric strings.", + "format": "int64", + "nullable": true, + "type": "integer" +}
- Changed
chrome_page_load_resource_summary1 field changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Optional max rows to return. Defaults to 100 and is capped at 5000.\nMust be > 0 when set."New value: +"Optional max rows to return. Defaults to 25 and is capped at 5000.\nMust be > 0 when set."
- Changed
chrome_page_load_script_hotspots1 field changed- added
Input schema / properties / machine_idAdded value: +{ + "default": null, + "description": "Optional machine id filter for multi-machine traces when the trace\nschema has `process.machine_id`. Accepts numbers and numeric strings.", + "format": "int64", + "nullable": true, + "type": "integer" +}
- Changed
chrome_page_load_summary1 field changed- added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional max rows to return. Defaults to 100 and is capped at 5000.\nMust be > 0 when set; accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +}
- Changed
chrome_scroll_jank_summary1 field changed- added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional max rows to return. Defaults to 100 and is capped at 5000.\nMust be > 0 when set; accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +}
- Changed
chrome_startup_summary1 field changed- added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional max rows to return. Defaults to 100 and is capped at 5000.\nMust be > 0 when set; accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +}
- Changed
chrome_web_content_interactions1 field changed- added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional max rows to return. Defaults to 100 and is capped at 5000.\nMust be > 0 when set; accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +}
- Changed
list_threads_in_process2 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional max rows to return. Defaults to 2000, capped at 5000.\nAccepts both numbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "default": null, + "description": "Optional row offset for pagination. Defaults to 0. Accepts both\nnumbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +}
12 tool updates
v0.15.12- Changed
chrome_main_thread_hotspots7 fields changed- added
Input schema / $defsAdded value: +{ + "ChromeMainThreadHotspotsPhase": { + "oneOf": [ + { + "const": "navigation_to_fcp", + "description": "Window from navigation_start_ts to fcp_ts.", + "type": "string" + }, + { + "const": "navigation_to_load", + "description": "Window from navigation_start_ts to load_event_ts.", + "type": "string" + }, + { + "const": "dcl_to_fcp", + "description": "Window from dom_content_loaded_event_ts to fcp_ts.", + "type": "string" + }, + { + "const": "fcp_to_load", + "description": "Window from fcp_ts to load_event_ts.", + "type": "string" + } + ] + } +} - added
Input schema / properties / end_ts_nsAdded value: +{ + "default": null, + "description": "Optional raw trace timestamp upper bound in nanoseconds, exclusive. This\nuses the same unit as the returned `ts` column. ANDs with any page-load\nwindow.", + "format": "int64", + "nullable": true, + "type": "integer" +} - added
Input schema / properties / max_string_lenAdded value: +{ + "default": null, + "description": "Optional per-string-cell character cap applied to returned rows only.\nUnset preserves full strings for precision; accepts both numbers and\nnumeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +} - added
Input schema / properties / navigation_idAdded value: +{ + "default": null, + "description": "Optional Chrome navigation id used to scope tasks to one navigation phase.\nMatches `chrome_page_loads.navigation_id`. Mutually exclusive with\n`page_load_id`. If set without `phase`, defaults to `navigation_to_fcp`.", + "format": "int64", + "nullable": true, + "type": "integer" +} - added
Input schema / properties / page_load_idAdded value: +{ + "default": null, + "description": "Optional page-load id used to scope tasks to one navigation phase.\nMatches `chrome_page_loads.id`. Mutually exclusive with `navigation_id`.\nIf set without `phase`, defaults to `navigation_to_fcp`.", + "format": "int64", + "nullable": true, + "type": "integer" +} - added
Input schema / properties / phaseAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/ChromeMainThreadHotspotsPhase" + }, + { + "const": null, + "nullable": true + } + ], + "default": null, + "description": "Optional page-load phase window. If set without `page_load_id` or\n`navigation_id`, uses the latest page load in the trace. Values:\nnavigation_to_fcp, navigation_to_load, dcl_to_fcp, fcp_to_load." +} - added
Input schema / properties / start_ts_nsAdded value: +{ + "default": null, + "description": "Optional raw trace timestamp lower bound in nanoseconds. This uses the\nsame unit as the returned `ts` column. ANDs with any page-load window.", + "format": "int64", + "nullable": true, + "type": "integer" +}
- Added
chrome_page_load_resource_hotspots - Added
chrome_page_load_resource_pipeline - Added
chrome_page_load_resource_summary - Added
chrome_page_load_script_hotspots - Changed
chrome_page_load_summary1 field changed- added
Input schema / propertiesAdded value: +{ + "max_string_len": { + "default": null, + "description": "Optional per-string-cell character cap applied to returned Chrome-tool\nrows only. Unset preserves full strings for precision; accepts both\nnumbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" + } +}
- Changed
chrome_scroll_jank_summary1 field changed- added
Input schema / propertiesAdded value: +{ + "max_string_len": { + "default": null, + "description": "Optional per-string-cell character cap applied to returned Chrome-tool\nrows only. Unset preserves full strings for precision; accepts both\nnumbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" + } +}
- Changed
chrome_startup_summary1 field changed- added
Input schema / propertiesAdded value: +{ + "max_string_len": { + "default": null, + "description": "Optional per-string-cell character cap applied to returned Chrome-tool\nrows only. Unset preserves full strings for precision; accepts both\nnumbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" + } +}
- Changed
chrome_web_content_interactions1 field changed- added
Input schema / propertiesAdded value: +{ + "max_string_len": { + "default": null, + "description": "Optional per-string-cell character cap applied to returned Chrome-tool\nrows only. Unset preserves full strings for precision; accepts both\nnumbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" + } +}
- Changed
execute_sql6 fields changed- added
Input schema / properties / columns_onlyAdded value: +{ + "default": false, + "description": "Return only column names and row-count metadata; omit row values.", + "type": "boolean" +} - added
Input schema / properties / headAdded value: +{ + "default": null, + "description": "Agent-friendly alias for `limit`: return only the first N decoded rows.\nThis trims returned rows only; it does not rewrite the SQL. Mutually\nexclusive with `limit`. Accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +} - added
Input schema / properties / include_row_countAdded value: +{ + "default": false, + "description": "Include decoded row-count metadata with a row-returning shaped response.", + "type": "boolean" +} - added
Input schema / properties / limitAdded value: +{ + "default": null, + "description": "Optional output row cap. This trims returned rows only; it does not\nrewrite or limit the SQL that trace_processor executes. Mutually\nexclusive with `head`. Accepts both numbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +} - added
Input schema / properties / max_string_lenAdded value: +{ + "default": null, + "description": "Optional per-string-cell character cap applied to returned rows only.\nAccepts both numbers and numeric strings. Must be > 0 when set.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" +} - added
Input schema / properties / summaryAdded value: +{ + "default": false, + "description": "Return column names, row-count metadata, and a small sample of rows.\nDefaults to 10 sample rows unless `head` or `limit` is provided.", + "type": "boolean" +}
- Changed
list_stdlib_modules1 field changed- added
Input schema / propertiesAdded value: +{ + "domain": { + "default": null, + "description": "Optional domain filter. Valid values: \"chrome\", \"android\", \"generic\".", + "nullable": true, + "type": "string" + }, + "limit": { + "default": null, + "description": "Optional max entries to return. Must be > 0 when set; accepts both\nnumbers and numeric strings.", + "format": "uint32", + "minimum": 0, + "nullable": true, + "type": "integer" + }, + "query": { + "default": null, + "description": "Optional case-insensitive search over module name, view names, and description.", + "nullable": true, + "type": "string" + } +}
- Added
slice_descendants_breakdown
12 tool updates
- Added
chrome_main_thread_hotspots - Added
chrome_page_load_summary - Added
chrome_scroll_jank_summary - Added
chrome_startup_summary - Added
chrome_web_content_interactions - Added
execute_sql - Added
list_processes - Added
list_stdlib_modules - Added
list_table_structure - Added
list_tables - Added
list_threads_in_process - Added
load_trace
TDQS
Scored across 17 tools
Most tools have distinct purposes (page-load summaries, resource hotspots, main-thread hotspots, scroll jank, startup, interactions). However, `chrome_page_load_resource_summary`, `chrome_page_load_resource_hotspots`, and `chrome_page_load_resource_pipeline` all deal with resource URL analysis and could be confused, though their descriptions clarify the intended sequence (summary → hotspots → pipeline). The generic `execute_sql` and `list_*` tools are clearly separate.
All tools follow a consistent snake_case pattern with a clear domain prefix: `chrome_*` for Chrome-specific analysis, `list_*` for exploration, `execute_sql`, `load_trace`, `slice_descendants_breakdown`. Verbs are uniform (list, load, execute, chrome_page_load_*, chrome_main_thread_*) and the naming clearly indicates the tool's function.
17 tools is on the higher side but justified for a comprehensive Perfetto trace analysis server covering Chrome performance domains (page loads, resources, main thread, jank, startup, interactions) plus general SQL and schema exploration. Each tool serves a distinct purpose, and the count reflects the breadth of the domain without being bloated.
The tool set covers major Chrome performance analysis workflows (page loads, resources, main-thread tasks, scroll jank, startup, web interactions) plus generic trace exploration (processes, threads, tables, SQL). Minor gaps exist: no dedicated tool for memory or CPU profile analysis, and the resource pipeline depends on the summary/hotspots sequence, but `execute_sql` covers custom needs.
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- FlicenseAqualityCmaintenanceA FastMCP server that provides LLMs with structured access to Scalene's CPU, GPU, and memory profiling for Python applications. It enables automated performance analysis, bottleneck identification, and optimization suggestions through natural language interactions in supported IDEs.71-
- AlicenseAqualityCmaintenanceSemantic vector DB as an MCP server for Claude Code — SQLite + FTS5 + local ONNX embeddings. Gives Claude persistent, searchable project knowledge across conversations.12MIT
- AlicenseAqualityAmaintenanceLocal-first MCP server that watches your coding sessions and injects a compact summary at the start of each new session. 85.6% token reduction, SQLite storage, no cloud. Works with Claude Code, Cursor, Cline, and Windsurf.1321 npm8MIT
- AlicenseAqualityBmaintenanceCode intelligence MCP server for Claude Code providing multi-project code graph, semantic search, session history, knowledge base, and web search.153MIT