@skyramp/mcp 0.0.45 → 0.0.47

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 (36) hide show
  1. package/build/index.js +66 -29
  2. package/build/prompts/test-recommendation/repository-analysis-prompt.js +7 -1
  3. package/build/prompts/test-recommendation/test-recommendation-prompt.js +7 -1
  4. package/build/prompts/testGenerationPrompt.js +1 -0
  5. package/build/services/AnalyticsService.js +78 -0
  6. package/build/services/DriftAnalysisService.js +6 -2
  7. package/build/services/TestExecutionService.js +322 -11
  8. package/build/services/TestHealthService.js +8 -5
  9. package/build/tools/auth/loginTool.js +12 -2
  10. package/build/tools/auth/logoutTool.js +12 -2
  11. package/build/tools/code-refactor/codeReuseTool.js +41 -15
  12. package/build/tools/code-refactor/modularizationTool.js +36 -9
  13. package/build/tools/executeSkyrampTestTool.js +45 -5
  14. package/build/tools/fixErrorTool.js +37 -13
  15. package/build/tools/generate-tests/generateContractRestTool.js +11 -3
  16. package/build/tools/generate-tests/generateE2ERestTool.js +8 -2
  17. package/build/tools/generate-tests/generateFuzzRestTool.js +11 -3
  18. package/build/tools/generate-tests/generateIntegrationRestTool.js +11 -3
  19. package/build/tools/generate-tests/generateLoadRestTool.js +11 -3
  20. package/build/tools/generate-tests/generateScenarioRestTool.js +10 -2
  21. package/build/tools/generate-tests/generateSmokeRestTool.js +11 -3
  22. package/build/tools/generate-tests/generateUIRestTool.js +10 -3
  23. package/build/tools/test-maintenance/actionsTool.js +175 -147
  24. package/build/tools/test-maintenance/analyzeTestDriftTool.js +14 -5
  25. package/build/tools/test-maintenance/calculateHealthScoresTool.js +13 -4
  26. package/build/tools/test-maintenance/discoverTestsTool.js +10 -2
  27. package/build/tools/test-maintenance/executeBatchTestsTool.js +14 -4
  28. package/build/tools/test-maintenance/stateCleanupTool.js +11 -3
  29. package/build/tools/test-recommendation/analyzeRepositoryTool.js +18 -4
  30. package/build/tools/test-recommendation/mapTestsTool.js +21 -5
  31. package/build/tools/test-recommendation/recommendTestsTool.js +17 -3
  32. package/build/tools/trace/startTraceCollectionTool.js +17 -4
  33. package/build/tools/trace/stopTraceCollectionTool.js +27 -3
  34. package/build/types/TestTypes.js +17 -3
  35. package/build/utils/AnalysisStateManager.js +3 -1
  36. package/package.json +2 -2
package/build/index.js CHANGED
@@ -30,6 +30,7 @@ import { registerExecuteBatchTestsTool } from "./tools/test-maintenance/executeB
30
30
  import { registerCalculateHealthScoresTool } from "./tools/test-maintenance/calculateHealthScoresTool.js";
31
31
  import { registerActionsTool } from "./tools/test-maintenance/actionsTool.js";
32
32
  import { registerStateCleanupTool } from "./tools/test-maintenance/stateCleanupTool.js";
