@skyramp/mcp 0.0.44 → 0.0.46

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 (45) hide show
  1. package/build/index.js +57 -12
  2. package/build/prompts/code-reuse.js +1 -1
  3. package/build/prompts/driftAnalysisPrompt.js +159 -0
  4. package/build/prompts/modularization/ui-test-modularization.js +2 -0
  5. package/build/prompts/testGenerationPrompt.js +2 -2
  6. package/build/prompts/testHealthPrompt.js +82 -0
  7. package/build/services/AnalyticsService.js +86 -0
  8. package/build/services/DriftAnalysisService.js +928 -0
  9. package/build/services/ModularizationService.js +16 -1
  10. package/build/services/TestDiscoveryService.js +237 -0
  11. package/build/services/TestExecutionService.js +504 -0
  12. package/build/services/TestGenerationService.js +16 -2
  13. package/build/services/TestHealthService.js +656 -0
  14. package/build/tools/auth/loginTool.js +13 -3
  15. package/build/tools/auth/logoutTool.js +13 -3
  16. package/build/tools/code-refactor/codeReuseTool.js +46 -18
  17. package/build/tools/code-refactor/modularizationTool.js +44 -11
  18. package/build/tools/executeSkyrampTestTool.js +29 -125
  19. package/build/tools/fixErrorTool.js +38 -14
  20. package/build/tools/generate-tests/generateContractRestTool.js +8 -2
  21. package/build/tools/generate-tests/generateE2ERestTool.js +9 -3
  22. package/build/tools/generate-tests/generateFuzzRestTool.js +9 -3
  23. package/build/tools/generate-tests/generateIntegrationRestTool.js +8 -2
  24. package/build/tools/generate-tests/generateLoadRestTool.js +9 -3
  25. package/build/tools/generate-tests/generateScenarioRestTool.js +8 -2
  26. package/build/tools/generate-tests/generateSmokeRestTool.js +9 -3
  27. package/build/tools/generate-tests/generateUIRestTool.js +9 -3
  28. package/build/tools/test-maintenance/actionsTool.js +230 -0
  29. package/build/tools/test-maintenance/analyzeTestDriftTool.js +197 -0
  30. package/build/tools/test-maintenance/calculateHealthScoresTool.js +257 -0
  31. package/build/tools/test-maintenance/discoverTestsTool.js +143 -0
  32. package/build/tools/test-maintenance/executeBatchTestsTool.js +198 -0
  33. package/build/tools/test-maintenance/stateCleanupTool.js +153 -0
  34. package/build/tools/test-recommendation/analyzeRepositoryTool.js +27 -3
  35. package/build/tools/test-recommendation/mapTestsTool.js +9 -2
  36. package/build/tools/test-recommendation/recommendTestsTool.js +21 -5
  37. package/build/tools/trace/startTraceCollectionTool.js +18 -5
  38. package/build/tools/trace/stopTraceCollectionTool.js +28 -4
  39. package/build/types/TestAnalysis.js +1 -0
  40. package/build/types/TestDriftAnalysis.js +1 -0
  41. package/build/types/TestExecution.js +6 -0
  42. package/build/types/TestHealth.js +4 -0
  43. package/build/utils/AnalysisStateManager.js +240 -0
  44. package/build/utils/utils.test.js +25 -9
  45. package/package.json +6 -3
@@ -1,8 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { SkyrampClient } from "@skyramp/skyramp";
3
3
  import { logger } from "../../utils/logger.js";
