@skyramp/mcp 0.4.4-rc.1 → 0.4.4

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.
Files changed (148) hide show
  1. package/build/index.js +239 -210
  2. package/build/playwright/PlaywrightTraceService.d.ts +1 -1
  3. package/build/playwright/blueprintDigestStore.d.ts +1 -1
  4. package/build/playwright/registerPlaywrightTools.d.ts +1 -1
  5. package/build/playwright/traceRecordingPrompt.d.ts +1 -1
  6. package/build/playwright/traceRecordingPrompt.js +2 -2
  7. package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
  8. package/build/prompts/local-dev/local-dev-prompts.js +2 -2
  9. package/build/prompts/startTraceCollectionPrompts.d.ts +1 -1
  10. package/build/prompts/startTraceCollectionPrompts.js +2 -3
  11. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +1 -1
  12. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +2 -2
  13. package/build/prompts/testbot/testbot-prompts.d.ts +1 -1
  14. package/build/prompts/testbot/testbot-prompts.js +4 -7
  15. package/build/recommendation/answers.d.ts +17 -52
  16. package/build/recommendation/answers.js +29 -99
  17. package/build/recommendation/pullRequestText.d.ts +0 -2
  18. package/build/recommendation/pullRequestText.js +0 -16
  19. package/build/recommendation/registerPlan.d.ts +4 -7
  20. package/build/recommendation/registerPlan.js +11 -37
  21. package/build/recommendation/types.d.ts +4 -21
  22. package/build/recommendation/verifierContracts.d.ts +4 -4
  23. package/build/recommendation/verifierContracts.js +4 -4
  24. package/build/recommendation/verifiers/citedPath.d.ts +2 -2
  25. package/build/recommendation/verifiers/citedPath.js +2 -2
  26. package/build/recommendation/verifiers/issueTraceability.d.ts +5 -1
  27. package/build/recommendation/verifiers/issueTraceability.js +35 -4
  28. package/build/resources/analysisResources.d.ts +1 -1
  29. package/build/resources/analysisResources.js +1 -1
  30. package/build/resources/progressResource.d.ts +1 -1
  31. package/build/resources/sutSetupResource.d.ts +1 -1
  32. package/build/resources/sutSetupResource.js +1 -1
  33. package/build/resources/testbotResource.d.ts +1 -1
  34. package/build/resources/testbotResource.js +1 -1
  35. package/build/services/AnalyticsService.d.ts +1 -1
  36. package/build/services/FleetExecutionService.d.ts +130 -0
  37. package/build/services/FleetExecutionService.js +391 -0
  38. package/build/services/ModularizationService.d.ts +1 -1
  39. package/build/services/TestExecutionService.d.ts +7 -0
  40. package/build/services/TestExecutionService.js +21 -0
  41. package/build/services/TestGenerationService.d.ts +1 -1
  42. package/build/tool-phases.js +2 -0
  43. package/build/tools/auth/loginTool.d.ts +1 -1
  44. package/build/tools/auth/loginTool.js +2 -2
  45. package/build/tools/auth/logoutTool.d.ts +1 -1
  46. package/build/tools/auth/logoutTool.js +2 -2
  47. package/build/tools/code-refactor/alignAssertionsTool.d.ts +1 -1
  48. package/build/tools/code-refactor/alignAssertionsTool.js +1 -1
  49. package/build/tools/code-refactor/assertionSkillTools.d.ts +1 -1
  50. package/build/tools/code-refactor/assertionSkillTools.js +2 -2
  51. package/build/tools/code-refactor/codeReuseTool.d.ts +1 -1
  52. package/build/tools/code-refactor/codeReuseTool.js +2 -2
  53. package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +1 -1
  54. package/build/tools/code-refactor/enhanceAssertionsTool.js +1 -1
  55. package/build/tools/code-refactor/modularizationTool.d.ts +1 -1
  56. package/build/tools/code-refactor/modularizationTool.js +2 -2
  57. package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
  58. package/build/tools/enrichTestWithMocksTool.js +2 -2
  59. package/build/tools/executeFleetTool.d.ts +28 -0
  60. package/build/tools/executeFleetTool.js +107 -0
  61. package/build/tools/executeSkyrampTestTool.d.ts +8 -5
  62. package/build/tools/executeSkyrampTestTool.js +5 -5
  63. package/build/tools/fixErrorTool.d.ts +1 -1
  64. package/build/tools/fixErrorTool.js +1 -1
  65. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +6 -57
  66. package/build/tools/generate-tests/batchMockGenerationTool.js +3 -3
  67. package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +9 -45
  68. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +29 -11
  69. package/build/tools/generate-tests/generateContractRestTool.d.ts +1 -2
  70. package/build/tools/generate-tests/generateContractRestTool.js +1 -1
  71. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -2
  72. package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
  73. package/build/tools/generate-tests/generateFuzzRestTool.d.ts +1 -1
  74. package/build/tools/generate-tests/generateFuzzRestTool.js +1 -1
  75. package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +1 -2
  76. package/build/tools/generate-tests/generateIntegrationRestTool.js +1 -1
  77. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -2
  78. package/build/tools/generate-tests/generateLoadRestTool.js +2 -1
  79. package/build/tools/generate-tests/generateMockRestTool.d.ts +1 -2
  80. package/build/tools/generate-tests/generateMockRestTool.js +3 -3
  81. package/build/tools/generate-tests/generateSmokeRestTool.d.ts +1 -1
  82. package/build/tools/generate-tests/generateSmokeRestTool.js +1 -1
  83. package/build/tools/generate-tests/generateUILoadRestTool.d.ts +64 -0
  84. package/build/tools/generate-tests/generateUILoadRestTool.js +512 -0
  85. package/build/tools/generate-tests/generateUIRestTool.d.ts +6 -7
  86. package/build/tools/generate-tests/generateUIRestTool.js +1 -1
  87. package/build/tools/generate-tests/loadTestSchema.d.ts +15 -15
  88. package/build/tools/generate-tests/trace-reuse-guard.d.ts +1 -1
  89. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +1 -2
  90. package/build/tools/generateEnrichedIntegrationTestTool.js +1 -1
  91. package/build/tools/localDevWorkerComposeTool.d.ts +1 -1
  92. package/build/tools/localDevWorkerComposeTool.js +2 -2
  93. package/build/tools/one-click/oneClickTool.d.ts +1 -1
  94. package/build/tools/one-click/oneClickTool.js +1 -1
  95. package/build/tools/preflightMockCheckTool.d.ts +1 -1
  96. package/build/tools/preflightMockCheckTool.js +3 -3
  97. package/build/tools/queryProxyMocksTool.d.ts +1 -1
  98. package/build/tools/queryProxyMocksTool.js +3 -3
  99. package/build/tools/submitReportTool.d.ts +111 -414
  100. package/build/tools/submitReportTool.js +154 -138
  101. package/build/tools/test-management/actionsTool.d.ts +1 -1
  102. package/build/tools/test-management/actionsTool.js +7 -7
  103. package/build/tools/test-management/analyzeChangesTool.d.ts +22 -118
  104. package/build/tools/test-management/analyzeChangesTool.js +4 -4
  105. package/build/tools/test-management/analyzeTestHealthTool.d.ts +1 -1
  106. package/build/tools/test-management/analyzeTestHealthTool.js +4 -4
  107. package/build/tools/test-management/registerTestPlanTool.d.ts +111 -743
  108. package/build/tools/test-management/registerTestPlanTool.js +20 -36
  109. package/build/tools/test-management/resolveScreenTool.d.ts +1 -1
  110. package/build/tools/test-management/resolveScreenTool.js +6 -2
  111. package/build/tools/trace/startTraceCollectionTool.d.ts +1 -1
  112. package/build/tools/trace/startTraceCollectionTool.js +4 -4
  113. package/build/tools/trace/stopTraceCollectionTool.d.ts +1 -1
  114. package/build/tools/trace/stopTraceCollectionTool.js +2 -2
  115. package/build/tools/verifyTestDependenciesTool.d.ts +1 -1
  116. package/build/tools/verifyTestDependenciesTool.js +1 -1
  117. package/build/tools/workspace/initScanWorkspaceTool.d.ts +1 -1
  118. package/build/tools/workspace/initScanWorkspaceTool.js +1 -1
  119. package/build/tools/workspace/initializeWorkspaceTool.d.ts +1 -1
  120. package/build/tools/workspace/initializeWorkspaceTool.js +1 -1
  121. package/build/types/RepositoryAnalysis.d.ts +164 -1170
  122. package/build/types/RepositoryAnalysis.js +12 -10
  123. package/build/types/StepMethod.d.ts +24 -1
  124. package/build/types/StepMethod.js +1 -1
  125. package/build/types/TestTypes.d.ts +34 -133
  126. package/build/types/TestTypes.js +3 -3
  127. package/build/types/TestbotReport.d.ts +37 -0
  128. package/build/types/TestbotReport.js +22 -0
  129. package/build/types/index.d.ts +1 -1
  130. package/build/types/index.js +1 -1
  131. package/build/utils/docker.d.ts +29 -7
  132. package/build/utils/docker.js +83 -27
  133. package/build/utils/initAgent.d.ts +3 -3
  134. package/build/utils/initAgent.js +58 -26
  135. package/build/utils/progress.d.ts +3 -4
  136. package/build/utils/progress.js +4 -4
  137. package/build/utils/utils.d.ts +1 -1
  138. package/build/utils/versions.d.ts +3 -3
  139. package/build/utils/versions.js +1 -1
  140. package/build/workspace/workspace.d.ts +117 -538
  141. package/build/workspace/workspace.js +2 -2
  142. package/package.json +6 -5
  143. package/plugin/prompts/testbot-task1.md +1 -1
  144. package/plugin/skills/repair-staged-files/SKILL.md +17 -0
  145. package/build/recommendation/blockerProbes.d.ts +0 -13
  146. package/build/recommendation/blockerProbes.js +0 -91
  147. package/build/recommendation/blockers.d.ts +0 -65
  148. package/build/recommendation/blockers.js +0 -135
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
+ export declare const fleetExecutionInputSchema: {
4
+ directory: z.ZodString;
5
+ entryClass: z.ZodOptional<z.ZodString>;
6
+ certsDir: z.ZodString;
7
+ credentials: z.ZodOptional<z.ZodString>;
8
+ libraryJar: z.ZodOptional<z.ZodString>;
9
+ executorImage: z.ZodOptional<z.ZodString>;
10
+ platform: z.ZodOptional<z.ZodEnum<{
11
+ linux: "linux";
12
+ windows: "windows";
13
+ }>>;
14
+ timeoutSec: z.ZodOptional<z.ZodNumber>;
15
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
16
+ };
17
+ /**
18
+ * Runs a generated fleet test and reports what happened.
19
+ *
20
+ * Generation ends at three files someone still has to run. This closes that loop: the same
21
+ * executor container every other generated test runs in compiles the trio and starts the
22
+ * fleet manager, and the caller gets the run's own report plus its result as data.
23
+ *
24
+ * The worker is deployed by the test, not by this tool, so the run needs a remote Docker
25
+ * engine: inside a container, a locally deployed worker is not reachable at the localhost
26
+ * address the fleet resolves for it.
27
+ */
28
+ export declare function registerExecuteFleetTool(server: McpServer): void;
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ import { executeFleet, JAVA_CLASS_NAME, } from "../services/FleetExecutionService.js";
3
+ import { logger } from "../utils/logger.js";
4
+ import { toolError } from "../utils/utils.js";
5
+ const TOOL_NAME = "skyramp_execute_fleet";
6
+ export const fleetExecutionInputSchema = {
7
+ directory: z
8
+ .string()
9
+ .describe("Directory holding a generated Java ui-load trio (the fleet, load and journey " +
10
+ "classes) and, usually, its credentials.csv. Java only: a python, typescript or " +
11
+ "javascript fleet manager is a script, run it directly."),
12
+ entryClass: z
13
+ .string()
14
+ .regex(JAVA_CLASS_NAME)
15
+ .optional()
16
+ .describe("The fleet class to run. Discovered from *FleetTest.java when omitted."),
17
+ certsDir: z
18
+ .string()
19
+ .describe("Docker client certificates for the remote engine (ca.pem, cert.pem, key.pem). " +
20
+ "Required: the run needs a remote engine, and a remote engine is mTLS. Mounted " +
21
+ "read-only and exported as SKYRAMP_DOCKER_CERTS."),
22
+ credentials: z
23
+ .string()
24
+ .optional()
25
+ .describe("Credential pool file. Defaults to credentials.csv beside the test."),
26
+ libraryJar: z
27
+ .string()
28
+ .optional()
29
+ .describe("A branch-built skyramp-library jar to compile and run against, for a fix that is not " +
30
+ "released yet. The executor image's own SDK is used when this is omitted."),
31
+ executorImage: z
32
+ .string()
33
+ .optional()
34
+ .describe("Container image to compile and run in. Defaults to the released executor, or " +
35
+ "SKYRAMP_EXECUTOR_IMAGE. Name a branch-built one when its baked SDK is what you " +
36
+ "are testing."),
37
+ platform: z
38
+ .enum(["linux", "windows"])
39
+ .optional()
40
+ .describe("The daemon's container OS. Omit it to use the daemon's own OS. If given, it " +
41
+ "must match the daemon, or the run is refused."),
42
+ timeoutSec: z
43
+ .number()
44
+ .int()
45
+ .positive()
46
+ .optional()
47
+ .describe("Seconds before the run is killed. Default 600."),
48
+ env: z
49
+ .record(z.string(), z.string())
50
+ .optional()
51
+ .describe("Extra environment for the run, e.g. SKYRAMP_TEST_BASE_URL."),
52
+ };
53
+ /**
54
+ * Runs a generated fleet test and reports what happened.
55
+ *
56
+ * Generation ends at three files someone still has to run. This closes that loop: the same
57
+ * executor container every other generated test runs in compiles the trio and starts the
58
+ * fleet manager, and the caller gets the run's own report plus its result as data.
59
+ *
60
+ * The worker is deployed by the test, not by this tool, so the run needs a remote Docker
61
+ * engine: inside a container, a locally deployed worker is not reachable at the localhost
62
+ * address the fleet resolves for it.
63
+ */
64
+ export function registerExecuteFleetTool(server) {
65
+ server.registerTool(TOOL_NAME, {
66
+ title: "Execute a generated fleet test",
67
+ description: "Compile and run a generated Java ui-load fleet trio in the Skyramp executor container, " +
68
+ "against a remote Docker engine, and return the run's report, its verdict and its " +
69
+ "structured result. Point it at the directory the generation wrote.",
70
+ inputSchema: z.object(fleetExecutionInputSchema),
71
+ }, async (args) => {
72
+ try {
73
+ const run = await executeFleet({
74
+ directory: args.directory,
75
+ executorImage: args.executorImage,
76
+ platform: args.platform,
77
+ entryClass: args.entryClass,
78
+ certsDir: args.certsDir,
79
+ credentials: args.credentials,
80
+ libraryJar: args.libraryJar,
81
+ timeoutSec: args.timeoutSec,
82
+ env: args.env,
83
+ });
84
+ const headline = run.timedOut
85
+ ? `Fleet run timed out after ${args.timeoutSec ?? 600}s`
86
+ : `Fleet run ${run.passed ? "PASSED" : "FAILED"} (${run.entryClass} in ${run.executorImage}, exit ${run.exitCode})`;
87
+ const text = [
88
+ headline,
89
+ run.report || "(the run printed no report lines)",
90
+ run.result
91
+ ? "Structured result:\n" + JSON.stringify(run.result, null, 2)
92
+ : "",
93
+ run.passed ? "" : "Output:\n" + run.output.slice(-4000),
94
+ ]
95
+ .filter(Boolean)
96
+ .join("\n\n");
97
+ return {
98
+ content: [{ type: "text", text }],
99
+ ...(run.passed ? {} : { isError: true }),
100
+ };
101
+ }
102
+ catch (error) {
103
+ logger.error(`${TOOL_NAME} failed: ${error}`);
104
+ return toolError(error instanceof Error ? error.message : String(error));
105
+ }
106
+ });
107
+ }
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
3
  import { TestExecutionStatus, TestExecutionResult, type TestExecutionRecord } from "../types/TestExecution.js";
