@testchimp/cli 0.1.26 → 0.1.28

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.
@@ -936,6 +936,33 @@ export function buildCliProgram() {
936
936
  const out = await runTool("mark-semantic-tests-distinct", merged, { postMcp });
937
937
  console.log(out);
938
938
  });
939
+ program
940
+ .command("list-semantic-nearby")
941
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-semantic-nearby").description)
942
+ .addOption(jsonInputOption())
943
+ .action(async (opts) => {
944
+ const merged = mergeBodies({}, opts.jsonInput);
945
+ const out = await runTool("list-semantic-nearby", merged, { postMcp });
946
+ console.log(out);
947
+ });
948
+ program
949
+ .command("mark-entity-distinct")
950
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "mark-entity-distinct").description)
951
+ .addOption(jsonInputOption())
952
+ .action(async (opts) => {
953
+ const merged = mergeBodies({}, opts.jsonInput);
954
+ const out = await runTool("mark-entity-distinct", merged, { postMcp });
955
+ console.log(out);
956
+ });
957
+ program
958
+ .command("unmark-entity-distinct")
959
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "unmark-entity-distinct").description)
960
+ .addOption(jsonInputOption())
961
+ .action(async (opts) => {
962
+ const merged = mergeBodies({}, opts.jsonInput);
963
+ const out = await runTool("unmark-entity-distinct", merged, { postMcp });
964
+ console.log(out);
965
+ });
939
966
  program
940
967
  .command("get-requirement-quality-report")
941
968
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-requirement-quality-report").description)
@@ -1107,6 +1134,68 @@ export function buildCliProgram() {
1107
1134
  }
1108
1135
  console.log(await runTool("upsert-plans-support-file", merged, { postMcp }));
1109
1136
  });
1137
+ program
1138
+ .command("list-api-operation-services")
1139
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-api-operation-services").description)
1140
+ .addOption(jsonInputOption())
1141
+ .action(async (opts) => {
1142
+ const merged = mergeBodies({}, opts.jsonInput);
1143
+ console.log(await runTool("list-api-operation-services", merged, { postMcp }));
1144
+ });
1145
+ program
1146
+ .command("list-api-operations")
1147
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-api-operations").description)
1148
+ .addOption(jsonInputOption())
1149
+ .option("--root-file-path <path>", "Repo-relative OpenAPI root path (preferred service resource id)")
1150
+ .option("--service-key <key>", "Internal service key alias")
1151
+ .option("--include-manual", "Include MANUAL test_mode coverage in previews")
1152
+ .option("--include-removed", "Include soft-deleted (REMOVED) operations")
1153
+ .action(async (opts) => {
1154
+ const body = {};
1155
+ if (opts.rootFilePath)
1156
+ body.rootFilePath = String(opts.rootFilePath);
1157
+ if (opts.serviceKey)
1158
+ body.serviceKey = String(opts.serviceKey);
1159
+ if (opts.includeManual)
1160
+ body.includeManual = true;
1161
+ if (opts.includeRemoved)
1162
+ body.includeRemoved = true;
1163
+ const merged = mergeBodies(body, opts.jsonInput);
1164
+ console.log(await runTool("list-api-operations", merged, { postMcp }));
1165
+ });
1166
+ program
1167
+ .command("get-api-operation-detail")
1168
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-api-operation-detail").description)
1169
+ .addOption(jsonInputOption())
1170
+ .option("--id <ulid>", "TestChimp operation id (ULID PK) — preferred")
1171
+ .option("--root-file-path <path>", "Repo-relative OpenAPI root path")
1172
+ .option("--service-key <key>", "Internal service key")
1173
+ .option("--oas-operation-id <id>", "OpenAPI operationId")
1174
+ .option("--http-method <method>", "HTTP method (with --path-template)")
1175
+ .option("--path-template <path>", "OpenAPI path template (with --http-method)")
1176
+ .option("--include-manual", "Include MANUAL test_mode coverage")
1177
+ .option("--include-removed", "Include soft-deleted schema fields / response codes")
1178
+ .action(async (opts) => {
1179
+ const body = {};
1180
+ if (opts.id)
1181
+ body.id = String(opts.id);
1182
+ if (opts.rootFilePath)
1183
+ body.rootFilePath = String(opts.rootFilePath);
1184
+ if (opts.serviceKey)
1185
+ body.serviceKey = String(opts.serviceKey);
1186
+ if (opts.oasOperationId)
1187
+ body.oasOperationId = String(opts.oasOperationId);
1188
+ if (opts.httpMethod)
1189
+ body.httpMethod = String(opts.httpMethod);
1190
+ if (opts.pathTemplate)
1191
+ body.pathTemplate = String(opts.pathTemplate);
1192
+ if (opts.includeManual)
1193
+ body.includeManual = true;
1194
+ if (opts.includeRemoved)
1195
+ body.includeRemoved = true;
1196
+ const merged = mergeBodies(body, opts.jsonInput);
1197
+ console.log(await runTool("get-api-operation-detail", merged, { postMcp }));
1198
+ });
1110
1199
  program.on("--help", () => {
1111
1200
  /* default */
1112
1201
  });