4
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
5
+ const TOOL_NAME = "skyramp_login";
4
6
  export function registerLoginTool(server) {
5
- server.registerTool("skyramp_login", {
7
+ server.registerTool(TOOL_NAME, {
6
8
  description: `Login to Skyramp platform
7
9
 
8
10
  Logging into Skyramp provides access to additional platform features and services.
@@ -12,10 +14,11 @@ Logging into Skyramp provides access to additional platform features and service
12
14
  .string()
13
15
  .describe("The prompt user provided to login to Skyramp"),
14
16
  },
15
- annotations: {
17
+ _meta: {
16
18
  keywords: ["login", "authenticate", "skyramp login"],
17
19
  },
18
20
  }, async (params) => {
21
+ let errorResult;
19
22
  logger.info("Logging in to Skyramp", {
20
23
  prompt: params.prompt,
21
24
  });
@@ -34,7 +37,7 @@ Logging into Skyramp provides access to additional platform features and service
34
37
  }
35
38
  catch (error) {
36
39
  const errorMessage = `Login to Skyramp failed: ${error.message}`;
37
- return {
40
+ errorResult = {
38
41
  content: [
39
42
  {
40
43
  type: "text",
@@ -43,6 +46,13 @@ Logging into Skyramp provides access to additional platform features and service
43
46
  ],
44
47
  isError: true,
45
48
  };
49
+ return errorResult;
50
+ }
51
+ finally {
52
+ const recordParams = {
53
+ prompt: params.prompt,
54
+ };
55
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, recordParams);
46
56
  }
47
57
  });
48
58
  }
@@ -1,8 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { SkyrampClient } from "@skyramp/skyramp";
3
3
  import { logger } from "../../utils/logger.js";
4
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
5
+ const TOOL_NAME = "skyramp_logout";
4
6
  export function registerLogoutTool(server) {
5
- server.registerTool("skyramp_logout", {
7
+ server.registerTool(TOOL_NAME, {
6
8
  description: `Logout from Skyramp platform
7
9
 
8
10
  Logout from Skyramp platform to end your authenticated session.`,
@@ -11,10 +13,11 @@ Logout from Skyramp platform to end your authenticated session.`,
11
13
  .string()
12
14
  .describe("The prompt user provided to logout from Skyramp"),
13
15
  },
14
- annotations: {
16
+ _meta: {
15
17
  keywords: ["logout", "sign out", "skyramp logout"],
16
18
  },
17
19
  }, async (params) => {
20
+ let errorResult;
18
21
  logger.info("Logging out from Skyramp", {
19
22
  prompt: params.prompt,
20
23
  });
@@ -32,7 +35,7 @@ Logout from Skyramp platform to end your authenticated session.`,
32
35
  }
33
36
  catch (error) {
34
37
  const errorMessage = `Logout from Skyramp failed: ${error.message}`;
35
- return {
38
+ errorResult = {
36
39
  content: [
37
40
  {
38
41
  type: "text",
@@ -41,6 +44,13 @@ Logout from Skyramp platform to end your authenticated session.`,
41
44
  ],
42
45
  isError: true,
43
46
  };
47
+ return errorResult;
48
+ }
49
+ finally {
50
+ const recordParams = {
51
+ prompt: params.prompt,
52
+ };
53
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, recordParams);
44
54
  }
45
55
  });
46
56
  }
@@ -3,6 +3,7 @@ import { logger } from "../../utils/logger.js";
3
3
  import { getCodeReusePrompt } from "../../prompts/code-reuse.js";
4
4
  import { codeRefactoringSchema, languageSchema, } from "../../types/TestTypes.js";
5
5
  import { SKYRAMP_UTILS_HEADER } from "../../utils/utils.js";
