MCP server¶
tsdive-mcp serves six tsdive analyses to an MCP client over stdio.
This page lists the tools, the shape of every answer, and how to launch
the server.
Install¶
The server needs the mcp extra. A base install does not carry it.
Install tsdive with the extra from git, or from the release wheel:
pip install "tsdive[mcp] @ git+https://github.com/NorthernLightx/tsdive.git"
pip install "tsdive[mcp] @ https://github.com/NorthernLightx/tsdive/releases/download/v0.10.0/tsdive-0.10.0-py3-none-any.whl"
From a clone, pip install -e ".[mcp]" installs it. Without the extra,
tsdive-mcp writes one line to stderr and exits 2:
error: the tsdive MCP server needs the mcp package (>=2.1); install tsdive with the mcp extra: pip install "tsdive[mcp] @ git+https://github.com/NorthernLightx/tsdive.git", or the release wheel with it, pip install "tsdive[mcp] @ https://github.com/NorthernLightx/tsdive/releases/download/v0.10.0/tsdive-0.10.0-py3-none-any.whl"
Launch¶
{
"mcpServers": {
"tsdive": {
"command": "tsdive-mcp"
}
}
}
stdio is the only transport. The server reads local parquet archives and
opens no network connection. It writes nothing, and every tool carries
readOnlyHint: true.
Tools¶
Each tool calls the function behind tsdive <command> --json, so the
same arguments give the same fields as the command line.
| Tool | Required | Optional | Evidence carries |
|---|---|---|---|
profile |
archive |
window, basis, stepped, tz, flatline |
sampling contract, unit resolution, coverage and gap classes, clipping, timestamp audit, quality counts, statistics, flatline verdict |
segment |
archive |
window, penalty, min_size, basis, stepped |
breakpoints, and one row per segment with n, median and mad |
screen |
archive, baseline, window |
method, k, mode, basis, stepped, max_events, max_runs |
center, scale, limits, n_screened, n_flagged, up to max_runs runs of consecutive flagged samples, and up to max_events flagged timestamps |
spc |
archive, baseline, window |
basis, stepped, max_events, max_runs |
individuals limits, and for BEYOND_3SIGMA, RUN_9_SAMESIDE and TREND_6 the hit count, up to max_runs runs of consecutive hits and up to max_events hits |
compare |
archives, before, after |
top, rate_s |
per-tag change rows, the pairwise correlation table, the joint MSPC structure |
switchback_analyze |
archives, plan, target |
covariates |
the verified plan digest, the B minus A estimate with its p-value and 95% interval, kept samples per block, the adjusted estimate |
archive is the path to one single-tag parquet archive. compare and
switchback_analyze take a list of them in archives. plan is the
path of a file tsdive switchback plan wrote.
Windows are ISO 8601 in UTC: START/END written
2024-03-01T00:00:00Z/2024-03-01T01:00:00Z, START/PT1H, PT1H/END, or a
date for one whole UTC day. screen and spc take a
baseline window and a window to monitor. compare takes before
and after. An option left out takes the default the command line
declares, so k is 3.0, min_size is 10 and top is 10.
screen and spc answer with counts and runs. A run is a stretch of
consecutive GOOD samples that all carry the flag or rule hit, given as
start, end and n. The per-sample lists, flagged in screen and
hits under each rule in spc, keep max_events entries (0 when left
out), and flagged_dropped or hits_dropped counts the entries left
out. runs keeps the first max_runs runs (40 when left out), per rule
in spc. runs_dropped counts the runs left out, at the top of a
screen answer and on each rule of an spc answer. The counts
n_flagged, n_hits and n cover every sample. tsdive screen --json
and tsdive spc --json print the full lists.
Result union¶
Every tool returns one JSON object carrying result_kind and
tsdive_version, the version that answered.
"evidence" holds the analysis, keyed as --json prints it. A
profile answer, trimmed to four of its ten blocks:
{
"result_kind": "evidence",
"tsdive_version": "0.10.0",
"tag": "demo:FIC101.PV",
"window": {"start": "2024-03-30T20:00:00+00:00", "end": "2024-03-30T23:00:00+00:00", "duration_s": 10800.0},
"units": {"raw": "m3/h", "canonical": "cubic meters per hour", "resolved": true},
"coverage": {"coverage": 1.0, "n_gaps": 0, "longest_gap_s": null}
}
"refusal" holds a check that has no answer on this data:
{
"result_kind": "refusal",
"tsdive_version": "0.10.0",
"error_type": "InsufficientQuality",
"cause": "tag demo:FIC101.PV: window is censored (clipped fraction 0.935); a clipped window may never serve as a baseline"
}
isError stays false on a refusal, so the call succeeds and the client
reads the reason from error_type and cause. tsdive <command> --json
prints the same object on stdout for a refusal and exits with status 3. error_type names a
class from tsdive.errors: SchemaError, InsufficientQuality,
IncomparableSamplingError, NonMonotonicIndex,
UnresolvedUnitError, IncomparableUnitsError, RegimeTooSparse,
ZeroSpreadBaseline, PopulationTooSparse, GroupLeakage, MspcAlignmentError,
DesignTooSmall, ScheduleMismatch or NarratorUnavailable. docs/SCOPE.md states which check raises which
class.
Tool errors¶
A tool error says the call was built wrong. A malformed window, a
rejected option value, an unreadable path, or a baseline overlapping the
monitored window raises instead of returning. The client receives
isError: true and the message the command line prints:
Error executing tool profile: window must be <START>/<END>, <START>/<DURATION>, <DURATION>/<END> or <DATE> in ISO 8601 UTC