33
+ import { AnalyticsService } from "./services/AnalyticsService.js";
33
34
  const server = new McpServer({
34
35
  name: "Skyramp MCP Server",
35
36
  version: "1.0.0",
@@ -71,23 +72,17 @@ const codeQualityTools = [
71
72
  registerCodeReuseTool,
72
73
  ];
73
74
  codeQualityTools.forEach((registerTool) => registerTool(server));
74
- // Register internal/test recommendation tools (controlled by environment variable)
75
- const enableInternalTools = process.env.SKYRAMP_ENABLE_INTERNAL_TOOLS === "true";
76
- if (enableInternalTools) {
77
- logger.info("Internal tools enabled - registering test recommendation tools");
78
- registerAnalyzeRepositoryTool(server);
79
- registerMapTestsTool(server);
80
- registerRecommendTestsTool(server);
81
- registerDiscoverTestsTool(server);
82
- registerAnalyzeTestDriftTool(server);
83
- registerExecuteBatchTestsTool(server);
84
- registerCalculateHealthScoresTool(server);
85
- registerActionsTool(server);
86
- registerStateCleanupTool(server);
87
- }
88
- else {
89
- logger.info("Internal tools disabled. Set SKYRAMP_ENABLE_INTERNAL_TOOLS=true to enable.");
90
- }
75
+ // Register test recommendation tools
76
+ registerAnalyzeRepositoryTool(server);
77
+ registerMapTestsTool(server);
78
+ registerRecommendTestsTool(server);
79
+ // Register test maintenance tools
80
+ registerDiscoverTestsTool(server);
81
+ registerAnalyzeTestDriftTool(server);
82
+ registerExecuteBatchTestsTool(server);
83
+ registerCalculateHealthScoresTool(server);
84
+ registerActionsTool(server);
85
+ registerStateCleanupTool(server);
91
86
  // Register other Skyramp tools
92
87
  const infrastructureTools = [
93
88
  registerLoginTool,
@@ -97,30 +92,72 @@ const infrastructureTools = [
97
92
  registerTraceStopTool,
98
93
  ];
99
94
  infrastructureTools.forEach((registerTool) => registerTool(server));
95
+ // Global error handlers for crash telemetry
96
+ process.on("uncaughtException", async (error) => {
97
+ logger.critical("Uncaught exception - MCP server crashing", {
98
+ error: error.message,
99
+ stack: error.stack,
100
+ });
101
+ try {
102
+ await AnalyticsService.pushServerCrashEvent("uncaughtException", error.message, error.stack);
103
+ }
104
+ catch (telemetryError) {
105
+ logger.error("Failed to send crash telemetry", { telemetryError });
106
+ }
107
+ process.exit(1);
108
+ });
109
+ process.on("unhandledRejection", async (reason, promise) => {
110
+ const errorMessage = reason instanceof Error ? reason.message : String(reason);
111
+ const errorStack = reason instanceof Error ? reason.stack : undefined;
112
+ logger.critical("Unhandled promise rejection - MCP server crashing", {
113
+ error: errorMessage,
114
+ stack: errorStack,
115
+ });
116
+ try {
117
+ await AnalyticsService.pushServerCrashEvent("unhandledRejection", errorMessage, errorStack);
118
+ }
119
+ catch (telemetryError) {
120
+ logger.error("Failed to send crash telemetry", { telemetryError });
121
+ }
122
+ process.exit(1);
123
+ });
100
124
  // Start MCP server
101
125
  async function main() {
102
126
  const transport = new StdioServerTransport();
103
127
  await server.connect(transport);
104
128
  logger.info("MCP Server started successfully");
105
129
  // Listen for stdin closure (parent process disconnected)
106
- process.stdin.on("end", () => {
107
- logger.info("STDIN closed, parent process disconnected. Exiting...");
108
- process.exit(0);
130
+ // Using multiple events for robustness across different disconnection scenarios
131
+ let isShuttingDown = false;
132
+ const handleParentDisconnect = (event) => {
133
+ if (isShuttingDown)
134
+ return;
135
+ isShuttingDown = true;
136
+ logger.info(`Parent process disconnected (${event}). Cleaning up and exiting...`);
137
+ server.close().finally(() => {
138
+ process.exit(0);
139
+ });
140
+ };
141
+ process.stdin.on("end", () => handleParentDisconnect("stdin end"));
142
+ process.stdin.on("close", () => handleParentDisconnect("stdin close"));
143
+ process.stdin.on("error", (err) => {
144
+ logger.error("STDIN error, parent likely disconnected", { error: err });
145
+ handleParentDisconnect("stdin error");
109
146
  });
110
147
  // Handle process termination signals
111
- process.on("SIGTERM", () => {
112
- logger.info("Received SIGTERM, shutting down gracefully...");
113
- process.exit(0);
114
- });
115
- process.on("SIGINT", () => {
116
- logger.info("Received SIGINT, shutting down gracefully...");
117
- process.exit(0);
118
- });
148
+ process.on("SIGTERM", () => handleParentDisconnect("SIGTERM"));
149
+ process.on("SIGINT", () => handleParentDisconnect("SIGINT"));
119
150
  }
120
- main().catch((error) => {
151
+ main().catch(async (error) => {
121
152
  logger.critical("Fatal error in main()", {
122
153
  error: error.message,
123
154
  stack: error.stack,
124
155
  });
156
+ try {
157
+ await AnalyticsService.pushServerCrashEvent("mainFatalError", error.message, error.stack);
158
+ }
159
+ catch (telemetryError) {
160
+ logger.error("Failed to send crash telemetry", { telemetryError });
161
+ }
125
162
  process.exit(1);
126
163
  });
@@ -282,6 +282,12 @@ VALIDATION CHECKLIST:
282
282
  - [ ] Infrastructure flags verified
283
283
  - [ ] Existing tests catalogued
284
284
 
285
- Begin analysis now. Return ONLY the JSON object, no other text.
285
+ **CRITICAL INSTRUCTIONS**:
286
+ - Return the JSON object directly in your response text.
287
+ - DO NOT create or save any files (no repository_analysis.json or .md files).
288
+ - DO NOT use file write tools or save analysis to disk.
289
+ - Output the complete analysis JSON inline in your response.
290
+
291
+ Begin analysis now. Return the JSON object directly in your response text.
286
292
  `;
287
293
  }
@@ -120,6 +120,12 @@ Return a JSON object with this structure:
120
120
  4. **Provide Guidance**: Clear instructions for creating missing artifacts
121
121
  5. **Include Evidence**: Reference specific repository characteristics in rationale
122
122
 
123
- Generate recommendations now. Return ONLY the JSON object, no other text.
123
+ **CRITICAL INSTRUCTIONS**:
124
+ - Return the JSON object directly in your response text.
125
+ - DO NOT create or save any files (no test_recommendations.md, .json, or other files).
126
+ - DO NOT use file write tools or save recommendations to disk.
127
+ - Output the complete recommendations JSON inline in your response.
128
+
129
+ Generate recommendations now. Return the JSON object directly in your response text.
124
130
  `;
125
131
  }
@@ -17,6 +17,7 @@ export function registerTestGenerationPrompt(mcpServer) {
17
17
  - ALWAYS SHOW STEPS TO GENERATE TEST USING MCP TOOLS AND NEVER SHOW THE CLI COMMANDS.
18
18
  - **CRITICAL: ONLY UI, INTEGRATION, E2E, LOAD TESTS GENERATED FROM TRACES MUST BE MODULARIZED USING skyramp_modularization TOOL. ADD A TASK TO MODULARIZE THE TEST USING skyramp_modularization TOOL AFTER GENERATING THESE(UI, INTEGRATION, E2E, LOAD) TESTS. DO NOT MODULARIZE THESE TESTS IF THEY ARE NOT GENERATED FROM TRACES.**
19
19
  - **CRITICAL: skyramp_reuse_code TOOL MUST BE CALLED IF DURING THE TEST GENERATION THE CODE REUSE FLAG IS SET TO TRUE EXPLICITLY BY THE USER AND THE TEST IS GENERATED FROM TRACES.**
20
+ - **CRITICAL: DO NOT READ apiSchema FILES (OpenAPI/Swagger specifications). These files can be very large (often several MB). Simply pass the file path or URL to the test generation tool - the backend will handle reading and processing it. Never use file reading tools on apiSchema parameters.**
20
21
 
21
22
  **MANDATORY RULES**:
22
23
  1. **Priority Scores Must Remain Unchanged**: When a test type is missing required inputs (e.g., Playwright recordings, traces), **DO NOT**:
@@ -0,0 +1,78 @@
1
+ import { pushToolEvent } from "@skyramp/skyramp";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { fileURLToPath } from "url";
5
+ export class AnalyticsService {
6
+ static entryPoint = "mcp";
7
+ static async pushTestGenerationToolEvent(toolName, result, params) {
8
+ const analyticsResult = {};
9
+ analyticsResult["prompt"] = params.prompt;
10
+ analyticsResult["language"] = params.language;
11
+ this.pushMCPToolEvent(toolName, result, analyticsResult);
12
+ }
13
+ static async pushMCPToolEvent(toolName, result, params) {
14
+ // Error message.
15
+ let errorMessage = "";
16
+ if (result && result.isError) {
17
+ for (const content of result?.content ?? []) {
18
+ if ("text" in content && content.text) {
19
+ errorMessage += content.text + ", ";
20
+ }
21
+ }
22
+ if (errorMessage.length > 0) {
23
+ errorMessage = errorMessage.slice(0, -2);
24
+ }
25
+ }
26
+ //add mcp server version from package.json
27
+ params.mcpServerVersion = getMCPPackageVersion();
28
+ console.error("pushToolEvent", {
29
+ entryPoint: this.entryPoint,
30
+ toolName: toolName,
31
+ errorMessage: errorMessage,
32
+ analyticsResult: params,
33
+ });
34
+ await pushToolEvent(this.entryPoint, toolName, errorMessage, params);
35
+ }
36
+ /**
37
+ * Track server crash events
38
+ */
39
+ static async pushServerCrashEvent(crashType, errorMessage, errorStack) {
40
+ const params = {
41
+ crashType: crashType,
42
+ errorStack: errorStack || "no stack trace",
43
+ mcpServerVersion: getMCPPackageVersion(),
44
+ };
45
+ console.error("pushServerCrashEvent", {
46
+ entryPoint: this.entryPoint,
47
+ toolName: "mcp_server_crash",
48
+ errorMessage: errorMessage,
49
+ analyticsResult: params,
50
+ });
51
+ await pushToolEvent(this.entryPoint, "mcp_server_crash", errorMessage, params);
52
+ }
53
+ /**
54
+ * Track tool timeout events
55
+ */
56
+ static async pushToolTimeoutEvent(toolName, timeoutMs, params) {
57
+ const errorMessage = `Tool ${toolName} timed out after ${timeoutMs}ms`;
58
+ const timeoutParams = {
59
+ ...params,
60
+ timeoutMs: timeoutMs.toString(),
61
+ mcpServerVersion: getMCPPackageVersion(),
62
+ };
63
+ console.error("pushToolTimeoutEvent", {
64
+ entryPoint: this.entryPoint,
65
+ toolName: toolName,
66
+ errorMessage: errorMessage,
67
+ analyticsResult: timeoutParams,
68
+ });
69
+ await pushToolEvent(this.entryPoint, `${toolName}_timeout`, errorMessage, timeoutParams);
70
+ }
71
+ }
72
+ function getMCPPackageVersion() {
73
+ const __filename = fileURLToPath(import.meta.url);
74
+ const __dirname = path.dirname(__filename);
75
+ const packageJson = fs.readFileSync(path.join(__dirname, "../../package.json"), "utf8");
76
+ const packageJsonData = JSON.parse(packageJson);
77
+ return packageJsonData.version;
78
+ }
@@ -411,8 +411,12 @@ export class EnhancedDriftAnalysisService {
411
411
  }
412
412
  // Check authentication changes
413
413
  // OpenAPI 3.x uses components.securitySchemes, Swagger 2.x uses securityDefinitions
414
- const oldAuth = JSON.stringify(oldParsed.components?.securitySchemes || oldParsed.securityDefinitions || {});
415
- const newAuth = JSON.stringify(newParsed.components?.securitySchemes || newParsed.securityDefinitions || {});
414
+ const oldAuth = JSON.stringify(oldParsed.components?.securitySchemes ||
415
+ oldParsed.securityDefinitions ||
416
+ {});
417
+ const newAuth = JSON.stringify(newParsed.components?.securitySchemes ||
418
+ newParsed.securityDefinitions ||
419
+ {});
416
420
  if (oldAuth !== newAuth) {
417
421
  changes.authenticationChanged = true;
418
422
  changes.authenticationDetails = "Security schemes have been modified";