6
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
6
7
  const codeReuseSchema = z.object({
7
8
  testFile: z
8
9
  .string()
@@ -14,8 +15,9 @@ const codeReuseSchema = z.object({
14
15
  .string()
15
16
  .describe("The code content to analyze and optimize for code reuse"),
16
17
  });
18
+ const TOOL_NAME = "skyramp_reuse_code";
17
19
  export function registerCodeReuseTool(server) {
18
- server.registerTool("skyramp_reuse_code", {
20
+ server.registerTool(TOOL_NAME, {
19
21
  description: `Analyzes code for reuse opportunities and enforces code reuse principles.
20
22
 
21
23
  This tool helps identify and reuse ONLY EXISTING helper functions from other test files (grep based on "${SKYRAMP_UTILS_HEADER}").
@@ -37,16 +39,18 @@ export function registerCodeReuseTool(server) {
37
39
  3. **ONLY IF** reusable helpers are found in OTHER test files → move to utils and update imports
38
40
  4. **IF NO** existing utils or reusable helpers are found in test files then reuse is complete, without creating any files or changes to the test files
39
41
  5. Verify no duplicate code remains and tests work as expected
40
- 6. **MANDATORY**: After code reuse is complete, proceed to modularization by calling skyramp_modularization tool
42
+ 6. **MANDATORY**: After code reuse is complete, proceed to modularization by calling skyramp_modularization tool ONLY for UI, E2E, INTEGRATION or LOAD tests generated from traces.
41
43
 
42
44
  **WHEN TO SKIP (DO NOTHING):**
43
45
  - Other test files only have repetitive patterns, no helper functions
44
46
  - Other test files are essentially identical to current file
45
47
  - No actual function definitions found in other test files
46
-
48
+
49
+ **MANDATORY**: ONLY ALLOW CODE REUSE IF THE IS TRACE BASED FLAG IS SET TO TRUE ELSE DO NOT ALLOW CODE REUSE AND LEAVE THE TEST FILE AS IS.
50
+ **CRITICAL**: NON TRACE BASED TESTS ARE ALREADY MODULARIZED AND DO NOT NEED CODE REUSE.
47
51
  The tool will provide step-by-step instructions that MUST be followed exactly.`,
48
52
  inputSchema: codeReuseSchema.shape,
49
- annotations: {
53
+ _meta: {
50
54
  keywords: [
51
55
  "code reuse",
52
56
  "duplicate code",
@@ -56,19 +60,43 @@ export function registerCodeReuseTool(server) {
56
60
  ],
57
61
  },
58
62
  }, async (params) => {
59
- logger.info("Analyzing code for reuse opportunities", {
60
- testFile: params.testFile,
61
- language: params.language,
62
- framework: params.framework,
63
- });
64
- const codeReusePrompt = getCodeReusePrompt(params.testFile, params.language);
65
- return {
66
- content: [
67
- {
68
- type: "text",
69
- text: codeReusePrompt,
70
- },
71
- ],
72
- };
63
+ let errorResult;
64
+ try {
65
+ logger.info("Analyzing code for reuse opportunities", {
66
+ testFile: params.testFile,
67
+ language: params.language,
68
+ framework: params.framework,
69
+ });
70
+ const codeReusePrompt = getCodeReusePrompt(params.testFile, params.language);
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: codeReusePrompt,
76
+ },
77
+ ],
78
+ };
79
+ }
80
+ catch (error) {
81
+ const errorMessage = `Code reuse analysis failed: ${error.message}`;
82
+ errorResult = {
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: errorMessage,
87
+ },
88
+ ],
89
+ isError: true,
90
+ };
91
+ return errorResult;
92
+ }
93
+ finally {
94
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
95
+ prompt: params.prompt,
96
+ testFile: params.testFile,
97
+ language: params.language,
98
+ framework: params.framework,
99
+ });
100
+ }
73
101
  });
74
102
  }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { logger } from "../../utils/logger.js";
3
3
  import { TestType } from "../../types/TestTypes.js";
4
4
  import { ModularizationService, } from "../../services/ModularizationService.js";
