From 6e4041b14d51cc879f495279f2b2a6adaf96a210 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Fri, 19 Jun 2026 15:44:12 -0700 Subject: [PATCH 1/2] feat(mcp): expose sections accessor in eval bindings Bind Worker::GetSections() as get_sections() so the TracySectionEnter / TracySectionLeave instrumentation added to the client is reachable from the MCP eval tool's ctx object. Returns a list of {start, end, text} dicts with nanosecond timestamps, matching the existing list-of-dict accessor convention. Documented in eval_guide.md. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_016EvfzHvUsDBSAwEzTfLTtA --- extra/mcp/eval_guide.md | 3 +++ python/bindings/ServerModule.cpp | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/extra/mcp/eval_guide.md b/extra/mcp/eval_guide.md index b67ccbe8..cbf3b530 100644 --- a/extra/mcp/eval_guide.md +++ b/extra/mcp/eval_guide.md @@ -21,6 +21,9 @@ data surface. Common entry points: - Threads: `get_threads()`, `get_thread_name(tid)`, `get_thread_context_switches(tid)` - Messages / plots / locks / memory / callstacks: `get_messages()`, `get_plots()`, `get_locks()`, `get_memory_events()`, `get_callstack_frames(...)` +- Sections: `get_sections()` — timed code sections from + `TracySectionEnter`/`TracySectionLeave` instrumentation. Returns a list of + `{start, end, text}` dicts (start/end in ns). - Capture metadata: `get_capture_name()`, `get_capture_program()`, `get_first_time()`, `get_last_time()`, `get_resolution()`, `get_host_info()` diff --git a/python/bindings/ServerModule.cpp b/python/bindings/ServerModule.cpp index d2bbb772..9bb6738a 100644 --- a/python/bindings/ServerModule.cpp +++ b/python/bindings/ServerModule.cpp @@ -214,6 +214,20 @@ PYBIND11_MODULE( TracyServerBindings, m ) return w.GetMessages().size(); } ) + // --- Sections --- + .def( "get_sections", []( const Worker& w ) { + py::list result; + for( auto& s : w.GetSections() ) + { + py::dict d; + d["start"] = s.start.Val(); + d["end"] = s.end.Val(); + d["text"] = std::string( w.GetString( s.text ) ); + result.append( d ); + } + return result; + } ) + // --- Source locations / zones --- .def( "get_src_loc", []( const Worker& w, int16_t id ) { return w.GetSourceLocation( id ); From bee6ac566e6645f2f34685057de4a8c05c54cb6f Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Fri, 19 Jun 2026 15:45:07 -0700 Subject: [PATCH 2/2] docs(mcp): drop dangling tracy://catalog reference eval_guide.md referenced a tracy://catalog resource that was never registered (only tracy://prompt and tracy://eval-guide exist), so an agent following the guide would try to read a nonexistent resource. Remove the references; the worked snippets the catalog described are already inlined under "Common query patterns". Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_016EvfzHvUsDBSAwEzTfLTtA --- extra/mcp/eval_guide.md | 15 +++++++-------- extra/mcp/tracy_mcp.py | 3 +-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/extra/mcp/eval_guide.md b/extra/mcp/eval_guide.md index cbf3b530..d061198b 100644 --- a/extra/mcp/eval_guide.md +++ b/extra/mcp/eval_guide.md @@ -1,7 +1,7 @@ # Tracy MCP eval guide -This document covers the bindings-layer detail that the curated catalog -(`tracy://catalog`) and analysis guidance (`tracy://prompt`) do not. +This document covers the bindings-layer detail that the analysis +guidance (`tracy://prompt`) does not. ## ctx @@ -44,24 +44,23 @@ Run `print([m for m in dir(ctx) if not m.startswith('_')])` for the full list. - Source-location IDs from `get_all_zone_source_locations()` are the join key between zone-name lookups and per-callsite queries. -## Translating catalog entries to ctx Python +## Common query patterns -The catalog (`tracy://catalog`) lists curated queries. Each maps to a small -Python snippet: +Small Python snippets for the queries you'll reach for most often: ```python -# zone_list — top 10 hottest zones by total time +# top 10 hottest zones by total time top = sorted(ctx.get_all_zone_stats().items(), key=lambda kv: kv[1].total, reverse=True)[:10] for k, v in top: print(f"{v.total/1e6:.2f}ms count={v.count} {k}") -# frame_list — primary frame set timing +# primary frame set timing times = ctx.get_frame_times() # ns per frame print(f"frames={len(times)} avg={sum(times)/len(times)/1e6:.2f}ms " f"p99={sorted(times)[int(len(times)*0.99)]/1e6:.2f}ms") -# zone_stats for a named zone — find the srcloc id, then drill in +# stats for a named zone — find the srcloc id, then drill in import re matches = [k for k in ctx.get_all_zone_stats() if k.startswith("MyFunc ")] sid = int(re.search(r"<(\d+)>$", matches[0]).group(1)) diff --git a/extra/mcp/tracy_mcp.py b/extra/mcp/tracy_mcp.py index f860ce87..1b8524c0 100644 --- a/extra/mcp/tracy_mcp.py +++ b/extra/mcp/tracy_mcp.py @@ -259,8 +259,7 @@ def _prompt_resource() -> str: @mcp_server.resource("tracy://eval-guide") def _eval_guide_resource() -> str: """Bindings-layer guide for the eval tool: ctx object model, time units, - source-location ID semantics, and worked examples translating catalog - entries into ctx Python.""" + source-location ID semantics, and worked examples of common ctx queries.""" return _read_text(_EVAL_GUIDE_PATH)