4
4
  import { ProgrammingLanguage, TestType } from "../types/TestTypes.js";
5
5
  import { MaintenanceActionCore, TestAnalysisResult } from "../types/TestAnalysis.js";
@@ -178,14 +178,17 @@ export declare const inputSchema: {
178
178
  cwd: z.ZodOptional<z.ZodString>;
179
179
  workspacePath: z.ZodOptional<z.ZodString>;
180
180
  testFile: z.ZodString;
181
- language: z.ZodNativeEnum<typeof ProgrammingLanguage>;
182
- testType: z.ZodNativeEnum<typeof TestType>;
183
- phase: z.ZodDefault<z.ZodEnum<["before", "after"]>>;
181
+ language: z.ZodEnum<typeof ProgrammingLanguage>;
182
+ testType: z.ZodEnum<typeof TestType>;
183
+ phase: z.ZodDefault<z.ZodEnum<{
184
+ before: "before";
185
+ after: "after";
186
+ }>>;
184
187
  stateFile: z.ZodOptional<z.ZodString>;
185
188
  repository: z.ZodString;
186
189
  token: z.ZodOptional<z.ZodString>;
187
190
  unauthenticated: z.ZodOptional<z.ZodBoolean>;
188
- rebaselineSnapshots: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
191
+ rebaselineSnapshots: z.ZodOptional<z.ZodArray<z.ZodString>>;
189
192
  timeout: z.ZodOptional<z.ZodNumber>;
190
193
  };