@@ -924,6 +924,64 @@ export declare const markSemanticTestsDistinctInput: z.ZodObject<{
924
924
  testName: z.ZodString;
925
925
  }, z.core.$strip>;
926
926
  }, z.core.$strip>;
927
+ /** LinkedEntityType names for semantic nearby (embedding-capable). */
928
+ export declare const semanticNearbyEntityTypeSchema: z.ZodEnum<{
929
+ STORY: "STORY";
930
+ SCENARIO: "SCENARIO";
931
+ TEST: "TEST";
932
+ ISSUE: "ISSUE";
933
+ EVENT: "EVENT";
934
+ }>;
935
+ export declare const listSemanticNearbyInput: z.ZodObject<{
936
+ sourceEntityType: z.ZodEnum<{
937
+ STORY: "STORY";
938
+ SCENARIO: "SCENARIO";
939
+ TEST: "TEST";
940
+ ISSUE: "ISSUE";
941
+ EVENT: "EVENT";
942
+ }>;
943
+ sourceTest: z.ZodOptional<z.ZodObject<{
944
+ folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
945
+ fileName: z.ZodString;
946
+ testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
947
+ testName: z.ZodString;
948
+ }, z.core.$strip>>;
949
+ sourceOrdinalId: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
950
+ sourceEventTitle: z.ZodOptional<z.ZodString>;
951
+ targetEntityTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<{
952
+ STORY: "STORY";
953
+ SCENARIO: "SCENARIO";
954
+ TEST: "TEST";
955
+ ISSUE: "ISSUE";
956
+ EVENT: "EVENT";
957
+ }>>>;
958
+ limit: z.ZodOptional<z.ZodNumber>;
959
+ }, z.core.$strip>;
960
+ export declare const markEntityDistinctInput: z.ZodObject<{
961
+ entityType: z.ZodEnum<{
962
+ STORY: "STORY";
963
+ SCENARIO: "SCENARIO";
964
+ TEST: "TEST";
965
+ ISSUE: "ISSUE";
966
+ EVENT: "EVENT";
967
+ }>;
968
+ focusTest: z.ZodOptional<z.ZodObject<{
969
+ folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
970
+ fileName: z.ZodString;
971
+ testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
972
+ testName: z.ZodString;
973
+ }, z.core.$strip>>;
974
+ otherTest: z.ZodOptional<z.ZodObject<{
975
+ folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
976
+ fileName: z.ZodString;
977
+ testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
978
+ testName: z.ZodString;
979
+ }, z.core.$strip>>;
980
+ focusOrdinalId: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
981
+ otherOrdinalId: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
982
+ focusEventTitle: z.ZodOptional<z.ZodString>;
983
+ otherEventTitle: z.ZodOptional<z.ZodString>;
984
+ }, z.core.$strip>;
927
985
  /** RequirementSubjectType — proto enum names (JsonFormat camelCase on wire). */
