rezolus-mcp
Investigate a Rezolus performance recording (.parquet, .rez, .dendro) through the rezolus MCP server. Discovery before query, verdicts and marks written back, links to the viewer.
Files1
View on GitHubSKILL.mdsrc/mcp/skill/SKILL.md
GitHubInvestigating a Rezolus recording
The rezolus MCP server opens a recording file and answers about it.
Every tool that reads a recording takes parquet_file, the path to a
.parquet, .rez or .dendro file (the name is historical; the format is
detected by content). A .rez is Rezolus's archive, which can hold several
recordings; a .dendro is the newer archive container and reads the same
way. viewer_link reads no recording and takes no path. Ask the person for
the file if you were not given one; rezolus record -o out.dendro writes one.
Workflow
describe_recordingfirst. It says what the file holds: source, agent version, time range, duration, and, for a multi-recording.rez, the list of recordings with therecordingselector that picks each.describe_metricsbefore any query. Metric names, types and labels come from the recording, not from memory. A counter is queried withirate(name[1m])(the per-step rate;rate(name[5m])is the average over five minutes), a gauge directly, a histogram withhistogram_quantile(0.99, name).extract_featuresfor the overview: per-metric stats, noise class, anomalies, regime shifts, uncertainty, correlations, resource rankings. Read it before forming hypotheses; it needs at least 10 s of data.query,detect_anomalies,analyze_correlationto test specific hypotheses.detect_anomaliesand a check need ONE series: aggregate withsum()/avg()or add label matchers.- Write back what you found (below), and hand the person a link.
Rules that hold on every recording:
- A missing metric is not zero. A sampler that was off or a kernel without the hook leaves the metric absent; say so rather than reading it as idle.
irate()andrate()values carry an uncertainty band[lo, hi]from the acquisition window: inqueryJSON it is thebands(andintervals) list aligned withvalues. A difference inside the band is not a difference. A recording with no acquisition windows (for example a parquet combined into a.rez) has no band, which says nothing about its precision.- Correlation does not establish causation. Report it as co-movement.
- On a multi-recording archive of one run, the tools read every recording
together unless a
recordingselector (e.g.{"source": "redis"}) names one: each series carries its recording's labels, sosum by (host)answers per host and{host="web-01"}selects one.extract_featuresneeds a selector, and so does every tool on a comparison (recordings carryingarm). Matching none or several is an error that lists the candidates; it never guesses.run_checkswithout a selector evaluates every recording and gives each its own verdicts.
Writing back
add_eventmarks an instant or a range (duration) in the recording; the viewer draws it on the timeline. Give akind(finding,spike,incident,deploy), a one-linedescription, and put the evidence (the query, the numbers) indetails.sourcedefaults tomcp, so your marks can be filtered or removed as a group.timestampis RFC 3339 or Unix seconds as a JSON number (never a digit-only string). The reply carries the event id; adding an event with anidalready present changes nothing, so retrying is safe (akind=checkevent is the exception: it replaces a stored check event with the same id).run_checksevaluates the recording's KPI checks (or a ServiceExtension object you pass asqueries) and returns each verdict with its violation windows;annotate: truewrites them as events.export_querywrites a range query as CSV or parquet (long form: series, timestamp, value, lo, hi) for analysis outside PromQL. It works only when the server was started with--export-dir.filenameis a bare name (no directories) and an existing file is never overwritten;stepdefaults to 1 s; results over a million rows are refused, so raisestepor aggregate; a heatmap is refused, so exporthistogram_quantile(...)of it.viewer_linkbuilds a link into a runningrezolus view: asection(cpu,memory, ..., orservice/<name>), optionalchart_id,from/to, and the rest of the view state. Withviewer_url(or a server started with--viewer-url) it is a full URL; otherwise append the returned query and fragment to the viewer's address.remove_eventsexists only when the server was started with--allow-mutating. It removes byids,kindand/orsource; an empty filter is refused.
Reporting
Lead with the finding and the instant it happened, then the evidence (metric, query, values with their bands), then what you wrote back (event ids) and the link. State what could not be measured.