191
194
  export declare function registerExecuteSkyrampTestTool(server: McpServer): void;
@@ -654,10 +654,10 @@ export const inputSchema = {
654
654
  .describe("Absolute path of the Skyramp workspace. Required when commandOverride is omitted, because the executor resolves the service and its base URL from it."),
655
655
  testFile: z.string().describe("Absolute path to the test file to execute."),
656
656
  language: z
657
- .nativeEnum(ProgrammingLanguage)
657
+ .enum(ProgrammingLanguage)
658
658
  .describe("Programming language of the test file to execute (e.g., python, javascript, typescript, java)"),
659
659
  testType: z
660
- .nativeEnum(TestType)
660
+ .enum(TestType)
661
661
  .describe("Type of the test to execute. Note: 'mock' is NOT a valid test type — mock files are deployed via their apply_mock() function, not executed as tests."),
662
662
  phase: z
663
663
  .enum(["before", "after"])
@@ -1035,12 +1035,12 @@ export function registerExecuteSkyrampTestTool(server) {
1035
1035
  idempotentHint: false,
1036
1036
  openWorldHint: true,
1037
1037
  },
1038
- inputSchema,
1038
+ inputSchema: z.object(inputSchema),
1039
1039
  _meta: {
1040
1040
  keywords: ["run test", "execute test"],
1041
1041
  },
1042
- }, async (params, extra) => {
1043
- const sendProgress = makeProgressReporter(extra);
1042
+ }, async (params, ctx) => {
1043
+ const sendProgress = makeProgressReporter(ctx);
1044
1044
  // Progress callback adapter for TestExecutionService.
1045
1045
  const onExecutionProgress = async (progress) => {
1046
1046
  await sendProgress(progress.percent, 100, progress.message);
@@ -1,2 +1,2 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  export declare function registerFixErrorTool(server: McpServer): void;
@@ -18,7 +18,7 @@ const TOOL_NAME = "skyramp_fix_errors";
18
18
  export function registerFixErrorTool(server) {
19
19
  server.registerTool(TOOL_NAME, {
20
20
  description: "Return guidance for repairing test reference, syntax, import, and missing-dependency errors while preserving the scenario, expected behavior, and assertion strength.",
21
- inputSchema: fixErrorSchema.shape,
21
+ inputSchema: fixErrorSchema,
22
22
  _meta: {
23
23
  keywords: [
24
24
  "modularization",
@@ -1,15 +1,14 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer, CallToolResult } from "@modelcontextprotocol/server";
2
2
  import { z } from "zod";
3
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
3
  import { MockProtocol } from "../../types/TestTypes.js";
5
4
  export { MockProtocol } from "../../types/TestTypes.js";
6
5
  export declare const BATCH_MOCK_PROTOCOL_EXAMPLES = "\n<example protocol=\"rest\">\nBatch REST item. Required fields: protocol=\"rest\", endpointURL, method unless apiSchema is provided.\n{\n \"protocol\": \"rest\",\n \"endpointURL\": \"http://identity-service:4000/api/internal/v1/users/validate\",\n \"method\": \"POST\",\n \"requestAware\": true,\n \"responseData\": \"{\"valid\":true}\"\n}\n</example>\n\n<example protocol=\"rest-traffic-simulation\">\nBatch REST item with traffic simulation. minLatency/maxLatency inject a random delay per response; dropRate drops a percentage of requests.\n{\n \"protocol\": \"rest\",\n \"endpointURL\": \"http://payment-service:5001/payments\",\n \"method\": \"POST\",\n \"responseData\": \"{\"status\":\"ok\"}\",\n \"minLatency\": 500,\n \"maxLatency\": 1000,\n \"dropRate\": 10\n}\n</example>\n\n<example protocol=\"rest-conditional\">\nBatch REST item with conditional response selection. Use \"when\" to match request fields.\n{\n \"protocol\": \"rest\",\n \"endpointURL\": \"http://payment-service:5001/api/v1/orders\",\n \"method\": \"POST\",\n \"when\": {\"request.body.payment.method\": \"card\"},\n \"requestSchema\": \"{\"type\":\"object\",\"required\":[\"orderId\",\"payment\"]}\",\n \"responseData\": \"{\"status\":\"confirmed\"}\",\n \"responseStatusCode\": \"201\",\n \"noMatchStatusCode\": 404,\n \"validationFailureStatusCode\": 422\n}\n</example>\n\n<example protocol=\"grpc\">\nBatch gRPC item. Required fields: protocol=\"grpc\", endpointURL as host:port, protoPath, grpcServiceName. method is the RPC name; empty means all service methods.\n{\n \"protocol\": \"grpc\",\n \"endpointURL\": \"profile-service:50051\",\n \"protoPath\": \"/repo/proto/profiles.proto\",\n \"grpcServiceName\": \"ProfileService\",\n \"method\": \"GetProfile\",\n \"responseData\": \"{\"id\":\"profile_123\"}\"\n}\n</example>\n\n<example protocol=\"grpc-traffic-simulation\">\nBatch gRPC item with traffic simulation. Same latency/drop fields as REST.\n{\n \"protocol\": \"grpc\",\n \"endpointURL\": \"profile-service:50051\",\n \"protoPath\": \"/repo/proto/profiles.proto\",\n \"grpcServiceName\": \"ProfileService\",\n \"method\": \"GetProfile\",\n \"responseData\": \"{\"eligible\":true}\",\n \"minLatency\": 200,\n \"maxLatency\": 800,\n \"dropRate\": 5\n}\n</example>\n\n<example protocol=\"grpc-status-error\">\nBatch gRPC status error item. Do not provide responseData with grpcStatusCode.\n{\n \"protocol\": \"grpc\",\n \"endpointURL\": \"profile-service:50051\",\n \"protoPath\": \"/repo/proto/profiles.proto\",\n \"grpcServiceName\": \"ProfileService\",\n \"method\": \"GetProfile\",\n \"grpcStatusCode\": 5,\n \"grpcStatusMessage\": \"profile not found\"\n}\n</example>\n\n<example protocol=\"kafka-producer\">\nBatch Kafka producer validation item. Required fields: protocol=\"kafka\", endpointURL as broker host:port, kafkaTopic, and requestData. Do not pass method or responseData. Traffic simulation is NOT supported for Kafka.\n{\n \"protocol\": \"kafka\",\n \"endpointURL\": \"broker:9092\",\n \"kafkaTopic\": \"orders\",\n \"requestData\": \"{\"order_id\":\"ord_123\"}\"\n}\n</example>\n\n<example protocol=\"kafka-consumer\">\nBatch Kafka consumer message item. Required fields: protocol=\"kafka\", endpointURL as broker host:port, kafkaTopic, and responseData. Do not pass method or requestData. Traffic simulation is NOT supported for Kafka.\n{\n \"protocol\": \"kafka\",\n \"endpointURL\": \"broker:9092\",\n \"kafkaTopic\": \"orders\",\n \"responseData\": \"{\"accepted\":true}\"\n}\n</example>";
7
6
  declare const mockSpecSchema: z.ZodObject<{
8
- protocol: z.ZodDefault<z.ZodNativeEnum<typeof MockProtocol>>;
7
+ protocol: z.ZodDefault<z.ZodEnum<typeof MockProtocol>>;
9
8
  endpointURL: z.ZodString;
10
9
  method: z.ZodDefault<z.ZodString>;
11
10
  responseData: z.ZodOptional<z.ZodString>;
12
- responseStatusCode: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
11
+ responseStatusCode: z.ZodDefault<z.ZodString>;
13
12
  grpcStatusCode: z.ZodOptional<z.ZodNumber>;
14
13
  grpcStatusMessage: z.ZodOptional<z.ZodString>;
15
14
  requestData: z.ZodDefault<z.ZodString>;
@@ -17,8 +16,8 @@ declare const mockSpecSchema: z.ZodObject<{
17
16
  apiSchema: z.ZodDefault<z.ZodString>;
18
17
  protoPath: z.ZodOptional<z.ZodString>;
19
18
  grpcServiceName: z.ZodOptional<z.ZodString>;
20
- protobufExtraFiles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
21
- protobufExtraImportPath: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
19
+ protobufExtraFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
20
+ protobufExtraImportPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
21
  kafkaTopic: z.ZodOptional<z.ZodString>;
23
22
  minLatency: z.ZodOptional<z.ZodNumber>;
24
23
  maxLatency: z.ZodOptional<z.ZodNumber>;
@@ -29,57 +28,7 @@ declare const mockSpecSchema: z.ZodObject<{
29
28
  validationFailureStatusCode: z.ZodOptional<z.ZodNumber>;
30
29
  output: z.ZodOptional<z.ZodString>;
31
30
  outputDir: z.ZodOptional<z.ZodString>;
32
- }, "strip", z.ZodTypeAny, {
33
- method: string;
34
- endpointURL: string;
35
- apiSchema: string;
36
- requestData: string;
37
- responseStatusCode: string;
38
- protocol: MockProtocol;
39
- requestAware: boolean;
40
- output?: string | undefined;
41
- outputDir?: string | undefined;
42
- responseData?: string | undefined;
43
- when?: Record<string, unknown> | undefined;
44
- protoPath?: string | undefined;
45
- grpcServiceName?: string | undefined;
46
- protobufExtraFiles?: string[] | undefined;
47
- protobufExtraImportPath?: string[] | undefined;
48
- kafkaTopic?: string | undefined;
49
- grpcStatusCode?: number | undefined;
50
- grpcStatusMessage?: string | undefined;
51
- minLatency?: number | undefined;
52
- maxLatency?: number | undefined;
53
- dropRate?: number | undefined;
54
- requestSchema?: string | undefined;
55
- noMatchStatusCode?: number | undefined;
56
- validationFailureStatusCode?: number | undefined;
57
- }, {
58
- endpointURL: string;
59
- output?: string | undefined;
60
- outputDir?: string | undefined;
61
- method?: string | undefined;
62
- apiSchema?: string | undefined;
63
- requestData?: string | undefined;
64
- responseStatusCode?: string | undefined;
65
- responseData?: string | undefined;
66
- when?: Record<string, unknown> | undefined;
67
- protocol?: MockProtocol | undefined;
68
- protoPath?: string | undefined;
69
- grpcServiceName?: string | undefined;
70
- protobufExtraFiles?: string[] | undefined;
71
- protobufExtraImportPath?: string[] | undefined;
72
- kafkaTopic?: string | undefined;
73
- grpcStatusCode?: number | undefined;
74
- grpcStatusMessage?: string | undefined;
75
- requestAware?: boolean | undefined;
76
- minLatency?: number | undefined;
77
- maxLatency?: number | undefined;
78
- dropRate?: number | undefined;
79
- requestSchema?: string | undefined;
80
- noMatchStatusCode?: number | undefined;
81
- validationFailureStatusCode?: number | undefined;
82
- }>;
31
+ }, z.core.$strip>;
83
32
  export type MockSpec = z.infer<typeof mockSpecSchema>;
84
33
  export type MockSpecInput = z.input<typeof mockSpecSchema>;
85
34
  export interface BatchMockResult {
@@ -112,7 +112,7 @@ Batch Kafka consumer message item. Required fields: protocol="kafka", endpointUR
112
112
  </example>`;
113
113
  const mockSpecSchema = z.object({
114
114
  protocol: z
115
- .nativeEnum(MockProtocol)
115
+ .enum(MockProtocol)
116
116
  .default(MockProtocol.Rest)
117
117
  .describe("Protocol for this mock: 'rest', 'grpc', or 'kafka'. See <example> blocks in the tool description for required fields."),
118
118
  endpointURL: z
@@ -198,7 +198,7 @@ const mockSpecSchema = z.object({
198
198
  .optional()
199
199
  .describe("Percentage [0-100] of requests dropped/errored for traffic simulation (REST and gRPC only)."),
200
200
  when: z
201
- .record(z.unknown())
201
+ .record(z.string(), z.unknown())
202
202
  .optional()
203
203
  .describe("Conditional-selection predicate (operator map) for REST and gRPC mocks. " +
204
204
  "Keys are request paths (request.body.<jsonpath>, request.path.<name>, etc.); " +
@@ -559,7 +559,7 @@ Use this tool when you need to mock 2+ downstream services simultaneously (e.g.,
559
559
  local-dev workflow with multiple dependencies).
560
560
 
561
561
  ${BATCH_MOCK_PROTOCOL_EXAMPLES}`,
562
- inputSchema: batchMockSchema,
562
+ inputSchema: z.object(batchMockSchema),
563
563
  }, async (params) => {
564
564
  const result = await executeBatchMockGeneration(params);
565
565
  AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch(() => {
@@ -1,50 +1,14 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  import { z } from "zod";
3
3
  import { HttpMethod } from "../../types/TestTypes.js";
4
- export declare const stepSchema: z.ZodEffects<z.ZodObject<{
5
- method: z.ZodNativeEnum<typeof HttpMethod>;
4
+ export declare const stepSchema: z.ZodObject<{
5
+ method: z.ZodEnum<typeof HttpMethod>;
6
6
  path: z.ZodString;
7
- requestBody: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
8
- queryParams: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
9
- responseBody: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
7
+ requestBody: z.ZodOptional<z.ZodString>;
8
+ queryParams: z.ZodOptional<z.ZodString>;
9
+ responseBody: z.ZodOptional<z.ZodString>;
10
10
  statusCode: z.ZodOptional<z.ZodNumber>;
11
- responseHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
12
- uniqueFields: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
13
- }, "strip", z.ZodTypeAny, {
14
- path: string;
15
- method: HttpMethod;
16
- queryParams?: string | undefined;
17
- statusCode?: number | undefined;
18
- requestBody?: string | undefined;
19
- responseBody?: string | undefined;
20
- responseHeaders?: Record<string, string[]> | undefined;
21
- uniqueFields?: string[] | undefined;
22
- }, {
23
- path: string;
24
- method: HttpMethod;
25
- queryParams?: string | undefined;
26
- statusCode?: number | undefined;
27
- requestBody?: string | undefined;
28
- responseBody?: string | undefined;
29
- responseHeaders?: Record<string, string[]> | undefined;
30
- uniqueFields?: string[] | undefined;
31
- }>, {
32
- path: string;
33
- method: HttpMethod;
34
- queryParams?: string | undefined;
35
- statusCode?: number | undefined;
36
- requestBody?: string | undefined;
37
- responseBody?: string | undefined;
38
- responseHeaders?: Record<string, string[]> | undefined;
39
- uniqueFields?: string[] | undefined;
40
- }, {
41
- path: string;
42
- method: HttpMethod;
43
- queryParams?: string | undefined;
44
- statusCode?: number | undefined;
45
- requestBody?: string | undefined;
46
- responseBody?: string | undefined;
47
- responseHeaders?: Record<string, string[]> | undefined;
48
- uniqueFields?: string[] | undefined;
49
- }>;
11
+ responseHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
12
+ uniqueFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
13
+ }, z.core.$strip>;
50
14
  export declare function registerBatchScenarioTestTool(server: McpServer): void;
@@ -1,5 +1,6 @@
1
1
  import { TOOL_BATCH_SCENARIO_TEST_GENERATION } from "../../toolNames.js";
2
2
  import { z } from "zod";
3
+ import os from "os";
3
4
  import path from "path";
4
5
  import { ScenarioGenerationService, } from "../../services/ScenarioGenerationService.js";
5
6
  import fs from "fs";
@@ -14,7 +15,22 @@ import { guardScenarioApproved } from "./planGuard.js";
14
15
  import { lintScenarioChaining } from "./scenarioLint.js";
15
16
  import { scenarioFileNameFor } from "./scenarioFileIdentity.js";
16
17
  import { toolError } from "../../utils/utils.js";
18
+ import { isTestbotEnabled } from "../../utils/featureFlags.js";
17
19
  import { isRecord } from "ts-is-record";
20
+ /**
21
+ * Where the scenario file is written. The file is only an input to integration
22
+ * generation — the generated test does not read it — so a Testbot run writes it
23
+ * outside the checkout, where staging the test directory cannot put it in the
24
+ * Testbot PR (SKYR-4552). A fresh directory per call keeps two same-named
25
+ * scenarios (one per related repo) from overwriting each other. Everywhere
26
+ * else it goes next to the test, as before.
27
+ */
28
+ function scenarioFilePath(outputDir, fileName) {
29
+ if (!isTestbotEnabled())
30
+ return path.join(outputDir, fileName);
31
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-scenario-"));
32
+ return path.join(dir, fileName);
33
+ }
18
34
  function isJsonValue(v) {
19
35
  if (v === undefined || v === null)
20
36
  return true;
@@ -51,7 +67,7 @@ function isJsonObject(v) {
51
67
  }
52
68
  export const stepSchema = z
53
69
  .object({
54
- method: z.nativeEnum(HttpMethod).describe("HTTP method for this step."),
70
+ method: z.enum(HttpMethod).describe("HTTP method for this step."),
55
71
  path: z
56
72
  .string()
57
73
  .startsWith("/", {
@@ -103,7 +119,7 @@ Workspace-configured api.defaultQueryParams (if set) are merged into every step
103
119
  .optional()
104
120
  .describe("Expected HTTP status code. Defaults: DELETE→204 and GET/PUT/PATCH→200. For POST, pass the confirmed statusCode explicitly after checking whether the endpoint creates a resource (commonly 201) or performs an action (often 200)."),
105
121
  responseHeaders: z
106
- .record(z.array(z.string()))
122
+ .record(z.string(), z.array(z.string()))
107
123
  .optional()
108
124
  .describe("Response headers as a JSON object. Defaults to Content-Type: application/json."),
109
125
  uniqueFields: z
@@ -134,7 +150,7 @@ Workspace-configured api.defaultQueryParams (if set) are merged into every step
134
150
  if (step.uniqueFields && step.uniqueFields.length > 0) {
135
151
  if (!isBodyMethod) {
136
152
  ctx.addIssue({
137
- code: z.ZodIssueCode.custom,
153
+ code: "custom",
138
154
  path: ["uniqueFields"],
139
155
  message: `uniqueFields is only valid on POST/PUT/PATCH steps (got ${step.method} ${step.path}). ` +
140
156
  `Omit it for GET/DELETE steps.`,
@@ -142,7 +158,7 @@ Workspace-configured api.defaultQueryParams (if set) are merged into every step
142
158
  }
143
159
  else if (!step.requestBody) {
144
160
  ctx.addIssue({
145
- code: z.ZodIssueCode.custom,
161
+ code: "custom",
146
162
  path: ["uniqueFields"],
147
163
  message: `uniqueFields is set for ${step.method} ${step.path} but there is no requestBody ` +
148
164
  `containing those fields.`,
@@ -152,7 +168,7 @@ Workspace-configured api.defaultQueryParams (if set) are merged into every step
152
168
  for (const fieldPath of step.uniqueFields) {
153
169
  if (!resolvesInJson(parsedBody, fieldPath)) {
154
170
  ctx.addIssue({
155
- code: z.ZodIssueCode.custom,
171
+ code: "custom",
156
172
  path: ["uniqueFields"],
157
173
  message: `uniqueFields path "${fieldPath}" does not resolve in the requestBody of ` +
158
174
  `${step.method} ${step.path}. The generator silently skips unresolvable paths, ` +
@@ -169,7 +185,7 @@ Workspace-configured api.defaultQueryParams (if set) are merged into every step
169
185
  !Array.isArray(parsedBody) &&
170
186
  Object.keys(parsedBody).length === 0) {
171
187
  ctx.addIssue({
172
- code: z.ZodIssueCode.custom,
188
+ code: "custom",
173
189
  path: ["requestBody"],
174
190
  message: `requestBody for ${step.method} ${step.path} is an empty object {}. ` +
175
191
  `Provide actual field values from the source code schema (Pydantic model, Zod type, DTO) — ` +
@@ -244,7 +260,7 @@ If a step fails, the error shows which step (N/total), method+path, and reason.
244
260
 
245
261
  ### After this tool
246
262
  Call \`skyramp_integration_test_generation\` with the returned \`scenarioFile\` path. Do NOT also pass \`apiSchema\` or \`endpointURL\` — the scenario file already contains all endpoint information and passing both will cause test generation to fail.`,
247
- inputSchema: batchScenarioSchema,
263
+ inputSchema: z.object(batchScenarioSchema),
248
264
  }, async (params) => {
249
265
  const guardMessage = await guardScenarioApproved({
250
266
  scenarioName: params.scenarioName,
@@ -526,14 +542,16 @@ Call \`skyramp_integration_test_generation\` with the returned \`scenarioFile\`
526
542
  ? `\n\n⚠️ **Chaining warnings** — the generated test may hardcode these instead of chaining:\n` +
527
543
  chainLint.warnings.map((w) => ` - ${w}`).join("\n")
528
544
  : "";
545
+ let writtenPath;
529
546
  try {
547
+ writtenPath = scenarioFilePath(params.outputDir, fileName);
530
548
  // The contract and integration generators create the test directory through
531
549
  // the SDK, so a batch scenario that is the FIRST call into a new directory
532
550
  // wrote into one that was not there and returned ENOENT. Same shape as
533
551
  // batchMockGenerationTool.ts, and inside the try so a mkdir failure reads
534
552
  // like a write failure.
535
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
536
- fs.writeFileSync(filePath, JSON.stringify(traceRequests, null, 2), "utf8");
553
+ fs.mkdirSync(path.dirname(writtenPath), { recursive: true });
554
+ fs.writeFileSync(writtenPath, JSON.stringify(traceRequests, null, 2), "utf8");
537
555
  }
538
556
  catch (error) {
539
557
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -555,8 +573,8 @@ Call \`skyramp_integration_test_generation\` with the returned \`scenarioFile\`
555
573
  text: `**Batch Scenario Generated — ${stepCount} steps**\n\n` +
556
574
  `**Scenario:** ${params.scenarioName}\n` +
557
575
  `**Steps:**\n${steps.map((s, i) => ` ${i + 1}. ${s.method} ${s.path} → ${s.statusCode ?? "default"}`).join("\n")}\n\n` +
558
- `**File:** ${filePath}\n\n` +
559
- `**Next:** Call \`skyramp_integration_test_generation\` with \`scenarioFile: "${filePath}"\`` +
576
+ `**File:** ${writtenPath}\n\n` +
577
+ `**Next:** Call \`skyramp_integration_test_generation\` with \`scenarioFile: "${writtenPath}"\`` +
560
578
  specValidationWarning +
561
579
  chainLintWarning,
562
580
  },
@@ -1,7 +1,6 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer, CallToolResult } from "@modelcontextprotocol/server";
2
2
  import { TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, BaseTestParams } from "../../services/TestGenerationService.js";
4
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
4
  type ContractParams = BaseTestParams & {
6
5
  enhanceAssertions?: boolean;
7
6
  assertOptions?: string;
@@ -439,7 +439,7 @@ ${CHAINING_SECTION}
439
439
  **Provider setup/teardown:**
440
440
  - \`skipProvisionParents\`: when true, skips generating setup/teardown functions for the provider contract test. Use this when \`apiSchema\` is unavailable and the endpoint requires a parent resource. Requires \`providerMode\`. Not allowed with \`parentRequestData\` or \`parentStatusCode\`.
441
441
  `,
442
- inputSchema: contractTestSchema,
442
+ inputSchema: z.object(contractTestSchema),
443
443
  }, async (params) => {
444
444
  const guardMessage = await guardScenarioApproved({
445
445
  scenarioName: params.scenarioName || undefined,
@@ -1,7 +1,6 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer, CallToolResult } from "@modelcontextprotocol/server";
2
2
  import { TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, BaseTestParams } from "../../services/TestGenerationService.js";
4
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
4
  export declare class E2ETestService extends TestGenerationService {
6
5
  protected getTestType(): TestType;
7
6
  protected buildGenerationOptions(params: BaseTestParams & {
@@ -54,7 +54,7 @@ E2E tests require both trace files (capturing backend API interactions) and Play
54
54
 
55
55
  **CRITICAL - When using trace parameter:**
56
56
  If \`trace\` parameter is provided (path to a trace file), DO NOT pass \`apiSchema\` or \`endpointURL\` parameters. The trace file already contains all necessary endpoint and schema information. Passing both will cause test generation to fail.`,
57
- inputSchema: e2eTestSchema,
57
+ inputSchema: z.object(e2eTestSchema),
58
58
  _meta: {
59
59
  keywords: ["e2e test", "end-to-end test"],
60
60
  },
@@ -1,4 +1,4 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  import { TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, BaseTestParams } from "../../services/TestGenerationService.js";
4
4
  export declare class FuzzTestService extends TestGenerationService {
@@ -28,7 +28,7 @@ export function registerFuzzTestTool(server) {
28
28
  Fuzz tests improve application security and reliability by sending invalid, malformed, or unexpected data to your API endpoints. They help discover edge cases, input validation issues, error handling problems, and potential security vulnerabilities.
29
29
 
30
30
  **IMPORTANT: If an apiSchema parameter (OpenAPI/Swagger file path or URL) is provided, DO NOT attempt to read or analyze the file contents. These files can be very large. Simply pass the path/URL to the tool - the backend will handle reading and processing the schema file.**`,
31
- inputSchema: fuzzTestSchema,
31
+ inputSchema: z.object(fuzzTestSchema),
32
32
  _meta: {
33
33
  keywords: ["negative test", "random test"],
34
34
  },
@@ -1,7 +1,6 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer, CallToolResult } from "@modelcontextprotocol/server";
2
2
  import { TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, BaseTestParams } from "../../services/TestGenerationService.js";
4
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
4
  export declare class IntegrationTestService extends TestGenerationService {
6
5
  protected getTestType(): TestType;
7
6
  generateTest(params: BaseTestParams & Record<string, any>): Promise<CallToolResult>;
@@ -115,7 +115,7 @@ Generate an integration test from a scenario file or a live endpoint trace.
115
115
  **Output filename:** When \`scenarioFile\` is provided and user did not specify a name, derive it: strip path and 'scenario_' prefix, replace hyphens/non-alphanum with underscores, append '_integration_test' + language extension. Example: 'scenario_orders-patch.json' → 'orders_patch_integration_test.py'. Never use the default 'integration_test.py' when scenarioFile is set — it collides.
116
116
 
117
117
  **IMPORTANT:** If \`apiSchema\` is provided in direct mode, pass the path/URL as-is — do NOT read the file contents. The backend processes it.`,
118
- inputSchema: integrationTestSchema,
118
+ inputSchema: z.object(integrationTestSchema),
119
119
  }, async (params) => {
120
120
  if (params.scenarioFile && (params.apiSchema || params.endpointURL)) {
121
121
  return {
@@ -1,7 +1,6 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer, CallToolResult } from "@modelcontextprotocol/server";
2
2
  import { TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, BaseTestParams } from "../../services/TestGenerationService.js";
4
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
4
  export { loadTestSchema, numericString } from "./loadTestSchema.js";
6
5
  export declare class LoadTestService extends TestGenerationService {
7
6
  protected getTestType(): TestType;
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  import { TestType } from "../../types/TestTypes.js";
2
3
  import { TestGenerationService, } from "../../services/TestGenerationService.js";
3
4
  import { AnalyticsService } from "../../services/AnalyticsService.js";
@@ -41,7 +42,7 @@ Load tests evaluate your application's performance, scalability, and stability u
41
42
 
42
43
  **CRITICAL - When using trace parameter:**
43
44
  If \`trace\` parameter is provided (path to a trace file), DO NOT pass \`apiSchema\` or \`endpointURL\` parameters. The trace file already contains all necessary endpoint and schema information. Passing both will cause test generation to fail.`,
44
- inputSchema: loadTestSchema,
45
+ inputSchema: z.object(loadTestSchema),
45
46
  _meta: {
46
47
  keywords: ["load test", "performance test"],
47
48
  },