928
986
  export declare const requirementSubjectTypeSchema: z.ZodEnum<{
929
987
  STORY: "STORY";
@@ -1234,11 +1292,11 @@ export declare const agentActionEntityTypeSchema: z.ZodEnum<{
1234
1292
  SCENARIO: "SCENARIO";
1235
1293
  ISSUE: "ISSUE";
1236
1294
  TEST_EXECUTION: "TEST_EXECUTION";
1295
+ EVENT: "EVENT";
1237
1296
  USER_STORY: "USER_STORY";
1238
1297
  POLICY: "POLICY";
1239
1298
  TEST_INVOCATION_BATCH: "TEST_INVOCATION_BATCH";
1240
1299
  EXPLORATION: "EXPLORATION";
1241
- EVENT: "EVENT";
1242
1300
  WORKFLOW: "WORKFLOW";
1243
1301
  }>;
1244
1302
  export declare const agentActionTypeSchema: z.ZodEnum<{
@@ -1295,11 +1353,11 @@ export declare const reportAgentActionInput: z.ZodObject<{
1295
1353
  SCENARIO: "SCENARIO";
1296
1354
  ISSUE: "ISSUE";
1297
1355
  TEST_EXECUTION: "TEST_EXECUTION";
1356
+ EVENT: "EVENT";
1298
1357
  USER_STORY: "USER_STORY";
1299
1358
  POLICY: "POLICY";
1300
1359
  TEST_INVOCATION_BATCH: "TEST_INVOCATION_BATCH";
1301
1360
  EXPLORATION: "EXPLORATION";
1302
- EVENT: "EVENT";
1303
1361
  WORKFLOW: "WORKFLOW";
1304
1362
  }>;
1305
1363
  entityIdentity: z.ZodOptional<z.ZodString>;
@@ -1357,3 +1415,21 @@ export declare const upsertPlansSupportFileInput: z.ZodObject<{
1357
1415
  content: z.ZodString;
1358
1416
  }, z.core.$strip>;
1359
1417
  export declare const listWorkflowCatalogInput: z.ZodObject<{}, z.core.$strip>;
1418
+ /** API operation coverage (OpenAPI ops + denorm coverage) — CLI ≥ 0.1.28 */
1419
+ export declare const listApiOperationServicesInput: z.ZodObject<{}, z.core.$strip>;
1420
+ export declare const listApiOperationsInput: z.ZodObject<{
1421
+ rootFilePath: z.ZodOptional<z.ZodString>;
1422
+ serviceKey: z.ZodOptional<z.ZodString>;
1423
+ includeManual: z.ZodOptional<z.ZodBoolean>;
1424
+ includeRemoved: z.ZodOptional<z.ZodBoolean>;
1425
+ }, z.core.$strip>;
1426
+ export declare const getApiOperationDetailInput: z.ZodObject<{
1427
+ id: z.ZodOptional<z.ZodString>;
1428
+ rootFilePath: z.ZodOptional<z.ZodString>;
1429
+ serviceKey: z.ZodOptional<z.ZodString>;
1430
+ oasOperationId: z.ZodOptional<z.ZodString>;
1431
+ httpMethod: z.ZodOptional<z.ZodString>;
1432
+ pathTemplate: z.ZodOptional<z.ZodString>;
1433
+ includeManual: z.ZodOptional<z.ZodBoolean>;
1434
+ includeRemoved: z.ZodOptional<z.ZodBoolean>;
1435
+ }, z.core.$strip>;
@@ -417,6 +417,83 @@ export const markSemanticTestsDistinctInput = z.object({
417
417
  focusTest: testLocatorSchema,
418
418
  distinctTest: testLocatorSchema,
419
419
  });
420
+ /** LinkedEntityType names for semantic nearby (embedding-capable). */
421
+ export const semanticNearbyEntityTypeSchema = z.enum([
422
+ "STORY",
423
+ "SCENARIO",
424
+ "TEST",
425
+ "ISSUE",
426
+ "EVENT",
427
+ ]);
428
+ export const listSemanticNearbyInput = z
429
+ .object({
430
+ sourceEntityType: semanticNearbyEntityTypeSchema,
431
+ sourceTest: testLocatorSchema.optional(),
432
+ sourceOrdinalId: z.union([z.number(), z.string()]).optional(),
433
+ sourceEventTitle: z.string().optional(),
434
+ targetEntityTypes: z.array(semanticNearbyEntityTypeSchema).optional(),
435
+ limit: z.number().int().positive().optional(),
436
+ })
437
+ .superRefine((val, ctx) => {
438
+ if (val.sourceEntityType === "TEST" && !val.sourceTest) {
439
+ ctx.addIssue({
440
+ code: z.ZodIssueCode.custom,
441
+ message: "TEST requires sourceTest (TestLocator)",
442
+ path: ["sourceTest"],
443
+ });
444
+ }
445
+ if ((val.sourceEntityType === "STORY" ||
446
+ val.sourceEntityType === "SCENARIO" ||
447
+ val.sourceEntityType === "ISSUE") &&
448
+ (val.sourceOrdinalId == null || String(val.sourceOrdinalId).trim() === "")) {
449
+ ctx.addIssue({
450
+ code: z.ZodIssueCode.custom,
451
+ message: `${val.sourceEntityType} requires sourceOrdinalId`,
452
+ path: ["sourceOrdinalId"],
453
+ });
454
+ }
455
+ if (val.sourceEntityType === "EVENT" && !(val.sourceEventTitle ?? "").trim()) {
456
+ ctx.addIssue({
457
+ code: z.ZodIssueCode.custom,
458
+ message: "EVENT requires sourceEventTitle",
459
+ path: ["sourceEventTitle"],
460
+ });
461
+ }
462
+ });
463
+ export const markEntityDistinctInput = z
464
+ .object({
465
+ entityType: semanticNearbyEntityTypeSchema,
466
+ focusTest: testLocatorSchema.optional(),
467
+ otherTest: testLocatorSchema.optional(),
468
+ focusOrdinalId: z.union([z.number(), z.string()]).optional(),
469
+ otherOrdinalId: z.union([z.number(), z.string()]).optional(),
470
+ focusEventTitle: z.string().optional(),
471
+ otherEventTitle: z.string().optional(),
472
+ })
473
+ .superRefine((val, ctx) => {
474
+ if (val.entityType === "TEST") {
475
+ if (!val.focusTest || !val.otherTest) {
476
+ ctx.addIssue({
477
+ code: z.ZodIssueCode.custom,
478
+ message: "TEST requires focusTest and otherTest",
479
+ });
480
+ }
481
+ }
482
+ else if (val.entityType === "EVENT") {
483
+ if (!(val.focusEventTitle ?? "").trim() || !(val.otherEventTitle ?? "").trim()) {
484
+ ctx.addIssue({
485
+ code: z.ZodIssueCode.custom,
486
+ message: "EVENT requires focusEventTitle and otherEventTitle",
487
+ });
488
+ }
489
+ }
490
+ else if (val.focusOrdinalId == null || val.otherOrdinalId == null) {
491
+ ctx.addIssue({
492
+ code: z.ZodIssueCode.custom,
493
+ message: `${val.entityType} requires focusOrdinalId and otherOrdinalId`,
494
+ });
495
+ }
496
+ });
420
497
  /** RequirementSubjectType — proto enum names (JsonFormat camelCase on wire). */
421
498
  export const requirementSubjectTypeSchema = z.enum(["STORY", "SCENARIO"]);
422
499
  /** RequirementFindingSeverity — proto enum names. */
@@ -693,3 +770,47 @@ export const upsertPlansSupportFileInput = z.object({
693
770
  content: z.string().min(1),
694
771
  });
695
772
  export const listWorkflowCatalogInput = z.object({});
773
+ /** API operation coverage (OpenAPI ops + denorm coverage) — CLI ≥ 0.1.28 */
774
+ export const listApiOperationServicesInput = z.object({});
775
+ export const listApiOperationsInput = z.object({
776
+ /** Preferred: repo-relative OpenAPI root path. */
777
+ rootFilePath: z.string().optional(),
778
+ /** Alias for rootFilePath resolution; internal service key. */
779
+ serviceKey: z.string().optional(),
780
+ includeManual: z.boolean().optional(),
781
+ includeRemoved: z.boolean().optional(),
782
+ });
783
+ export const getApiOperationDetailInput = z
784
+ .object({
785
+ /** TestChimp operation id (ULID PK). Preferred. */
786
+ id: z.string().optional(),
787
+ rootFilePath: z.string().optional(),
788
+ serviceKey: z.string().optional(),
789
+ oasOperationId: z.string().optional(),
790
+ httpMethod: z.string().optional(),
791
+ pathTemplate: z.string().optional(),
792
+ includeManual: z.boolean().optional(),
793
+ includeRemoved: z.boolean().optional(),
794
+ })
795
+ .superRefine((v, ctx) => {
796
+ const id = v.id?.trim();
797
+ const root = v.rootFilePath?.trim();
798
+ const service = v.serviceKey?.trim();
799
+ const oas = v.oasOperationId?.trim();
800
+ const method = v.httpMethod?.trim();
801
+ const path = v.pathTemplate?.trim();
802
+ const hasService = !!(root || service);
803
+ if (id)
804
+ return;
805
+ if (oas && hasService)
806
+ return;
807
+ if (method && path && hasService)
808
+ return;
809
+ if (oas && !hasService)
810
+ return; // server allows project-wide oas fallback
811
+ ctx.addIssue({
812
+ code: "custom",
813
+ message: "Provide --id (TestChimp operation ULID), or --root-file-path/--service-key with --oas-operation-id, " +
814
+ "or --root-file-path/--service-key with --http-method and --path-template",
815
+ });
816
+ });
@@ -328,6 +328,8 @@ export const TOOL_DEFINITIONS = [
328
328
  "Use simple fields for common creates, or pass the full curated contract via --json-input " +
329
329
  "(description, issueType, category, severity, status, reportedReleaseId, dueDateMillis, assignee, " +
330
330
  "linkTargets, labels, source, environment, attachments, artifactReference). " +
331
+ "For /testchimp implement TASK_ISSUE creates: set labels=[\"TestChimp Implement\"] (not source), " +
332
+ "severity from task priority, category (e.g. FUNCTIONAL), and linkTargets for STORY and/or SCENARIO ordinals. " +
331
333
  "Optional agentTraceability (or flat workflowId/policyFile/…) records CREATED Activity inline — " +
332
334
  "prefer this over a separate report-agent-action for issue creates. " +
333
335
  "Authenticated via project API key; project is resolved from the key.",
@@ -783,6 +785,75 @@ export const TOOL_DEFINITIONS = [
783
785
  });
784
786
  },
785
787
  },
