关于 Canli Validation
Canli Validation 是供编码 Agent 和其他客户端检查回测的 MCP 服务,提供统计验证器和本地分析工具。结果会说明限制;API 验证附带签名收据,本地模式则不向 API 发送数据。
主要功能
- 01Deflated Sharpe 和过拟合检查
- 02针对多个变体的数据窥探测试
- 03跟踪记录和回测长度检查
- 04组合式回测审计
- 05本地收益序列分析工具
- 06离线验证签名收据
适用场景
- 01结合尝试过的变体评估 Sharpe 比率
- 02检查多种策略的数据窥探问题
- 03使用多个验证器审计回测
- 04离线验证验证收据
MCP 相关
向 MCP 客户端提供验证、审计、收据、状态、财务历史和本地实验室工具。可使用托管 API、本地运行且不提交数据,或连接托管 MCP 端点。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://canlicapital.com/mcpclaude mcp add --transport http arhancanli-canli-validation https://canlicapital.com/mcp{"mcpServers":{"arhancanli-canli-validation":{"type":"http","url":"https://canlicapital.com/mcp"}}}在 Cursor 中打开{"servers":{"arhancanli-canli-validation":{"type":"http","url":"https://canlicapital.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"arhancanli-canli-validation":{"type":"http","url":"https://canlicapital.com/mcp"}}}{"mcpServers":{"arhancanli-canli-validation":{"serverUrl":"https://canlicapital.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://canlicapital.com/mcp需要授权工具
18| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| skew | number | 否 | 收益的偏度;正态分布时为 0。 |
| returns | array | 否 | 按周期排列的收益率,以小数表示(0.01 = 1%),从最早到最晚;用于替代 Sharpe、观测数、偏度和峰度。 |
| observations | integer | 否 | 收益观测数。 |
| periods_per_year | number | 否 | 每年的周期数:每日为 252,加密货币为 365,每周为 52,每月为 12。 |
| non_excess_kurtosis | number | 否 | 峰度(非超额峰度);正态分布时为 3。 |
| observed_sharpe_annualized | number | 否 | 观测到的年化夏普比率。 |
| effective_independent_trials | integer | 否 | 选择此变体前尝试的独立变体数量。 |
| cross_trial_sharpe_sd_annualized | number | 否 | 这些试验中年化夏普比率的标准差。 |
详细介绍
canli-validation-mcp
你的最佳回测结果是真实的吗,还是你尝试过的多个变体中运气最好的一个? 这个 MCP 服务 让 Claude、Cursor 或任何 MCP 客户端都能通过标准校正方法回答这个问题:折减夏普比率、CSCV 回测过拟合概率、针对所有尝试变体的数据窥探检验(Hansen's SPA、White's Reality Check、Romano-Wolf StepM)、最低跟踪记录长度、折扣夏普比率和运气等效试验次数。免费,采用 MIT 许可证。
快速开始
# 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
然后可以这样提问:“我尝试了 229 个变体并保留了最佳结果:730 个日收益率(每年 365 个)的年化夏普比率为
1.5,偏度为 -0.5,峰度为 5,变体的夏普比率标准差为 0.57。这结果可靠吗?” 助手会调用 validate_deflated_sharpe:仅靠运气,229 个没有技能的变体中最佳结果就能达到 1.60;因此,将搜索过程纳入考虑后,夏普比率高于零的概率会从 98.1% 降至 44.4%。Claude Desktop 和其他任何 stdio 客户端(Cursor、VS Code)都运行相同的 npx 命令;请参阅下文的“Claude Desktop”和“通用 stdio 客户端”。
功能
这是一个 MCP(Model Context Protocol)服务,通过 canlicapital.com 的免费、有密钥保护的验证 API 提供服务,并配有可在本机计算的实验室。它为编码 Agent 提供二十种工具:申请免费密钥、运行九种验证器(折减夏普比率、CSCV 过拟合、数据窥探检验(Hansen's SPA、White's Reality Check 和 Romano-Wolf StepM)、论文证据符合性、广度上限、最低跟踪记录长度、最低回测长度、折扣夏普比率、运气等效试验次数)、在一次调用中使用多种验证器审计一次回测、离线验证收据签名、读取服务状态、从 SEC 文件中读取公司的已披露财务历史,以及六种实验室工具:对参数网格回测规则、汇总长序列、对策略收益进行压力测试、根据经纪商限制检查计划、检查信号是否存在前视偏差,以及使用安慰剂数据测试整个研究流程。每个验证结果除了数值,还附有说明其不能证明什么的句子,以及记录该结果的收据(无论成功还是出错),因此 Agent 不会只看到数字而看不到其局限。
此软件包已发布到 npm,名称为 canli-validation-mcp。
它也已列入官方 MCP Registry(io.github.arhancanli/canli-validation-mcp)和
cursor.directory。如下所示,使用 npx 运行,无需安装。本地检出仅在开发或测试此软件包本身时才需要;请参阅文末附近的“本地检出”。
此 README 描述的是 package.json 中的版本。不指定版本的 npx 会运行 npm 的最新
发布版本;npx -y canli-validation-mcp@<version> 则会固定到某个版本。
Agent 的使用效果
一项固定基准测试会向模型提供这些工具,并根据由同一份已检查代码计算出的真实结果,评估模型是否选择了正确的工具并返回正确答案。三个模型的测试结果以及每次运行的记录见
bench/agent/README.md。
API 是什么(以及不是什么)
引擎才是产品。该服务会用你提交的数字进行计算,采用与 canlicapital.com 自身论文记录相同的诚实计算方式,并返回一个任何人都能根据回执重新计算的判定结果。它会为每份回执签名,不接收市场数据,不评估策略,也从未看到你的数据源、其成本,或构建序列时是否存在前视偏差。完整设计请参阅主仓库中的 docs/superpowers/specs/2026-09-05-developer-key-validation-api-design.md。
工具
尚未发布的源码为 validate_paper_evidence 增加了本地日志绑定:在仓库中运行
CANLI_LOCAL=1 node mcp/src/server.mjs,并发送 record 或 record_file 中的一个,以及
journal_file,以检查来源哈希、签名和重新计算的声明。record_file 接受标准记录、{record,signature} 信封,或完整的执行导出包;完整导出包中的配套指标/观测值也会经过检查。
签名记录需要附带签名文件。来源验证通过的条件是 bindings.all_match 必须为 true。
没有日志时,结果会明确报告仅符合结构要求。在托管/远程模式下,文件和签名会被拒绝,也绝不会上传。本地结果不含 Canli 回执。当前 npm/托管版本仍保留现有的仅记录 API。
| 工具 | 调用 | 是否需要密钥 |
|---|---|---|
get_key | POST /api/v1/keys(仅在未配置密钥时列出) | 否 |
validate_deflated_sharpe | POST /api/v1/validate/deflated-sharpe | 是 |
validate_overfitting | POST /api/v1/validate/overfitting | 是 |
validate_paper_evidence | POST /api/v1/validate/paper-evidence | 是 |
validate_breadth | POST /api/v1/validate/breadth | 是 |
validate_track_record | POST /api/v1/validate/track-record | 是 |
validate_backtest_length | POST /api/v1/validate/backtest-length | 是 |
validate_haircut_sharpe | POST /api/v1/validate/haircut-sharpe | 是 |
validate_luck_trials | POST /api/v1/validate/luck-trials | 是 |
validate_reality_check | POST /api/v1/validate/reality-check(matrix_file 会在你的计算机上读取,并作为数字发送) | 是 |
audit_backtest | 调用去膨胀夏普和业绩记录路由,然后生成摘要:提供 variants 时,调用过拟合和数据窥探路由;否则调用运气试验。每项验证各执行一次 | 是 |
verify_receipt | 提供 ID 时调用 GET /api/v1/receipts/{id}(include_receipt 会返回存储的回执);检查在本地运行 | 否 |
service_status | GET /api/v1/validate/status | 否 |
company_financial_history | GET /company-data/{cik}.json(股票代码会通过 GET /api/v1/company-tickers.json 解析) | 否 |
validate_deflated_sharpe 只接受以下两种输入格式之一,不得混用:
- 七个契约字段:
observed_sharpe_annualized、observations、periods_per_year、skew、non_excess_kurtosis、effective_independent_trials、cross_trial_sharpe_sd_annualized; - 或者收益序列及其背后的试验次数:
returns、periods_per_year、effective_independent_trials、cross_trial_sharpe_sd_annualized。
如果同时发送两种格式的字段,或两种格式的字段都未发送,系统会在请求离开进程前拒绝该请求;请参阅 src/schemas.mjs。
validate_reality_check 接受搜索尝试过的所有变体的收益:每个期间占一行、每个变体占一列,以 matrix 或 matrix_file(你计算机上的 CSV 或 JSON 文件)形式传入,并可选提供 benchmark 序列;若未提供,变体会与零进行比较。该工具会基于一次固定种子的平稳自助抽样运行三项检验:
- Hansen 的 SPA:如果没有任何变体具有优势,表现最佳变体的学生化超额收益达到这一水平的概率,并给出上下界(
spa.p_value是一致 p 值,也是核心指标;monte_carlo_se是其抽样误差); - White 的 Reality Check:不进行学生化时,同样的问题,因此一个波动较大的变体可能会主导结果;
- Romano 和 Wolf 的 StepM:哪些变体胜过基准,同时将家族错误率控制在
alpha。
使用 seed 即可精确复现结果。在三个固定种子的案例中,p 值与 Python 的 arch 8.0 以及对 Hansen 公式的 numpy 转写结果一致,误差在蒙特卡洛误差范围内;StepM 集合也与 arch 的结果一致(js/snooping-core.test.js)。只有实际发送的变体会计入:如果一次搜索尝试的变体多于发送的数量,运气看起来就会比实际情况更好。
company_financial_history 与其他工具不同:它读取 canlicapital.com 上公开的公司参考数据,而非验证 API。提供一个 CIK(1 至 10 位数字)即可列出公司可用的财务历史记录;提供 CIK 和一个 us-gaap 概念(例如 Revenues)即可获取观测值,按时间从新到旧排列(limit 默认为 40,最大为 200)。每条观测都保留其申报文件 accession、表格类型、提交日期和单位;结果还附带原始 SEC 响应的 SHA-256,以及记录自身的边界说明:这些是向 SEC 报告的会计数值,不是市场价格、收益或建议。当前版本未涵盖的公司和概念会返回错误,并列出可用概念。
实验室:回测、汇总、压力测试、可行性、前视偏差、安慰剂测试
六种工具均在服务器进程本身中运行,可在你的机器上或托管端点上执行;不会向 API 发送任何内容,也不会存储回执。每个结果都会标明其计算所依据的确切数值的 SHA-256,并说明它不能证明什么。
backtest_strategy会针对你的价格数据,在参数网格中的每组参数上运行一条规则:sma_cross(快线、慢线)、momentum(回看期、跳过期)、mean_reversion(窗口、入场 z 值)、breakout(回看期)或buy_and_hold;仅做多,或启用allow_short做空;并按换手量收取单位成本。 每个周期持有的仓位根据截至前一个周期的收盘价决定,因此任何规则都无法看到未来(测试会更改后续价格, 并检查是否有更早的仓位发生变化)。随后,它会使用本次调用实际运行的变体数量验证最佳变体,而不是 使用某人自行声明的数量:根据网格中实测夏普比率的离散程度计算 Deflated Sharpe Ratio、基于每个变体 收益率计算 CSCV 回测过拟合概率、概率夏普比率和最低业绩记录要求,并与同一时间窗口的买入并持有策略 对比。每次调用最多 200 个变体、20,000 个价格。不会运行任何代码:策略就是一个策略系列加上一组数字。- **
summarize_series**读取较长的价格或收益率序列,并用约 100 个词进行概述,同时为每项指标提供字段: 增长、波动率、夏普比率和漂移 t 统计量、包含日期和恢复情况的最大回撤、趋势、波动率状态(按自身 21 期 波动率划分为三分位)、尾部、跳跃(超过稳健标准差 6 倍)、自相关、陈旧数据;若提供基准,还会给出相关性 和 beta。五年期日频序列约有 1,260 个数字;摘要则是一段文字。 - **
stress_test**使用平稳区块自助法对策略收益率进行重采样(带种子,因此重复运行会得到完全相同的结果), 并报告回撤限额被突破和夏普比率转为负值的频率;随后应用四种明确说明规则的情景:在权益高点发生崩盘 (默认幅度为 20% 和最差周期跌幅 3 倍中的较大者)、波动率倍增、重复经历两次最差阶段,以及在最差周期 之后仓位连续数个周期无法变动。脆弱性占比指重采样历史中突破回撤限额或经风险调整后亏损的比例。 不使用生成式模型:用单条序列训练的模型会记住它,或虚构无法验证的动态。 - **
check_feasibility**在交易前,根据真实经纪商检查计划的可行性:经纪商公布的下单速率限制与调仓时的 订单突发量(Alpaca 每分钟 200 笔,Interactive Brokers 每秒约 50 笔)、最低订单金额(Alpaca 名义金额 1 USD)、截至 2026 年的美国日内交易规则(FINRA 于 2026 年 6 月 4 日废除了模式日内交易者规则及其 25,000 USD 最低资金要求;各公司可在 2027 年 10 月 20 日前逐步实施替代规则)、现金账户的 T+1 结算、 每笔订单占日成交量的比例、平方根市场冲击(系数 Y,默认值为 1;同一策略的每个副本均计入),以及成本 和冲击会吞噬预期总收益时所需的资金规模。每项经纪商信息均附有核查日期和来源。 - **
check_leakage**无需查看信号代码即可查找其中的前视泄漏。在前 n 行上计算的因果信号,其结果应与完整 运行在这 n 行上的结果完全相同。plan会选取截点(带种子,位于序列的 40% 到 95% 之间);你需要在每个 截点之前的行上重新运行自己的代码,而compare会检查每一列:若移除后续行后某个值发生变化,就说明 该值用到了后续行。在你的机器上,columns_file接受你脚本写入的 JSON 文件路径{cuts, columns}(Python 的NaN会按缺失值读取),无需粘贴数千个数字。结果会指出泄漏模式:未来行及其前视跨度(shift(-5)表示读取未来 5 行)、全样本(在整个序列上进行归一化、排名、缩放或拟合),或分散行(向后填补空缺)。 在固定的 22 个 pandas 和 statsmodels 信号集合上(config/research/leakage-zoo.json,来自scripts/research/leakage/),11 个泄漏全部被检出且模式判断正确,11 个诚实指标均未被误报。通过测试 仅适用于已检查的截点:幸存者偏差、数据供应商修订,或仅出现在首行的泄漏都不会留下痕迹。 - **
placebo_test**一次性检验整个研究工作流。plan会在系统临时目录中的新文件夹里写入你的面板 (real.csv)和 19 个安慰剂数据集:收益率相同,但周期顺序随机打乱,且所有资产使用同一顺序,因此每项 资产保留自身收益率,每天也保留横截面,但任何内容都无法预测。将工作流原样运行于每个数据集,包括所有 搜索、筛选和参数选择,然后compare会将真实结果与安慰剂结果进行排名。工作流所做的每项选择都会计入, 因为它会在每个安慰剂数据集上重新做出这些选择。一项预注册研究选定了这种重排方式(scripts/research/placebo/v1/、config/research/placebo-v1-evaluation.json):在 30 种模拟市场与工作流组合中,结果均无法预测 (每种组合进行 10,000 次检验;包含五种收益率形态、平稳和漂移市场,以及资产仅在常数均值上不同的市场; 使用 SMA、时间序列动量和横截面动量网格),名义显著性水平为 5% 时,假阳性率为 4.6% 至 5.5%。 在相同市场中,对最佳规则进行 t 检验,有 10.9% 至 78.9% 的概率发现优势;在市场存在漂移时, Bonferroni 校正后的比例为 8.0% 至 10.3%,而在资产仅均值不同时则为 58.5% 至 59.7%。19 个安慰剂的 最小 p 值为 0.05;99 个安慰剂可提供更细的粒度。 在自己的机器上,prices_file、series_file和returns_file接受 CSV 或 JSON 路径,而不是数值。只会读取数值,以及文件中存在的 ISO 日期列,这样结果就能指出回撤开始的日期。
试验台账:记录 Agent 尝试的每个变体
Agent 可以在一小时内尝试数千种策略变体,其中表现最好的一种单凭运气就会显得很出色。运气的影响有多大,取决于尝试过多少种变体,以及它们的结果分散程度;因此,要诚实地评判报告中的赢家,就需要了解整个搜索过程。台账会记录这一切。
通过 CANLI_TOOLSETS=validate,lab,ledger(或 all)启用,然后:
- 每尝试一个变体,就调用一次
ledger_record_trial:提供其收益(或收益文件),或年化 Sharpe 和样本量,以及标签和参数。首次调用会创建一个台账并返回其名称;后续调用沿用该名称。每次回复都会统计截至目前的整个搜索过程。 - 调用
ledger_summary获取评判结果:最佳试验、数量相同的纯靠运气试验中最佳试验能达到的 Sharpe、计入所有试验后的最佳试验 deflated Sharpe ratio,以及所有试验的收益序列对齐时的回测过拟合概率(CSCV)。 - 调用
ledger_export将搜索结果交给他人。每个试验都会通过 SHA-256 与前一个试验链接,因此一旦试验被删除、重新排序或编辑,就会显示出来。
台账是位于 CANLI_LEDGER_DIR 下的 JSON-lines 文件(默认路径为 ~/.canli/ledgers);数据不会离开你的机器。以这种方式记录 20 个纯噪声变体,得到的最佳年化 Sharpe 约为 1.5,单靠运气的预期值约为 1.7,deflated Sharpe 接近 0.4:台账会如实揭示赢家的真实水平。统计数据与 validate_deflated_sharpe 和 validate_overfitting 使用的代码相同,并且 test/ledger.test.mjs 会检查两种情况(噪声会被标记;噪声中的真实优势会让 deflated Sharpe 保持在 0.95 以上)。
一次调用审计回测
audit_backtest 接收一个策略的收益序列,最好也提供每个变体的收益(variants 或 variants_file,包括被舍弃的变体);如果不提供,则需提供尝试过的变体数量及其夏普比率分布。结果首先包含:
headline:选择一项测试,其假阳性率是在任何人查看你的数据之前测定的。Null Zoo v1(仓库中的scripts/research/null-zoo/v1/)从九种已知真实情况的收益形态中,抽取了数十万次模拟搜索;门槛和选择测试的规则都在运行前提交。提供变体时,概要来自数据窥探测试(validate_reality_check,含其凭证);不提供变体时,则来自 Lo 自相关修正后的运气试验。概要句会引用收益形态与你相似时测得的假阳性率,以及九种形态中的最坏值。fix_next:最多五项后续步骤,每项包含{id, why, next},并带有稳定的 ID。computed:Lo 修正后的夏普比率、夏普比率的平稳自助法 95% 区间、折减后的夏普比率、最低回测时长;如果提供了变体,还包括这些变体相当于多少次独立试验(Li 和 Ji),以及所选变体的样本外衰减。
接下来是各项检查:对收益序列执行 validate_deflated_sharpe(估算值),对检查得出的夏普比率、偏度和峰度执行 validate_track_record;如果提供了变体,还会执行 validate_overfitting。每项检查的返回结果与对应工具完全一致,并附有自己的凭证;折减夏普比率会使用已声明和已计数的试验次数及夏普比率分布中较大的值,以免将搜索规模说小。拒绝执行或无法调用的检查会报告该检查的错误。审计本身不会另行评级。通过 API 时,每项检查使用一次验证。
在你的机器上运行服务时,returns_file 和 variants_file 可接收回测输出文件的路径,而不是数字:支持 CSV(逗号、分号或制表符分隔,有或没有标题行;日期列和标签列会被忽略,无名索引列或计数索引列会被跳过并报告)或 JSON 数组。存在多个列时,使用 returns_column 选择列。只读取数字;托管端点会拒绝文件路径。Agent 将长序列复制到调用中时可能漏掉数值,而且复制会消耗令牌;在我们的 Agent 基准测试中,改为读取文件后,gpt-5.4-mini 在 9 个审计问题中答对的问题从 4 个提升到 8 个。
提示词、资源和结构化结果
支持 MCP 提示词的客户端提供八种引导式工作流:validate_backtest(先检查折减夏普比率,再检查过拟合,最后给出所需的历史记录,并说明每个数值无法证明什么)、track_record_needed、backtest_and_validate、stress_my_strategy、production_check、summarize_market_series、check_signal_for_lookahead 和 test_pipeline_on_placebos。资源包括:canli://limits,每个结果都会附带的边界说明;canli://sources,各验证器依据的论文,以及每项验证器如何根据论文进行检查;canli://strategy-spec,每个策略类别及其参数的 JSON Schema;以及 canli://openapi,API 的 OpenAPI 3.1 文档。还有两个资源模板用于编写调用工具的代码:canli://schemas/{tool} 返回工具确切的输入和输出 JSON Schema,canli://examples/{language}/{tool} 返回可运行的调用示例,支持 python、javascript 或 curl(两个变量都必须填写)。测试会编译每个生成的 Python 和 JavaScript 示例,并检查每个示例的参数是否为有效输入。每个工具结果都会以文本和 structuredContent 两种形式携带其封装内容。
紧凑上下文(0.3.0)
Agent 需要为工具返回的每个 token 付费,包括它从未读取的空白字符。自 0.3.0 起,
每个结果都是精简后的 JSON,公司历史会将观测值作为一个 columns
表头和每个观测值一行返回,并且所有行共用的单位只声明一次。不丢弃任何字段:每条
边界句、登记编号、表格、提交日期和源哈希仍保留在结果中,columns + rows 可精确
重建每个观测值。
使用 bench/token_cost.py 在实时记录上测得(分词器:tiktoken o200k_base;其他
分词器的绝对计数会有所不同),每条记录各 20 个观测值:
| 记录 | 0.2.0(缩进格式) | 精简格式 | 0.3.0(精简列式格式) |
|---|---|---|---|
| Apple,StockholdersEquity | 2,214 | 1,560(−29.5%) | 1,060(−52.1%) |
| Microsoft,CashAndCashEquivalentsAtCarryingValue | 2,231 | 1,574(−29.4%) | 1,065(−52.3%) |
验证工具仅通过精简格式减少 token:实时 service_status 封套在缩进格式下为 593
个 token,精简后为 475 个(−19.9%);其中的边界句逐字保留。这些数字仅针对这些结果,
不代表其他服务。
与 0.2.0 不兼容的变更: history.observations 现在是 {unit?, columns, rows},不再是
对象数组。
配置
| 变量 | 默认值 | 含义 |
|---|---|---|
CANLI_API_BASE | https://canlicapital.com | API 所在地址。可将其指向预览部署以进行测试。 |
CANLI_KEY | 未设置 | 已通过 POST /api/v1/keys 签发的密钥。设置后,get_key 不会发送请求,而是报告密钥已配置;其他每个工具都会将其作为 Authorization: Bearer <key> 发送。 |
CANLI_FULL_ENVELOPE | 未设置 | 设为 1 或 true 时,每项验证都会返回完整 API 封套,而非紧凑结果(见下文)。 |
CANLI_TOOLSETS | 全部 | 要列出的工具:从 validate、receipts、company、status 和 lab 中选择,以逗号分隔;也可设为 all。启动时会拒绝未知名称。参见下文的“工具集”。 |
CANLI_LOCAL | 未设置 | 设为 1 或 true 时,在此机器上运行八个验证器(下文的私有本地模式):无需密钥、无需联网、无需收据。 |
如果未设置 CANLI_KEY 且未启用本地模式,则每个会话都应在运行验证器前调用一次 get_key。它
返回的密钥仅在会话期间保存在当前进程的内存中;不会写入
磁盘。
HTTP 失败和 API 错误封套会标记为 MCP 工具错误,同时保留 完整 JSON 封套。验证成功但判定为否的结果仍是正常结果。请求的截止时间为 30 秒,涵盖响应头和响应正文;请求会拒绝 重定向,且不会自动重试。服务处理完请求后仍可能发生超时;再次提交前,请检查服务状态。 非 JSON 响应正文和原始网络错误不会包含在工具错误中。
安装
无需安装。首次运行时,npx 会获取已发布的软件包,因此下方的每个客户端配置都只会
启动 npx -y canli-validation-mcp。若要开发或测试此软件包本身,而不是运行已发布版本,请参见靠近文末的“本地检出”。
托管端点(无需安装)
相同的工具也通过 MCP Streamable HTTP 在 https://canlicapital.com/mcp 上提供,适用于连接 URL 而非启动进程的客户端(Claude.ai connectors、ChatGPT、Cursor 的远程服务)。无需安装,也无需在你的机器上安装 Node.js。
claude mcp add --transport http canli https://canlicapital.com/mcp
如果不提供密钥,请求将使用共享匿名密钥运行,因此所有托管调用者共享每日验证配额。当天共享配额用完后,仍会返回验证结果,由托管端点使用相同的代码计算,但不会存储回执;结果会说明这一点。若要使用自己的配额,请申请免费密钥(参见 /developers),并将其作为请求头发送:
claude mcp add --transport http canli https://canlicapital.com/mcp --header "Authorization: Bearer $CANLI_KEY"
在 URL 中添加 ?toolsets=,即可只列出部分工具(参见下文“工具集”),例如
https://canlicapital.com/mcp?toolsets=company。
该端点是无状态的。在此端点上,get_key 不会签发密钥,只会说明当前使用的密钥,因为在此处签发的密钥无法用于下一次请求。格式错误的 Authorization 请求头会被拒绝,而不会替换为共享密钥。
Claude Desktop
将以下内容添加到 claude_desktop_config.json(设置、开发者、编辑配置):
{
"mcpServers": {
"canli": {
"command": "npx",
"args": ["-y", "canli-validation-mcp"]
}
}
}
之后重启 Claude Desktop。添加带有 CANLI_API_BASE 的 "env" 对象,即可将其指向预览部署,而非默认部署。
Claude Code
claude mcp add canli -- npx -y canli-validation-mcp
运行 claude mcp list 确认已注册,运行 claude mcp remove canli 将其移除。
私有本地模式
设置 CANLI_LOCAL=1,八个验证器便会在你的机器上运行:你提交的序列不会有任何内容发送到 canlicapital.com,无需密钥,也不会存储回执。计算逻辑与 API 自身一致,并逐字节随 src/local 一同发布(如果两者出现差异,测试会失败),因此本地结果与托管结果相同;由于没有生成回执,因此不会提供回执 ID。
claude mcp add canli-local --env CANLI_LOCAL=1 -- npx -y canli-validation-mcp
verify_receipt 按 ID 查询、service_status 和 company_financial_history 仍会从 canlicapital.com 读取数据;它们不会发送序列。在 Claude Desktop 扩展中,这对应“私有本地模式”设置。
通用 stdio 客户端
任何能够启动进程并通过 stdio 通信的 MCP 客户端都可以使用。以下示例直接使用官方 SDK,从 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();
结果无法证明什么(边界说明)
此服务返回的每个信封都包含以下句子,内容原封不动地来自 API 本身
(api/_lib/limits.js):
- 此判定针对提交的原始序列。服务从未见过数据源、成本、存活偏差,也不了解构建该序列时是否存在前视偏差。
- 无论去膨胀夏普比率或过拟合概率高于还是低于任何阈值,都不代表获得任何资格,也不是预测。
- 回执经过内容哈希处理,可根据其指定的开源核心重现,并由 Ed25519 签名;对应公钥发布于 https://canlicapital.com/.well-known/canli-receipt-keys.json。
- 配额:每个密钥每天(UTC)1000 次验证,每个客户端每天(UTC)5 个密钥,每个验证请求 1048576 字节,每个密钥撤销请求 1024 字节,每个序列 20000 个观测值,每个矩阵 200 个变体。
每个工具的描述中也会包含其中一句,因此 Agent 在调用工具之前就能看到边界,而不必等到调用之后。
精简结果(Token)
验证结果包含答案(data)、上述句子(不包括配额行),以及回执的 ID 和 URL;错误则保留其错误信息。API 信封的其余内容(架构、端点、时间戳、声明和资本类别、人类可读页面、源文件哈希和配额行)描述的是服务而非答案,Agent 每次调用都要为其中的每个 Token 付费。这些内容仍会保留在已存储的回执中;verify_receipt 在使用 include_receipt 时会完整返回回执,service_status 也会返回这些内容。
对于 breadth 结果,这大约能减少一半文本。设置 CANLI_FULL_ENVELOPE=1 即可接收所有字段。
工具集(令牌数)
客户端每轮都会向模型发送完整的工具列表,而这通常占每轮提示词的大部分:
验证结果只有几百个令牌,而所有工具的列表则有几千个。需要某一类工具的客户端可以使用 CANLI_TOOLSETS(stdio)或
?toolsets=(托管端点)只列出该类工具。默认包含除 company 和 ledger 以外的所有工具集:company 中的单个工具 canli-fundamentals-mcp 能更好地提供时点数据;ledger 会将文件保存在你的机器上,且仅限本地使用;all 会同时添加这两个工具集。仅在未配置密钥时才会列出 get_key。
| 工具集 | 工具 |
|---|---|
validate | get_key、九个验证器、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) |
使用 bench/tool_list_tokens.py 测得(分词器:tiktoken o200k_base;其他模型的分词器得出的绝对数量会有所不同),采用 OpenAI 风格客户端发送列表时的格式:
| CANLI_TOOLSETS | 工具 | 每轮令牌数 | 占全部的比例 |
|---|---|---|---|
| (默认) | 19 | 5,978 | 85% |
| (默认,配置了 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% |
提供商会缓存每轮都相同的工具列表,并按较低费率对缓存部分计费(test/tool-list-stable.test.mjs 可确保每个列表的字节内容保持稳定);无论如何,列表越小,成本越低。
本地检出
仅在开发或测试此软件包本身时需要,运行已发布的软件包则不需要。
cd mcp
npm ci
node src/server.mjs
在上述任意配置中,将 npx -y canli-validation-mcp 替换为启动 node /absolute/path/to/meridian/mcp/src/server.mjs,即可让客户端使用本地检出版本,而非 npm 上的版本。
测试
npm test
npm run test:package
运行 node --test,测试 test/*.test.mjs:针对 API 自身的 OpenAPI 和清单示例进行架构往返测试;针对每个需要密钥的工具,分别测试一次成功、错误封装和配额 429 情况(使用模拟的 fetch 代替网络);检查每个工具描述是否都包含限制说明;检查这些说明是否与 api/_lib/limits.js 保持一致;检查发布的文件中是否不含 em dash;以及运行一项测试,启动实际服务器二进制文件,并通过 stdio 与本地 HTTP stub 完成真实的 MCP tools/list 和 callTool 握手,从而验证接线确实有效,而非仅凭假设。
test:package 会创建实际的 npm tarball,检查其文件列表和许可证是否完全符合预期,在临时的使用方目录中安装,并针对已安装的入口运行 stdio 测试。安装依赖时会连接 npm;工具调用仅使用本地 HTTP stub。此过程既不会发布软件包,也不会签发生产 API 密钥。
依赖项
仅依赖 @modelcontextprotocol/server(固定到精确版本;MCP SDK 的服务器软件包,该软件包本身仅依赖 @modelcontextprotocol/core 和 zod)以及 zod(固定到精确版本):安装后的依赖树共包含四个软件包,而 0.7 及更早版本会通过 @modelcontextprotocol/sdk 引入约 95 个软件包。不会添加其他运行时依赖;此软件包中的任何内容都不会触及站点根目录下的 package.json、.vercelignore、api/、scripts/、js/ 或 public/。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。