@zltquant/zlt-mcp 0.7.4 → 0.7.5

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
@@ -1077,7 +1077,7 @@
1077
1077
  },
1078
1078
  {
1079
1079
  "name": "mcp-get-strategy-list",
1080
- "description": "查询本地策略列表(只展示 templateVal=strategy 的数据),返回策略ID、名称、类型、本地路径等。treeId 是策略分类(folder)ID:默认 1(用户策略默认所在文件夹);传其他值只查该分类;传 0 则跨所有分类聚合并按 strategyId 去重(ZLTAF 原生 treeId=0 查不到数据,聚合由 MCP 实现)。status 固定为 0,必须显式传入。",
1080
+ "description": "查询本地策略列表(只展示 templateVal=strategy 的数据),默认只返回定位字段,其他字段用 fields 点名(见 disclosure.availableFields)。treeId 是策略分类(folder)ID:默认 1(用户策略默认所在文件夹);传其他值只查该分类;传 0 则跨所有分类聚合并按 strategyId 去重(ZLTAF 原生 treeId=0 查不到数据,聚合由 MCP 实现)。status 固定为 0,必须显式传入。",
1081
1081
  "inputSchema": {
1082
1082
  "type": "object",
1083
1083
  "properties": {
@@ -1118,7 +1118,7 @@
1118
1118
  "type": "string",
1119
1119
  "maxLength": 128
1120
1120
  },
1121
- "description": "代理层按需保留的顶层字段名,不发送给上游;省略时保留原字段。"
1121
+ "description": "代理层按需保留的顶层字段名,不发送给上游;省略时只返回默认五个字段,传入则完全按所列字段返回。"
1122
1122
  }
1123
1123
  },
1124
1124
  "required": [
@@ -1132,7 +1132,7 @@
1132
1132
  },
1133
1133
  {
1134
1134
  "name": "mcp-get-backtest-list",
1135
- "description": "查询指定策略ID数组对应的回测列表,返回回测ID、名称、回测周期、回测状态与回测时间——**不要展示收益相关的信息**。pageSize 与 runType 是固定值,必须显式传入,不要依赖 default 自动补值。",
1135
+ "description": "查询指定策略ID数组对应的回测列表——**不要展示收益相关的信息**。默认只返回定位字段(code 即 codePath),其他字段用 fields 点名(见 disclosure.availableFields)。pageSize 与 runType 必须显式传入,不要依赖 default 自动补值。",
1136
1136
  "inputSchema": {
1137
1137
  "type": "object",
1138
1138
  "properties": {
@@ -1152,11 +1152,10 @@
1152
1152
  },
1153
1153
  "pageSize": {
1154
1154
  "type": "integer",
1155
- "enum": [
1156
- 100
1157
- ],
1158
- "default": 100,
1159
- "description": "每页数量,固定为 100,必须显式传入。不要依赖 default 自动补值。"
1155
+ "minimum": 1,
1156
+ "maximum": 100,
1157
+ "default": 20,
1158
+ "description": "每页数量,传 20;最大 100。必须显式传入,不要依赖 default 自动补值。"
1160
1159
  },
1161
1160
  "runType": {
1162
1161
  "type": "integer",
@@ -1165,6 +1164,15 @@
1165
1164
  ],
1166
1165
  "default": 2,
1167
1166
  "description": "回测运行类型,固定为 2,必须显式传入。不要依赖 default 自动补值。"
1167
+ },
1168
+ "fields": {
1169
+ "type": "array",
1170
+ "maxItems": 50,
1171
+ "items": {
1172
+ "type": "string",
1173
+ "maxLength": 128
1174
+ },
1175
+ "description": "代理层按需保留的顶层字段名,不发送给上游;省略时只返回默认八个字段,传入则完全按所列字段返回。"
1168
1176
  }
1169
1177
  },
1170
1178
  "required": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zltquant/zlt-mcp",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "智量通 ZLT Quant MCP server(Windows x64;量化策略创建与本地回测)",
