Skip to main content
Glama

canli-validation-mcp

npm OpenSSF Scorecard OpenSSF Best Practices Glama score

Is your best backtest real, or just the luckiest of the variants you tried? This MCP server lets Claude, Cursor or any MCP client answer that with the standard corrections: the deflated Sharpe ratio, the CSCV probability of backtest overfitting, data-snooping tests on every variant tried (Hansen's SPA, White's Reality Check, Romano-Wolf StepM), the minimum track record length, the haircut Sharpe ratio, and luck-equivalent trials. Free and MIT-licensed.

Quick start

# Claude Code, computed on your machine: no key, nothing sent anywhere
claude mcp add canli-local --env CANLI_LOCAL=1 -- npx -y canli-validation-mcp

# the same tools with signed, stored receipts from the free API (a free key is issued on first use)
claude mcp add canli -- npx -y canli-validation-mcp

# nothing to install: the hosted endpoint
claude mcp add --transport http canli https://canlicapital.com/mcp

Then ask, for example: "I tried 229 variants and kept the best: an annualised Sharpe of 1.5 over 730 daily returns (365 a year), skew -0.5, kurtosis 5, and the variants' Sharpe ratios spread by 0.57. Is it real?" The assistant calls validate_deflated_sharpe: the best of 229 skill-less variants would reach 1.60 by luck alone, so the probability that the Sharpe is above zero falls from 98.1% to 44.4% once the search is counted. Claude Desktop and any other stdio client (Cursor, VS Code) run the same npx command; see "Claude Desktop" and "Generic stdio client" below.

Related MCP server: Equibles Agent Terminal

What it does

An MCP (Model Context Protocol) server over canlicapital.com's free, keyed validation API, with a lab that computes on your machine. It gives a coding agent twenty tools: issue a free key, run the nine validators (deflated Sharpe, CSCV overfitting, data-snooping tests (Hansen's SPA, White's Reality Check and Romano-Wolf StepM), paper-evidence conformance, breadth ceiling, minimum track record length, minimum backtest length, haircut Sharpe ratio, luck-equivalent trials), audit one backtest with several of them in a single call, verify a receipt's signature offline, read service status, read a company's reported financial history from SEC filings, and six lab tools: backtest a rule over a parameter grid, summarize a long series, stress-test a strategy's returns, check a plan against a broker's limits, check a signal for lookahead, and test a whole research pipeline on placebo data. Every validation result carries, beside the number, the sentences that say what it does not establish and the receipt that records it, success or error, so the agent cannot see a number without its limits.

This package is published to npm as canli-validation-mcp. Also listed on the official MCP Registry (io.github.arhancanli/canli-validation-mcp) and cursor.directory. Run it with npx, no install step, as shown below. A local checkout is only needed to develop or test this package itself; see "Local checkout" near the bottom.

This README describes the version in package.json. Unversioned npx runs npm's latest release; npx -y canli-validation-mcp@<version> pins one.

How well agents use it

A fixed benchmark gives models these tools and scores whether they pick the right one and return the right answer, against ground truth computed from the same checked code. Results for three models, with every run recorded, are in bench/agent/README.md.

What the API is (and is not)

The engine is the product. The service runs your submitted numbers through the same honesty arithmetic canlicapital.com's own paper record runs on itself and hands back a verdict anyone can recompute from the receipt. It signs every receipt, does not accept market data, does not grade a strategy, and never saw your data source, its costs, or any lookahead in how a series was built. See docs/superpowers/specs/2026-09-05-developer-key-validation-api-design.md in the main repository for the full design.

Tools

Unreleased source adds local journal binding to validate_paper_evidence: run CANLI_LOCAL=1 node mcp/src/server.mjs from the repository, and send exactly one of record or record_file, plus journal_file to check source hashes, signatures and recomputed claims. record_file accepts a standard record, a {record,signature} envelope, or the full execution export bundle; companion metrics/observations are checked for full bundles. Signed records need the detached signature. bindings.all_match must be true for source validation to pass. Without a journal, the result explicitly reports structure-only conformance. Files and signatures are refused in hosted/remote mode and never uploaded. Local results have no Canli receipt. The current npm/hosted release retains the existing record-only API.

Tool

Calls

Key required

get_key

POST /api/v1/keys (listed only when no key is configured)

no

validate_deflated_sharpe

POST /api/v1/validate/deflated-sharpe

yes

validate_overfitting

POST /api/v1/validate/overfitting

yes

validate_paper_evidence

POST /api/v1/validate/paper-evidence

yes

validate_breadth

POST /api/v1/validate/breadth

yes

validate_track_record

POST /api/v1/validate/track-record

yes

validate_backtest_length

POST /api/v1/validate/backtest-length

yes

validate_haircut_sharpe

POST /api/v1/validate/haircut-sharpe

yes

validate_luck_trials

POST /api/v1/validate/luck-trials

yes

validate_reality_check

POST /api/v1/validate/reality-check (a matrix_file is read on your machine and sent as numbers)

yes

audit_backtest

the deflated Sharpe and track record routes, then the headline: with variants, the overfitting and data-snooping routes; without, luck trials. One validation each

yes

verify_receipt

GET /api/v1/receipts/{id} when given an id (include_receipt returns the stored receipt); the checks run locally

no

service_status

GET /api/v1/validate/status

no

company_financial_history

GET /company-data/{cik}.json (a ticker resolves through GET /api/v1/company-tickers.json)

no

validate_deflated_sharpe accepts exactly one of two input shapes, never a mix of both:

  • the seven contract fields: observed_sharpe_annualized, observations, periods_per_year, skew, non_excess_kurtosis, effective_independent_trials, cross_trial_sharpe_sd_annualized;

  • or a return series plus the trials behind it: returns, periods_per_year, effective_independent_trials, cross_trial_sharpe_sd_annualized.

Sending fields from both shapes, or from neither, is rejected before any request leaves the process; see src/schemas.mjs.

validate_reality_check takes the returns of every variant the search tried, one row per period and one column per variant, as matrix or as matrix_file (a CSV or JSON on your machine), and an optional benchmark series; with none, variants are tested against zero. It runs three tests on one seeded stationary bootstrap:

  • Hansen's SPA: the chance that the best variant's studentized excess return is this good if no variant has an edge, with lower and upper bounds (spa.p_value, the consistent p-value, is the headline, and monte_carlo_se its sampling error);

  • White's Reality Check: the same question without studentizing, so one volatile variant can dominate it;

  • Romano and Wolf's StepM: which variants beat the benchmark, with the familywise error held at alpha.

A result reproduces exactly from its seed. On three fixed-seed cases the p-values agree with Python's arch 8.0 and with a numpy transcription of Hansen's formulas within Monte Carlo error, and the StepM sets match arch's (js/snooping-core.test.js). Only the variants sent are counted: a search that tried more than it sends makes luck look smaller than it was.

company_financial_history is different from the other tools: it reads the public company reference at canlicapital.com, not the validation API. Give it a CIK (1 to 10 digits) to list a company's available financial histories, or a CIK and a us-gaap concept such as Revenues to get the observations, newest first (limit defaults to 40, maximum 200). Every observation keeps its filing accession, form, filed date and unit, and the result carries the SHA-256 of the original SEC response and the record's own boundary sentence: these are accounting values as reported to the SEC, not market prices, returns or a recommendation. Companies and concepts outside the current release return an error with the available concepts listed.

The lab: backtest, summarize, stress, feasibility, lookahead, placebos

