@wukongcrm/mcp-server 0.2.5 → 0.2.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/dist/nocode.js CHANGED
@@ -416,11 +416,11 @@ export const nocodeToolDefinitions = [
416
416
  export function createNocodeToolHandlers(config = {}, sharedClient) {
417
417
  const client = sharedClient ?? new CrmClient(config);
418
418
  return {
419
- nocode_list_applications: async () => readonlyResult("/moduleMetadata/customAppList", await client.post("/moduleMetadata/customAppList")),
419
+ nocode_list_applications: async () => readonlyResult("/moduleMetadata/customAppList", await client.read("/moduleMetadata/customAppList")),
420
420
  nocode_get_application: async (args) => {
421
421
  const applicationId = requiredId(args.applicationId, "applicationId");
422
422
  const targetPath = `/moduleMetadata/queryById/${applicationId}`;
423
- return readonlyResult(targetPath, await client.post(targetPath));
423
+ return readonlyResult(targetPath, await client.read(targetPath));
424
424
  },
425
425
  nocode_list_modules: async (args) => {
426
426
  const applicationId = requiredId(args.applicationId, "applicationId");
@@ -432,17 +432,17 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
432
432
  : mode === "all"
433
433
  ? `/moduleM/list/${applicationId}`
434
434
  : `/moduleM/released/list/${applicationId}`;
435
- return readonlyResult(targetPath, await client.post(targetPath), { mode });
435
+ return readonlyResult(targetPath, await client.read(targetPath), { mode });
436
436
  },
437
437
  nocode_get_module: async (args) => {
438
438
  const moduleId = requiredId(args.moduleId, "moduleId");
439
439
  if (args.version !== undefined) {
440
440
  const version = requiredVersion(args.version);
441
441
  const targetPath = `/moduleM/queryDetail/${moduleId}/${version}`;
442
- return readonlyResult(targetPath, await client.post(targetPath));
442
+ return readonlyResult(targetPath, await client.read(targetPath));
443
443
  }
444
444
  const targetPath = `/moduleM/queryById/${moduleId}`;
445
- return readonlyResult(targetPath, await client.post(targetPath, undefined, { isLatest: args.isLatest ?? true }));
445
+ return readonlyResult(targetPath, await client.read(targetPath, undefined, { isLatest: args.isLatest ?? true }));
446
446
  },
447
447
  nocode_get_module_schema: async (args) => {
448
448
  const moduleId = requiredId(args.moduleId, "moduleId");
@@ -451,9 +451,9 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
451
451
  // 旧后端会直接拆箱 filterHidden;显式传 false 与无代码前端的字段配置请求保持一致,避免空值触发 500。
452
452
  const formQuery = { ...query, filterHidden: false };
453
453
  const [fields, form, listHeadOutcome, layout, unionModules] = await Promise.all([
454
- client.post("/moduleField/queryList", query),
455
- client.post("/moduleField/formList", formQuery),
456
- client.post("/moduleField/queryListHead", query)
454
+ client.read("/moduleField/queryList", query),
455
+ client.read("/moduleField/formList", formQuery),
456
+ client.read("/moduleField/queryListHead", query)
457
457
  .then((data) => ({ data, warning: undefined }))
458
458
  .catch((error) => {
459
459
  // 旧端的列表头服务只读取“已发布激活”的模块。新建草稿在字段已经存在时仍会返回 4303,
@@ -466,16 +466,16 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
466
466
  }
467
467
  throw error;
468
468
  }),
469
- client.post(`/moduleM/pageLayout/${moduleId}/${version}`),
470
- client.post(`/moduleM/unionModules/${moduleId}/${version}`)
469
+ client.read(`/moduleM/pageLayout/${moduleId}/${version}`),
470
+ client.read(`/moduleM/unionModules/${moduleId}/${version}`)
471
471
  ]);
472
472
  const extended = args.includeExtended === false
473
473
  ? undefined
474
474
  : {
475
- options: await client.post(`/moduleFieldOptions/list/${moduleId}/${version}`),
476
- formulas: await client.post(`/moduleFieldFormula/list/${moduleId}/${version}`),
477
- tags: await client.post(`/moduleFieldTags/list/${moduleId}/${version}`),
478
- serialNumberRules: await client.post(`/moduleFieldSerialNumberRules/list/${moduleId}/${version}`)
475
+ options: await client.read(`/moduleFieldOptions/list/${moduleId}/${version}`),
476
+ formulas: await client.read(`/moduleFieldFormula/list/${moduleId}/${version}`),
477
+ tags: await client.read(`/moduleFieldTags/list/${moduleId}/${version}`),
478
+ serialNumberRules: await client.read(`/moduleFieldSerialNumberRules/list/${moduleId}/${version}`)
479
479
  };
480
480
  return {
481
481
  readonly: true,
@@ -495,21 +495,21 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
495
495
  const targetPath = `/moduleData/queryPageList/${moduleId}`;
496
496
  // 分页上限由工具 schema 控制,不能让透传 payload 绕过顶层的 page/limit 约束。
497
497
  const body = cleanObject({ ...safePayload(args.payload), page: args.page ?? 1, limit: args.limit ?? 15 });
498
- return readonlyResult(targetPath, await client.post(targetPath, body), { body });
498
+ return readonlyResult(targetPath, await client.read(targetPath, body), { body });
499
499
  },
500
500
  nocode_get_record: async (args) => {
501
501
  const dataId = requiredId(args.dataId, "dataId");
502
502
  const targetPath = `/moduleFieldData/query/${dataId}/${args.replaceMask ?? true}`;
503
- return readonlyResult(targetPath, await client.post(targetPath));
503
+ return readonlyResult(targetPath, await client.read(targetPath));
504
504
  },
505
- nocode_calculate_formula: async (args) => readonlyResult("/moduleFieldData/calculateFormula", await client.post("/moduleFieldData/calculateFormula", safePayload(args.payload))),
506
- nocode_check_duplicate: async (args) => readonlyResult("/moduleFieldData/doubleCheck", await client.post("/moduleFieldData/doubleCheck", safePayload(args.payload))),
505
+ nocode_calculate_formula: async (args) => readonlyResult("/moduleFieldData/calculateFormula", await client.read("/moduleFieldData/calculateFormula", safePayload(args.payload))),
506
+ nocode_check_duplicate: async (args) => readonlyResult("/moduleFieldData/doubleCheck", await client.read("/moduleFieldData/doubleCheck", safePayload(args.payload))),
507
507
  nocode_list_team_members: async (args) => {
508
508
  const moduleId = requiredId(args.moduleId, "moduleId");
509
509
  const dataId = requiredId(args.dataId, "dataId");
510
510
  const [members, currentUser] = await Promise.all([
511
- client.post(`/moduleFieldData/teamMember/${moduleId}/${dataId}`),
512
- client.post(`/moduleFieldData/teamMemberInfo/${moduleId}/${dataId}`)
511
+ client.read(`/moduleFieldData/teamMember/${moduleId}/${dataId}`),
512
+ client.read(`/moduleFieldData/teamMemberInfo/${moduleId}/${dataId}`)
513
513
  ]);
514
514
  return { readonly: true, moduleId, dataId, members, currentUser };
515
515
  },
@@ -517,9 +517,9 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
517
517
  nocode_list_scenes: async (args) => {
518
518
  const moduleId = requiredId(args.moduleId, "moduleId");
519
519
  const targetPath = `/moduleScene/list/${moduleId}`;
520
- return readonlyResult(targetPath, await client.post(targetPath));
520
+ return readonlyResult(targetPath, await client.read(targetPath));
521
521
  },
522
- nocode_list_flows: async (args) => readonlyResult("/moduleFlow/queryFlow", await client.post("/moduleFlow/queryFlow", undefined, safePayload(args.payload))),
522
+ nocode_list_flows: async (args) => readonlyResult("/moduleFlow/queryFlow", await client.read("/moduleFlow/queryFlow", undefined, safePayload(args.payload))),
523
523
  nocode_list_stages: async (args) => {
524
524
  let targetPath;
525
525
  if (args.dataId !== undefined) {
@@ -528,17 +528,17 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
528
528
  else {
529
529
  targetPath = `/moduleStageSetting/queryList/${requiredId(args.moduleId, "moduleId")}/${requiredVersion(args.version)}`;
530
530
  }
531
- return readonlyResult(targetPath, await client.post(targetPath));
531
+ return readonlyResult(targetPath, await client.read(targetPath));
532
532
  },
533
533
  nocode_list_custom_buttons: async (args) => {
534
534
  const targetPath = `/moduleCustomButton/queryList/${requiredId(args.moduleId, "moduleId")}/${requiredVersion(args.version)}`;
535
- return readonlyResult(targetPath, await client.post(targetPath));
535
+ return readonlyResult(targetPath, await client.read(targetPath));
536
536
  },
537
537
  nocode_list_tabs: async (args) => {
538
538
  const targetPath = `/moduleTab/queryList/${requiredId(args.moduleId, "moduleId")}`;
539
- return readonlyResult(targetPath, await client.post(targetPath));
539
+ return readonlyResult(targetPath, await client.read(targetPath));
540
540
  },
541
- nocode_get_module_file: async (args) => readonlyResult("/moduleFile/query", await client.post("/moduleFile/query", safePayload(args.payload))),
541
+ nocode_get_module_file: async (args) => readonlyResult("/moduleFile/query", await client.read("/moduleFile/query", safePayload(args.payload))),
542
542
  nocode_query_fields: async (args) => executeNocodeRead(client, queryFieldRoute(args)),
543
543
  nocode_query_records: async (args) => executeNocodeRead(client, queryRecordRoute(args)),
544
544
  nocode_query_workflow: async (args) => executeNocodeRead(client, queryWorkflowRoute(args)),
@@ -596,7 +596,7 @@ export function createNocodeToolHandlers(config = {}, sharedClient) {
596
596
  };
597
597
  }
598
598
  async function executeNocodeRead(client, route) {
599
- return readonlyResult(route.targetPath, await client.post(route.targetPath, route.body, route.query), cleanObject({ operation: route.operation, body: route.body, query: route.query }));
599
+ return readonlyResult(route.targetPath, await client.read(route.targetPath, route.body, route.query), cleanObject({ operation: route.operation, body: route.body, query: route.query }));
600
600
  }
601
601
  async function executePrintingRead(client, args) {
602
602
  const route = queryPrintingRoute(args);
@@ -903,34 +903,34 @@ function unsupportedRoute(domain, operation) {
903
903
  async function queryPermissions(client, args) {
904
904
  switch (args.kind) {
905
905
  case "auth":
906
- return readonlyResult("/moduleRole/auth", await client.post("/moduleRole/auth"));
906
+ return readonlyResult("/moduleRole/auth", await client.read("/moduleRole/auth"));
907
907
  case "roles": {
908
908
  const applicationId = requiredId(args.applicationId, "applicationId");
909
909
  const targetPath = `/moduleRole/list/${applicationId}`;
910
- return readonlyResult(targetPath, await client.post(targetPath));
910
+ return readonlyResult(targetPath, await client.read(targetPath));
911
911
  }
912
912
  case "rolesByIds":
913
- return readonlyResult("/moduleRole/listByRoleId", await client.post("/moduleRole/listByRoleId", requiredIds(args.ids, "ids")));
913
+ return readonlyResult("/moduleRole/listByRoleId", await client.read("/moduleRole/listByRoleId", requiredIds(args.ids, "ids")));
914
914
  case "usersRoles":
915
- return readonlyResult("/moduleRole/roles/users", await client.post("/moduleRole/roles/users", requiredIds(args.ids, "ids")));
915
+ return readonlyResult("/moduleRole/roles/users", await client.read("/moduleRole/roles/users", requiredIds(args.ids, "ids")));
916
916
  case "viewableUserIds": {
917
917
  const moduleId = requiredId(args.moduleId, "moduleId");
918
918
  const targetPath = `/moduleRole/queryViewableUserIds/${moduleId}`;
919
- return readonlyResult(targetPath, await client.post(targetPath));
919
+ return readonlyResult(targetPath, await client.read(targetPath));
920
920
  }
921
921
  case "data": {
922
922
  const dataId = requiredId(args.dataId, "dataId");
923
923
  const targetPath = `/moduleRole/dataAuth/${dataId}`;
924
- return readonlyResult(targetPath, await client.post(targetPath));
924
+ return readonlyResult(targetPath, await client.read(targetPath));
925
925
  }
926
926
  case "field": {
927
927
  const moduleId = requiredId(args.moduleId, "moduleId");
928
928
  const userId = requiredId(args.userId, "userId");
929
929
  const targetPath = `/moduleRole/fieldAuth/${moduleId}/${userId}`;
930
- return readonlyResult(targetPath, await client.post(targetPath));
930
+ return readonlyResult(targetPath, await client.read(targetPath));
931
931
  }
932
932
  case "roleField":
933
- return readonlyResult("/moduleRole/roleField", await client.post("/moduleRole/roleField", safePayload(args.payload)));
933
+ return readonlyResult("/moduleRole/roleField", await client.read("/moduleRole/roleField", safePayload(args.payload)));
934
934
  default:
935
935
  throw new Error(`不支持的无代码权限查询类型:${String(args.kind)}`);
936
936
  }
@@ -1019,7 +1019,7 @@ async function publishModuleDraft(client, args) {
1019
1019
  const moduleId = requiredId(args.moduleId, "moduleId");
1020
1020
  const version = requiredExplicitVersion(args.version, "version");
1021
1021
  const targetPath = `/moduleM/active/${moduleId}`;
1022
- const latest = requiredObject(await client.post(`/moduleM/queryById/${moduleId}`, undefined, { isLatest: true }), "无法读取待发布模块的最新版本。");
1022
+ const latest = requiredObject(await client.read(`/moduleM/queryById/${moduleId}`, undefined, { isLatest: true }), "无法读取待发布模块的最新版本。");
1023
1023
  const latestVersion = requiredExplicitVersion(latest.version, "latest.version");
1024
1024
  // 发布接口本身不接收版本号;必须在调用前锁定调用方确认过的草稿版本,避免误发新草稿。
1025
1025
  if (latestVersion !== version) {
@@ -1038,7 +1038,7 @@ async function publishModuleDraft(client, args) {
1038
1038
  preflight: { latestVersion, status: latest.status, isActive: latest.isActive }
1039
1039
  };
1040
1040
  }
1041
- const published = requiredObject(await client.post(targetPath), "发布接口未返回模块信息,无法确认发布结果。");
1041
+ const published = requiredObject(await client.write(targetPath), "发布接口未返回模块信息,无法确认发布结果。");
1042
1042
  const publishedVersion = requiredExplicitVersion(published.version, "published.version");
1043
1043
  const verified = publishedVersion === version && published.isActive === true && Number(published.status) === 1;
1044
1044
  return {
@@ -1058,7 +1058,7 @@ async function executeRelationFieldReplacement(client, args) {
1058
1058
  const targetModuleId = requiredId(args.targetModuleId, "targetModuleId");
1059
1059
  const baseVersion = requiredExplicitVersion(args.baseVersion, "baseVersion");
1060
1060
  const relationFieldName = requiredText(args.relationFieldName, "relationFieldName");
1061
- const moduleDetail = requiredObject(await client.post(`/moduleM/queryById/${moduleId}`, undefined, { isLatest: true }), "无法读取来源模块的最新版本。");
1061
+ const moduleDetail = requiredObject(await client.read(`/moduleM/queryById/${moduleId}`, undefined, { isLatest: true }), "无法读取来源模块的最新版本。");
1062
1062
  const latestVersion = requiredExplicitVersion(moduleDetail.version, "module.version");
1063
1063
  if (latestVersion !== baseVersion) {
1064
1064
  throw new Error(`模块版本已变化:baseVersion=${baseVersion},当前最新 version=${latestVersion}。请重新读取结构后再替换。`);
@@ -1070,7 +1070,7 @@ async function executeRelationFieldReplacement(client, args) {
1070
1070
  throw new Error("来源模块不是可编辑的已发布版本或草稿版本,已拒绝字段替换。");
1071
1071
  }
1072
1072
  const mainFieldId = requiredId(moduleDetail.mainFieldId, "module.mainFieldId");
1073
- const fields = requiredObjectArray(await client.post("/moduleField/queryList", { moduleId: numericValue(moduleId), version: baseVersion }), "模块字段列表");
1073
+ const fields = requiredObjectArray(await client.read("/moduleField/queryList", { moduleId: numericValue(moduleId), version: baseVersion }), "模块字段列表");
1074
1074
  const sourceField = fields.find((field) => sameId(field.fieldId, sourceFieldId));
1075
1075
  if (!sourceField) {
1076
1076
  throw new Error(`sourceFieldId=${sourceFieldId} 不在模块 ${moduleId} 的 version=${baseVersion} 字段列表中。`);
@@ -1098,8 +1098,8 @@ async function executeRelationFieldReplacement(client, args) {
1098
1098
  if (fields.some((field) => Number(field.type) === 68)) {
1099
1099
  throw new Error("模块包含树字段;旧后端查询结果缺少聚合保存所需的临时展示字段 ID,已保守阻断替换。");
1100
1100
  }
1101
- const defaultValueConfigs = requiredObjectArray(await client.post(`/moduleFieldDefault/list/${moduleId}/${baseVersion}`), "字段默认值配置");
1102
- const fieldStatisticConfigs = requiredObjectArray(await client.post(`/moduleFieldStatistic/query/${moduleId}/${baseVersion}`), "字段统计配置");
1101
+ const defaultValueConfigs = requiredObjectArray(await client.read(`/moduleFieldDefault/list/${moduleId}/${baseVersion}`), "字段默认值配置");
1102
+ const fieldStatisticConfigs = requiredObjectArray(await client.read(`/moduleFieldStatistic/query/${moduleId}/${baseVersion}`), "字段统计配置");
1103
1103
  // /moduleField/save 会先清空再重建这两类配置;语义工具没有完整编辑上下文时宁可拒绝,也不能静默擦除。
1104
1104
  if (defaultValueConfigs.length > 0 || fieldStatisticConfigs.length > 0) {
1105
1105
  throw new Error(`模块包含 ${defaultValueConfigs.length} 条字段默认值配置和 ${fieldStatisticConfigs.length} 条字段统计配置,已保守阻断替换。`);
@@ -1118,11 +1118,11 @@ async function executeRelationFieldReplacement(client, args) {
1118
1118
  groupId: 0
1119
1119
  }]
1120
1120
  };
1121
- const sourceDataPage = await client.post(`/moduleData/queryPageList/${moduleId}`, sourceDataQuery);
1121
+ const sourceDataPage = await client.read(`/moduleData/queryPageList/${moduleId}`, sourceDataQuery);
1122
1122
  if (pageHasRows(sourceDataPage)) {
1123
1123
  throw new Error(`字段“${String(sourceField.name ?? sourceFieldName)}”存在非空数据,替换会在发布时丢失原值,已阻断。`);
1124
1124
  }
1125
- const deleteImpact = requiredObject(await client.post("/moduleField/checkFieldDelete", {
1125
+ const deleteImpact = requiredObject(await client.read("/moduleField/checkFieldDelete", {
1126
1126
  moduleId: numericValue(moduleId),
1127
1127
  fieldId: numericValue(sourceFieldId),
1128
1128
  fieldName: sourceFieldName,
@@ -1133,7 +1133,7 @@ async function executeRelationFieldReplacement(client, args) {
1133
1133
  if (dependentFields.length > 0 || dependentFlows.length > 0) {
1134
1134
  throw new Error(`字段仍被 ${dependentFields.length} 个字段配置和 ${dependentFlows.length} 个流程配置引用,已阻断替换。`);
1135
1135
  }
1136
- const targetModule = requiredObject(await client.post(`/moduleM/queryById/${targetModuleId}`, undefined, { isLatest: false }), "无法读取关联目标模块的已发布版本。");
1136
+ const targetModule = requiredObject(await client.read(`/moduleM/queryById/${targetModuleId}`, undefined, { isLatest: false }), "无法读取关联目标模块的已发布版本。");
1137
1137
  if (targetModule.isActive !== true || Number(targetModule.status) !== 1) {
1138
1138
  throw new Error("关联目标模块必须存在已发布激活版本。");
1139
1139
  }
@@ -1203,10 +1203,37 @@ async function executeRelationFieldReplacement(client, args) {
1203
1203
  body: saveBody
1204
1204
  };
1205
1205
  }
1206
- const savedModule = requiredObject(await client.post("/moduleField/save", saveBody), "字段保存接口未返回模块信息,无法回读验证。");
1206
+ const savedModule = requiredObject(await client.write("/moduleField/save", saveBody), "字段保存接口未返回模块信息,无法回读验证。");
1207
1207
  const savedVersion = requiredExplicitVersion(savedModule.version, "savedModule.version");
1208
1208
  const expectedSavedVersion = moduleDetail.isActive === true ? baseVersion + 1 : baseVersion;
1209
- const readbackFields = requiredObjectArray(await client.post("/moduleField/queryList", { moduleId: numericValue(moduleId), version: savedVersion }), "保存后字段列表");
1209
+ let readbackFields;
1210
+ try {
1211
+ readbackFields = requiredObjectArray(await client.read("/moduleField/queryList", { moduleId: numericValue(moduleId), version: savedVersion }), "保存后字段列表");
1212
+ }
1213
+ catch (error) {
1214
+ // 草稿保存已经 code=0;回读失败时保留“已保存、验证未知”,并阻止后续发布。
1215
+ return {
1216
+ preview: false,
1217
+ action: "replaceFieldWithRelation",
1218
+ targetPath: "/moduleField/save",
1219
+ moduleId,
1220
+ baseVersion,
1221
+ savedVersion,
1222
+ saved: true,
1223
+ verified: false,
1224
+ publishReady: false,
1225
+ message: "字段草稿已保存,但后续回读失败;请检查草稿,不要发布或直接重放保存请求。",
1226
+ preflight,
1227
+ verification: {
1228
+ status: "unknown",
1229
+ error: {
1230
+ name: error instanceof Error ? error.name : "Error",
1231
+ message: error instanceof Error ? error.message : String(error)
1232
+ }
1233
+ },
1234
+ data: savedModule
1235
+ };
1236
+ }
1210
1237
  const retainedFieldIds = retainedFields.map((field) => requiredId(field.fieldId, "retainedField.fieldId"));
1211
1238
  const replacementMatches = readbackFields.filter((field) => {
1212
1239
  const optionsData = isObject(field.optionsData) ? field.optionsData : {};
@@ -1270,6 +1297,7 @@ async function executeRelationFieldReplacement(client, args) {
1270
1297
  : "字段草稿已保存,但回读验证未通过;请检查草稿,不要发布。",
1271
1298
  preflight,
1272
1299
  verification: {
1300
+ status: verified ? "confirmed" : "mismatch",
1273
1301
  errors: verificationErrors,
1274
1302
  sourceRemoved: !readbackFields.some((field) => sameId(field.fieldId, sourceFieldId)),
1275
1303
  retainedFieldsPresent: missingRetainedIds.length === 0,
@@ -1366,7 +1394,7 @@ async function confirmedPost(client, args, action, targetPath, body, query) {
1366
1394
  targetPath,
1367
1395
  body,
1368
1396
  query,
1369
- data: await client.post(targetPath, body, query)
1397
+ data: await client.write(targetPath, body, query)
1370
1398
  };
1371
1399
  }
1372
1400
  function readonlyResult(targetPath, data, extra = {}) {