@zltquant/zlt-mcp 0.7.4 → 0.7.6
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 +16 -8
- package/package.json +1 -1
- package/zlt-mcp-proxy.bundle.cjs +66 -11
package/config.json
CHANGED
|
@@ -1077,7 +1077,7 @@
|
|
|
1077
1077
|
},
|
|
1078
1078
|
{
|
|
1079
1079
|
"name": "mcp-get-strategy-list",
|
|
1080
|
-
"description": "查询本地策略列表(只展示 templateVal=strategy
|
|
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
|
|
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
|
-
"
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
"
|
|
1159
|
-
"description": "每页数量,固定为 100,必须显式传入。不要依赖 default 自动补值。"
|
|
1155
|
+
"minimum": 1,
|
|
1156
|
+
"maximum": 50,
|
|
1157
|
+
"default": 20,
|
|
1158
|
+
"description": "每页数量,传 20;最大 50,超出按 50 处理。必须显式传入,不要依赖 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
package/zlt-mcp-proxy.bundle.cjs
CHANGED
|
@@ -10687,6 +10687,7 @@ var CliEvidence = class {
|
|
|
10687
10687
|
teeWrite;
|
|
10688
10688
|
constructor(directory, provenance, command) {
|
|
10689
10689
|
const root2 = path.resolve(directory);
|
|
10690
|
+
fs.mkdirSync(path.dirname(root2), { recursive: true });
|
|
10690
10691
|
fs.mkdirSync(root2);
|
|
10691
10692
|
this.resultFile = path.join(root2, "result.json");
|
|
10692
10693
|
this.readableFile = path.join(root2, "result.readable.txt");
|
|
@@ -24642,6 +24643,49 @@ var MAX_FIELDS = 50;
|
|
|
24642
24643
|
var MAX_FIELD_NAME_BYTES = 128;
|
|
24643
24644
|
var MAX_UNKNOWN_FIELDS = 50;
|
|
24644
24645
|
var MAX_OMITTED_FIELDS = 100;
|
|
24646
|
+
var DEFAULT_FIELDS = {
|
|
24647
|
+
"mcp-get-strategy-list": ["strategyId", "strategyName", "localPath", "tags", "updateTime"],
|
|
24648
|
+
"mcp-get-backtest-list": ["runId", "runName", "strategyId", "status", "startTime", "endTime", "errorMsg", "code"]
|
|
24649
|
+
};
|
|
24650
|
+
var FIELD_PROJECTION_TOOLS = /* @__PURE__ */ new Set(["mcp-get-backtest-list"]);
|
|
24651
|
+
function selectFields(toolName, args, source) {
|
|
24652
|
+
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)) : [];
|
|
24653
|
+
const allAvailableFields = [...new Set(source.flatMap((row) => isRecord4(row) ? Object.keys(row) : []))];
|
|
24654
|
+
const defaultFields = requestedFields.length ? [] : (DEFAULT_FIELDS[toolName] ?? []).filter((field) => allAvailableFields.includes(field));
|
|
24655
|
+
const fields = requestedFields.length ? requestedFields : defaultFields;
|
|
24656
|
+
const unknownFields = requestedFields.filter((field) => !allAvailableFields.includes(field));
|
|
24657
|
+
return { requestedFields, allAvailableFields, defaultFields, fields, unknownFields };
|
|
24658
|
+
}
|
|
24659
|
+
function project(row, fields) {
|
|
24660
|
+
return isRecord4(row) && fields.length ? Object.fromEntries(Object.entries(row).filter(([key]) => fields.includes(key))) : row;
|
|
24661
|
+
}
|
|
24662
|
+
function shapeFieldProjection(tool, args, result) {
|
|
24663
|
+
if (!FIELD_PROJECTION_TOOLS.has(tool.name) || result.isError) return result;
|
|
24664
|
+
try {
|
|
24665
|
+
const envelope = JSON.parse(result.content[0]?.text ?? "");
|
|
24666
|
+
if (!isRecord4(envelope) || envelope.disclosure || Number(envelope.ErrNo ?? 0) !== 0) return result;
|
|
24667
|
+
if (!Array.isArray(envelope.Data)) return result;
|
|
24668
|
+
const { requestedFields, allAvailableFields, defaultFields, fields, unknownFields } = selectFields(tool.name, args, envelope.Data);
|
|
24669
|
+
const pageNum = integer2(args.pageNum, 1, 1, Number.MAX_SAFE_INTEGER);
|
|
24670
|
+
const pageSize = integer2(args.pageSize, 0, 0, Number.MAX_SAFE_INTEGER);
|
|
24671
|
+
const pagingIgnored = pageSize > 0 && envelope.Data.length > pageSize;
|
|
24672
|
+
const fullPage = pageSize > 0 && envelope.Data.length === pageSize;
|
|
24673
|
+
const disclosure = {
|
|
24674
|
+
pageNum,
|
|
24675
|
+
pageSize,
|
|
24676
|
+
returned: envelope.Data.length,
|
|
24677
|
+
possiblyMore: fullPage,
|
|
24678
|
+
nextPageNum: fullPage ? pageNum + 1 : null,
|
|
24679
|
+
...pagingIgnored ? { pagingIgnored: true } : {},
|
|
24680
|
+
availableFields: allAvailableFields.slice(0, MAX_FIELDS),
|
|
24681
|
+
...defaultFields.length ? { defaultFields } : {},
|
|
24682
|
+
...requestedFields.length && unknownFields.length ? { unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS) } : {}
|
|
24683
|
+
};
|
|
24684
|
+
return replace(envelope, envelope.Data.map((row) => project(row, fields)), disclosure, result);
|
|
24685
|
+
} catch {
|
|
24686
|
+
return result;
|
|
24687
|
+
}
|
|
24688
|
+
}
|
|
24645
24689
|
function shapeListResultDisclosure(tool, args, result) {
|
|
24646
24690
|
if (!LIST_DISCLOSURE_TOOLS.has(tool.name) || result.isError) return result;
|
|
24647
24691
|
try {
|
|
@@ -24651,8 +24695,7 @@ function shapeListResultDisclosure(tool, args, result) {
|
|
|
24651
24695
|
const source = envelope.Data;
|
|
24652
24696
|
const offset = integer2(args.offset, 0, 0, Number.MAX_SAFE_INTEGER);
|
|
24653
24697
|
const limit = integer2(args.limit, 20, 1, 50);
|
|
24654
|
-
const
|
|
24655
|
-
const allAvailableFields = [...new Set(source.flatMap((row) => isRecord4(row) ? Object.keys(row) : []))];
|
|
24698
|
+
const { requestedFields, allAvailableFields, defaultFields, fields, unknownFields } = selectFields(tool.name, args, source);
|
|
24656
24699
|
const availableFields = allAvailableFields.slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES));
|
|
24657
24700
|
const rows = [];
|
|
24658
24701
|
let nextCursor = offset;
|
|
@@ -24665,13 +24708,11 @@ function shapeListResultDisclosure(tool, args, result) {
|
|
|
24665
24708
|
hasMore: nextCursor < source.length,
|
|
24666
24709
|
nextOffset: nextCursor < source.length ? nextCursor : null,
|
|
24667
24710
|
availableFields,
|
|
24668
|
-
...
|
|
24669
|
-
|
|
24670
|
-
|
|
24671
|
-
|
|
24672
|
-
|
|
24673
|
-
};
|
|
24674
|
-
})() : {},
|
|
24711
|
+
...defaultFields.length ? { defaultFields } : {},
|
|
24712
|
+
...requestedFields.length ? {
|
|
24713
|
+
unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)),
|
|
24714
|
+
...unknownFields.length > MAX_UNKNOWN_FIELDS ? { unknownFieldsTruncated: true } : {}
|
|
24715
|
+
} : {},
|
|
24675
24716
|
...allAvailableFields.length > availableFields.length ? { availableFieldsTruncated: true } : {},
|
|
24676
24717
|
...omittedFields.length ? {
|
|
24677
24718
|
omittedFields: omittedFields.slice(0, MAX_OMITTED_FIELDS).map((entry) => ({ ...entry, field: entry.field.slice(0, MAX_FIELD_NAME_BYTES) })),
|
|
@@ -25366,6 +25407,9 @@ function stripControlParams(args, toolName) {
|
|
|
25366
25407
|
delete filtered.limit;
|
|
25367
25408
|
delete filtered.fields;
|
|
25368
25409
|
}
|
|
25410
|
+
if (toolName && FIELD_PROJECTION_TOOLS.has(toolName)) {
|
|
25411
|
+
delete filtered.fields;
|
|
25412
|
+
}
|
|
25369
25413
|
if (toolName && DATA_DISCLOSURE_TOOLS.has(toolName)) {
|
|
25370
25414
|
delete filtered.offset;
|
|
25371
25415
|
delete filtered.limit;
|
|
@@ -27387,7 +27431,7 @@ function prepareToolArgs(tool, args, contexts) {
|
|
|
27387
27431
|
const oversizedWindow = refuseOversizedBacktestPreloadWindow(tool, dated);
|
|
27388
27432
|
if (oversizedWindow) return oversizedWindow;
|
|
27389
27433
|
const named = normalizeBacktestRunName(tool, dated);
|
|
27390
|
-
const prepared = stripEmptyLegacyUserId(tool, named);
|
|
27434
|
+
const prepared = clampBacktestListPageSize(tool, stripEmptyLegacyUserId(tool, named));
|
|
27391
27435
|
const refused = refuseMaskedFuturesBacktest(tool, prepared);
|
|
27392
27436
|
if (refused) return refused;
|
|
27393
27437
|
capturePendingBacktestAttempt(tool, prepared, contexts);
|
|
@@ -27477,7 +27521,11 @@ function shapeToolResult(tool, args, result, session) {
|
|
|
27477
27521
|
const diagnosed = tool.name === "mcp-factor-calculate-detail" ? diagnoseFactorFailure(withWorkspace) : withWorkspace;
|
|
27478
27522
|
const distilled = distillFactorDetectReport(tool, args, diagnosed);
|
|
27479
27523
|
const enriched = injectDebugRunId(tool, injectStrategyDocsHint(tool, distilled, session.docsPath));
|
|
27480
|
-
return
|
|
27524
|
+
return shapeFieldProjection(
|
|
27525
|
+
tool,
|
|
27526
|
+
args,
|
|
27527
|
+
shapeDataResultDisclosure(tool, args, shapeListResultDisclosure(tool, args, enriched))
|
|
27528
|
+
);
|
|
27481
27529
|
}
|
|
27482
27530
|
function backtestStatusNumber(status) {
|
|
27483
27531
|
return typeof status === "number" || typeof status === "string" && status.trim() !== "" ? Number(status) : NaN;
|
|
@@ -27717,6 +27765,13 @@ function subtractMonthsClamped(value, months) {
|
|
|
27717
27765
|
target.setDate(Math.min(day, lastDay));
|
|
27718
27766
|
return target;
|
|
27719
27767
|
}
|
|
27768
|
+
var MAX_BACKTEST_LIST_PAGE_SIZE = 50;
|
|
27769
|
+
function clampBacktestListPageSize(tool, args) {
|
|
27770
|
+
if (tool.name !== "mcp-get-backtest-list") return args;
|
|
27771
|
+
const pageSize = args.pageSize;
|
|
27772
|
+
if (typeof pageSize !== "number" || !Number.isFinite(pageSize) || pageSize <= MAX_BACKTEST_LIST_PAGE_SIZE) return args;
|
|
27773
|
+
return { ...args, pageSize: MAX_BACKTEST_LIST_PAGE_SIZE };
|
|
27774
|
+
}
|
|
27720
27775
|
function stripEmptyLegacyUserId(tool, args) {
|
|
27721
27776
|
if (!toolHasUserIdField(tool)) return args;
|
|
27722
27777
|
if (!Object.prototype.hasOwnProperty.call(args, "userId")) return args;
|