list_series
Enumerate every stored data series the remote vike-datahub server holds, each with its cheap coverage, so an agent can pick a real date range before it writes a profile.
list_series answers the question every backtest starts with: what data is actually there? It
returns one row per stored series with the span and row count that series covers, which is what a
profile's [data] table can name.
Read-only and remote. tools_spec advertises it with readOnlyHint: true,
idempotentHint: true and openWorldHint: true — it changes nothing, the same call twice gives
the same answer, and it reaches off this machine to do it.
Arguments
None. Its inputSchema declares an object with no properties, so the call is the empty object.
{ "name": "list_series", "arguments": {} }What comes back
Server::call_tool routes to tool_list_series, which connects to the datahub, calls
DatahubClient::inventory, and projects each row into JSON:
{
"series": [
{
"kind": "bar", "venue": "binance", "symbol": "BTCUSDT", "interval": "1m",
"first_ts": 1704067200000, "last_ts": 1735689600000, "rows": 525600
}
]
}Seven fields, four from vike_data::series::SeriesId and three from SeriesCoverage. The
SeriesId tuple is exactly what the store's leaf directory encodes —
kind=…/venue=…/symbol=…[/interval=…] — so interval is present for bars, which sub-partition by
bar step, and null for tick series. The layouts each kind implies have their own pages under
the data-kind reference, and the store itself is described in
The history store.
Coverage is cheap on purpose. SeriesCoverage's own doc states it is computed from the manifest
file-index with no DataFusion scan, which is why an inventory over a large store is a metadata
read rather than a query.
Four fields the projection drops
SeriesCoverage also carries bytes, parts and dates, and SeriesId carries group.
tool_list_series projects none of them.
A grouped series reports an empty symbol
SeriesId::group is Some(g) for a grouped series — one part file holding many symbols, told
apart by a row-level symbol column instead of one series per symbol. Its doc is explicit that
symbol is empty in that case, deliberately, so a consumer scanning by id.symbol fails
visibly rather than silently scanning "". The tool does not project group, so such a row
arrives here as a blank symbol with no replacement label. SeriesId::label — group if grouped,
else symbol — is the accessor that resolves it, and it is not on this wire. Treat a blank symbol
as "grouped, ask the store", never as "no symbol".
It needs a reachable datahub
The address comes from vike-cli mcp --addr <host:port>, defaulting to DEFAULT_ADDR,
127.0.0.1:7878. If nothing is listening there the tool returns a clean error result whose text
begins cannot connect to datahub at — never a panic and never a dead stdio session.
remote_run_tools_without_a_reachable_datahub_are_clean_errors pins that for this tool alongside
run_sweep and run_walk_forward, by pointing the server at a port that refuses immediately.
The vike-datahub server is the process that holds the store; see
its binary page for how it is run and
Connect an agent for wiring the MCP server up in the first
place.
Where it sits in a session
list_series is the first of the three remote read tools an authoring loop uses: this one says
what data exists, list_strategies says which compiled
strategy names a profile can resolve, and
list_indicators says what a Rhai script may actually call.
Only then does the profile you hand run_backtest name a series
that is really in the store over a range that is really covered.
What series does the datahub have for binance, and how far back does the 1m BTCUSDT bar data go?