Six tools compute in the server process itself, on your machine or on the hosted endpoint, with nothing sent to the API and no receipt stored. Each result names the SHA-256 of exactly the numbers it was computed from, and states what it does not establish.

  • backtest_strategy runs a rule over every parameter set in a grid, on your prices: sma_cross (fast, slow), momentum (lookback, skip), mean_reversion (window, entry_z), breakout (lookback) or buy_and_hold, long-only or with allow_short, after a cost per unit of turnover. The position held over each period is decided from closes up to the one before it, so no rule can see the future (a test changes later prices and checks that no earlier position moves). It then validates the best variant with the number of variants this call ran, not a number someone declared: the deflated Sharpe ratio across the grid's measured Sharpe dispersion, the CSCV probability of backtest overfitting on every variant's returns, the probabilistic Sharpe and the minimum track record, next to buy and hold over the same window. At most 200 variants and 20,000 prices per call. No code is ever run: a strategy is a family plus numbers.

  • summarize_series reads a long price or return series and states it in about a hundred words, plus a field for every figure: growth, volatility, Sharpe and drift t-statistic, the worst drawdown with its dates and recovery, trend, the volatility regime (terciles of its own 21-period volatility), tails, jumps (beyond six robust standard deviations), autocorrelation, stale data and, with a benchmark, correlation and beta. A five-year daily series is about 1,260 numbers; the summary is a paragraph.

  • stress_test resamples a strategy's returns with a stationary block bootstrap (seeded, so a run reproduces exactly) and reports how often the drawdown limit breaks and the Sharpe turns negative, then applies four named scenarios with their rules stated: a crash at the equity high (default the larger of 20% and three times the worst period), volatility multiplied, the worst stretch lived twice, and positions stuck for several periods after the worst one. The fragility share is the part of resampled histories that break the drawdown limit or lose money on a risk-adjusted basis. Generative models are not used: trained on one series they memorize it or invent dynamics nobody can check.

  • check_feasibility checks a plan against a real broker before it trades: the broker's published order-rate limit against the rebalance's burst of orders (Alpaca 200 a minute, Interactive Brokers about 50 a second), the minimum order (Alpaca 1 USD notional), US day-trading rules as they stand in 2026 (FINRA retired the pattern day trader rule and its 25,000 USD minimum on 4 June 2026; firms may phase in its replacement until 20 October 2027), T+1 settlement in cash accounts, each order's share of daily volume, square-root market impact (coefficient Y, default 1) with every copy of the same strategy counted, and the capital at which costs and impact eat the expected gross return. Every broker fact carries the date it was checked and its source.

  • check_leakage finds lookahead in a signal without seeing its code. A causal signal computed on the first n rows gives exactly the values the full run gives for those rows. plan picks the cuts (seeded, between 40% and 95% of the series); you rerun your own code on the rows before each cut, and compare checks every column: a value that changed when the later rows were removed used them. On your machine, columns_file takes the path of a JSON file {cuts, columns} your script wrote (Python's NaN reads as missing) instead of thousands of pasted numbers. The result names the pattern: future rows with their horizon (a shift(-5) reads as five rows), the full sample (a normalization, rank, scaling or fit over the whole series), or scattered rows (filling gaps backwards). On a fixed zoo of 22 pandas and statsmodels signals (config/research/leakage-zoo.json, from scripts/research/leakage/), all 11 leaks are found with the right pattern and none of the 11 honest indicators is flagged. A pass covers only the cuts tested: survivorship, vendor revisions or a leak confined to the first rows leave no trace.

  • placebo_test tests a whole research pipeline at once. plan writes your panel (real.csv) and 19 placebos to a new folder in the system's temporary directory: the same returns with the periods in a random order, the same order for every asset, so each asset keeps its returns and each day its cross-section, but nothing can be predicted. Run the pipeline unchanged on each, every search, filter and parameter choice included, and compare ranks its real result among the placebo results. Every choice the pipeline makes is counted, because it makes them again on every placebo. A pre-registered study chose the reordering (scripts/research/placebo/v1/, config/research/placebo-v1-evaluation.json): in all 30 combinations of simulated market and pipeline where nothing can be predicted (10,000 tests each; five return shapes, flat, drifting and with assets that differ only in their constant means; SMA, time-series and cross-sectional momentum grids), its false-positive rate at a nominal 5% was 4.6% to 5.5%. On the same markets a t-test on the best rule found an edge 10.9% to 78.9% of the time, and Bonferroni's correction 8.0% to 10.3% wherever the market drifted and 58.5% to 59.7% where assets only differed in their means. With 19 placebos the smallest p is 0.05; 99 give a finer one.

On your own machine, prices_file, series_file and returns_file take a CSV or JSON path instead of the numbers. Only numbers are read, plus an ISO date column when the file has one, so results can name the day a drawdown began.

The trial ledger: count every variant an agent tries

An agent can try thousands of strategy variants in an hour, and the best of them looks skilled by luck alone. How much luck depends on how many were tried and how spread out their results were, so the honest verdict on a reported winner needs the whole search. The ledger keeps it.

Turn it on with CANLI_TOOLSETS=validate,lab,ledger (or all), then:

  1. ledger_record_trial for every variant, as it is tried: its returns (or a returns file), or its annualized Sharpe and sample size, plus a label and its parameters. The first call creates a ledger and returns its name; reuse it. Each reply already counts the whole search so far.

  2. ledger_summary for the verdict: the best trial, the Sharpe that the best of that many skill-less trials reaches by luck, the best trial's deflated Sharpe ratio after counting every trial, and the probability of backtest overfitting (CSCV) when every trial has aligned returns.

  3. ledger_export to hand the search to someone else. Each trial is chained to the previous one with SHA-256, so a removed, reordered or edited trial shows.

Ledgers are JSON-lines files under CANLI_LEDGER_DIR (default ~/.canli/ledgers); nothing leaves your machine. Twenty variants of pure noise, recorded this way, give a best annualized Sharpe of about 1.5, a luck-alone expectation of about 1.7 and a deflated Sharpe near 0.4: the ledger calls that winner what it is. The statistics are the same checked code as validate_deflated_sharpe and validate_overfitting; test/ledger.test.mjs checks both directions (noise is flagged, a real edge among noise keeps a deflated Sharpe above 0.95).

Auditing a backtest in one call

audit_backtest takes one strategy's return series and, ideally, every variant's returns (variants or variants_file, the dropped ones too); without them, the number of variants tried and their Sharpe spread. The result opens with:

  • headline: one test chosen because its false-positive rate was measured before anyone looked at your numbers. Null Zoo v1 (scripts/research/null-zoo/v1/ in the repository) drew hundreds of thousands of simulated searches from nine return shapes with known ground truth; the bar and the rule that picks the test were committed before the run. With variants the headline comes from the data-snooping tests (validate_reality_check, with its receipt); without, from luck trials with Lo's autocorrelation correction. Its sentence quotes the measured false-positive rate for returns shaped like yours, and the worst across the nine shapes.

  • fix_next: at most five next steps, each {id, why, next} with a stable id.

  • computed: Lo's adjusted Sharpe, a stationary-bootstrap 95% interval for the Sharpe, the haircut Sharpe, the minimum backtest length and, with variants, how many independent trials they count as (Li and Ji) and the selected variant's out-of-sample decay.

Then the checks: validate_deflated_sharpe on the series (an estimate), validate_track_record on the Sharpe, skew and kurtosis that check derived and, with variants, validate_overfitting. Each is exactly what its own tool returns, with its own receipt; the deflated Sharpe runs with the larger of the declared and counted trials and Sharpe spread, so a search cannot be made to look smaller than it was. A check that refuses or cannot be reached is reported as that check's error. The audit adds no grade of its own. Through the API it uses one validation per check.

When the server runs on your machine, returns_file and variants_file take the path of the backtest's output instead of the numbers: a CSV (comma, semicolon or tab separated, with or without a header; date and label columns are ignored, an unnamed or counting index column is skipped and reported) or a JSON array. returns_column picks the column when there are several. Only the numbers are read; the hosted endpoint refuses file paths. An agent copying a long series into a call can drop values, and the copy costs tokens; in our agent benchmark, reading the file instead took three audit questions from 4 of 9 to 8 of 9 answered correctly on gpt-5.4-mini.

Prompts, resources and structured results

Clients that show MCP prompts offer eight guided workflows: validate_backtest (deflated Sharpe, then overfitting, then the track record needed, reported with what each number does not establish), track_record_needed, backtest_and_validate, stress_my_strategy, production_check, summarize_market_series, check_signal_for_lookahead and test_pipeline_on_placebos. Resources: canli://limits, the boundary sentences every result carries; canli://sources, the papers behind each validator and how each is checked against them; canli://strategy-spec, the JSON Schema of every strategy family and its parameters; and canli://openapi, the API's OpenAPI 3.1 document. Two resource templates are for writing code against the tools: canli://schemas/{tool} returns a tool's exact input and output JSON Schema, and canli://examples/{language}/{tool} a working call in python, javascript or curl (both variables complete). A test compiles every generated Python and JavaScript example and checks that every example's arguments are valid input. Every tool result carries its envelope both as text and as structuredContent.

Compact context (0.3.0)

An agent pays for every token a tool returns, including whitespace it never reads. Since 0.3.0 every result is minified JSON, and a company history returns its observations as one columns header and one row per observation, with a unit shared by every row stated once. No field is dropped: every boundary sentence, accession number, form, filed date and source hash is still in the result, and columns + rows rebuild each observation exactly.

Measured with bench/token_cost.py on live records (tokenizer: tiktoken o200k_base; other tokenizers give different absolute counts), 20 observations each:

Record

0.2.0 (indented)

minified

0.3.0 (minified, columnar)

Apple, StockholdersEquity

2,214

1,560 (−29.5%)

1,060 (−52.1%)

Microsoft, CashAndCashEquivalentsAtCarryingValue

2,231

1,574 (−29.4%)

1,065 (−52.3%)

The validation tools gain the minification only: the live service_status envelope measured 593 tokens indented and 475 minified (−19.9%); their boundary sentences are kept word for word. These are measurements of these results, not a claim about any other server.

Breaking change from 0.2.0: history.observations is now {unit?, columns, rows} instead of an array of objects.

Configuration

Variable

Default

Meaning

CANLI_API_BASE

https://canlicapital.com

Where the API lives. Point it at a preview deployment for testing.

CANLI_KEY

unset

A key already issued from POST /api/v1/keys. When set, get_key sends no request and reports the key is already configured; every other tool sends it as Authorization: Bearer <key>.

CANLI_FULL_ENVELOPE

unset

1 or true returns each validation's full API envelope instead of the compact result (below).

CANLI_TOOLSETS

all

Which tools to list: a comma-separated choice of validate, receipts, company, status and lab, or all. An unknown name is refused at startup. See "Toolsets" below.

CANLI_LOCAL

unset

1 or true runs the eight validators on this machine (private local mode, below): no key, no network, no receipt.

If CANLI_KEY is not set and local mode is off, call get_key once per session before the validators. The key it returns lives only in this process's memory for the life of the session; it is not written to disk.

HTTP failures and API error envelopes are marked as MCP tool errors while preserving the complete JSON envelope. A successful validation with a negative verdict remains a normal result. Requests have a 30-second deadline covering headers and body, reject redirects, and are never retried automatically. A timeout may occur after the service has processed a request; check service status before deciding to submit again. Non-JSON response bodies and raw network errors are omitted from tool errors.

Install

No install step. npx fetches the published package on first run, so every client config below just spawns npx -y canli-validation-mcp. See "Local checkout" near the bottom to develop or test this package itself instead of running the published one.

Hosted endpoint (no install)

The same tools are served at https://canlicapital.com/mcp over MCP Streamable HTTP, for clients that connect to a URL instead of spawning a process (Claude.ai connectors, ChatGPT, Cursor's remote servers). Nothing to install, and no Node.js on your machine.

claude mcp add --transport http canli https://canlicapital.com/mcp

Without a key, requests run under a shared anonymous key, so the daily validation quota is shared by every hosted caller. When that shared quota is used up for the day, validations are still answered, computed by the same code on the hosted endpoint, but without a stored receipt; the result says so. For your own quota, issue a free key (see /developers) and send it as a header:

claude mcp add --transport http canli https://canlicapital.com/mcp --header "Authorization: Bearer $CANLI_KEY"

Add ?toolsets= to the URL to list only some tools (see "Toolsets" below), for example https://canlicapital.com/mcp?toolsets=company.

The endpoint is stateless. On it, get_key issues nothing and says which key is in use, because a key issued there would not reach the next request. A malformed Authorization header is refused rather than replaced with the shared key.

Claude Desktop

Add to claude_desktop_config.json (Settings, Developer, Edit Config):

{
  "mcpServers": {
    "canli": {
      "command": "npx",
      "args": ["-y", "canli-validation-mcp"]
    }
  }
}

Restart Claude Desktop afterward. Add an "env" object with CANLI_API_BASE to point this at a preview deployment instead of the default.

Claude Code

claude mcp add canli -- npx -y canli-validation-mcp

Run claude mcp list to confirm it is registered, and claude mcp remove canli to remove it.

Private local mode

Set CANLI_LOCAL=1 and the eight validators run on your machine: nothing about the series you submit is sent to canlicapital.com, no key is needed, and no receipt is stored. The computation is the API's own, shipped byte for byte in src/local (a test fails if it drifts), so a local result equals the hosted one; it names no receipt id because none was made.

claude mcp add canli-local --env CANLI_LOCAL=1 -- npx -y canli-validation-mcp

verify_receipt by id, service_status and company_financial_history still read from canlicapital.com; they send no series. In the Claude Desktop extension this is the "Private local mode" setting.

Generic stdio client

Any MCP client that can spawn a process and speak stdio will work. Using the official SDK directly, from Node:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "canli-validation-mcp"],
  env: { ...process.env, CANLI_API_BASE: "https://canlicapital.com" },
});

const client = new Client({ name: "my-agent", version: "0.1.0" });
await client.connect(transport);

