@zltquant/zlt-mcp 0.1.0-rc.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/config.json CHANGED
@@ -167,7 +167,7 @@
167
167
  ]
168
168
  },
169
169
  {
170
- "name": "mcp-create-tree",
170
+ "name": "mcp-create-strategy-tree",
171
171
  "description": "创建策略分类。",
172
172
  "inputSchema": {
173
173
  "type": "object",
@@ -213,7 +213,7 @@
213
213
  "timeoutParamKey": "timeout"
214
214
  },
215
215
  {
216
- "name": "mcp-get-tree",
216
+ "name": "mcp-get-strategy-tree-list",
217
217
  "description": "获取策略分类列表。treeType 为分类类型,strategy 表示默认策略树,research 表示策略研究树,默认 strategy;parentId 为父级分类 ID,可选,不传时仅按 treeType 查询。",
218
218
  "inputSchema": {
219
219
  "type": "object",
@@ -271,11 +271,11 @@
271
271
  "properties": {
272
272
  "exchange_id": {
273
273
  "type": "string",
274
- "description": "市场标识,取云端路径里的市场字符串。股票市场:sh 上交所,sz 深交所,bj 北交所。期货市场:zj 中金所,zs 郑商所,ds 大商所,sq 上期所,gq 广期所。另有 sj 上金所、bs 渤商。期货回测要下的就是这五个期货市场里对应交易所的数据。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度,本工具必须显式传 exchange_id:实测省略时上游返回空 times,会被误读成本地没有数据(本机 sh/etf 有 242 个文件,不带 exchange_id 查却是空,带上就是 2020-01-01→2020-12-31)。"
274
+ "description": "市场标识,取值与构词见 mcp-download-data 同名参数(sh/sz/bj 股票;zj/zs/ds/sq/gq 期货)。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度,本工具必须显式传 exchange_id:实测省略时上游返回空 times,会被误读成本地没有数据。"
275
275
  },
276
276
  "data_type": {
277
277
  "type": "string",
278
- "description": "数据类型 token,按不透明字符串原样使用,不要拆分或做进制转换。基础行情是「行情类型 + 证券类别码」的组合:行情类型 dk 日线、mk 分钟线、tk 快照;证券类别码 1 股票、2 债券、3 基金、4 指数、5 期货、6 期权、7 港股、d 功能。例如 dk1 日线·股票、mk5 分钟线·期货、tkd 快照·功能。非行情类别直接用 pr 专业财务、co 核心财务、mr 市场规则、etf ETF。"
278
+ "description": "数据类型 token,按不透明字符串原样使用,不要拆分。构词与全表见 mcp-download-data 同名参数;例如 dk1 日线·股票、mk5 分钟线·期货,非行情类别 pr、co、mr、etf。"
279
279
  }
280
280
  },
281
281
  "required": [
@@ -364,7 +364,7 @@
364
364
  "responseTransform": "downloadProgress"
365
365
  },
366
366
  {
367
- "name": "mcp-list-cloud-data",
367
+ "name": "mcp-get-cloud-data-list",
368
368
  "description": "查询云端可下载的数据范围,只读,不创建任务,不改本地缓存。用于回答「云端有没有这段历史」——本地 mcp-get-data-range 只说明已经下过什么,不代表上游只有这些。Data 内按序列返回 series(market、datatype、sectype、startDate、endDate、objectCount、totalBytes)、totalObjects、truncated 和 nextAction。totalBytes 是该序列云端对象的总字节数,可用来向用户说明下载量。truncated=true 表示上游还有更多对象未列出,不能当作完整范围。",
369
369
  "inputSchema": {
370
370
  "type": "object",
@@ -385,7 +385,7 @@
385
385
  "properties": {
386
386
  "exchange_id": {
387
387
  "type": "string",
388
- "description": "市场标识,取云端路径里的市场字符串。股票市场:sh 上交所,sz 深交所,bj 北交所。期货市场:zj 中金所,zs 郑商所,ds 大商所,sq 上期所,gq 广期所。另有 sj 上金所、bs 渤商。期货回测要下的就是这五个期货市场里对应交易所的数据。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度;本工具省略 exchange_id 时按全部市场展开(实测 download 取回 sh 与 sz,cloudlist 返回含两市的 3836 个对象)。注意 mcp-get-data-range 不同,那边必须显式传。"
388
+ "description": "市场标识,取值与构词见 mcp-download-data 同名参数。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度;本工具省略 exchange_id 时按全部市场展开。注意 mcp-get-data-range 不同,那边必须显式传。"
389
389
  },
390
390
  "data_type": {
391
391
  "type": "string",
@@ -436,11 +436,11 @@
436
436
  "properties": {
437
437
  "exchange_id": {
438
438
  "type": "string",
439
- "description": "市场标识,取云端路径里的市场字符串。股票市场:sh 上交所,sz 深交所,bj 北交所。期货市场:zj 中金所,zs 郑商所,ds 大商所,sq 上期所,gq 广期所。另有 sj 上金所、bs 渤商。期货回测要下的就是这五个期货市场里对应交易所的数据。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度;本工具省略 exchange_id 时按全部市场展开(实测 download 取回 sh 与 sz,cloudlist 返回含两市的 3836 个对象)。注意 mcp-get-data-range 不同,那边必须显式传。"
439
+ "description": "市场标识,取值与构词见 mcp-download-data 同名参数。财务(pr/co)和市场规则(mr)没有市场维度,省略本字段;ETF(etf)有市场维度;本工具省略 exchange_id 时按全部市场展开。注意 mcp-get-data-range 不同,那边必须显式传。"
440
440
  },
441
441
  "data_type": {
442
442
  "type": "string",
443
- "description": "数据类型 token,按不透明字符串原样使用,不要拆分或做进制转换。基础行情是「行情类型 + 证券类别码」的组合:行情类型 dk 日线、mk 分钟线、tk 快照;证券类别码 1 股票、2 债券、3 基金、4 指数、5 期货、6 期权、7 港股、d 功能。例如 dk1 日线·股票、mk5 分钟线·期货、tkd 快照·功能。非行情类别直接用 pr 专业财务、co 核心财务、mr 市场规则、etf ETF。"
443
+ "description": "数据类型 token,按不透明字符串原样使用,不要拆分。构词与全表见 mcp-download-data 同名参数;例如 dk1 日线·股票、mk5 分钟线·期货,非行情类别 pr、co、mr、etf。"
444
444
  }
445
445
  },
446
446
  "required": [
@@ -507,7 +507,7 @@
507
507
  },
508
508
  {
509
509
  "name": "mcp-create-and-run-backtest",
510
- "description": "创建并启动回测。strategyId 必须来自 mcp-create-strategy 返回的策略ID;runType 固定为 2;普通日线回测只传 strategyId,其余参数 MCP 补齐。未指定周期时 end 取自然日 T-1、start 从 end 往前推半年;ZLTAF 按实际交易日执行,非交易日不产生行情或策略调用。run/create 失败直接报错,不要去复用策略里自动生成的 debug runId(建策略时已回显为 debugRunId,跑它等于跑创建那一刻的模板快照)。\n\n日线类频率只可见到 context.previous_date:要用交易日 T 的收盘,end 必须设成 T 的下一个交易日;end 落在未来不报错但结果为空。展开见返回的 dailyVisibilityNote / endWarning。\n\n返回 Data 回显 resolvedStart/resolvedEnd/resolvedCapital——向用户汇报区间和初始资金时一律以这些字段为准,不要自行推算或臆测。**基准不在此列**:回显的 requestedBenchmark 只是请求值,策略 initialize 里的 set_benchmark() 会覆盖它,收益产物里的「基准收益」按策略实际用的基准算。说基准是什么之前先读策略代码里的 set_benchmark,否则会把一只个股的涨跌报成指数的。\n\n**期货回测要同时改三处,少一处引擎就按股票跑**:runParams.marketIds 加上对应期货交易所(zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所),account_list 的 account_type 改成 2(实测用 6 直接废单),费率用 ratio_tpl_obj.future。合约代码形如 zjIM2605。基准保持默认 sz399300 即可,它对期货策略只是业绩比较基准。数据前置见 mcp-download-data:除行情外还必须有市场规则 mr。",
510
+ "description": "创建并启动回测。strategyId 必须来自 mcp-create-strategy 返回的策略ID;runType 固定为 2;普通日线回测只传 strategyId,其余参数 MCP 补齐。未指定周期时 end 取自然日 T-1、start 从 end 往前推半年;ZLTAF 按实际交易日执行,非交易日不产生行情或策略调用。run/create 失败直接报错,不要去复用策略里自动生成的 debug runId(建策略时已回显为 debugRunId,跑它等于跑创建那一刻的模板快照)。\n\n**返回 runId 后立即调用 mcp-wait(kind=backtest,id=runId)阻塞等待回测结束,不要用 mcp-get-backtest-state 轮询。**\n\n日线类频率只可见到 context.previous_date:要用交易日 T 的收盘,end 必须设成 T 的下一个交易日;end 落在未来不报错但结果为空。展开见返回的 dailyVisibilityNote / endWarning。\n\n返回 Data 回显 resolvedStart/resolvedEnd/resolvedCapital——向用户汇报区间和初始资金时一律以这些字段为准,不要自行推算或臆测。**基准不在此列**:回显的 requestedBenchmark 只是请求值,策略 initialize 里的 set_benchmark() 会覆盖它,收益产物里的「基准收益」按策略实际用的基准算。说基准是什么之前先读策略代码里的 set_benchmark,否则会把一只个股的涨跌报成指数的。\n\n**期货回测要同时改三处,少一处引擎就按股票跑**:runParams.marketIds 加上对应期货交易所(zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所),account_list 的 account_type 改成 2(实测用 6 直接废单),费率用 ratio_tpl_obj.future。合约代码形如 zjIM2605。基准保持默认 sz399300 即可,它对期货策略只是业绩比较基准。数据前置见 mcp-download-data:除行情外还必须有市场规则 mr。",
511
511
  "inputSchema": {
512
512
  "type": "object",
513
513
  "properties": {
@@ -529,7 +529,7 @@
529
529
  },
530
530
  "runParams": {
531
531
  "type": "object",
532
- "description": "回测参数。未传时应按各字段默认值组装;日期字段按用户描述动态计算。",
532
+ "description": "回测参数。普通日线回测可整体不传,MCP 按系统默认组装(含参数/费率模板与回测模式等服务端默认);要改哪项传哪项,日期字段按用户描述动态计算。",
533
533
  "properties": {
534
534
  "account_list": {
535
535
  "type": "array",
@@ -568,7 +568,7 @@
568
568
  7
569
569
  ],
570
570
  "default": 1,
571
- "description": "账号类型。1 表示股票,2 表示期货,6 表示金融期货,7 表示融资融券。默认 1 只适用于股票回测:账号类型必须和 runParams.marketIds 里的市场对得上,做期货回测(marketIds 含 zj/zs/ds/sq/gq)时要显式改。**实测取 2**:中金所股指期货 zjIF2403 用 account_type=2 能通过引擎的合约类型校验,用 6 会被判「帐号类型与合约编码类型不匹配」并直接废单。6(金融期货)适用于哪些合约尚未实测,没有把握就用 2。卖空只有期货类账号支持,股票/ETF 账号下单 side=short 会被 SDK 直接拒绝。"
571
+ "description": "账号类型:1 股票、2 期货、6 金融期货、7 融资融券,必须和 runParams.marketIds 的市场对得上。期货回测**实测取 2**(中金所股指期货 zjIF2403 用 account_type=2 通过校验,用 6 被判「帐号类型与合约编码类型不匹配」直接废单;6 适用面未实测,没把握就用 2)。卖空只有期货类账号支持。"
572
572
  }
573
573
  },
574
574
  "required": [
@@ -605,237 +605,18 @@
605
605
  "default": "day",
606
606
  "description": "回测频率。day 表示日频,min 表示分钟,tick 表示逐笔。省略时默认 day。"
607
607
  },
608
- "btmode": {
609
- "type": "integer",
610
- "default": 3,
611
- "description": "回测模式,默认 3。"
612
- },
613
608
  "kcount": {
614
609
  "type": "integer",
615
610
  "default": 400,
616
611
  "description": "预加载 K 线条数,默认 400。"
617
612
  },
618
- "base_tpl_id": {
619
- "type": "string",
620
- "default": "defaultTpl",
621
- "description": "参数模板 ID,默认 defaultTpl。"
622
- },
623
- "ratio_tpl_id": {
624
- "type": "string",
625
- "default": "defaultTpl",
626
- "description": "费率模板 ID,默认 defaultTpl。"
627
- },
628
613
  "base_tpl_obj": {
629
614
  "type": "object",
630
- "description": "参数模板对象,默认使用系统默认参数模板。",
631
- "properties": {
632
- "name": {
633
- "type": "string",
634
- "default": "defaultTpl",
635
- "description": "模板名称。"
636
- },
637
- "zhCnName": {
638
- "type": "string",
639
- "default": "系统默认参数模板",
640
- "description": "模板中文名称。"
641
- },
642
- "benchmark": {
643
- "type": "string",
644
- "default": "sz399300",
645
- "description": "基准代码。"
646
- },
647
- "match_with_order_book": {
648
- "type": "boolean",
649
- "default": false,
650
- "description": "是否按委托簿撮合。"
651
- },
652
- "matching_mode": {
653
- "type": "string",
654
- "default": "close",
655
- "description": "撮合模式,默认 close。"
656
- },
657
- "avoid_future": {
658
- "type": "boolean",
659
- "default": true,
660
- "description": "是否开启未来函数规避。"
661
- },
662
- "open_cache": {
663
- "type": "boolean",
664
- "default": true,
665
- "description": "是否开启缓存。"
666
- },
667
- "jv_kuan_open_avg_cost_switch": {
668
- "type": "string",
669
- "default": "1",
670
- "description": "开仓均价成本开关。"
671
- },
672
- "adjust_aqty_by_avail": {
673
- "type": "string",
674
- "default": "3",
675
- "description": "按可用量调整委托数量配置。"
676
- },
677
- "take_fee_type": {
678
- "type": "string",
679
- "default": "1",
680
- "description": "费用收取类型。"
681
- },
682
- "slippage": {
683
- "type": "string",
684
- "default": "0.00246",
685
- "description": "滑点配置。"
686
- },
687
- "max_trade_ratio": {
688
- "type": "string",
689
- "default": "1.0",
690
- "description": "最大交易比例。"
691
- },
692
- "order_volume_ratio": {
693
- "type": "boolean",
694
- "default": true,
695
- "description": "是否按委托量比例处理。"
696
- }
697
- },
698
- "additionalProperties": false
615
+ "description": "参数模板,整体可不传,MCP 按系统默认模板补齐;要改哪项传哪项,其余沿用默认。字段:benchmark(默认 sz399300,会被策略 set_benchmark 覆盖)、matching_mode、slippage(默认 0.00246)、avoid_future、open_cache、match_with_order_book、max_trade_ratio、order_volume_ratio、take_fee_type、adjust_aqty_by_avail、jv_kuan_open_avg_cost_switch。"
699
616
  },
700
617
  "ratio_tpl_obj": {
701
618
  "type": "object",
702
- "description": "费率模板对象,默认使用系统默认费率模板。",
703
- "properties": {
704
- "name": {
705
- "type": "string",
706
- "default": "defaultTpl",
707
- "description": "模板名称。"
708
- },
709
- "zhCnName": {
710
- "type": "string",
711
- "default": "系统默认费率模板",
712
- "description": "模板中文名称。"
713
- },
714
- "stock": {
715
- "type": "object",
716
- "description": "股票费率配置。",
717
- "properties": {
718
- "open_commission": {
719
- "type": "string",
720
- "default": "3",
721
- "description": "开仓佣金。"
722
- },
723
- "close_commission": {
724
- "type": "string",
725
- "default": "3",
726
- "description": "平仓佣金。"
727
- },
728
- "min_commission": {
729
- "type": "string",
730
- "default": "5",
731
- "description": "最低佣金。"
732
- },
733
- "open_tax": {
734
- "type": "string",
735
- "default": "0",
736
- "description": "开仓税费。"
737
- },
738
- "close_tax": {
739
- "type": "string",
740
- "default": "1",
741
- "description": "平仓税费。"
742
- }
743
- },
744
- "additionalProperties": false
745
- },
746
- "future": {
747
- "type": "object",
748
- "description": "期货费率配置。",
749
- "properties": {
750
- "open_commission": {
751
- "type": "string",
752
- "default": "0.23",
753
- "description": "开仓佣金。"
754
- },
755
- "close_commission": {
756
- "type": "string",
757
- "default": "0.23",
758
- "description": "平仓佣金。"
759
- },
760
- "close_today_commission": {
761
- "type": "string",
762
- "default": "23",
763
- "description": "平今佣金。"
764
- },
765
- "min_commission": {
766
- "type": "string",
767
- "default": "0",
768
- "description": "最低佣金。"
769
- },
770
- "margin_ratio": {
771
- "type": "string",
772
- "default": "12",
773
- "description": "保证金比例。"
774
- }
775
- },
776
- "additionalProperties": false
777
- },
778
- "fund": {
779
- "type": "object",
780
- "description": "基金费率配置。",
781
- "properties": {
782
- "open_commission": {
783
- "type": "string",
784
- "default": "0.1",
785
- "description": "申购佣金。"
786
- },
787
- "close_commission": {
788
- "type": "string",
789
- "default": "0.1",
790
- "description": "赎回佣金。"
791
- },
792
- "min_commission": {
793
- "type": "string",
794
- "default": "5",
795
- "description": "最低佣金。"
796
- }
797
- },
798
- "additionalProperties": false
799
- },
800
- "bond": {
801
- "type": "object",
802
- "description": "债券费率配置。",
803
- "properties": {
804
- "open_commission": {
805
- "type": "string",
806
- "default": "0.3",
807
- "description": "买入佣金。"
808
- },
809
- "close_commission": {
810
- "type": "string",
811
- "default": "0.3",
812
- "description": "卖出佣金。"
813
- },
814
- "min_commission": {
815
- "type": "string",
816
- "default": "5",
817
- "description": "最低佣金。"
818
- }
819
- },
820
- "additionalProperties": false
821
- }
822
- },
823
- "additionalProperties": false
824
- },
825
- "st_parmas": {
826
- "type": "string",
827
- "default": "[]",
828
- "description": "策略参数 JSON 字符串,默认 []。"
829
- },
830
- "mode": {
831
- "type": "string",
832
- "default": "0",
833
- "description": "运行模式,默认 0。"
834
- },
835
- "class_type": {
836
- "type": "string",
837
- "default": "1",
838
- "description": "分类类型,默认 1。"
619
+ "description": "费率模板,整体可不传,MCP 按系统默认模板补齐;要改哪项传哪项。按资产类分节:stock/future/fund/bond 各含 open_commission、close_commission、min_commission;stock 另有 open_tax、close_tax;future 另有 close_today_commission、margin_ratio。期货费率在 future 节。"
839
620
  },
840
621
  "marketIds": {
841
622
  "type": "array",
@@ -843,7 +624,7 @@
843
624
  "sh",
844
625
  "sz"
845
626
  ],
846
- "description": "市场列表,决定策略引擎加载哪些市场的行情,默认 sh + sz(股票)。股票市场:sh 上交所、sz 深交所。期货市场:zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所。**做期货回测必须把对应的期货交易所写进来**,只留 sh/sz 引擎就取不到期货行情。期货与股票可以同时列出做跨品种策略。市场一旦包含期货交易所,account_list 里要有 account_type=2(期货,实测中金所股指期货用 2;用 6 会被判「帐号类型与合约编码类型不匹配」)的账号,费率用 ratio_tpl_obj.future,并且本地要先备好该交易所的期货日线(dk5)或分钟线(mk5)以及市场规则(mr)数据——用 mcp-get-data-range 查、mcp-download-data 补。",
627
+ "description": "市场列表,决定策略引擎加载哪些市场的行情,默认 sh + sz(股票)。期货市场:zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所。**做期货回测必须把对应的期货交易所写进来**(只留 sh/sz 引擎取不到期货行情),且 account_list 要有 account_type=2 的期货账号、费率用 ratio_tpl_obj.future、数据前置(dk5/mk5 与 mr)见 mcp-download-data。期货与股票可同时列出做跨品种策略。",
847
628
  "items": {
848
629
  "type": "string",
849
630
  "enum": [
@@ -876,6 +657,59 @@
876
657
  ],
877
658
  "additionalProperties": false
878
659
  },
660
+ "bodyDefaults": {
661
+ "runParams": {
662
+ "btmode": 3,
663
+ "base_tpl_id": "defaultTpl",
664
+ "ratio_tpl_id": "defaultTpl",
665
+ "st_parmas": "[]",
666
+ "mode": "0",
667
+ "class_type": "1",
668
+ "base_tpl_obj": {
669
+ "name": "defaultTpl",
670
+ "zhCnName": "系统默认参数模板",
671
+ "benchmark": "sz399300",
672
+ "match_with_order_book": false,
673
+ "matching_mode": "close",
674
+ "avoid_future": true,
675
+ "open_cache": true,
676
+ "jv_kuan_open_avg_cost_switch": "1",
677
+ "adjust_aqty_by_avail": "3",
678
+ "take_fee_type": "1",
679
+ "slippage": "0.00246",
680
+ "max_trade_ratio": "1.0",
681
+ "order_volume_ratio": true
682
+ },
683
+ "ratio_tpl_obj": {
684
+ "name": "defaultTpl",
685
+ "zhCnName": "系统默认费率模板",
686
+ "stock": {
687
+ "open_commission": "3",
688
+ "close_commission": "3",
689
+ "min_commission": "5",
690
+ "open_tax": "0",
691
+ "close_tax": "1"
692
+ },
693
+ "future": {
694
+ "open_commission": "0.23",
695
+ "close_commission": "0.23",
696
+ "close_today_commission": "23",
697
+ "min_commission": "0",
698
+ "margin_ratio": "12"
699
+ },
700
+ "fund": {
701
+ "open_commission": "0.1",
702
+ "close_commission": "0.1",
703
+ "min_commission": "5"
704
+ },
705
+ "bond": {
706
+ "open_commission": "0.3",
707
+ "close_commission": "0.3",
708
+ "min_commission": "5"
709
+ }
710
+ }
711
+ }
712
+ },
879
713
  "ipcUri": "/zltaf_slave/v1/run/create",
880
714
  "bodyFromParams": true,
881
715
  "timeoutParamKey": "timeout",
@@ -907,7 +741,7 @@
907
741
  },
908
742
  {
909
743
  "name": "mcp-re-backtest",
910
- "description": "重新运行会话中最新的回测:用同一个 runId 重跑**该次回测已生成的代码快照**(策略工程 backtest/ 目录下那份副本)。\n\n**它不会把你在策略源工程里刚改过的 main.py 拷进去**——刚编辑过源代码就必须改用 mcp-create-and-run-backtest 生成新的代码快照,否则会重复运行修改前的旧代码,表现为「源码已修复却仍报同样的错误」。所以本工具只适合调整 runParams(回测区间、资金等)后重跑。\n\nstrategyId、strategyName、runId、runType、runParams 从当前会话最近一次 mcp-create-and-run-backtest 的成功结果里取得并传入本工具,不需要用户手动输入;会话中没有运行结果就提示无回测,无法重新回测。runParams 默认沿用最近一次创建回测的条件,允许用户修改部分回测参数;MCP 重启后这份上下文会丢失,届时必须传完整 runParams。返回的 resolved* 是本次实际生效的区间、资金与基准,向用户报告时以它为准。",
744
+ "description": "重新运行会话中最新的回测:用同一个 runId 重跑**该次回测已生成的代码快照**(策略工程 backtest/ 目录下那份副本)。\n\n**它不会把你在策略源工程里刚改过的 main.py 拷进去**——刚编辑过源代码就必须改用 mcp-create-and-run-backtest 生成新的代码快照,否则会重复运行修改前的旧代码,表现为「源码已修复却仍报同样的错误」。所以本工具只适合调整 runParams(回测区间、资金等)后重跑。\n\nstrategyId、strategyName、runId、runType、runParams 从当前会话最近一次 mcp-create-and-run-backtest 的成功结果里取得并传入本工具,不需要用户手动输入;会话中没有运行结果就提示无回测,无法重新回测。runParams 默认沿用最近一次创建回测的条件,允许用户修改部分回测参数;MCP 重启后这份上下文会丢失,届时必须传完整 runParams。返回的 resolved* 是本次实际生效的区间、资金与基准,向用户报告时以它为准。\n\n重跑启动后同样立即调用 mcp-wait(kind=backtest,id=runId)阻塞等待结束,不要轮询状态。",
911
745
  "inputSchema": {
912
746
  "type": "object",
913
747
  "properties": {
@@ -933,83 +767,10 @@
933
767
  },
934
768
  "runParams": {
935
769
  "type": "object",
936
- "description": "回测参数。默认沿用最近一次创建回测的条件,用户只需要说明想修改的字段;没传的字段(含基准、撮合模式、滑点、费率模板这些本 schema 表达不了的)都按上一次原样继承。MCP 重启会丢掉这份上下文,之后必须传完整参数,否则会以「缺少必填字段」失败。",
770
+ "description": "回测参数,与 mcp-create-and-run-backtest 的 runParams 同构,字段说明见该工具。默认沿用最近一次创建回测的条件,用户只需要说明想修改的字段,没传的字段(含基准、撮合模式、滑点、费率模板)都按上一次原样继承;MCP 重启会丢掉这份上下文,之后必须传完整参数,否则会以「缺少必填字段」失败。改用期货市场(marketIds 含 zj/zs/ds/sq/gq)时,account_list 的 account_type 要一并改为 2(期货)。",
937
771
  "properties": {
938
- "account_list": {
939
- "type": "array",
940
- "description": "回测账号列表。未传时沿用最近一次回测的账号配置。",
941
- "items": {
942
- "type": "object",
943
- "properties": {
944
- "pindex": {
945
- "type": "integer",
946
- "description": "账号数组下标,按 account_list 的数组 index 自动生成,无需用户设置。"
947
- },
948
- "account_id": {
949
- "type": "string",
950
- "description": "账号 ID,默认空字符串,无需用户设置。"
951
- },
952
- "cash": {
953
- "type": "number",
954
- "description": "账号初始资金,用户可修改。"
955
- },
956
- "account_type": {
957
- "type": "integer",
958
- "enum": [
959
- 1,
960
- 2,
961
- 6,
962
- 7
963
- ],
964
- "description": "账号类型。1 表示股票,2 表示期货,6 表示金融期货,7 表示融资融券。"
965
- }
966
- },
967
- "additionalProperties": false
968
- }
969
- },
970
- "initial_capital": {
971
- "type": "number",
972
- "description": "初始资金。未传时沿用最近一次回测的配置。"
973
- },
974
- "start": {
975
- "type": "string",
976
- "format": "date",
977
- "description": "回测开始日期(北京时区),格式 YYYY-MM-DD。未传时沿用最近一次回测的配置。"
978
- },
979
- "end": {
980
- "type": "string",
981
- "format": "date",
982
- "description": "回测结束日期(北京时区),格式 YYYY-MM-DD。未传时沿用最近一次回测的配置。"
983
- },
984
- "freq": {
985
- "type": "string",
986
- "enum": [
987
- "day",
988
- "min",
989
- "tick"
990
- ],
991
- "description": "回测频率。day 表示日频,min 表示分钟,tick 表示逐笔。"
992
- },
993
- "trade_type": {
994
- "type": "integer",
995
- "enum": [
996
- 0,
997
- 1,
998
- 2
999
- ],
1000
- "description": "撮合频率。0 表示分钟 min,1 表示 tick,2 表示日线 day。"
1001
- },
1002
- "btmode": {
1003
- "type": "integer",
1004
- "description": "回测模式。未传时沿用最近一次回测的配置。"
1005
- },
1006
- "kcount": {
1007
- "type": "integer",
1008
- "description": "预加载 K 线条数。未传时沿用最近一次回测的配置。"
1009
- },
1010
772
  "marketIds": {
1011
773
  "type": "array",
1012
- "description": "市场列表。未传时沿用最近一次回测的配置。股票市场 sh 上交所、sz 深交所;期货市场 zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所。改成期货市场时,account_list 的 account_type 也要一并改为 2(期货)。",
1013
774
  "items": {
1014
775
  "type": "string",
1015
776
  "enum": [
@@ -1024,7 +785,7 @@
1024
785
  }
1025
786
  }
1026
787
  },
1027
- "additionalProperties": false
788
+ "additionalProperties": true
1028
789
  }
1029
790
  },
1030
791
  "required": [
@@ -1128,7 +889,7 @@
1128
889
  },
1129
890
  {
1130
891
  "name": "mcp-get-backtest-state",
1131
- "description": "查询回测运行状态与进度。立即返回:只做一次查询,不会阻塞等待状态变化。status:0 准备中/1 运行中/2 失败/3 取消/4 终止/5 完成;status=5 前不要调用收益查询。\n\n未进终态时返回一定带 nextPollAfterMs:按它等待后再查一次,不要自己拍一个间隔,也不要用 shell sleep 空转;终态不带该字段。数据准备阶段的进度取自磁盘 result.json,只要 download_update_time 仍在推进就视为有进展;durationSeconds 变化不算进展。若实际工作状态连续无变化但数据准备刚更新,返回 dataPrepInProgress=true,继续等待再查一次;若数据准备也已停滞,返回 pollingStopped=true、stopAutoPolling=true 和 manualRecheckAfterMs,此时暂停自动轮询、约 1 分钟后手动再查一次,不要密集轮询。若磁盘 result.json 已确认数据准备或策略引擎启动失败,即使 IPC 仍报 status=1,也会返回 ErrNo 10043 让你停止。",
892
+ "description": "查询回测运行状态与进度,是手动/兜底查询入口:适用于用户主动询问进度,或 mcp-wait 异常中断后复查。**等回测结束请用 mcp-wait(kind=backtest,id=runId),不要用本工具循环轮询。** 立即返回:只做一次查询,不会阻塞等待状态变化。status:0 准备中/1 运行中/2 失败/3 取消/4 终止/5 完成;status=5 前不要调用收益查询。\n\n兜底查询时未进终态的返回一定带 nextPollAfterMs,那是 wait 不可用时的节奏参考;终态不带该字段。数据准备阶段的进度取自磁盘 result.json,只要 download_update_time 仍在推进就视为有进展;durationSeconds 变化不算进展。若实际工作状态连续无变化但数据准备刚更新,返回 dataPrepInProgress=true;若数据准备也已停滞,返回 pollingStopped=true、stopAutoPolling=true 和 manualRecheckAfterMs,此时停止查询、约 1 分钟后手动再查一次。若磁盘 result.json 已确认数据准备或策略引擎启动失败,即使 IPC 仍报 status=1,也会返回 ErrNo 10043 让你停止。",
1132
893
  "inputSchema": {
1133
894
  "type": "object",
1134
895
  "properties": {
@@ -1233,7 +994,7 @@
1233
994
  "timeoutParamKey": "timeout"
1234
995
  },
1235
996
  {
1236
- "name": "mcp-get-st-for-backtest-list",
997
+ "name": "mcp-get-backtest-list",
1237
998
  "description": "查询指定策略ID数组对应的回测列表,返回回测ID、名称、回测周期、回测状态与回测时间——**不要展示收益相关的信息**。pageSize 与 runType 是固定值,必须显式传入,不要依赖 default 自动补值。",
1238
999
  "inputSchema": {
1239
1000
  "type": "object",
@@ -1334,6 +1095,33 @@
1334
1095
  },
1335
1096
  "ipcUri": "/zltaf_slave/v1/strategy/open-vscode",
1336
1097
  "bodyFromParams": true
1098
+ },
1099
+ {
1100
+ "name": "mcp-wait",
1101
+ "description": "阻塞等待一个异步任务结束,直到需要 agent 行动的状态才返回。kind=backtest 等回测,id 传 mcp-create-and-run-backtest / mcp-re-backtest 返回的 runId;kind=download 等数据下载,id 传 mcp-download-data 返回的 uuid(传 \"0\" 等本机当前最新下载任务)。拿到任务 id 后应立即调用本工具,等待期间不要做任何其他事、不要轮询状态。\n\nkind=backtest 返回与 mcp-get-backtest-state 相同的终态结果(status 2 失败/3 取消/4 终止/5 完成;status=5 才能查收益)。\n\nkind=download 返回与 mcp-get-download-progress 相同的结果,按其中 nextAction 行动。除下载中以外的任何状态都会立即返回:resume-required / await-credential / report-stopped 表示任务不会自己结束,需要用户决定。\n\n任一 kind 带 waitStopped=no-progress 表示约 3 分钟毫无进展、先交回现状(回测可能仍在准备数据);可用对应状态工具复查一次,再调用本工具继续等。",
1102
+ "inputSchema": {
1103
+ "type": "object",
1104
+ "properties": {
1105
+ "kind": {
1106
+ "type": "string",
1107
+ "enum": [
1108
+ "backtest",
1109
+ "download"
1110
+ ],
1111
+ "description": "任务类别:backtest 回测,download 数据下载。"
1112
+ },
1113
+ "id": {
1114
+ "type": "string",
1115
+ "description": "任务标识:kind=backtest 传 runId;kind=download 传 uuid(\"0\" 表示本机当前最新下载任务)。"
1116
+ }
1117
+ },
1118
+ "required": [
1119
+ "kind",
1120
+ "id"
1121
+ ],
1122
+ "additionalProperties": false
1123
+ },
1124
+ "timeoutMs": 15000
1337
1125
  }
1338
1126
  ]
1339
1127
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zltquant/zlt-mcp",
3
- "version": "0.1.0-rc.0",
3
+ "version": "0.1.0",
4
4
  "description": "智量通 ZLT Quant MCP server(Windows x64;量化策略创建与本地回测)",
5
5
  "bin": {
6
6
  "zlt-mcp": "./zlt-mcp-proxy.bundle.cjs"
@@ -20834,11 +20834,22 @@ var UNIVERSAL_AGENT_IPC_TOOL_NAMES = Object.freeze([
20834
20834
  "mcp-get-strategy-list",
20835
20835
  "mcp-create-and-run-backtest",
20836
20836
  "mcp-re-backtest",
20837
- "mcp-get-st-for-backtest-list",
20837
+ "mcp-get-backtest-list",
20838
20838
  "mcp-stop-backtest",
20839
20839
  "mcp-get-backtest-state",
20840
20840
  "mcp-get-backtest-profit",
20841
- "mcp-delete-strategy"
20841
+ "mcp-delete-strategy",
20842
+ // Data workflow + blocking wait, opened to the universal lane 2026-08-26.
20843
+ // The six ship together: download-data's contract points at data-range
20844
+ // (gap check), disk-space (mr/etf confirmation), and mcp-wait (blocking
20845
+ // wait); get-download-progress is wait's early-return fallback; stop-download
20846
+ // is the cancel valve. Listing a subset ships guidance at unreachable tools.
20847
+ "mcp-get-data-range",
20848
+ "mcp-download-data",
20849
+ "mcp-get-download-progress",
20850
+ "mcp-get-data-disk-space",
20851
+ "mcp-stop-download",
20852
+ "mcp-wait"
20842
20853
  ]);
20843
20854
  var UNIVERSAL_AGENT_TOOL_NAMES = Object.freeze([
20844
20855
  ...UNIVERSAL_AGENT_RUNTIME_TOOL_NAMES,
@@ -20849,12 +20860,12 @@ var NPM_PACKAGE_CONFIG_TOOL_NAMES = Object.freeze([
20849
20860
  "mcp-strategy-get-template-list",
20850
20861
  "mcp-create-strategy-with-template",
20851
20862
  "mcp-create-strategy",
20852
- "mcp-create-tree",
20853
- "mcp-get-tree",
20863
+ "mcp-create-strategy-tree",
20864
+ "mcp-get-strategy-tree-list",
20854
20865
  "mcp-get-data-range",
20855
20866
  "mcp-download-data",
20856
20867
  "mcp-get-download-progress",
20857
- "mcp-list-cloud-data",
20868
+ "mcp-get-cloud-data-list",
20858
20869
  "mcp-get-cache-diff",
20859
20870
  "mcp-get-data-disk-space",
20860
20871
  "mcp-stop-download",
@@ -20865,9 +20876,10 @@ var NPM_PACKAGE_CONFIG_TOOL_NAMES = Object.freeze([
20865
20876
  "mcp-get-backtest-profit",
20866
20877
  "mcp-get-backtest-entrust",
20867
20878
  "mcp-get-strategy-list",
20868
- "mcp-get-st-for-backtest-list",
20879
+ "mcp-get-backtest-list",
20869
20880
  "mcp-delete-strategy",
20870
- "mcp-open-vscode"
20881
+ "mcp-open-vscode",
20882
+ "mcp-wait"
20871
20883
  ]);
20872
20884
 
20873
20885
  // src/tool-pipeline.ts
@@ -22464,6 +22476,25 @@ function applySchemaDefaults(schema, value) {
22464
22476
  }
22465
22477
  return result;
22466
22478
  }
22479
+ function applyBodyDefaults(defaults, value) {
22480
+ if (!isRecord2(defaults)) return value;
22481
+ if (value === void 0) return cloneDefaultValue(defaults);
22482
+ if (!isRecord2(value)) return value;
22483
+ const result = { ...value };
22484
+ for (const [key, defaultValue] of Object.entries(defaults)) {
22485
+ const has = Object.prototype.hasOwnProperty.call(value, key) && value[key] !== void 0;
22486
+ if (!has) {
22487
+ result[key] = cloneDefaultValue(defaultValue);
22488
+ } else if (isRecord2(defaultValue) && isRecord2(value[key])) {
22489
+ result[key] = applyBodyDefaults(defaultValue, value[key]);
22490
+ }
22491
+ }
22492
+ return result;
22493
+ }
22494
+ function applyToolArgDefaults(tool, args) {
22495
+ const schemaDefaulted = applySchemaDefaults(tool.inputSchema, args);
22496
+ return applyBodyDefaults(tool.bodyDefaults, schemaDefaulted);
22497
+ }
22467
22498
  function cloneDefaultValue(value) {
22468
22499
  if (Array.isArray(value)) {
22469
22500
  return value.map((item) => cloneDefaultValue(item));
@@ -23941,8 +23972,19 @@ async function startMcpServer() {
23941
23972
  inputSchema: t.inputSchema
23942
23973
  }))
23943
23974
  }));
23944
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
23975
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
23945
23976
  const { name, arguments: args } = request.params;
23977
+ const progressToken = request.params._meta?.progressToken;
23978
+ const waitControl = {
23979
+ heartbeat: progressToken === void 0 ? void 0 : (progress) => {
23980
+ void extra.sendNotification({
23981
+ method: "notifications/progress",
23982
+ params: { progressToken, progress, total: 100 }
23983
+ }).catch(() => {
23984
+ });
23985
+ },
23986
+ abortSignal: extra.signal
23987
+ };
23946
23988
  const tool = callableTools.find((t) => t.name === name);
23947
23989
  if (!tool) {
23948
23990
  return {
@@ -23950,7 +23992,7 @@ async function startMcpServer() {
23950
23992
  isError: true
23951
23993
  };
23952
23994
  }
23953
- const defaultedToolArgs = applySchemaDefaults(tool.inputSchema, args ?? {});
23995
+ const defaultedToolArgs = applyToolArgDefaults(tool, args ?? {});
23954
23996
  const preparedArgs = prepareToolArgs(tool, defaultedToolArgs, backtestRunContexts);
23955
23997
  if ("content" in preparedArgs) return preparedArgs;
23956
23998
  const toolArgs = preparedArgs;
@@ -24022,7 +24064,14 @@ async function startMcpServer() {
24022
24064
  repairHint: withRuntimeRepairHint
24023
24065
  };
24024
24066
  const dataRoots = tool.responseTransform === "dataRange" ? resolveDataRoots(readiness.clientRootDir) : void 0;
24025
- const special = await dispatchSpecialTool(tool, toolArgs, ipcClient, timeout, session);
24067
+ const special = await dispatchSpecialTool(
24068
+ tool,
24069
+ toolArgs,
24070
+ ipcClient,
24071
+ timeout,
24072
+ session,
24073
+ tool.name === "mcp-wait" ? waitControl : void 0
24074
+ );
24026
24075
  if (special) return special;
24027
24076
  if (tool.steps && tool.steps.length > 0) {
24028
24077
  const result = await executeSteps(tool.steps, ipcClient, stripControlParams(toolArgs), timeout, withRuntimeRepairHint);