5
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
5
6
  const modularizationSchema = {
6
7
  testFile: z
7
8
  .string()
@@ -10,22 +11,29 @@ const modularizationSchema = {
10
11
  testType: z
11
12
  .enum([TestType.UI, TestType.E2E, TestType.INTEGRATION])
12
13
  .describe("Specifies the type of test (UI, E2E, or Integration). DO NOT USE TEST NAME/DESCRIPTION AS TEST TYPE. ONLY USE UI, E2E, OR INTEGRATION."),
14
+ isTraceBased: z
15
+ .boolean()
16
+ .default(false)
17
+ .describe("Whether the test is generated from traces. Scan the test file and check if the test is generated from traces."),
13
18
  prompt: z
14
19
  .string()
15
20
  .describe("The prompt or code content to process with modularization principles applied"),
16
21
  };
22
+ const TOOL_NAME = "skyramp_modularization";
17
23
  export function registerModularizationTool(server) {
18
- server.registerTool("skyramp_modularization", {
24
+ server.registerTool(TOOL_NAME, {
19
25
  description: `Provides modularization instructions and test file content. YOU MUST immediately modularize the code and write it back to the file. The tool returns:
20
26
  1. Complete modularization instructions
21
27
  2. The current test file content
22
28
  3. Step-by-step requirements you must complete
23
29
 
30
+ **MANDATORY**: ONLY MODULARIZE THE TEST IF THE IS TRACE BASED FLAG IS SET TO TRUE ELSE DO NOT MODULARIZE THE TEST AND LEAVE THE TEST FILE AS IS.
31
+ **CRITICAL**: NON TRACE BASED TESTS ARE ALREADY MODULARIZED AND DO NOT NEED MODULARIZATION.
24
32
  After modularization, if errors remain, call skyramp_fix_errors.
25
33
 
26
- CRITICAL: This tool expects you to complete the modularization by writing the refactored code back to the file.`,
34
+ **CRITICAL**: This tool expects you to complete the modularization by writing the refactored code back to the file.`,
27
35
  inputSchema: modularizationSchema,
28
- annotations: {
36
+ _meta: {
29
37
  keywords: [
30
38
  "modularization",
31
39
  "code organization",
@@ -34,13 +42,38 @@ CRITICAL: This tool expects you to complete the modularization by writing the re
34
42
  ],
35
43
  },
36
44
  }, async (params) => {
37
- logger.info("Generating modularization", {
38
- testFile: params.testFile,
39
- language: params.language,
40
- prompt: params.prompt,
41
- testType: params.testType,
42
- });
43
- const service = new ModularizationService();
44
- return await service.processModularizationRequest(params);
45
+ let errorResult;
46
+ try {
47
+ logger.info("Generating modularization", {
48
+ testFile: params.testFile,
49
+ language: params.language,
50
+ prompt: params.prompt,
51
+ testType: params.testType,
52
+ });
53
+ const service = new ModularizationService();
54
+ return await service.processModularizationRequest(params);
55
+ }
56
+ catch (error) {
57
+ const errorMessage = `Modularization failed: ${error.message}`;
58
+ logger.error(errorMessage, error);
59
+ errorResult = {
60
+ content: [
61
+ {
62
+ type: "text",
63
+ text: errorMessage,
64
+ },
65
+ ],
66
+ isError: true,
67
+ };
68
+ return errorResult;
69
+ }
70
+ finally {
71
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
72
+ prompt: params.prompt,
73
+ testFile: params.testFile,
74
+ language: params.language,
75
+ testType: params.testType,
76
+ });
77
+ }
45
78
  });
46
79
  }
@@ -1,14 +1,10 @@
1
1
  import { z } from "zod";
2
- import Docker from "dockerode";
3
- import path from "path";
4
- import { Writable } from "stream";
5
- import { logger } from "../utils/logger.js";
6
2
  import { stripVTControlCharacters } from "util";
7
- import fs from "fs";
8
- const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.2.37";
9
- const DOCKER_PLATFORM = "linux/amd64";
3
+ import { TestExecutionService } from "../services/TestExecutionService.js";
4
+ import { AnalyticsService } from "../services/AnalyticsService.js";
5
+ const TOOL_NAME = "skyramp_execute_test";
10
6
  export function registerExecuteSkyrampTestTool(server) {
11
- server.registerTool("skyramp_execute_test", {
7
+ server.registerTool(TOOL_NAME, {
12
8
  description: `Execute a Skyramp-generated test in isolated containerized environments for reliable, deterministic testing.
13
9
 
14
10
  Skyramp is a comprehensive testing platform that generates reliable, out-of-the-box functional and performance tests with AI-powered scaffolding. The test execution engine runs your generated tests in controlled, isolated environments to ensure consistent results.
@@ -51,145 +47,44 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
51
47
  .string()
52
48
  .describe("Skyramp authentication token for test execution. USE EMPTY STRING WHEN USER CONFIRMS 'No token required'"),
53
49
  },
54
- annotations: {
50
+ _meta: {
55
51
  keywords: ["run test", "execute test"],
56
52
  },
57
53
  }, async (params) => {
58
- var docker = new Docker();
59
- const containerMountPath = "/home/user";
60
- // Use path.basename for safer filename extraction
61
- const filename = path.basename(params.testFile);
62
- if (!filename) {
63
- throw new Error("Invalid test file path: could not extract filename");
64
- }
65
- const dockerSocketPath = "/var/run/docker.sock";
66
- //remove workspace path from test file path
67
- let testFilePath = path.relative(params.workspacePath, params.testFile);
68
- testFilePath = path.resolve(containerMountPath, testFilePath);
69
- var command = [
70
- "./root/runner.sh",
71
- params.language,
72
- testFilePath,
73
- params.testType,
74
- ];
75
- const workspacePath = path.resolve(params.workspacePath);
76
- // check if workspace valid path
77
- // Validate that the workspace path exists and is accessible
78
- try {
79
- fs.accessSync(workspacePath, fs.constants.R_OK);
80
- }
81
- catch (err) {
82
- throw new Error(`Workspace path does not exist or is not readable: ${workspacePath}`);
83
- }
84
- const hostConfig = {
85
- ExtraHosts: ["host.docker.internal:host-gateway"],
86
- Mounts: [
87
- {
88
- Type: "bind",
89
- Target: dockerSocketPath,
90
- Source: dockerSocketPath,
91
- },
92
- ],
93
- };
94
- //lets mount the files and directories inside the workspace path to the container and exclude package-lock.json, package.json and node_modules directory
95
- const workspaceFiles = fs.readdirSync(workspacePath);
96
- const filesToMount = workspaceFiles.filter((file) => file !== "package-lock.json" &&
97
- file !== "package.json" &&
98
- file !== "node_modules");
99
- hostConfig.Mounts?.push(...filesToMount.map((file) => ({
100
- Type: "bind",
101
- Target: path.join(containerMountPath, file),
102
- Source: path.join(workspacePath, file),
103
- })));
104
- const env = [
105
- "SKYRAMP_TEST_TOKEN=" + params.token,
106
- "SKYRAMP_IN_DOCKER=true",
107
- ];
108
- if (process.env.SKYRAMP_DEBUG) {
109
- env.push("SKYRAMP_DEBUG=" + process.env.SKYRAMP_DEBUG);
110
- }
111
- if (process.env.API_KEY) {
112
- env.push("API_KEY=" + process.env.API_KEY);
113
- }
114
- var output = "";
115
- class DockerStream extends Writable {
116
- _write(data, encode, cb) {
117
- output += data.toString();
118
- cb();
119
- }
120
- }
121
- var stream = new DockerStream();
54
+ let errorResult;
122
55
  try {
123
- var statusCode = 0;
124
- // check if image exists
125
- const images = await docker.listImages();
126
- const imageExists = images.some((img) => (img.RepoTags && img.RepoTags.includes(EXECUTOR_DOCKER_IMAGE)) ||
127
- (img.RepoDigests &&
128
- img.RepoDigests.includes(EXECUTOR_DOCKER_IMAGE)));
129
- if (!imageExists) {
130
- // Pull the image if it does not exist
131
- await new Promise((resolve, reject) => {
132
- docker.pull(EXECUTOR_DOCKER_IMAGE, { platform: DOCKER_PLATFORM }, (err, stream) => {
133
- if (err)
134
- return reject(err);
135
- if (!stream)
136
- return reject(new Error("No stream received from docker pull"));
137
- docker.modem.followProgress(stream, (err, res) => {
138
- if (err)
139
- return reject(err);
140
- resolve(res);
141
- });
142
- });
143
- });
144
- }
145
- await docker
146
- .run(EXECUTOR_DOCKER_IMAGE, command, stream, {
147
- Env: env,
148
- HostConfig: hostConfig,
149
- })
150
- .then(function (data) {
151
- var result = data[0];
152
- var container = data[1];
153
- stream.end();
154
- statusCode = result.StatusCode;
155
- logger.debug("Docker container execution completed");
156
- return container.remove();
157
- })
158
- .then(function (data) {
159
- logger.debug("Docker container removed successfully");
160
- })
161
- .catch(function (err) {
162
- logger.error("Docker container execution failed", {
163
- error: err.message,
164
- });
165
- throw err;
166
- });
167
- logger.info("Test execution completed", {
168
- output: output.substring(0, 200) + (output.length > 200 ? "..." : ""),
169
- statusCode,
56
+ const executionService = new TestExecutionService();
57
+ const result = await executionService.executeTest({
58
+ testFile: params.testFile,
59
+ workspacePath: params.workspacePath,
60
+ language: params.language,
61
+ testType: params.testType,
62
+ token: params.token,
170
63
  });
171
- if (statusCode !== 0) {
172
- return {
64
+ if (!result.passed) {
65
+ errorResult = {
173
66
  content: [
174
67
  {
175
68
  type: "text",
176
- text: `Test execution failed: ${stripVTControlCharacters(output)}
69
+ text: `Test execution failed: ${stripVTControlCharacters(result.output || "")}
177
70
  **IMPORTANT: IF THE EXECUTION FAILED BECAUSE OF A 401 STATUS CODE, ASK THE USER TO PROVIDE THE AUTHENTICATION TOKEN TO THE TOOL OR A PLACE FROM WHERE WE CAN READ THE TOKEN. DO NOT UPDATE THE GENERATED TEST FILE.**`,
178
71
  },
179
72
  ],
73
+ isError: true,
180
74
  };
75
+ return errorResult;
181
76
  }
182
77
  return {
183
78
  content: [
184
79
  {
185
80
  type: "text",
186
- text: `Test execution result: ${stripVTControlCharacters(output)}`,
81
+ text: `Test execution result: ${stripVTControlCharacters(result.output || "")}`,
187
82
  },
188
83
  ],
189
84
  };
190
85
  }
191
86
  catch (err) {
192
- return {
87
+ errorResult = {
193
88
  content: [
194
89
  {
195
90
  type: "text",
@@ -198,6 +93,15 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
198
93
  ],
199
94
  isError: true,
200
95
  };
96
+ return errorResult;
97
+ }
98
+ finally {
99
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
100
+ testFile: params.testFile,
101
+ workspacePath: params.workspacePath,
102
+ language: params.language,
103
+ testType: params.testType,
104
+ });
201
105
  }
202
106
  });
203
107
  }
@@ -3,6 +3,7 @@ import { logger } from "../utils/logger.js";
3
3
  import { getFixErrorsPrompt } from "../prompts/fix-error-prompt.js";
4
4
  import { languageSchema } from "../types/TestTypes.js";
5
5
  import { getLanguageSteps } from "../utils/language-helper.js";
6
+ import { AnalyticsService } from "../services/AnalyticsService.js";
6
7
  const fixErrorSchema = z.object({
7
8
  testFile: z
8
9
  .string()
@@ -13,11 +14,12 @@ const fixErrorSchema = z.object({
13
14
  .string()
14
15
  .describe("The prompt or code content to process with modularization principles applied"),
15
16
  });
17
+ const TOOL_NAME = "skyramp_fix_errors";
16
18
  export function registerFixErrorTool(server) {
17
- server.registerTool("skyramp_fix_errors", {
19
+ server.registerTool(TOOL_NAME, {
18
20
  description: `Review the provided code for errors, inconsistencies, or missing pieces. If any are found, return corrected code. Otherwise, return the code unchanged.`,
19
21
  inputSchema: fixErrorSchema.shape,
20
- annotations: {
22
+ _meta: {
21
23
  keywords: [
22
24
  "modularization",
23
25
  "code organization",
@@ -26,19 +28,41 @@ export function registerFixErrorTool(server) {
26
28
  ],
27
29
  },
28
30
  }, async (params) => {
29
- logger.info("Generating modularization", {
30
- prompt: params.prompt,
31
- testFile: params.testFile,
32
- });
33
- return {
34
- content: [
35
- {
36
- type: "text",
37
- text: `
31
+ let errorResult;
32
+ try {
33
+ logger.info("Generating modularization", {
34
+ prompt: params.prompt,
35
+ testFile: params.testFile,
36
+ });
37
+ return {
38
+ content: [
39
+ {
40
+ type: "text",
41
+ text: `
38
42
  ${getFixErrorsPrompt()}
39
43
  ${getLanguageSteps(params)}`,
40
- },
41
- ],
42
- };
44
+ },
45
+ ],
46
+ };
47
+ }
48
+ catch (error) {
49
+ const errorMessage = `Fix error generation failed: ${error.message}`;
50
+ errorResult = {
51
+ content: [
52
+ {
53
+ type: "text",
54
+ text: errorMessage,
55
+ },
56
+ ],
57
+ isError: true,
58
+ };
59
+ return errorResult;
60
+ }
61
+ finally {
62
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
63
+ prompt: params.prompt,
64
+ testFile: params.testFile,
65
+ });
66
+ }
43
67
  });
44
68
  }
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { baseTestSchema, TestType } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, } from "../../services/TestGenerationService.js";
4
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
4
5
  const contractTestSchema = {
5
6
  ...baseTestSchema,
6
7
  assertOptions: z
@@ -23,14 +24,19 @@ export class ContractTestService extends TestGenerationService {
23
24
  };
24
25
  }
25
26
  }
27
+ const TOOL_NAME = "skyramp_contract_test_generation";
26
28
  export function registerContractTestTool(server) {
27
- server.registerTool("skyramp_contract_test_generation", {
29
+ server.registerTool(TOOL_NAME, {
28
30
  description: `Generate a contract test using Skyramp's deterministic test generation platform.
29
31
 
30
32
  Contract tests ensure your API implementation matches its OpenAPI/Swagger specification exactly. They validate request/response schemas, status codes, headers, and data types to prevent contract violations and API breaking changes.`,
31
33
  inputSchema: contractTestSchema,
32
34
  }, async (params) => {
33
35
  const service = new ContractTestService();
34
- return await service.generateTest(params);
36
+ const result = await service.generateTest(params);
37
+ AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
38
+ console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
39
+ });
40
+ return result;
35
41
  });
36
42
  }
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { baseSchema, baseTraceSchema, TestType, codeRefactoringSchema, } from "../../types/TestTypes.js";
3
3
  import { TestGenerationService, } from "../../services/TestGenerationService.js";
4
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
4
5
  const e2eTestSchema = {
5
6
  ...baseTraceSchema.shape,
6
7
  playwrightInput: z
@@ -24,8 +25,9 @@ export class E2ETestService extends TestGenerationService {
24
25
  return null;
25
26
  }
26
27
  }
28
+ const TOOL_NAME = "skyramp_e2e_test_generation";
27
29
  export function registerE2ETestTool(server) {
28
- server.registerTool("skyramp_e2e_test_generation", {
30
+ server.registerTool(TOOL_NAME, {
29
31
  description: `Generate an End-to-End (E2E) test using Skyramp's deterministic test generation platform.
30
32
 
31
33
  End-to-End tests validate complete user journeys by testing the entire application flow from frontend UI interactions to backend API responses. They ensure that all components work together correctly in realistic user scenarios, providing the highest confidence in application functionality.
@@ -33,11 +35,15 @@ End-to-End tests validate complete user journeys by testing the entire applicati
33
35
  TRACE & UI INTEGRATION:
34
36
  E2E tests require both trace files (capturing backend API interactions) and Playwright recordings (capturing UI interactions captured using start_trace_collection tool) to generate comprehensive tests that validate the complete user experience.`,
35
37
  inputSchema: e2eTestSchema,
36
- annotations: {
38
+ _meta: {
37
39
  keywords: ["e2e test", "end-to-end test"],
38
40
  },
39
41
  }, async (params) => {
40
42
  const service = new E2ETestService();
41
- return await service.generateTest(params);
43
+ const result = await service.generateTest(params);
44
+ AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
45
+ console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
46
+ });
47
+ return result;
42
48
  });
43
49
  }
@@ -1,6 +1,7 @@
1
1
  import { baseTestSchema, TestType } from "../../types/TestTypes.js";
2
2
  import { TestGenerationService, } from "../../services/TestGenerationService.js";
3
3
  import { z } from "zod";
4
+ import { AnalyticsService } from "../../services/AnalyticsService.js";
4
5
  const fuzzTestSchema = {
5
6
  ...baseTestSchema,
6
7
  responseData: z
@@ -19,17 +20,22 @@ export class FuzzTestService extends TestGenerationService {
19
20
  };
20
21
  }
21
22
  }
23
+ const TOOL_NAME = "skyramp_fuzz_test_generation";
22
24
  export function registerFuzzTestTool(server) {
23
- server.registerTool("skyramp_fuzz_test_generation", {
25
+ server.registerTool(TOOL_NAME, {
24
26
  description: `Generate a fuzz test using Skyramp's deterministic test generation platform.
25
27
 
26
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.`,
27
29
  inputSchema: fuzzTestSchema,
28
- annotations: {
30
+ _meta: {
29
31
  keywords: ["negative test", "random test"],
30
32
  },
31
33
  }, async (params) => {
32
34
  const service = new FuzzTestService();
33
- return await service.generateTest(params);
35
+ const result = await service.generateTest(params);
36
+ AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
37
+ console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
38
+ });
39
+ return result;
34
40
  });
35
41
  }