const { tools } = await client.listTools();
console.log(tools.map((t) => t.name));

const keyResult = await client.callTool({ name: "get_key", arguments: { label: "my-agent" } });
if (keyResult.isError) throw new Error("Key setup failed; inspect the error privately.");
// The session retains the issued key. Avoid printing its envelope into logs.

const result = await client.callTool({
  name: "validate_deflated_sharpe",
  arguments: {
    returns: [0.004, -0.002, 0.007, 0.001, -0.003, 0.005, 0.002, -0.001],
    periods_per_year: 252,
    effective_independent_trials: 30,
    cross_trial_sharpe_sd_annualized: 0.5,
  },
});
console.log(result.content[0].text); // the answer, its limits and its receipt

await client.close();

What a result does not establish (boundary language)

Every envelope this server returns carries these sentences, verbatim, from the API itself (api/_lib/limits.js):

  • This verdict is about the series exactly as submitted. The service never saw the data source, its costs, survivorship, or any lookahead in how the series was built.

  • A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

  • The receipt is content-hashed, reproducible from the open-source core it names, and signed with Ed25519 by a key published at https://canlicapital.com/.well-known/canli-receipt-keys.json.

  • Quotas: 1000 validations per key per UTC day, 5 keys per client per UTC day, 1048576 bytes per validation request, 1024 bytes per key revocation request, 20000 observations per series, 200 variants per matrix.

Each tool's description also states one of these sentences, so an agent sees the boundary before it calls the tool, not only after.

Compact results (tokens)

A validation result is the answer (data), the sentences above except the quota line, and the receipt's id and URL; an error keeps its error. The rest of the API envelope (schema, endpoint, timestamps, claim and capital class, the human page, the source-file hashes and the quota line) describes the service rather than the answer, and an agent pays for every token of it on every call. It stays in the stored receipt, which verify_receipt returns in full with include_receipt, and in service_status. On a breadth result this is about half the text. Set CANLI_FULL_ENVELOPE=1 to receive every field.

Toolsets (tokens)

A client sends the model the whole tool list on every turn, and it is most of each turn's prompt: a validation result is a few hundred tokens, the list of every tool several thousand. A client that needs one kind of tool can list only that kind, with CANLI_TOOLSETS (stdio) or ?toolsets= (hosted endpoint). The default is every toolset except company, whose one tool canli-fundamentals-mcp does better and point in time, and ledger, which keeps files on your machine and is local only; all adds both. get_key is listed only when no key is configured.

toolset

tools

validate

get_key, the nine validators, audit_backtest

receipts

verify_receipt

company

company_financial_history

status

service_status

lab

backtest_strategy, summarize_series, stress_test, check_feasibility, check_leakage, placebo_test

ledger

ledger_record_trial, ledger_summary, ledger_export (stdio only)