788
+ {
789
+ kebab: "list-semantic-nearby",
790
+ description: "List semantically nearby entities across types (Story/Scenario/Test/Issue/Event). " +
791
+ "TEST uses TestLocator; STORY/SCENARIO/ISSUE use sourceOrdinalId; EVENT uses sourceEventTitle. " +
792
+ "Response TEST hits include TestLocator (never platform test_id).",
793
+ inputSchema: S.listSemanticNearbyInput,
794
+ execute: async (args, { postMcp }) => {
795
+ const a = args;
796
+ const body = {
797
+ sourceEntityType: a.sourceEntityType,
798
+ };
799
+ if (a.sourceTest)
800
+ body.sourceTest = a.sourceTest;
801
+ if (a.sourceOrdinalId != null)
802
+ body.sourceOrdinalId = Number(a.sourceOrdinalId);
803
+ if (a.sourceEventTitle)
804
+ body.sourceEventTitle = a.sourceEventTitle;
805
+ if (a.targetEntityTypes?.length)
806
+ body.targetEntityTypes = a.targetEntityTypes;
807
+ if (a.limit != null)
808
+ body.limit = a.limit;
809
+ return postMcp("/api/mcp/list_semantic_nearby", body);
810
+ },
811
+ },
812
+ {
813
+ kebab: "mark-entity-distinct",
814
+ description: "Mark two same-type entities as distinct. TEST uses TestLocators; " +
815
+ "STORY/SCENARIO/ISSUE use ordinals; EVENT uses titles.",
816
+ inputSchema: S.markEntityDistinctInput,
817
+ execute: async (args, { postMcp }) => {
818
+ const a = args;
819
+ const body = { entityType: a.entityType };
820
+ if (a.focusTest)
821
+ body.focusTest = a.focusTest;
822
+ if (a.otherTest)
823
+ body.otherTest = a.otherTest;
824
+ if (a.focusOrdinalId != null)
825
+ body.focusOrdinalId = Number(a.focusOrdinalId);
826
+ if (a.otherOrdinalId != null)
827
+ body.otherOrdinalId = Number(a.otherOrdinalId);
828
+ if (a.focusEventTitle)
829
+ body.focusEventTitle = a.focusEventTitle;
830
+ if (a.otherEventTitle)
831
+ body.otherEventTitle = a.otherEventTitle;
832
+ return postMcp("/api/mcp/mark_entity_distinct", body);
833
+ },
834
+ },
835
+ {
836
+ kebab: "unmark-entity-distinct",
837
+ description: "Remove a distinct mark between two same-type entities (same identity rules as mark-entity-distinct).",
838
+ inputSchema: S.markEntityDistinctInput,
839
+ execute: async (args, { postMcp }) => {
840
+ const a = args;
841
+ const body = { entityType: a.entityType };
842
+ if (a.focusTest)
843
+ body.focusTest = a.focusTest;
844
+ if (a.otherTest)
845
+ body.otherTest = a.otherTest;
846
+ if (a.focusOrdinalId != null)
847
+ body.focusOrdinalId = Number(a.focusOrdinalId);
848
+ if (a.otherOrdinalId != null)
849
+ body.otherOrdinalId = Number(a.otherOrdinalId);
850
+ if (a.focusEventTitle)
851
+ body.focusEventTitle = a.focusEventTitle;
852
+ if (a.otherEventTitle)
853
+ body.otherEventTitle = a.otherEventTitle;
854
+ return postMcp("/api/mcp/unmark_entity_distinct", body);
855
+ },
856
+ },
786
857
  {
787
858
  kebab: "get-requirement-quality-report",
788
859
  description: "Fetch the stored requirement quality report (metrics + findings with user states) for a user story or test scenario. " +
@@ -1004,6 +1075,60 @@ export const TOOL_DEFINITIONS = [
1004
1075
  inputSchema: S.listWorkflowCatalogInput,
1005
1076
  execute: async (_args, { postMcp }) => postMcp("/api/mcp/list_workflow_catalog", {}),
1006
1077
  },
1078
+ {
1079
+ kebab: "list-api-operation-services",
1080
+ description: "List API operation service resources for the project (configured OpenAPI root file paths + operation counts). " +
1081
+ "Use rootFilePath as the service resource id for list-api-operations / get-api-operation-detail.",
1082
+ inputSchema: S.listApiOperationServicesInput,
1083
+ execute: async (_args, { postMcp }) => postMcp("/api/mcp/list_api_operation_services", {}),
1084
+ },
1085
+ {
1086
+ kebab: "list-api-operations",
1087
+ description: "List API operations for a service resource with covering-test previews and coverageSummary scores " +
1088
+ "(same payload as the Operations list UI). Prefer --root-file-path (repo-relative OpenAPI root).",
1089
+ inputSchema: S.listApiOperationsInput,
1090
+ execute: async (args, { postMcp }) => {
1091
+ const a = args;
1092
+ const body = {};
1093
+ if (a.rootFilePath != null && a.rootFilePath.trim() !== "")
1094
+ body.rootFilePath = a.rootFilePath.trim();
1095
+ if (a.serviceKey != null && a.serviceKey.trim() !== "")
1096
+ body.serviceKey = a.serviceKey.trim();
1097
+ if (a.includeManual != null)
1098
+ body.includeManual = a.includeManual;
1099
+ if (a.includeRemoved != null)
1100
+ body.includeRemoved = a.includeRemoved;
1101
+ return postMcp("/api/mcp/list_api_operations", body);
1102
+ },
1103
+ },
1104
+ {
1105
+ kebab: "get-api-operation-detail",
1106
+ description: "Fetch detailed API operation coverage (request/query/response fields, response codes, covering tests) — " +
1107
+ "same payload as the Operation detail UI. Prefer TestChimp operation id (--id ULID); " +
1108
+ "or rootFilePath + oasOperationId; or rootFilePath + httpMethod + pathTemplate.",
1109
+ inputSchema: S.getApiOperationDetailInput,
1110
+ execute: async (args, { postMcp }) => {
1111
+ const a = args;
1112
+ const body = {};
1113
+ if (a.id != null && a.id.trim() !== "")
1114
+ body.id = a.id.trim();
1115
+ if (a.rootFilePath != null && a.rootFilePath.trim() !== "")
1116
+ body.rootFilePath = a.rootFilePath.trim();
1117
+ if (a.serviceKey != null && a.serviceKey.trim() !== "")
1118
+ body.serviceKey = a.serviceKey.trim();
1119
+ if (a.oasOperationId != null && a.oasOperationId.trim() !== "")
1120
+ body.oasOperationId = a.oasOperationId.trim();
1121
+ if (a.httpMethod != null && a.httpMethod.trim() !== "")
1122
+ body.httpMethod = a.httpMethod.trim();
1123
+ if (a.pathTemplate != null && a.pathTemplate.trim() !== "")
1124
+ body.pathTemplate = a.pathTemplate.trim();
1125
+ if (a.includeManual != null)
1126
+ body.includeManual = a.includeManual;
1127
+ if (a.includeRemoved != null)
1128
+ body.includeRemoved = a.includeRemoved;
1129
+ return postMcp("/api/mcp/get_api_operation_detail", body);
1130
+ },
1131
+ },
1007
1132
  ];
1008
1133
  const TOOL_BY_KEBAB = new Map(TOOL_DEFINITIONS.map((t) => [t.kebab, t]));
1009
1134
  export function getToolDefinition(kebab) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@testchimp/cli",
3
- "version": "0.1.26",
4
- "description": "TestChimp CLI and MCP server \u2014 coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
3
+ "version": "0.1.28",
4
+ "description": "TestChimp CLI and MCP server \u2014 coverage, plans, EaaS, TrueCoverage, API operations (calls /api/mcp/*)",
5
5
  "type": "module",
6
6
  "main": "dist/bin/testchimp.js",
7
7
  "types": "dist/bin/testchimp.d.ts",