5
5
  "bin": {
6
6
  "zlt-mcp": "./zlt-mcp-proxy.bundle.cjs"
@@ -24642,6 +24642,48 @@ var MAX_FIELDS = 50;
24642
24642
  var MAX_FIELD_NAME_BYTES = 128;
24643
24643
  var MAX_UNKNOWN_FIELDS = 50;
24644
24644
  var MAX_OMITTED_FIELDS = 100;
24645
+ var DEFAULT_FIELDS = {
24646
+ "mcp-get-strategy-list": ["strategyId", "strategyName", "localPath", "tags", "updateTime"],
24647
+ "mcp-get-backtest-list": ["runId", "runName", "strategyId", "status", "startTime", "endTime", "errorMsg", "code"]
24648
+ };
24649
+ var FIELD_PROJECTION_TOOLS = /* @__PURE__ */ new Set(["mcp-get-backtest-list"]);
24650
+ function selectFields(toolName, args, source) {
24651
+ const requestedFields = Array.isArray(args.fields) ? [...new Set(args.fields.filter((field) => typeof field === "string"))].slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)) : [];
24652
+ const allAvailableFields = [...new Set(source.flatMap((row) => isRecord4(row) ? Object.keys(row) : []))];
24653
+ const defaultFields = requestedFields.length ? [] : (DEFAULT_FIELDS[toolName] ?? []).filter((field) => allAvailableFields.includes(field));
24654
+ const fields = requestedFields.length ? requestedFields : defaultFields;
24655
+ const unknownFields = requestedFields.filter((field) => !allAvailableFields.includes(field));
24656
+ return { requestedFields, allAvailableFields, defaultFields, fields, unknownFields };
24657
+ }
24658
+ function project(row, fields) {
24659
+ return isRecord4(row) && fields.length ? Object.fromEntries(Object.entries(row).filter(([key]) => fields.includes(key))) : row;
24660
+ }
24661
+ function shapeFieldProjection(tool, args, result) {
24662
+ if (!FIELD_PROJECTION_TOOLS.has(tool.name) || result.isError) return result;
24663
+ try {
24664
+ const envelope = JSON.parse(result.content[0]?.text ?? "");
24665
+ if (!isRecord4(envelope) || envelope.disclosure || Number(envelope.ErrNo ?? 0) !== 0) return result;
24666
+ if (!Array.isArray(envelope.Data)) return result;
24667
+ const { requestedFields, allAvailableFields, defaultFields, fields, unknownFields } = selectFields(tool.name, args, envelope.Data);
24668
+ const pageNum = integer2(args.pageNum, 1, 1, Number.MAX_SAFE_INTEGER);
24669
+ const pageSize = integer2(args.pageSize, 0, 0, Number.MAX_SAFE_INTEGER);
24670
+ const pagingIgnored = pageSize > 0 && envelope.Data.length > pageSize;
24671
+ const fullPage = pageSize > 0 && envelope.Data.length === pageSize;
24672
+ const disclosure = {
24673
+ pageNum,
24674
+ returned: envelope.Data.length,
24675
+ possiblyMore: fullPage,
24676
+ nextPageNum: fullPage ? pageNum + 1 : null,
24677
+ ...pagingIgnored ? { pagingIgnored: true } : {},
24678
+ availableFields: allAvailableFields.slice(0, MAX_FIELDS),
24679
+ ...defaultFields.length ? { defaultFields } : {},
24680
+ ...requestedFields.length && unknownFields.length ? { unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS) } : {}
24681
+ };
24682
+ return replace(envelope, envelope.Data.map((row) => project(row, fields)), disclosure, result);
24683
+ } catch {
24684
+ return result;
24685
+ }
24686
+ }
24645
24687
  function shapeListResultDisclosure(tool, args, result) {
24646
24688
  if (!LIST_DISCLOSURE_TOOLS.has(tool.name) || result.isError) return result;
24647
24689
  try {
@@ -24651,8 +24693,7 @@ function shapeListResultDisclosure(tool, args, result) {
24651
24693
  const source = envelope.Data;
24652
24694
  const offset = integer2(args.offset, 0, 0, Number.MAX_SAFE_INTEGER);
24653
24695
  const limit = integer2(args.limit, 20, 1, 50);
24654
- const fields = Array.isArray(args.fields) ? [...new Set(args.fields.filter((field) => typeof field === "string"))].slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)) : [];
24655
- const allAvailableFields = [...new Set(source.flatMap((row) => isRecord4(row) ? Object.keys(row) : []))];
24696
+ const { requestedFields, allAvailableFields, defaultFields, fields, unknownFields } = selectFields(tool.name, args, source);
24656
24697
  const availableFields = allAvailableFields.slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES));
24657
24698
  const rows = [];
24658
24699
  let nextCursor = offset;
@@ -24665,13 +24706,11 @@ function shapeListResultDisclosure(tool, args, result) {
24665
24706
  hasMore: nextCursor < source.length,
24666
24707
  nextOffset: nextCursor < source.length ? nextCursor : null,
24667
24708
  availableFields,
24668
- ...fields.length ? (() => {
24669
- const unknownFields = fields.filter((field) => !allAvailableFields.includes(field));
24670
- return {
24671
- unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)),
24672
- ...unknownFields.length > MAX_UNKNOWN_FIELDS ? { unknownFieldsTruncated: true } : {}
24673
- };
24674
- })() : {},
24709
+ ...defaultFields.length ? { defaultFields } : {},
24710
+ ...requestedFields.length ? {
24711
+ unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)),
24712
+ ...unknownFields.length > MAX_UNKNOWN_FIELDS ? { unknownFieldsTruncated: true } : {}
24713
+ } : {},
24675
24714
  ...allAvailableFields.length > availableFields.length ? { availableFieldsTruncated: true } : {},
24676
24715
  ...omittedFields.length ? {
24677
24716
  omittedFields: omittedFields.slice(0, MAX_OMITTED_FIELDS).map((entry) => ({ ...entry, field: entry.field.slice(0, MAX_FIELD_NAME_BYTES) })),
@@ -25366,6 +25405,9 @@ function stripControlParams(args, toolName) {
25366
25405
  delete filtered.limit;
25367
25406
  delete filtered.fields;
25368
25407
  }
25408
+ if (toolName && FIELD_PROJECTION_TOOLS.has(toolName)) {
25409
+ delete filtered.fields;
25410
+ }
25369
25411
  if (toolName && DATA_DISCLOSURE_TOOLS.has(toolName)) {
25370
25412
  delete filtered.offset;
25371
25413
  delete filtered.limit;
@@ -27477,7 +27519,11 @@ function shapeToolResult(tool, args, result, session) {
27477
27519
  const diagnosed = tool.name === "mcp-factor-calculate-detail" ? diagnoseFactorFailure(withWorkspace) : withWorkspace;
27478
27520
  const distilled = distillFactorDetectReport(tool, args, diagnosed);
27479
27521
  const enriched = injectDebugRunId(tool, injectStrategyDocsHint(tool, distilled, session.docsPath));
27480
- return shapeDataResultDisclosure(tool, args, shapeListResultDisclosure(tool, args, enriched));
27522
+ return shapeFieldProjection(
27523
+ tool,
27524
+ args,
27525
+ shapeDataResultDisclosure(tool, args, shapeListResultDisclosure(tool, args, enriched))
27526
+ );
27481
27527
  }
27482
27528
  function backtestStatusNumber(status) {
27483
27529
  return typeof status === "number" || typeof status === "string" && status.trim() !== "" ? Number(status) : NaN;