Measured with bench/tool_list_tokens.py (tokenizer: tiktoken o200k_base; other models' tokenizers give different absolute counts), in the shape an OpenAI-style client sends the list:

CANLI_TOOLSETS

tools

tokens per turn

of all

(default)

19

5,978

85%

(default, with CANLI_KEY)

18

5,842

83%

all

23

7,019

100%

validate

11

3,658

52%

receipts

1

182

3%

company

1

273

4%

status

1

89

1%

lab

6

2,055

29%

ledger

3

772

11%

Providers cache a tool list that is identical from turn to turn and bill the cached part at a fraction of the price (test/tool-list-stable.test.mjs keeps each list byte-stable); a smaller list costs less either way.

Local checkout

Only needed to develop or test this package itself, not to run the published one.

cd mcp
npm ci
node src/server.mjs

Point a client at the checkout instead of npm by spawning node /absolute/path/to/meridian/mcp/src/server.mjs in place of npx -y canli-validation-mcp in any config above.

Testing

npm test
npm run test:package

Runs node --test over test/*.test.mjs: schema round-trips against the API's own OpenAPI and manifest examples, one success, error-envelope and quota-429 case per keyed tool (a fake fetch stands in for the network), a check that every tool description carries a limits sentence, a check that those sentences have not drifted from api/_lib/limits.js, a check that no shipped file contains an em dash, and one test that spawns the actual server binary and performs a real MCP tools/list and callTool handshake over stdio against a local HTTP stub, so the wiring is proven rather than assumed.

test:package creates the actual npm tarball, checks its exact file list and license, installs it in a temporary consumer directory, and runs the stdio test against that installed entry. Dependency installation contacts npm; tool calls use only the local HTTP stub. It neither publishes a package nor issues a production API key.

Dependencies

Only @modelcontextprotocol/server (pinned exact; the MCP SDK's server package, which itself depends only on @modelcontextprotocol/core and zod) and zod (pinned exact): four packages in the installed tree, where 0.7 and earlier pulled in about 95 through @modelcontextprotocol/sdk. No other runtime dependency is added, and nothing in this package touches the site's root package.json, .vercelignore, api/, scripts/, js/, or public/.

Available Tools

19 tools
audit_backtestAudit a backtestA

One-call audit of a strategy's returns. Headline: one test whose false-positive rate was measured on nine return shapes (White's Reality Check with variants, luck trials with Lo's correction without). Then deflated Sharpe, minimum track record and, with variants, overfitting and out-of-sample decay, each with its receipt, plus fix_next. Send every variant tried (variants_file) so trials are counted; point returns_file at a CSV instead of pasting. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
returnsNoPeriodic returns as fractions (0.01 = 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis.
n_splitsNoEven number of blocks, at least 2; default 16.
variantsNoOptional returns of every variant tried (this one included), one row per period, one column per variant; adds the overfitting check.
confidenceNoBetween 0 and 1; default 0.95.
returns_fileNoPath to a CSV or JSON of the returns on this machine (not on the hosted endpoint), instead of returns.
variants_fileNoPath to a CSV or JSON with one numeric column per variant, instead of variants.
returns_columnNoColumn name or 1-based position, when returns_file has several numeric columns.
periods_per_yearYesPeriods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly.
benchmark_sharpe_annualizedNoAnnualized Sharpe to beat; default 0.
effective_independent_trialsNoIndependent variants tried before choosing this one. Optional with variants: counted from them, and the larger number is used.
cross_trial_sharpe_sd_annualizedNoStandard deviation of annualized Sharpe across those trials. Optional with variants: measured from them, and the larger is used.

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
errorNo
checksNo
limitsNo
not_runNo
readingsNo

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false, destructive=false, openWorld=true, so the description carries most of the burden. It adds real behavioral context: each result ships with 'its receipt, plus fix_next', and it explicitly warns that a deflated Sharpe or overfitting probability above/below any threshold 'is not admission to anything and is not a forecast' – an important interpretive caveat. It stops short of noting that file arguments are read from the local machine (left to the schema).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, which is good, but the prose is dense and run-on, with parenthetical jargon like 'luck trials with Lo's correction without' that is hard to parse. No sentence is pure padding, yet the readability cost is real for a description this compressed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not enumerate return fields, and it still summarizes the payload (deflated Sharpe, minimum track record, overfitting, OOS decay, receipts, fix_next). For an 11-parameter statistical tool this is largely complete; the main omission is any hint about compute cost or runtime for large variants files.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 and the schema already documents all 11 parameters. The description adds only emphasis – 'Send every variant tried (variants_file) so trials are counted' – reinforcing the variant/trial-counting interplay rather than supplying new format or syntax detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource: 'One-call audit of a strategy's returns', and immediately enumerates the bundled analyses (Reality Check, luck trials, deflated Sharpe, track record, overfitting, OOS decay). This clearly places it as the aggregate counterpart to the granular validate_* siblings, though it never names them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives useful conditional guidance ('with variants, overfitting and out-of-sample decay', 'point returns_file at a CSV instead of pasting'), which tells the agent how inputs change outputs. However, it never states when to choose this one-call audit over the many sibling validators (validate_reality_check, validate_deflated_sharpe, etc.), leaving the primary routing decision to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backtest_strategyBacktest a rule over a parameter grid, validatedA
Read-onlyIdempotent

Backtest a rule on your prices over a whole parameter grid, then validate the best with the count of variants actually run: deflated Sharpe, overfitting probability, minimum track record, vs buy and hold, after costs. A backtest, deflated or not, is not a forecast and not advice.

ParametersJSON Schema
NameRequiredDescriptionDefault
gridNoValues per parameter, e.g. {"fast":[10,20],"slow":[50,200]}; every valid combination runs (max 200).
datesNoOptional ISO dates, one per value.
familyYessma_cross (fast, slow), momentum (lookback, skip), mean_reversion (window, entry_z), breakout (lookback), buy_and_hold.
pricesNoPrices, oldest first.
cost_bpsNoCost per unit of turnover, bps; default 5.
allow_shortNoShort instead of flat; default false.
prices_fileNoCSV or JSON of prices on this machine; local server only.
prices_columnNoColumn name or 1-based position.
periods_per_yearNo252 daily (default), 365 crypto, 52 weekly, 12 monthly.

Output Schema

ParametersJSON Schema
NameRequiredDescription
limitsNo
sourceNo
selectedNo
variantsNo
validationNo
buy_and_holdNo
plain_readingNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real behavioral context beyond them: validation is conditioned on the count of variants actually run, results are net of costs, and comparison against buy-and-hold, plus an explicit 'not a forecast / not advice' disclaimer. It stops short of describing result structure, but an output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and followed by the validation metric list and the disclaimer. Slightly dense in the colon-list clause but no wasted sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description covers the pipeline, cost treatment, and the deflated-Sharpe/overfitting/track-record validation angle. What is missing is sibling routing and any note on grid-size limits (that lives in the schema), so it is nearly but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented in the schema (grid cap of 200, periods_per_year conventions, family parameter mapping). The description only gestures at the grid and cost concepts and adds no syntax or format detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (backtest) and resource (a rule over a price series via a parameter grid) plus the follow-on validation step, so the agent understands this is a backtest-plus-validation pipeline. It does not, however, name or contrast itself with the many validate_* / audit_backtest siblings, so the agent must infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the description – you call this to run a grid backtest and get validation metrics – but there is no explicit when-to-use vs. the sibling validators (validate_deflated_sharpe, validate_overfitting, audit_backtest), nor any stated prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_feasibilityCheck a plan against broker limits and impactA
Read-onlyIdempotent

Check a trading plan before it trades: broker order-rate and minimum-order limits, 2026 US day-trading rules, square-root market impact with crowding, and the capital where costs eat the return. Checks the plan as described against published broker limits and a market-impact model; it never contacts a broker or sees an account.

ParametersJSON Schema
NameRequiredDescriptionDefault
brokerNoDefault other.
copiesNoAgents trading the same signal at once; default 1.
accountNo
adv_usdYesDaily dollar volume of a typical holding.
asset_classNo
capital_usdYes
daily_volatilityYesOf a typical holding, e.g. 0.02.
turnover_per_yearYesBuys plus sells a year / capital.
impact_coefficientNoSquare-root law Y; default 1.
rebalances_per_yearYes
spread_and_fees_bpsNoPer trade; default 0.
orders_per_rebalanceYes
expected_gross_returnNoAnnual, before costs; adds capacity.
minutes_per_rebalanceNoDefault 1.
orders_per_minute_limitNoIf the broker's is not on file.

Output Schema

ParametersJSON Schema
NameRequiredDescription
checksNo
limitsNo
sourcesNo
verdictNo
to_changeNo
plain_readingNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/openWorldHint/idempotent/destructive, so the bar is lower. The description still adds value: it enumerates the specific rules and models applied (2026 US day-trading rules, square-root impact with crowding) and clarifies the tool performs a pure computation with no broker or account access.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the check and the scope of the model, followed by the isolation constraint. Dense but no filler; the second sentence's boundary statement earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not needed. For a 15-parameter modeling tool the description conveys the model's components and its read-only, offline nature, though it leaves the roughly one-third of undocumented parameters to the schema alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, a middle band where the schema documents most inputs on its own. The description gestures at parameter domains (broker order-rate limits, impact, cost capacity) but gives no syntax, units, or defaults beyond what the schema already states, so it neither compensates for the gap nor repeats the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (check) and resource (a trading plan) with a tightly bounded scope — broker limits, day-trading rules, market impact, and cost capacity — that reads distinctly from the validate_* and backtest_strategy siblings. It does not, however, explicitly name any sibling to differentiate itself from them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Check a trading plan before it trades' gives a clear usage context (pre-trade feasibility screening) and the closing clause states a boundary (never contacts a broker, never sees an account). No explicit when-not-to-use or routing to an alternative sibling is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_leakageCheck a signal for lookaheadB
Read-onlyIdempotent

Does a signal look ahead? plan gives cuts; rerun your code on the first cut rows for each, then compare. Rows that changed used later rows; the result names the pattern and horizon. No code is sent. A pass covers only these cuts: the columns are the caller's, and survivorship, vendor revisions or a leak no cut reaches leave no trace.

ParametersJSON Schema
NameRequiredDescriptionDefault
cutsNocompare: plan's cuts.
seedNo
actionYes
columnsNocompare: {name: {full: [all rows], prefixes: [[first cuts[i] rows], ...]}}, null for missing.
prefixesNoplan: cuts, default 5.
toleranceNoDefault 1e-9.
timestampsNo
columns_fileNocompare, on your machine: a JSON file {cuts, columns} instead.
observationsNoplan: rows in the series.

Output Schema

ParametersJSON Schema
NameRequiredDescription
cutsNo
seedNo
limitsNo
sourceNo
columnsNo
verdictNo
plain_readingNo
flagged_columnsNo

TDQS

B3.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnlyHint=true, idempotent, non-destructive, closed world), so the bar is lower, and the description still adds real context: 'No code is sent' (privacy guarantee) and an explicit coverage caveat about survivorship, vendor revisions, and leaks no cut reaches. That honest scope disclosure is exactly the kind of behavioral detail annotations cannot provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The front-loaded question is good, but the prose is telegraphic and partly unparseable: 'A pass covers only these cuts: the columns are the caller's, and survivorship, vendor revisions or a leak no cut reaches leave no trace' packs three unrelated caveats into one fragment. Information density is high but clarity suffers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 9 parameters, an enum action, nested columns, and an output schema, the description should at minimum clarify what plan versus compare each return and how the two phases connect. It sketches the workflow and its limits, but omits the distinction between the two actions' outputs and leaves several parameters unexplained, so it is only marginally complete for a tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, so the baseline is 3. The description touches on cuts, the columns payload, and prefixes implicitly, but adds no meaning for seed, tolerance, timestamps, observations, or columns_file beyond what the schema already documents. It does not compensate for the uncovered third.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening question 'Does a signal look ahead?' and the title state the goal (detecting lookahead bias in a signal), but the description spends most of its text on the mechanics of a two-phase protocol (plan → rerun → compare) rather than crisply stating what the tool returns. An agent can infer the purpose, but the verb+resource framing is buried and the sibling set (placebo_test, validate_overfitting, validate_backtest_length) is never distinguished.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does convey a usage workflow: call plan to get cuts, rerun your code on the first cut rows for each, then compare. That is genuine guidance. However it never says when to prefer this over the numerous validation siblings, nor when a check is unnecessary, so the routing guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_keyGet a free validation keyA

Issue a free validation key for this session. Rarely needed: the first validation issues one itself unless CANLI_KEY or local mode is set, and the read tools need none. Quotas: 1000 validations per key per UTC day, 5 keys per client per UTC day, 1048576 bytes per validation request, 1024 bytes per key revocation request, 20000 observations per series, 200 variants per matrix.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoName for the key.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
key_sourceNo
key_presentNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true), and the description goes well beyond them by disclosing concrete quotas: 1000 validations/key/UTC day, 5 keys/client/UTC day, per-request byte limits, and series/matrix size caps. It also discloses the auto-issuance behavior of the first validation call, which is genuine operational context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then the rarely-needed caveat, then quotas. The quota sentence is a dense run-on list, but every figure is actionable operational data rather than filler, so it earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the description covers purpose, necessity, prerequisites, and rate limits. Nothing an agent needs to decide whether and how to call this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is only one optional parameter ('label'), and schema description coverage is 100%, so the schema already documents it fully. The description adds no semantics for the label beyond the schema, which is the expected baseline when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb+resource ('Issue a free validation key for this session'). It also differentiates itself from the sibling validate_* tools by stating that read tools need no key, so an agent can route correctly without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when this tool is NOT needed ('Rarely needed: the first validation issues one itself unless CANLI_KEY or local mode is set, and the read tools need none'), which is exactly the when/when-not guidance required. It names the conditions (CANLI_KEY set, local mode) that make the call unnecessary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

placebo_testTest a research pipeline on placebo dataA

Does your pipeline find edges in noise? plan writes placebo files (your data's returns in random orders, so nothing is predictable); run the whole pipeline on real.csv and on each, then compare for a p-value that counts every choice it makes. Beating the placebos shows the pipeline finds more in the real order of the returns than in random orders of the same returns; it does not show the edge survives costs, capacity or the future.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoplan: default prices.
realNocompare: the pipeline's result on the real data.
seedNo
actionYes
methodNo
columnsNoplan: {asset: [values]} instead of data_file.
placebosNoplan: default 19, up to 199.
data_fileNoplan, on your machine: CSV or JSON, a column per asset, dates optional.
lower_is_betterNo
placebo_resultsNocompare: its result on each placebo, in file order.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dirNo
filesNo
limitsNo
sourceNo
p_valueNo
placeboNo
verdictNo
plain_readingNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are non-readonly, non-destructive, non-idempotent, and closed-world, and the description explains why: 'plan writes placebo files' on your data. It also discloses the key interpretive limit ('does not show the edge survives costs, capacity or the future'), which goes well beyond the annotation set.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with a framing question and every clause carries content, but the heavy nested parentheses make it denser and harder to parse than necessary. Still, there is no filler sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, two-mode tool with an output schema (so return values need no explanation), the description conveys the conceptual workflow and the limits of the result. The remaining gap is that several non-enum parameters are left to the schema, but nothing critical to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 60%, and most parameter meaning (real, placebos default 19 up to 199, columns, data_file) lives in the schema descriptions rather than the prose. The prose adds conceptual context (permuted returns, p-value counting every choice) but says nothing about method, seed, or lower_is_better, so it does not fully compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete verb and resource: it writes placebo files with returns in random orders, has you run the pipeline on real and placebo data, and compares them for a p-value. This is far more specific than the title. It does not, however, name or contrast the sibling validate_* tools, so sibling differentiation is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies the workflow (plan writes placebos, then run the pipeline, then compare) and frames the use case as 'Does your pipeline find edges in noise?'. But there is no explicit when-to-use/when-not guidance versus the many sibling validation tools, and the action flow is only implied rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_statusService statusA
Read-only

Whether the validation API is up, with its quotas; check after a timeout before resubmitting. No key. This verdict is about the series exactly as submitted. The service never saw the data source, its costs, survivorship, or any lookahead in how the series was built.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
errorNo
limitsNo

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint=false and openWorldHint, so safety is covered. The description adds genuinely useful context — 'No key' (no auth required) and that quotas are returned. But the trailing sentences about the service never seeing data source, costs, survivorship or lookahead describe a validation verdict, not a health check, adding confusion rather than behavioral clarity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded well in the first clause, but two of the three sentences are off-topic content that does not describe this status tool at all. For a zero-parameter health check, those sentences fail to earn their place and actively dilute the definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values (including quotas) need not be explained, and purpose, timing and auth are covered. The definition is adequate but is undermined by the irrelevant series-validation disclaimer, leaving the agent with a slightly muddled picture of what this endpoint actually reports.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. The only parameter-adjacent statement, 'No key', usefully confirms no credential input is expected, matching the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening clause states a specific resource and condition — 'Whether the validation API is up, with its quotas' — which cleanly separates it from the validation siblings (audit_backtest, stress_test, etc.). However, the remaining sentences drift into what looks like boilerplate about validating a series, which does not describe a status endpoint and muddies the otherwise clear purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'check after a timeout before resubmitting' gives an explicit triggering condition for calling this tool, and 'No key' removes an auth question. No alternative tools are named, but the when-to-use context is concrete enough that an agent knows exactly when to reach for this over the validation tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stress_testStress-test a strategy's returnsA
Read-onlyIdempotent

Stress a strategy's returns: bootstrap histories (how often the drawdown limit breaks or Sharpe turns negative) and named crash, volatility, repeat and stuck-position scenarios, with a fragility share. Frequencies over resampled histories are not forecasts of the future.

ParametersJSON Schema
NameRequiredDescriptionDefault
seedNoDefault 42; reproduces exactly.
blockNoMean block length; default cube root of n.
crashNoCrash size, negative; default min(-0.2, 3x worst period).
pathsNoDefault 1000.
returnsNoStrategy returns as fractions, oldest first.
returns_fileNoCSV or JSON of returns on this machine; local server only.
drawdown_limitNoFraction; default 0.2.
outage_periodsNoStuck periods after the worst; default 5.
returns_columnNoColumn name or 1-based position.
periods_per_yearNo252 daily (default), 365 crypto, 52 weekly, 12 monthly.
volatility_multiplierNoDefault 2.

Output Schema

ParametersJSON Schema
NameRequiredDescription
limitsNo
sourceNo
baselineNo
fragilityNo
resampledNo
scenariosNo
plain_readingNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuine epistemic context beyond that: it reports frequencies (drawdown-limit breaches, negative Sharpe, a fragility share) and explicitly warns that these resampled frequencies are not forecasts of the future. Return-value detail is partly redundant with the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences, front-loaded with the core action and modes. The closing caveat about non-forecasting frequencies is short and earns its place, though the mode list is compressed densely enough to read slightly telegraphically.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 11 optional parameters, full schema coverage, an output schema, and complete annotations, the description only needs to convey purpose, modes, and interpretation caveats, which it does. It could be stronger by stating the required input form (returns or returns_file) or routing among sibling validators, but nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter's meaning and default is already documented in the schema. The description references the drawdown limit and negative-Sharpe condition conceptually but adds no syntax, units, or default information beyond what the schema provides; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (stress) plus resource (a strategy's returns) and enumerates the two modes it runs: bootstrap resampling and named crash/volatility/repeat/stuck-position scenarios. It does not, however, differentiate itself from nearby siblings such as placebo_test or backtest_strategy, which also consume a strategy's return series.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is for robustness/fragility analysis of a return series. There is no explicit when-to-use or when-not-to-use statement, and no sibling tool is named as the alternative for a related question.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

summarize_seriesSummarize a price or return seriesA
Read-onlyIdempotent

A long price or return series in about 100 words plus fields: growth, risk, dated drawdowns, trend, volatility regime, tails, jumps, stale data. Use instead of reading raw bars. Nothing here is a forecast or advice.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoLabel for the text.
datesNoOptional ISO dates, one per value.
pricesNoPrices, oldest first; or returns, or series_file.
returnsNoReturns as fractions, oldest first.
series_fileNoCSV or JSON of prices or returns on this machine; local server only.
series_kindNoseries_file holds; default prices.
series_columnNoColumn name or 1-based position.
periods_per_yearNo252 daily (default), 365 crypto, 52 weekly, 12 monthly.
benchmark_returnsNoSame-period benchmark returns; adds beta.

Output Schema

ParametersJSON Schema
NameRequiredDescription
riskNo
textNo
jumpsNo
tailsNo
trendNo
growthNo
limitsNo
sourceNo
drawdownNo
volatilityNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely new context: the output is roughly 100 words plus named fields, and it explicitly scopes the tool by stating it is 'not a forecast or advice' — a useful boundary that annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core purpose before the output inventory and the disclaimer. The first sentence is a fragment ('A long price or return series in about 100 words'), which is slightly compressed but costs nothing in clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, yet the description still names the output fields helpfully. All 9 parameters are documented in-schema and annotations carry the safety profile, leaving only the absence of usage routing as a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% across all 9 parameters, so the schema already documents prices vs returns vs series_file, periods_per_year conventions and benchmark_returns. The description adds no parameter-level detail beyond the generic 'price or return series' phrasing, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (summarize) and resource (a long price or return series), and enumerates the output content (growth, risk, drawdowns, trend, volatility regime, tails, jumps, stale data). It is clearly distinguishable from the validation/backtest siblings, though it never names a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The line 'Use instead of reading raw bars' gives a directional when-to-use hint, which is more than nothing. However, there is no explicit when-not guidance, no mention of prerequisites (e.g. minimum series length), and no routing between this and the backtest/validation siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_backtest_lengthMinimum backtest lengthA

Minimum backtest length (years) before the best of N independent trials is not expected to reach a target Sharpe by luck; with backtest_years, the most trials those years allow. For planning a search; once it has a result, use validate_deflated_sharpe. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
backtest_yearsNoBacktest length in years, for the most trials it allows.
target_sharpe_annualizedNoIn-sample annualized Sharpe you would call a discovery; default 1.
effective_independent_trialsNoIndependent trials tried (backtests, parameter sets, ideas).

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=false, openWorldHint=true, so safety is partly covered. The description adds an interpretive caution ('not admission to anything and is not a forecast'), but that sentence concerns deflated Sharpe / overfitting thresholds, which read as properties of sibling tools rather than this one, making the added behavioral signal ambiguous.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is compact and front-loads the core computation, but the final sentence about deflated Sharpe and overfitting thresholds is off-topic for this tool and dilutes focus, and the middle clause is syntactically tangled.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the description supplies purpose, planning context, and the sibling handoff. What is missing is any statement of prerequisites or assumptions (e.g., independence of trials) that would let an agent know when the answer is valid.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all three parameters carry their own descriptions, so the schema already does the heavy lifting. The description's mention of backtest_years ('the most trials those years allow') and target Sharpe adds only marginal framing beyond that baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the resource (minimum backtest length in years) and the quantity it is derived from (N independent trials vs. a target Sharpe), and it hints at the inverse query via backtest_years. However, the phrasing is circular and dense ('the most trials those years allow'), so an agent must already understand the underlying statistics to be sure what the call returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing: 'For planning a search; once it has a result, use validate_deflated_sharpe.' That names the alternative and the condition that selects it. It stops short of a full when/when-not matrix (e.g., how it relates to validate_luck_trials or check_feasibility among the many sibling validators).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_breadthValidate breadth ceilingA

Book Sharpe ceiling from adding sleeves of this quality and correlation, the Sharpe at a sleeve count, and the sleeves a target needs. For portfolio construction; it validates no single strategy. This verdict is about the series exactly as submitted. The service never saw the data source, its costs, survivorship, or any lookahead in how the series was built.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoTarget book Sharpe, for the sleeves it needs.
sleevesNoSleeve count, for that book's Sharpe.
sleeve_sharpeYesAnnualized Sharpe of one sleeve.
average_pairwise_correlationYesAverage correlation between sleeves, -1 to 1.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover safety (readOnlyHint=false, destructiveHint=false, openWorldHint=true), and the description adds genuinely useful behavioral context beyond them: the verdict applies only to the series 'exactly as submitted,' and the service has not seen the data source, costs, survivorship, or lookahead. That is real disclosure of scope and limitations an agent needs to interpret the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with what is computed and followed by scope caveats; little is wasted. The opening sentence is a dense run-on that could have been split, but the information density justifies its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and annotations carry the safety profile. The description adds the key caveat that the verdict applies only to the submitted series and ignores data-source provenance, which is the main interpretive gap an agent would otherwise face.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes further by mapping outputs to inputs: 'this quality and correlation' ties to sleeve_sharpe and average_pairwise_correlation, 'the Sharpe at a sleeve count' to sleeves, and 'the sleeves a target needs' to target. This clarifies the relationship between the optional inputs and which result each drives.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the three quantities computed (Sharpe ceiling from adding sleeves, Sharpe at a given sleeve count, sleeves needed for a target), which is a specific computational purpose rather than a tautology. It also scopes itself against siblings by stating 'it validates no single strategy,' implicitly distinguishing it from the per-strategy validators. The run-on phrasing of the first sentence makes it slightly harder to parse than an ideal verb+resource statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'For portfolio construction; it validates no single strategy' gives implied usage context, steering the agent toward breadth/portfolio questions rather than single-series validation. However, no alternative tool is named and no explicit when-not condition is given, so the agent must infer the boundary from the sibling list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_deflated_sharpeValidate deflated SharpeA

Deflated Sharpe ratio: the probability (0 to 1) that the selected strategy's Sharpe beats the best that luck gives across the variants tried, with the probabilistic Sharpe and that luck benchmark. Send the seven statistics or a return series. With every variant's returns use validate_overfitting; luck as a trial count, validate_luck_trials; a multiple-testing haircut, validate_haircut_sharpe. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
skewNoSkewness of returns; 0 if Normal.
returnsNoPeriodic returns as fractions (0.01 = 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis.
observationsNoNumber of return observations.
periods_per_yearNoPeriods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly.
non_excess_kurtosisNoKurtosis, not excess kurtosis; 3 if Normal.
observed_sharpe_annualizedNoAnnualized Sharpe as observed.
effective_independent_trialsNoIndependent variants tried before choosing this one.
cross_trial_sharpe_sd_annualizedNoStandard deviation of annualized Sharpe across those trials.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=false, openWorldHint=true and readOnlyHint=false, so the safety profile is largely covered. The description adds an interpretive caveat ('not admission to anything and is not a forecast') that usefully frames the result as non-decisional, but it says nothing about cost, rate limits, or determinism. With annotations doing the safety work, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core definition before the input modes and sibling routing, and every sentence carries content. It is dense for a single paragraph, but no sentence is wasted; the closing caveat is long yet load-bearing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter statistical validator with 100% schema coverage, an output schema, and annotations present, the description covers input modes, sibling routing, and result interpretation adequately. Return values need not be explained given the output schema, so remaining gaps are minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all eight parameters (including the returns-replaces-four-statistics note) are already documented in the schema. The description only hints at the two input modes ('seven statistics or a return series'), adding marginal value beyond the structured fields. Baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific computation ('probability (0 to 1) that the selected strategy's Sharpe beats the best that luck gives across the variants tried') with its two outputs (probabilistic Sharpe and the luck benchmark). It also routes explicitly to three named siblings, so an agent can distinguish it from validate_overfitting, validate_luck_trials and validate_haircut_sharpe without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the alternative-input condition ('Send the seven statistics or a return series') and names three alternatives with the condition that selects each: variant-level returns -> validate_overfitting, trial counts -> validate_luck_trials, multiple-testing haircut -> validate_haircut_sharpe. Explicit when-to-use routing, nothing left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_haircut_sharpeHaircut Sharpe ratioA

Haircut Sharpe for multiple testing (Harvey and Liu 2015): the Sharpe a single test would have needed, by Bonferroni and independent tests, and with the other tests' Sharpes, Holm and BHY. For the probability the Sharpe is real, use validate_deflated_sharpe. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
testsNoTests run, this one included; gives the Bonferroni and independent-test haircuts.
observationsYesReturn observations behind the Sharpe.
autocorrelationNoLag-1 autocorrelation of returns, -1 to 1; default 0. Corrects the annualized Sharpe (Lo 2002).
periods_per_yearYesPeriods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly.
observed_sharpe_annualizedYesAnnualized Sharpe as observed.
other_sharpe_ratios_annualizedNoAnnualized Sharpes of the other tests over the same observations; adds Holm and BHY.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds interpretive context — that threshold crossings are not 'admission to anything' and not a forecast — which is genuinely useful caveating. It says nothing about computational behavior such as determinism, limits, or failure modes beyond the schema's bounds.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with what the tool computes, followed by the sibling redirect and the interpretive caveat. Dense with finance jargon, but each clause carries information and nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description covers the computation, the sibling alternative, and the interpretation warning. For a six-parameter statistical tool it is adequately complete, though it assumes the reader knows the surrounding multiple-testing framework.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and every parameter is already documented, so the baseline is 3. The description's mapping of 'tests' to Bonferroni/independent-test haircuts and 'other_sharpe_ratios_annualized' to Holm/BHY largely restates what the schema descriptions already say, adding little beyond them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the specific quantity (the Haircut Sharpe for multiple testing, Harvey and Liu 2015) and the exact estimators produced (Bonferroni, independent-test, Holm, BHY), which lets an agent distinguish it from validate_deflated_sharpe. It lacks an explicit verb framing, but the resource and scope are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes the agent to the alternative: 'For the probability the Sharpe is real, use validate_deflated_sharpe.' That is a clear use-when-other condition. It stops short of stating the positive condition for when this tool should be chosen (e.g., multiple-testing scenarios with a trial count), but the sibling routing is concrete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_luck_trialsLuck-equivalent trialsA

How many skill-less strategies a search would need for its best to reach this Sharpe by luck (Monte Carlo), and with a trial count, the chance it did. States luck as the best of N random tries; for the probability the Sharpe is real, use validate_deflated_sharpe. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
skewNoSkewness; below -0.5 the reading warns the counts are too generous.
observationsYesReturn observations behind the Sharpe.
autocorrelationNoLag-1 autocorrelation of returns, -1 to 1; default 0. Corrects the annualized Sharpe (Lo 2002).
periods_per_yearYesPeriods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly.
observed_sharpe_annualizedYesAnnualized Sharpe as observed.
effective_independent_trialsNoIndependent trials tried; adds the chance the best reached this Sharpe by luck.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true). The description adds Monte Carlo method context and clarifies that luck is the best of N random tries, plus an interpretation caveat. It does not explain why readOnlyHint is false, but it goes beyond the annotations in useful ways.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences: first defines the core output, second gives method and alternative, third adds a caution. No wasted words, though the final sentence is somewhat abstract and could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a complex statistical tool, the description covers purpose, method, alternative, and interpretation caveat; required parameters are left to the schema, which is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters are already fully documented. The description mentions 'with a trial count' mapping to effective_independent_trials, but adds no syntax or format details beyond the schema. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific computation: how many skill-less strategies a search would need for its best to reach this Sharpe by luck, and the chance it did with a trial count. It distinguishes itself from validate_deflated_sharpe, so an agent can tell the two apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly directs to validate_deflated_sharpe for the probability the Sharpe is real, and warns that a threshold on deflated Sharpe or overfitting probability is not admission or forecast. This gives clear context for when to use this tool versus its sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_overfittingValidate overfitting (CSCV)A

Probability of backtest overfitting (0 to 1) by CSCV: how often the in-sample best variant falls below the out-of-sample median. Needs every variant's returns (periods by variants); with summary statistics only, use validate_deflated_sharpe. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
seedNoSampling seed; default 42.
matrixYesReturns as fractions, one row per period, one column per variant.
n_splitsNoEven number of blocks, at least 2; default 16.
max_combinationsNoMost splits evaluated, up to 2000 (default).

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already declaring destructiveHint=false and openWorldHint=true, the description still adds real context: the required input shape, the meaning and range of the output, and an explicit caveat that crossing any threshold 'is not admission to anything and is not a forecast'. It does not explain determinism/reproducibility of the sampling seed or the combinatorial cost of the run, so it falls short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the metric and method, then the input requirement, then the alternative, then a caution. Every sentence carries weight, though the final disclaimer sentence is somewhat tangential to tool selection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return structure need not be described, and the description still supplies the output range and interpretation, the input shape, the routing alternative, and the key interpretive caveat. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters (matrix, n_splits, max_combinations, seed) are already documented in the schema. The description only restates the matrix orientation ('periods by variants') and adds nothing about seed, n_splits, or max_combinations, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific metric (probability of backtest overfitting, 0-1) and the exact method (CSCV), plus a one-line definition of what the number means (how often the in-sample best falls below the out-of-sample median). It is immediately distinguishable from the sibling validate_deflated_sharpe.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the data prerequisite ('needs every variant's returns, periods by variants') and names the explicit alternative for the other case ('with summary statistics only, use validate_deflated_sharpe'). This is a clear when-to-use / when-not-to-use routing rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_paper_evidenceValidate paper evidenceA

Checks paper-evidence.v0 structure and disclosures. With CANLI_LOCAL=1, record_file reads an export bundle and journal_file verifies signatures, source hashes and recomputed claims. Without a journal, source facts and signatures are unchecked. Local files are never uploaded. This verdict is about the series exactly as submitted. The service never saw the data source, its costs, survivorship, or any lookahead in how the series was built.

ParametersJSON Schema
NameRequiredDescriptionDefault
recordNoA canli.paper-evidence.v0 record.
signatureNoDetached record signature for a signed inline record; requires journal_file.
record_fileNoLocal record or export-bundle JSON path; requires CANLI_LOCAL=1.
journal_fileNoLocal signed journal to recompute and bind; requires CANLI_LOCAL=1.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations give a baseline (non-read-only, non-destructive, open-world), and the description adds real context beyond them: local files are never uploaded, CANLI_LOCAL=1 gates record_file/journal_file behavior, and unsigned/unjournalled inputs leave facts and signatures unchecked. It also pre-empts a misread of the verdict ('about the series exactly as submitted'). This is meaningful behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences, front-loaded with the purpose, then mode behavior, then the scope limitation of the verdict. Every sentence carries information, though the closing sentence about survivorship and lookahead is dense enough to need a second read.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and the description covers the important gaps for a validation tool: local-file handling, the journal requirement, and the boundary of what the verdict does and does not prove. Complete for its complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents the CANLI_LOCAL and journal_file requirements for each parameter, so the description largely restates that gating. Baseline 3 is appropriate; the prose adds only framing, not new syntax or format detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Checks paper-evidence.v0 structure and disclosures') and names the exact format version it operates on, which naturally separates it from the validate_backtest_length / validate_deflated_sharpe family of numeric validators. It stops short of naming a sibling it is not, so it is clear but not maximally differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage via the CANLI_LOCAL=1 mode and the journal/no-journal branch, and notes the consequence of omitting a journal (source facts and signatures unchecked). However it never states the plain when-to-use condition or points to an alternative tool such as verify_receipt, so guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_reality_checkData-snooping tests (SPA, Reality Check, StepM)A

Data-snooping tests on every variant a search tried: Hansen's SPA p-value that the best beat the benchmark only by luck, White's Reality Check, and the variants Romano-Wolf StepM finds better. Send all variants tried, not only the winners. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
repsNoBootstrap draws; default 2000.
seedNoSampling seed; default 42.
alphaNoFamilywise error for StepM; default 0.05.
matrixNoReturns of every variant the search tried, one row per period, one column per variant.
benchmarkNoBenchmark return per period; default zero.
matrix_fileNoPath to a CSV or JSON with one numeric column per variant, instead of matrix.
block_lengthNoMean bootstrap block in periods; default round(n^(1/3)).

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=false, openWorldHint=true, so the safety profile is partly covered externally. The description adds interpretive context — that a deflated Sharpe or overfitting probability crossing a threshold is neither an admission nor a forecast — which is genuine value beyond the annotations. It discloses no cost, runtime, or bootstrap-behavior details, so with annotations present a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, purpose front-loaded with the three test names, then the input requirement, then the interpretive caveat. No filler, though the final sentence is semantically loose (mixing deflated Sharpe, overfitting, and 'not a forecast' into one clause) and is more cautionary than actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. The description covers what distinguishes this test family, the critical input requirement, and the interpretive limits of the result — enough for a zero-required-parameter, fully schema-documented tool. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters (reps, seed, alpha, matrix, benchmark, matrix_file, block_length) are already documented with defaults and ranges in the schema. The description only reinforces one of them via 'all variants tried' and implies matrix_file can substitute for matrix. Baseline 3 for a fully documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names specific tests (Hansen's SPA, White's Reality Check, Romano-Wolf StepM) operating on a clearly stated resource — the returns of every variant a search tried. That is a concrete verb+resource combination an agent can recognize. It does not, however, explicitly route the agent away from the many validate_* siblings (deflated Sharpe, luck_trials, overfitting); it only references a deflated Sharpe as a caveat rather than as an alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is one strong usage requirement — 'Send all variants tried, not only the winners' — which tells the agent the precondition for a valid run, and the scope statement ('on every variant a search tried') implies the data-snooping scenario. But no alternatives are compared or excluded, and the borderline case of many trials vs. the sibling overfitting/deflated-Sharpe tools is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_track_recordMinimum track record lengthA

Minimum track record length (observations and years) for an observed Sharpe to beat a benchmark at a confidence level; with observations, the record's probabilistic Sharpe so far. For live or paper records; to size a backtest for its trials, use validate_backtest_length. A deflated Sharpe or overfitting probability above or below any threshold is not admission to anything and is not a forecast.

ParametersJSON Schema
NameRequiredDescriptionDefault
skewYesSkewness of returns; 0 if Normal.
confidenceNoBetween 0 and 1; default 0.95.
observationsNoRecord length so far, for its probabilistic Sharpe.
periods_per_yearYesPeriods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly.
non_excess_kurtosisYesKurtosis, not excess kurtosis; 3 if Normal.
observed_sharpe_annualizedYesAnnualized Sharpe as observed.
benchmark_sharpe_annualizedNoAnnualized Sharpe to beat; default 0.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
noteNo
errorNo
limitsNo
receiptNo
computedNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true) and the description does not contradict them. Beyond that, it adds a genuine interpretive caveat that the outputs "are not admission to anything and are not a forecast," which is useful behavioral context about how results should be read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded and the alternative tool and interpretive caveat follow. It is dense with semicolons and clauses, but each clause carries distinct information and nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is unnecessary, and all parameters are fully documented in the schema. The description supplies purpose, scope, the sibling alternative, and an interpretation caveat, leaving little an agent would need to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all seven parameters with ranges and defaults. The description adds only the conditional meaning of the observations parameter ("with observations, the record's probabilistic Sharpe so far"), which is a marginal gain over the schema's own text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource (minimum track record length in observations and years) and the computation it performs (Sharpe beating a benchmark at a confidence level), and it distinguishes itself by naming the sibling validate_backtest_length for the backtest-sizing case. The core action is expressed as a noun phrase rather than a verb, which slightly softens the clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the applicable domain ("For live or paper records") and names the alternative with the condition that selects it ("to size a backtest for its trials, use validate_backtest_length"). This is explicit routing, though it stops short of enumerating when-not conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_receiptVerify a receiptA
Read-only

Verify a receipt offline: its Ed25519 signature against the bundled canlicapital.com key, its output hash and its id. Send an id to fetch it first, or the receipt itself. The receipt is content-hashed, reproducible from the open-source core it names, and signed with Ed25519 by a key published at https://canlicapital.com/.well-known/canli-receipt-keys.json.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoReceipt id from a validation result.
receiptNoA receipt object, to verify without fetching.
include_receiptNoWith id: also return the stored receipt.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNo
validNo
checksNo
key_idNo
meaningNo
receipt_idNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/destructiveHint, so the safety profile is covered. The description adds substantial non-structured context: verification is offline, the algorithm is Ed25519, the key is bundled/published at a specific well-known URL, and receipts are content-hashed and reproducible from a named open-source core.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and efficiently packed. Slightly redundant, restating the signature/Ed25519/key concept twice and appending a long URL mid-sentence, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't document return values, and it covers both input paths plus the crypto semantics. The only gap is failure behavior — what a failed or tampered-verification result looks like — which the output schema may or may not cover.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes beyond the schema by clarifying the id-vs-receipt relationship (id triggers a fetch, receipt verifies without fetching), which resolves the real ambiguity in a zero-required-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (verify) and resource (receipt), and enumerates exactly what is checked: the Ed25519 signature against a named key, the output hash, and the id. An agent can distinguish this from the validate_* and backtest siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly covers the two input modes — 'Send an id to fetch it first, or the receipt itself' — which is the key usage decision for this tool. It does not, however, say when verification is warranted versus skipping it, nor reference any sibling tool.

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.

  1. 19 tool updatesv0.13.0
    • Changedaudit_backtest7 fields changed
      • removedInput schema / properties / n_splits / maximum
        Removed value: -9007199254740991
      • changedInput schema / properties / returns_column / anyOf
        Previous value: -[
        -  {
        -    "maxLength": 200,
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  {
        -    "maximum": 9007199254740991,
        -    "minimum": 1,
        -    "type": "integer"
        -  }
        -]New value: +[
        +  {
        +    "maxLength": 200,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  {
        +    "minimum": 1,
        +    "type": "integer"
        +  }
        +]
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / checks / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / not_run / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / readings / additionalProperties
        Removed value: -{}
    • Changedbacktest_strategy8 fields changed
      • removedInput schema / properties / grid / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedInput schema / properties / prices_column / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "maximum": 9007199254740991,
        -    "minimum": -9007199254740991,
        -    "type": "integer"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "integer"
        +  }
        +]
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / buy_and_hold / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / selected / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / source / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / validation / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / variants / additionalProperties
        Removed value: -{}
    • Changedcheck_feasibility6 fields changed
      • removedInput schema / properties / copies / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / copies / minimum
        Removed value: --9007199254740991
      • removedInput schema / properties / orders_per_rebalance / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / orders_per_rebalance / minimum
        Removed value: --9007199254740991
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / sources / additionalProperties
        Removed value: -{}
    • Addedcheck_leakage
    • Changedget_key3 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Addedplacebo_test
    • Changedservice_status3 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedstress_test12 fields changed
      • removedInput schema / properties / outage_periods / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / outage_periods / minimum
        Removed value: --9007199254740991
      • removedInput schema / properties / paths / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / paths / minimum
        Removed value: --9007199254740991
      • changedInput schema / properties / returns_column / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "maximum": 9007199254740991,
        -    "minimum": -9007199254740991,
        -    "type": "integer"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "integer"
        +  }
        +]
      • removedInput schema / properties / seed / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / seed / minimum
        Removed value: --9007199254740991
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / baseline / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / fragility / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / resampled / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / source / additionalProperties
        Removed value: -{}
    • Changedsummarize_series10 fields changed
      • changedInput schema / properties / series_column / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "maximum": 9007199254740991,
        -    "minimum": -9007199254740991,
        -    "type": "integer"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "integer"
        +  }
        +]
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / drawdown / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / growth / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / jumps / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / risk / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / source / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / tails / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / trend / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / volatility / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_backtest_length4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_breadth4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_deflated_sharpe4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_haircut_sharpe4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_luck_trials4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_overfitting5 fields changed
      • removedInput schema / properties / n_splits / maximum
        Removed value: -9007199254740991
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_paper_evidence6 fields changed
      • removedInput schema / properties / record / additionalProperties
        Removed value: -{}
      • removedInput schema / properties / record / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_reality_check6 fields changed
      • removedInput schema / properties / seed / maximum
        Removed value: -9007199254740991
      • removedInput schema / properties / seed / minimum
        Removed value: --9007199254740991
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedvalidate_track_record4 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • removedOutput schema / properties / data / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedOutput schema / properties / receipt / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedverify_receipt4 fields changed
      • removedInput schema / properties / receipt / additionalProperties
        Removed value: -{}
      • removedInput schema / properties / receipt / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • removedOutput schema / additionalProperties
        Removed value: -{}
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": {},
        -    "properties": {},
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {},
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  2. 9 tool updatesv0.12.0
    • Changedaudit_backtest3 fields changed
      • changedInput schema / properties / cross_trial_sharpe_sd_annualized / description
        Previous value: -"Standard deviation of annualized Sharpe across those trials."New value: +"Standard deviation of annualized Sharpe across those trials. Optional with variants: measured from them, and the larger is used."
      • changedInput schema / properties / effective_independent_trials / description
        Previous value: -"Independent variants tried before choosing this one."New value: +"Independent variants tried before choosing this one. Optional with variants: counted from them, and the larger number is used."
      • changedInput schema / required
        Previous value: -[
        -  "periods_per_year",
        -  "effective_independent_trials",
        -  "cross_trial_sharpe_sd_annualized"
        -]New value: +[
        +  "periods_per_year"
        +]
    • Addedbacktest_strategy
    • Addedcheck_feasibility
    • Removedcompany_financial_history
    • Removedget_receipt
    • Addedstress_test
    • Addedsummarize_series
    • Changedvalidate_paper_evidence4 fields changed
      • addedInput schema / properties / journal_file
        Added value: +{
        +  "description": "Local signed journal to recompute and bind; requires CANLI_LOCAL=1.",
        +  "maxLength": 1000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / record_file
        Added value: +{
        +  "description": "Local record or export-bundle JSON path; requires CANLI_LOCAL=1.",
        +  "maxLength": 1000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / signature
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Detached record signature for a signed inline record; requires journal_file.",
        +  "properties": {
        +    "public_key": {
        +      "maxLength": 64,
        +      "type": "string"
        +    },
        +    "scheme": {
        +      "const": "Ed25519",
        +      "type": "string"
        +    },
        +    "signature": {
        +      "maxLength": 128,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "scheme",
        +    "public_key",
        +    "signature"
        +  ],
        +  "type": "object"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "record"
        -]
    • Changedverify_receipt2 fields changed
      • addedInput schema / properties / include_receipt
        Added value: +{
        +  "description": "With id: also return the stored receipt.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / receipt / description
        Previous value: -"A receipt as get_receipt returns it, to verify without fetching."New value: +"A receipt object, to verify without fetching."
  3. 15 tool updatesv0.10.1
    • Changedaudit_backtest10 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / cross_trial_sharpe_sd_annualized / description
        Previous value: -"Standard deviation of the annualized Sharpe across those trials."New value: +"Standard deviation of annualized Sharpe across those trials."
      • changedInput schema / properties / periods_per_year / description
        Previous value: -"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."New value: +"Periods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly."
      • changedInput schema / properties / returns / description
        Previous value: -"Periodic returns as fractions (0.01 is 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis fields."New value: +"Periodic returns as fractions (0.01 = 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis."
      • changedInput schema / properties / returns_column / description
        Previous value: -"Header name or 1-based position of the returns column when returns_file has several numeric columns."New value: +"Column name or 1-based position, when returns_file has several numeric columns."
      • changedInput schema / properties / returns_file / description
        Previous value: -"Path to a CSV or JSON file of the returns on the machine running this server, instead of returns. Not available on the hosted endpoint."New value: +"Path to a CSV or JSON of the returns on this machine (not on the hosted endpoint), instead of returns."
      • changedInput schema / properties / variants / description
        Previous value: -"Optional returns of every variant tried, this one included, as fractions: one row per period, one column per variant. Adds the overfitting check."New value: +"Optional returns of every variant tried (this one included), one row per period, one column per variant; adds the overfitting check."
      • addedInput schema / properties / variants / items / maxItems
        Added value: +200
      • changedInput schema / properties / variants_file / description
        Previous value: -"Path to a CSV or JSON file of every variant's returns (one numeric column per variant), instead of variants."New value: +"Path to a CSV or JSON with one numeric column per variant, instead of variants."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "checks holds each check's full validate_ result by name; readings one sentence per check; not_run the checks skipped and why.",
        +  "properties": {
        +    "checks": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "not_run": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "readings": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedcompany_financial_history2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "Without a concept, histories lists what is available; with one, history holds the observations newest first as columns and rows, each with its filing. Values are as reported to the SEC.",
        +  "properties": {
        +    "claim_boundary": {
        +      "type": "string"
        +    },
        +    "company": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "histories": {
        +      "items": {},
        +      "type": "array"
        +    },
        +    "history": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "source": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedget_key2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "key_source says which key the session uses; data.key is set when a new key was issued.",
        +  "properties": {
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "key_present": {
        +      "type": "boolean"
        +    },
        +    "key_source": {
        +      "type": "string"
        +    },
        +    "note": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedget_receipt2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data is the stored receipt: validator, input, output, their hashes, source hashes and signature.",
        +  "properties": {
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedservice_status2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.store_reachable, data.quotas and, when available, data.usage for this key.",
        +  "properties": {
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_backtest_length5 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / backtest_years / description
        Previous value: -"Length of the backtest in years, to get the most independent trials it allows."New value: +"Backtest length in years, for the most trials it allows."
      • changedInput schema / properties / effective_independent_trials / description
        Previous value: -"Independent trials (backtests, parameter sets, ideas) tried; gives the minimum backtest length."New value: +"Independent trials tried (backtests, parameter sets, ideas)."
      • changedInput schema / properties / target_sharpe_annualized / description
        Previous value: -"In-sample annualized Sharpe you would take as a discovery; default 1."New value: +"In-sample annualized Sharpe you would call a discovery; default 1."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_breadth4 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / sleeves / description
        Previous value: -"Sleeve count, to get that book's Sharpe."New value: +"Sleeve count, for that book's Sharpe."
      • changedInput schema / properties / target / description
        Previous value: -"Target book Sharpe, to get the sleeves it needs."New value: +"Target book Sharpe, for the sleeves it needs."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_deflated_sharpe6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / cross_trial_sharpe_sd_annualized / description
        Previous value: -"Standard deviation of the annualized Sharpe across those trials."New value: +"Standard deviation of annualized Sharpe across those trials."
      • changedInput schema / properties / periods_per_year / description
        Previous value: -"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."New value: +"Periods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly."
      • changedInput schema / properties / returns / description
        Previous value: -"Periodic returns as fractions (0.01 is 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis fields."New value: +"Periodic returns as fractions (0.01 = 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis."
      • changedInput schema / properties / skew / description
        Previous value: -"Skewness of the returns; below -0.5 the reading warns that the counts are too generous."New value: +"Skewness of returns; 0 if Normal."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_haircut_sharpe7 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / autocorrelation / description
        Previous value: -"First-order autocorrelation of the returns, -1 to 1; default 0. Corrects the annualized Sharpe as Lo (2002)."New value: +"Lag-1 autocorrelation of returns, -1 to 1; default 0. Corrects the annualized Sharpe (Lo 2002)."
      • changedInput schema / properties / observations / description
        Previous value: -"Number of return observations behind the Sharpe ratio."New value: +"Return observations behind the Sharpe."
      • changedInput schema / properties / other_sharpe_ratios_annualized / description
        Previous value: -"Annualized Sharpe ratios of the other tests, over the same observations; adds the Holm and BHY haircuts."New value: +"Annualized Sharpes of the other tests over the same observations; adds Holm and BHY."
      • changedInput schema / properties / periods_per_year / description
        Previous value: -"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."New value: +"Periods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly."
      • changedInput schema / properties / tests / description
        Previous value: -"Total tests run, this one included; gives the Bonferroni and independent-test haircuts."New value: +"Tests run, this one included; gives the Bonferroni and independent-test haircuts."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_luck_trials7 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / autocorrelation / description
        Previous value: -"First-order autocorrelation of the returns, -1 to 1; default 0. Corrects the annualized Sharpe as Lo (2002)."New value: +"Lag-1 autocorrelation of returns, -1 to 1; default 0. Corrects the annualized Sharpe (Lo 2002)."
      • changedInput schema / properties / effective_independent_trials / description
        Previous value: -"Independent trials tried; adds the chance that the best of them reached this Sharpe by luck."New value: +"Independent trials tried; adds the chance the best reached this Sharpe by luck."
      • changedInput schema / properties / observations / description
        Previous value: -"Number of return observations behind the Sharpe ratio."New value: +"Return observations behind the Sharpe."
      • changedInput schema / properties / periods_per_year / description
        Previous value: -"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."New value: +"Periods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly."
      • changedInput schema / properties / skew / description
        Previous value: -"Skewness of the returns; below -0.5 the reading warns that the counts are too generous."New value: +"Skewness; below -0.5 the reading warns the counts are too generous."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_overfitting4 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / matrix / description
        Previous value: -"Returns as fractions: one row per period, one column per variant."New value: +"Returns as fractions, one row per period, one column per variant."
      • addedInput schema / properties / matrix / items / maxItems
        Added value: +200
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedvalidate_paper_evidence2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedvalidate_reality_check
    • Changedvalidate_track_record5 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / observations / description
        Previous value: -"Record length so far, to get its probabilistic Sharpe."New value: +"Record length so far, for its probabilistic Sharpe."
      • changedInput schema / properties / periods_per_year / description
        Previous value: -"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."New value: +"Periods per year: 252 daily, 365 crypto, 52 weekly, 12 monthly."
      • changedInput schema / properties / skew / description
        Previous value: -"Skewness of the returns; below -0.5 the reading warns that the counts are too generous."New value: +"Skewness of returns; 0 if Normal."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "data.result holds the statistics (data.plain_reading states them); limits say what the result does not establish; receipt ({id, url}) is the signed record, null when none was stored; error ({code, message}) is set only on refusal.",
        +  "properties": {
        +    "computed": {
        +      "type": "string"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {},
        +      "type": "object"
        +    },
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "limits": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "note": {
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedverify_receipt3 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / receipt / description
        Previous value: -"A receipt as get_receipt returns it (its data), to verify without fetching it."New value: +"A receipt as get_receipt returns it, to verify without fetching."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": {},
        +  "description": "valid is true only when the signature, output hash and content id all check out; checks lists each.",
        +  "properties": {
        +    "checks": {},
        +    "error": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "properties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "key_id": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "meaning": {
        +      "type": "string"
        +    },
        +    "receipt_id": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "valid": {
        +      "type": "boolean"
        +    }
        +  },
        +  "type": "object"
        +}
  4. 13 tool updatesv0.6.0
    • Addedaudit_backtest
    • Changedcompany_financial_history4 fields changed
      • addedInput schema / properties / cik / description
        Added value: +"SEC CIK; send cik or ticker."
      • addedInput schema / properties / concept / description
        Added value: +"us-gaap concept such as Assets; omit to list them."
      • addedInput schema / properties / limit / description
        Added value: +"Most observations, newest first; default 40."
      • addedInput schema / properties / ticker / description
        Added value: +"Ticker such as AAPL; send ticker or cik."
    • Changedget_key1 field changed
      • addedInput schema / properties / label / description
        Added value: +"Name for the key."
    • Changedget_receipt1 field changed
      • addedInput schema / properties / id / description
        Added value: +"Receipt id from a validation result."
    • Addedvalidate_backtest_length
    • Changedvalidate_breadth4 fields changed
      • addedInput schema / properties / average_pairwise_correlation / description
        Added value: +"Average correlation between sleeves, -1 to 1."
      • addedInput schema / properties / sleeve_sharpe / description
        Added value: +"Annualized Sharpe of one sleeve."
      • addedInput schema / properties / sleeves / description
        Added value: +"Sleeve count, to get that book's Sharpe."
      • addedInput schema / properties / target / description
        Added value: +"Target book Sharpe, to get the sleeves it needs."
    • Changedvalidate_deflated_sharpe8 fields changed
      • addedInput schema / properties / cross_trial_sharpe_sd_annualized / description
        Added value: +"Standard deviation of the annualized Sharpe across those trials."
      • addedInput schema / properties / effective_independent_trials / description
        Added value: +"Independent variants tried before choosing this one."
      • addedInput schema / properties / non_excess_kurtosis / description
        Added value: +"Kurtosis, not excess kurtosis; 3 if Normal."
      • addedInput schema / properties / observations / description
        Added value: +"Number of return observations."
      • addedInput schema / properties / observed_sharpe_annualized / description
        Added value: +"Annualized Sharpe as observed."
      • addedInput schema / properties / periods_per_year / description
        Added value: +"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."
      • addedInput schema / properties / returns / description
        Added value: +"Periodic returns as fractions (0.01 is 1%), oldest first; replaces the Sharpe, observations, skew and kurtosis fields."
      • addedInput schema / properties / skew / description
        Added value: +"Skewness of the returns; below -0.5 the reading warns that the counts are too generous."
    • Addedvalidate_haircut_sharpe
    • Addedvalidate_luck_trials
    • Changedvalidate_overfitting4 fields changed
      • addedInput schema / properties / matrix / description
        Added value: +"Returns as fractions: one row per period, one column per variant."
      • addedInput schema / properties / max_combinations / description
        Added value: +"Most splits evaluated, up to 2000 (default)."
      • addedInput schema / properties / n_splits / description
        Added value: +"Even number of blocks, at least 2; default 16."
      • addedInput schema / properties / seed / description
        Added value: +"Sampling seed; default 42."
    • Changedvalidate_paper_evidence1 field changed
      • addedInput schema / properties / record / description
        Added value: +"A canli.paper-evidence.v0 record."
    • Changedvalidate_track_record7 fields changed
      • addedInput schema / properties / benchmark_sharpe_annualized / description
        Added value: +"Annualized Sharpe to beat; default 0."
      • addedInput schema / properties / confidence / description
        Added value: +"Between 0 and 1; default 0.95."
      • addedInput schema / properties / non_excess_kurtosis / description
        Added value: +"Kurtosis, not excess kurtosis; 3 if Normal."
      • addedInput schema / properties / observations / description
        Added value: +"Record length so far, to get its probabilistic Sharpe."
      • addedInput schema / properties / observed_sharpe_annualized / description
        Added value: +"Annualized Sharpe as observed."
      • addedInput schema / properties / periods_per_year / description
        Added value: +"Observations per year: 252 daily, 365 daily crypto, 52 weekly, 12 monthly."
      • addedInput schema / properties / skew / description
        Added value: +"Skewness of the returns; below -0.5 the reading warns that the counts are too generous."
    • Addedverify_receipt
  5. 9 tool updatesv0.5.0
    • First observedcompany_financial_history
    • First observedget_key
    • First observedget_receipt
    • First observedservice_status
    • First observedvalidate_breadth
    • First observedvalidate_deflated_sharpe
    • First observedvalidate_overfitting
    • First observedvalidate_paper_evidence
    • First observedvalidate_track_record

TDQS

A3.8/5.0

Scored across 19 tools

Disambiguation4/5

The validate_* family shares a theme (multiple-testing/luck), but descriptions clearly separate each method and even cross-reference the right alternative (e.g. 'for the probability the Sharpe is real, use validate_deflated_sharpe'). The main soft spot is the overlap between the umbrella audit_backtest and its component validators, which an agent must reason about, but the docs reduce this to occasional hesitation rather than true ambiguity.

Naming Consistency4/5

A strong verb_noun convention dominates (validate_*, check_*, get_key, verify_receipt, backtest_strategy, stress_test), with only minor deviations like the noun-style service_status. Overall readable and predictable, not chaotic.

Tool Count4/5

19 tools is slightly on the heavy side, but each maps to a distinct statistical method or workflow step (validation, key handling, receipts, backtesting, diagnostics), so most earn their place. It sits just above the ideal range but is defensible given the specialized domain.

Completeness5/5

The surface covers the full strategy-validation lifecycle: key/status management, individual and bundled validation methods, offline receipt verification, backtesting, series summarization, stress testing, feasibility, leakage, and placebo testing. No obvious gaps or dead ends for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    Verify a number before an agent asserts it — a Deflated Sharpe Ratio for backtest, plus eval-gap, subset-win, and judge-bias checks, with signed receipts anyone can verify offline.
    34
    MIT
  • F
    license
    Not graded
    quality
    F
    maintenance
    Provides financial data and market filings via Streamable HTTP tools. Enables AI agents to resolve equity entities, fetch SEC filings, compare institutional holders, and export finance receipts.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides tools to research crypto trading strategies via backtesting, walk-forward validation, and paper trading, with a deflated-Sharpe overfitting check. Enables natural-language-driven analysis and interpretation of strategy performance.
    2
    Apache 2.0
  • A
    license
    B
    quality
    C
    maintenance
    Enables auditing and verification of algorithmic trading backtests from coding agents like Claude Code, Cursor, and Windsurf, including look-ahead bias detection, overfitting checks, and sealed audit proof verification.
    3
    MIT