@skyramp/mcp 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/index.js +6 -2
- package/build/services/ModularizationService.js +109 -0
- package/build/services/TestGenerationService.js +16 -11
- package/build/tools/executeSkyrampTestTool.js +3 -2
- package/build/tools/generateE2ERestTool.js +2 -2
- package/build/tools/generateLoadRestTool.js +4 -4
- package/build/tools/generateModularizationTool.js +56 -0
- package/build/tools/generateUIRestTool.js +1 -1
- package/build/tools/loginTool.js +11 -10
- package/build/tools/logoutTool.js +12 -12
- package/build/tools/startTraceCollectionTool.js +15 -1
- package/build/tools/stopTraceCollectionTool.js +17 -5
- package/build/types/TestTypes.js +6 -3
- package/build/utils/language-helper.js +1 -1
- package/build/utils/modularization-prompts.js +4 -3
- package/build/utils/utils.js +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -134,9 +134,9 @@ This MCP server provides the following tools:
|
|
|
134
134
|
| skyramp_load_test_generation | Generate a load test |
|
|
135
135
|
| skyramp_integration_test_generation | Generate an integration test |
|
|
136
136
|
| skyramp_e2e_test_generation | Generate an E2E test |
|
|
137
|
-
| skyramp_ui_test_generation | Generate
|
|
137
|
+
| skyramp_ui_test_generation | Generate a UI test |
|
|
138
138
|
| skyramp_start_trace_collection | Start trace collection |
|
|
139
|
-
|
|
|
139
|
+
| skyramp_stop_trace_collection | Stop trace collection |
|
|
140
140
|
| skyramp_execute_test | Execute a Skyramp test |
|
|
141
141
|
|
|
142
142
|
## Available prompts
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { registerFuzzTestTool } from "./tools/generateFuzzRestTool.js";
|
|
|
13
13
|
import { registerContractTestTool } from "./tools/generateContractRestTool.js";
|
|
14
14
|
import { registerLoadTestTool } from "./tools/generateLoadRestTool.js";
|
|
15
15
|
import { registerIntegrationTestTool } from "./tools/generateIntegrationRestTool.js";
|
|
16
|
-
import {
|
|
16
|
+
import { registerE2ETestTool } from "./tools/generateE2ERestTool.js";
|
|
17
17
|
import { registerLoginTool } from "./tools/loginTool.js";
|
|
18
18
|
import { registerLogoutTool } from "./tools/logoutTool.js";
|
|
19
19
|
const server = new McpServer({
|
|
@@ -23,18 +23,22 @@ const server = new McpServer({
|
|
|
23
23
|
resources: {},
|
|
24
24
|
tools: {},
|
|
25
25
|
prompts: {},
|
|
26
|
+
sampling: {},
|
|
27
|
+
elicitation: {},
|
|
26
28
|
},
|
|
27
29
|
});
|
|
28
30
|
// Register prompts
|
|
31
|
+
logger.info("Starting prompt registration process");
|
|
29
32
|
registerTestGenerationPrompt(server);
|
|
30
33
|
registerStartTraceCollectionPrompt(server);
|
|
34
|
+
logger.info("All prompts registered successfully");
|
|
31
35
|
// Register test generation tools
|
|
32
36
|
registerSmokeTestTool(server);
|
|
33
37
|
registerFuzzTestTool(server);
|
|
34
38
|
registerContractTestTool(server);
|
|
35
39
|
registerLoadTestTool(server);
|
|
36
40
|
registerIntegrationTestTool(server);
|
|
37
|
-
|
|
41
|
+
registerE2ETestTool(server);
|
|
38
42
|
registerUITestTool(server);
|
|
39
43
|
// Register other Skyramp tools
|
|
40
44
|
registerLoginTool(server);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
import { getModularizationPrompt } from "../utils/modularization-prompts.js";
|
|
3
|
+
export class ModularizationService {
|
|
4
|
+
constructor() {
|
|
5
|
+
// Initialize any required dependencies
|
|
6
|
+
}
|
|
7
|
+
async processModularizationRequest(params) {
|
|
8
|
+
try {
|
|
9
|
+
const validationResult = this.validateInputs(params);
|
|
10
|
+
if (validationResult.isError) {
|
|
11
|
+
return validationResult;
|
|
12
|
+
}
|
|
13
|
+
const processedResponse = this.buildModularizationResponse(params);
|
|
14
|
+
const finalResponse = this.applyModularization(processedResponse, params);
|
|
15
|
+
logger.info("Modularization request processed successfully", {
|
|
16
|
+
promptLength: params.prompt.length,
|
|
17
|
+
contextType: params.contextType,
|
|
18
|
+
includeModularization: params.includeModularization,
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
type: "text",
|
|
24
|
+
text: finalResponse,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
isError: false,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
logger.error("Error in modularization service", {
|
|
32
|
+
error: error instanceof Error ? error.message : String(error),
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: `Modularization service failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
validateInputs(params) {
|
|
46
|
+
const errors = [];
|
|
47
|
+
if (!params.prompt || params.prompt.trim().length === 0) {
|
|
48
|
+
errors.push("Prompt cannot be empty");
|
|
49
|
+
}
|
|
50
|
+
if (params.prompt && params.prompt.length > 10000) {
|
|
51
|
+
errors.push("Prompt is too long (maximum 10,000 characters)");
|
|
52
|
+
}
|
|
53
|
+
if (errors.length > 0) {
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Validation errors:\n${errors
|
|
59
|
+
.map((err) => `- ${err}`)
|
|
60
|
+
.join("\n")}`,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
isError: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { content: [], isError: false };
|
|
67
|
+
}
|
|
68
|
+
buildModularizationResponse(params) {
|
|
69
|
+
const contextPrefix = this.getContextPrefix(params.contextType || "general");
|
|
70
|
+
const processedPrompt = this.processPrompt(params.prompt);
|
|
71
|
+
return `${contextPrefix}
|
|
72
|
+
|
|
73
|
+
**Processed Prompt:** "${processedPrompt}"
|
|
74
|
+
|
|
75
|
+
**MCP Modularization Context:**
|
|
76
|
+
This tool has received and processed your prompt within the MCP (Model Context Protocol) framework with modularization principles applied. Since this MCP tool is being called by an LLM (like Claude), the LLM should now respond to the original prompt with structured, modularized output.
|
|
77
|
+
|
|
78
|
+
**Original Prompt:**
|
|
79
|
+
"${params.prompt}"
|
|
80
|
+
|
|
81
|
+
**Instructions for LLM:**
|
|
82
|
+
The LLM should provide a comprehensive, modularized response based on the prompt content, applying modularization principles to structure the output with logical grouping, clear separation of concerns, and maintainable organization.`;
|
|
83
|
+
}
|
|
84
|
+
getContextPrefix(contextType) {
|
|
85
|
+
switch (contextType) {
|
|
86
|
+
case "technical":
|
|
87
|
+
return "**Technical Context Analysis:**\nProcessing technical prompt with specialized context handling.";
|
|
88
|
+
case "creative":
|
|
89
|
+
return "**Creative Context Analysis:**\nProcessing creative prompt with enhanced imaginative context.";
|
|
90
|
+
default:
|
|
91
|
+
return "**General Context Analysis:**\nProcessing prompt with standard context handling.";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
processPrompt(prompt) {
|
|
95
|
+
// Apply basic prompt processing (trim, normalize whitespace)
|
|
96
|
+
return prompt.trim().replace(/\s+/g, " ");
|
|
97
|
+
}
|
|
98
|
+
applyModularization(response, params) {
|
|
99
|
+
if (params.includeModularization) {
|
|
100
|
+
return `${response}
|
|
101
|
+
|
|
102
|
+
${getModularizationPrompt()}
|
|
103
|
+
|
|
104
|
+
**Modularization Applied:**
|
|
105
|
+
The response has been structured using modularization principles to improve readability and maintainability.`;
|
|
106
|
+
}
|
|
107
|
+
return response;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -3,6 +3,7 @@ import { analyzeOpenAPIWithGivenEndpoint } from "../utils/analyze-openapi.js";
|
|
|
3
3
|
import { getPathParameterValidationError, OUTPUT_DIR_FIELD_NAME, PATH_PARAMS_FIELD_NAME, QUERY_PARAMS_FIELD_NAME, FORM_PARAMS_FIELD_NAME, validateParams, validatePath, validateRequestData, TELEMETRY_entrypoint_FIELD_NAME, } from "../utils/utils.js";
|
|
4
4
|
import { getLanguageSteps } from "../utils/language-helper.js";
|
|
5
5
|
import { getModularizationPrompt } from "../utils/modularization-prompts.js";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
6
7
|
export class TestGenerationService {
|
|
7
8
|
client;
|
|
8
9
|
constructor() {
|
|
@@ -10,22 +11,25 @@ export class TestGenerationService {
|
|
|
10
11
|
}
|
|
11
12
|
async generateTest(params) {
|
|
12
13
|
try {
|
|
14
|
+
// Log prompt parameter using reusable utility
|
|
15
|
+
logger.info("Generating test", {
|
|
16
|
+
prompt: params.prompt,
|
|
17
|
+
testType: this.getTestType(),
|
|
18
|
+
language: params.language,
|
|
19
|
+
outputDir: params.outputDir,
|
|
20
|
+
});
|
|
13
21
|
const validationResult = this.validateInputs(params);
|
|
14
22
|
if (validationResult.isError) {
|
|
15
23
|
return validationResult;
|
|
16
24
|
}
|
|
17
25
|
const generateOptions = this.buildGenerationOptions(params);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// );
|
|
23
|
-
// if (apiAnalysisResult) {
|
|
24
|
-
// return apiAnalysisResult;
|
|
25
|
-
// }
|
|
26
|
+
const apiAnalysisResult = await this.handleApiAnalysis(params, generateOptions);
|
|
27
|
+
if (apiAnalysisResult) {
|
|
28
|
+
return apiAnalysisResult;
|
|
29
|
+
}
|
|
26
30
|
const result = await this.executeGeneration(generateOptions);
|
|
27
31
|
const testType = this.getTestType();
|
|
28
|
-
const shouldModularize = testType
|
|
32
|
+
const shouldModularize = testType === "ui" || testType === "e2e" || testType === "integration";
|
|
29
33
|
const languageSteps = getLanguageSteps({
|
|
30
34
|
language: params.language || "",
|
|
31
35
|
testType: params.testType,
|
|
@@ -86,7 +90,7 @@ export class TestGenerationService {
|
|
|
86
90
|
: errList;
|
|
87
91
|
}
|
|
88
92
|
async handleApiAnalysis(params, generateOptions) {
|
|
89
|
-
if (params.apiSchema && params.endpointURL && params.method
|
|
93
|
+
if (params.apiSchema && params.endpointURL && params.method === "") {
|
|
90
94
|
try {
|
|
91
95
|
const requiredPathParams = await analyzeOpenAPIWithGivenEndpoint(params.apiSchema, params.endpointURL, params.pathParams ?? "");
|
|
92
96
|
if (requiredPathParams && requiredPathParams.trim().length > 0) {
|
|
@@ -94,7 +98,8 @@ export class TestGenerationService {
|
|
|
94
98
|
content: [
|
|
95
99
|
{
|
|
96
100
|
type: "text",
|
|
97
|
-
text: getPathParameterValidationError(requiredPathParams)
|
|
101
|
+
text: `${getPathParameterValidationError(requiredPathParams)}
|
|
102
|
+
**IMPORTANT: MAKE SURE TO PROVIDE THE PATH PARAMS THAT DO NOT GIVE 404 ERROR FOR GET/DELETE METHODS. IT WILL BE USED AS PATH PARAMS IN THE TEST GENERATION.**`,
|
|
98
103
|
},
|
|
99
104
|
],
|
|
100
105
|
isError: true,
|
|
@@ -135,12 +135,13 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
|
|
|
135
135
|
output: output.substring(0, 200) + (output.length > 200 ? "..." : ""),
|
|
136
136
|
statusCode,
|
|
137
137
|
});
|
|
138
|
-
if (statusCode
|
|
138
|
+
if (statusCode !== 0) {
|
|
139
139
|
return {
|
|
140
140
|
content: [
|
|
141
141
|
{
|
|
142
142
|
type: "text",
|
|
143
|
-
text: `Test execution failed: ${output}
|
|
143
|
+
text: `Test execution failed: ${output}
|
|
144
|
+
**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.**`,
|
|
144
145
|
},
|
|
145
146
|
],
|
|
146
147
|
};
|
|
@@ -6,7 +6,7 @@ const e2eTestSchema = {
|
|
|
6
6
|
...baseTraceSchema.shape,
|
|
7
7
|
playwrightInput: z
|
|
8
8
|
.string()
|
|
9
|
-
.describe("MUST be absolute path to the playwright input file like
|
|
9
|
+
.describe("MUST be absolute path to the playwright input file like /path/to/playwright-ui-test.zip and MUST be a zip file"),
|
|
10
10
|
};
|
|
11
11
|
export class E2ETestService extends TestGenerationService {
|
|
12
12
|
getTestType() {
|
|
@@ -20,7 +20,7 @@ export class E2ETestService extends TestGenerationService {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
export function
|
|
23
|
+
export function registerE2ETestTool(server) {
|
|
24
24
|
server.registerTool("skyramp_e2e_test_generation", {
|
|
25
25
|
description: `Generate an End-to-End (E2E) test using Skyramp's deterministic test generation platform.
|
|
26
26
|
|
|
@@ -6,7 +6,7 @@ const loadTestSchema = {
|
|
|
6
6
|
loadCount: z
|
|
7
7
|
.string()
|
|
8
8
|
.default("")
|
|
9
|
-
.describe("Total string of iteration to be
|
|
9
|
+
.describe("Total string of iteration to be executed for the test. DO NOT ASSUME VALUE"),
|
|
10
10
|
loadDuration: z
|
|
11
11
|
.string()
|
|
12
12
|
.default("5")
|
|
@@ -54,14 +54,14 @@ export function registerLoadTestTool(server) {
|
|
|
54
54
|
|
|
55
55
|
Load tests evaluate your application's performance, scalability, and stability under various traffic conditions. They simulate multiple concurrent users, measure response times, identify performance bottlenecks, and ensure your system can handle expected traffic volumes.
|
|
56
56
|
|
|
57
|
-
***IMPORTANT
|
|
58
|
-
-At any given time you can provide duration of the test or test execution count
|
|
57
|
+
***IMPORTANT***
|
|
58
|
+
- At any given time you can provide duration of the test or test execution count
|
|
59
59
|
- IF THE USER DOES NOT PROVIDE LOAD PARAMETERS, THEN USE DEFAULT VALUES FOR LOAD TESTS:
|
|
60
60
|
- loadDuration: "5" (5 seconds)
|
|
61
61
|
- loadNumThreads: "1" (1 thread)
|
|
62
62
|
- Other load parameters should remain empty unless explicitly specified by the user
|
|
63
63
|
|
|
64
|
-
For detailed documentation visit: https://www.skyramp.dev/docs/load-test`,
|
|
64
|
+
For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advanced-generation#start-trace-collection`,
|
|
65
65
|
inputSchema: loadTestSchema,
|
|
66
66
|
annotations: {
|
|
67
67
|
keywords: ["load test", "performance test"],
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ModularizationService, } from "../services/ModularizationService.js";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
const modularizationSchema = {
|
|
5
|
+
prompt: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("The prompt or code content to process with modularization principles applied"),
|
|
8
|
+
includeModularization: z
|
|
9
|
+
.boolean()
|
|
10
|
+
.optional()
|
|
11
|
+
.default(true)
|
|
12
|
+
.describe("Whether to include detailed modularization instructions in the response"),
|
|
13
|
+
contextType: z
|
|
14
|
+
.enum(["general", "technical", "creative"])
|
|
15
|
+
.optional()
|
|
16
|
+
.default("general")
|
|
17
|
+
.describe("The type of context for processing: general for standard content, technical for code/technical content, creative for creative/artistic content"),
|
|
18
|
+
};
|
|
19
|
+
export function registerModularizationTool(server) {
|
|
20
|
+
server.registerTool("skyramp_modularization", {
|
|
21
|
+
description: `Process prompts and content using MCP modularization principles.
|
|
22
|
+
|
|
23
|
+
This tool applies modularization principles to structure and organize content, code, or responses in a logical, maintainable way. It's particularly useful for:
|
|
24
|
+
|
|
25
|
+
• Code refactoring with modularization best practices
|
|
26
|
+
• Structuring complex responses into logical modules
|
|
27
|
+
• Applying separation of concerns to content organization
|
|
28
|
+
• Creating maintainable and readable output structures
|
|
29
|
+
|
|
30
|
+
MODULARIZATION PRINCIPLES:
|
|
31
|
+
• Logical grouping of related functionality
|
|
32
|
+
• Clear separation of concerns
|
|
33
|
+
• Parameterization for flexibility
|
|
34
|
+
• Preservation of original functionality
|
|
35
|
+
• Helper function extraction where applicable
|
|
36
|
+
|
|
37
|
+
The tool processes your prompt within the MCP framework and provides structured guidance for modularized responses.`,
|
|
38
|
+
inputSchema: modularizationSchema,
|
|
39
|
+
annotations: {
|
|
40
|
+
keywords: [
|
|
41
|
+
"modularization",
|
|
42
|
+
"code organization",
|
|
43
|
+
"structure",
|
|
44
|
+
"refactor",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
}, async (params) => {
|
|
48
|
+
logger.info("Generating modularization", {
|
|
49
|
+
prompt: params.prompt,
|
|
50
|
+
contextType: params.contextType,
|
|
51
|
+
includeModularization: params.includeModularization,
|
|
52
|
+
});
|
|
53
|
+
const service = new ModularizationService();
|
|
54
|
+
return await service.processModularizationRequest(params);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -21,7 +21,7 @@ const uiTestSchema = {
|
|
|
21
21
|
...baseSchema.shape,
|
|
22
22
|
playwrightInput: z
|
|
23
23
|
.string()
|
|
24
|
-
.describe("MUST be absolute path to the playwright input file like
|
|
24
|
+
.describe("MUST be absolute path to the playwright input file like /path/to/playwright-ui-test.zip and MUST be a zip file"),
|
|
25
25
|
};
|
|
26
26
|
export function registerUITestTool(server) {
|
|
27
27
|
server.registerTool("skyramp_ui_test_generation", {
|
package/build/tools/loginTool.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
3
4
|
export function registerLoginTool(server) {
|
|
@@ -5,34 +6,34 @@ export function registerLoginTool(server) {
|
|
|
5
6
|
description: `Login to Skyramp platform
|
|
6
7
|
|
|
7
8
|
Logging into Skyramp provides access to additional platform features and services.
|
|
8
|
-
|
|
9
9
|
`,
|
|
10
|
-
inputSchema: {
|
|
10
|
+
inputSchema: {
|
|
11
|
+
prompt: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe("The prompt user provided to login to Skyramp"),
|
|
14
|
+
},
|
|
11
15
|
annotations: {
|
|
12
16
|
keywords: ["login", "authenticate", "skyramp login"],
|
|
13
17
|
},
|
|
14
|
-
}, async () => {
|
|
18
|
+
}, async (params) => {
|
|
19
|
+
logger.info("Logging in to Skyramp", {
|
|
20
|
+
prompt: params.prompt,
|
|
21
|
+
});
|
|
15
22
|
const client = new SkyrampClient();
|
|
16
23
|
try {
|
|
17
|
-
logger.info("Attempting to login to Skyramp...");
|
|
18
24
|
const result = await client.login();
|
|
19
|
-
// Strip ANSI codes if result contains them
|
|
20
|
-
const cleanResult = result.replace(/\u001b\[[0-9;]*m/g, "");
|
|
21
25
|
logger.info("Skyramp login successful");
|
|
22
26
|
return {
|
|
23
27
|
content: [
|
|
24
28
|
{
|
|
25
29
|
type: "text",
|
|
26
|
-
text:
|
|
30
|
+
text: result,
|
|
27
31
|
},
|
|
28
32
|
],
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
35
|
catch (error) {
|
|
32
36
|
const errorMessage = `Login to Skyramp failed: ${error.message}`;
|
|
33
|
-
logger.error("Skyramp login failed", {
|
|
34
|
-
error: error.message,
|
|
35
|
-
});
|
|
36
37
|
return {
|
|
37
38
|
content: [
|
|
38
39
|
{
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
3
4
|
export function registerLogoutTool(server) {
|
|
4
5
|
server.registerTool("skyramp_logout", {
|
|
5
6
|
description: `Logout from Skyramp platform
|
|
6
7
|
|
|
7
|
-
Logout from Skyramp platform to end your authenticated session
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Logout from Skyramp platform to end your authenticated session.`,
|
|
9
|
+
inputSchema: {
|
|
10
|
+
prompt: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("The prompt user provided to logout from Skyramp"),
|
|
13
|
+
},
|
|
10
14
|
annotations: {
|
|
11
15
|
keywords: ["logout", "sign out", "skyramp logout"],
|
|
12
16
|
},
|
|
13
|
-
}, async () => {
|
|
17
|
+
}, async (params) => {
|
|
18
|
+
logger.info("Logging out from Skyramp", {
|
|
19
|
+
prompt: params.prompt,
|
|
20
|
+
});
|
|
14
21
|
const client = new SkyrampClient();
|
|
15
22
|
try {
|
|
16
|
-
logger.info("Attempting to logout from Skyramp...");
|
|
17
23
|
const result = await client.logout();
|
|
18
|
-
// Strip ANSI codes if result contains them
|
|
19
|
-
const cleanResult = result.replace(/\u001b\[[0-9;]*m/g, "");
|
|
20
|
-
logger.info("Skyramp logout successful");
|
|
21
24
|
return {
|
|
22
25
|
content: [
|
|
23
26
|
{
|
|
24
27
|
type: "text",
|
|
25
|
-
text:
|
|
28
|
+
text: result,
|
|
26
29
|
},
|
|
27
30
|
],
|
|
28
31
|
};
|
|
29
32
|
}
|
|
30
33
|
catch (error) {
|
|
31
34
|
const errorMessage = `Logout from Skyramp failed: ${error.message}`;
|
|
32
|
-
logger.error("Skyramp logout failed", {
|
|
33
|
-
error: error.message,
|
|
34
|
-
});
|
|
35
35
|
return {
|
|
36
36
|
content: [
|
|
37
37
|
{
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { SkyrampClient } from "@skyramp/skyramp";
|
|
3
3
|
import openProxyTerminalTracked from "../utils/proxy-terminal.js";
|
|
4
4
|
import { TELEMETRY_entrypoint_FIELD_NAME } from "../utils/utils.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
5
6
|
export function registerTraceTool(server) {
|
|
6
7
|
server.registerTool("skyramp_start_trace_collection", {
|
|
7
8
|
description: `Start trace collection using Skyramp's comprehensive tracing capabilities.
|
|
@@ -19,7 +20,7 @@ WORKFLOW:
|
|
|
19
20
|
3. Stop trace collection to save captured data
|
|
20
21
|
4. Use traces to generate realistic test scenarios
|
|
21
22
|
|
|
22
|
-
For detailed documentation visit:https://www.skyramp.dev/docs/load-test/advanced-generation#start-trace-collection`,
|
|
23
|
+
For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advanced-generation#start-trace-collection`,
|
|
23
24
|
inputSchema: {
|
|
24
25
|
playwright: z
|
|
25
26
|
.boolean()
|
|
@@ -49,11 +50,24 @@ For detailed documentation visit:https://www.skyramp.dev/docs/load-test/advanced
|
|
|
49
50
|
.number()
|
|
50
51
|
.default(35142)
|
|
51
52
|
.describe("Port number for the Docker worker service during trace collection"),
|
|
53
|
+
prompt: z
|
|
54
|
+
.string()
|
|
55
|
+
.describe("The prompt user provided to start trace collection"),
|
|
52
56
|
},
|
|
53
57
|
annotations: {
|
|
54
58
|
keywords: ["start trace", "trace collection", "trace generation"],
|
|
55
59
|
},
|
|
56
60
|
}, async (params) => {
|
|
61
|
+
logger.info("Starting trace collection", {
|
|
62
|
+
playwright: params.playwright,
|
|
63
|
+
runtime: params.runtime,
|
|
64
|
+
include: params.include,
|
|
65
|
+
exclude: params.exclude,
|
|
66
|
+
noProxy: params.noProxy,
|
|
67
|
+
dockerNetwork: params.dockerNetwork,
|
|
68
|
+
dockerWorkerPort: params.dockerWorkerPort,
|
|
69
|
+
prompt: params.prompt,
|
|
70
|
+
});
|
|
57
71
|
const client = new SkyrampClient();
|
|
58
72
|
const generateOptions = {
|
|
59
73
|
testType: "trace",
|
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { PLAYWRIGHT_OUTPUT_FILE_FIELD_NAME, TELEMETRY_entrypoint_FIELD_NAME, TRACE_OUTPUT_FILE_FIELD_NAME, validatePath, } from "../utils/utils.js";
|
|
5
5
|
import { logger } from "../utils/logger.js";
|
|
6
6
|
export function registerTraceStopTool(server) {
|
|
7
|
-
server.registerTool("
|
|
7
|
+
server.registerTool("skyramp_stop_trace_collection", {
|
|
8
8
|
description: `Stop trace collection and save captured data using Skyramp's comprehensive tracing capabilities.
|
|
9
9
|
|
|
10
10
|
Stopping trace collection finalizes the monitoring process and exports all captured data to specified files. This includes API calls, service communications, user interactions, and network traffic that occurred during the collection period.
|
|
@@ -27,11 +27,20 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
27
27
|
playwrightOutput: z
|
|
28
28
|
.string()
|
|
29
29
|
.describe("MUST be absolute path to save the Playwright output file (e.g., /path/to/playwright.zip). Only used when playwright is true"),
|
|
30
|
+
prompt: z
|
|
31
|
+
.string()
|
|
32
|
+
.describe("The prompt user provided to stop trace collection"),
|
|
30
33
|
},
|
|
31
34
|
annotations: {
|
|
32
35
|
keywords: ["stop trace", "collect generated trace"],
|
|
33
36
|
},
|
|
34
37
|
}, async (params) => {
|
|
38
|
+
logger.info("Stopping trace collection", {
|
|
39
|
+
traceOutputFile: params.traceOutputFile,
|
|
40
|
+
playwright: params.playwright,
|
|
41
|
+
playwrightOutput: params.playwrightOutput,
|
|
42
|
+
prompt: params.prompt,
|
|
43
|
+
});
|
|
35
44
|
const client = new SkyrampClient();
|
|
36
45
|
try {
|
|
37
46
|
const stopTraceOptions = {
|
|
@@ -45,8 +54,8 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
45
54
|
content: [],
|
|
46
55
|
isError: true,
|
|
47
56
|
};
|
|
48
|
-
if (stopTraceOptions.output
|
|
49
|
-
stopTraceOptions.playwrightOutput
|
|
57
|
+
if (stopTraceOptions.output === "" &&
|
|
58
|
+
stopTraceOptions.playwrightOutput === "") {
|
|
50
59
|
errList.content.push({
|
|
51
60
|
type: "text",
|
|
52
61
|
text: "Error: Either trace output file or playwright output file is required.",
|
|
@@ -67,7 +76,7 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
67
76
|
if (err && err.content) {
|
|
68
77
|
errList.content.push(err.content[0]);
|
|
69
78
|
}
|
|
70
|
-
//
|
|
79
|
+
// If error is not empty, return error
|
|
71
80
|
if (errList.content.length > 0) {
|
|
72
81
|
return errList;
|
|
73
82
|
}
|
|
@@ -77,7 +86,10 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
77
86
|
content: [
|
|
78
87
|
{
|
|
79
88
|
type: "text",
|
|
80
|
-
text: `Trace collection is stopped: ${result}. Trace is generated to given output file
|
|
89
|
+
text: `Trace collection is stopped: ${result}. Trace is generated to given output file
|
|
90
|
+
|
|
91
|
+
**IMPORTANT: GO THROUGH THE TRACE AND LET THE USER KNOW THE ENDPOINT DOMAINS CAPTURED AND MAKE SURE USER WANTS TO INCLUDE THEN FOR INTEGRATION/E2E/LOAD TEST GENERATION.
|
|
92
|
+
UI TESTS CAN BE GENERATED USING PLAYWRIGHT FILES ONLY.**`,
|
|
81
93
|
},
|
|
82
94
|
],
|
|
83
95
|
};
|
package/build/types/TestTypes.js
CHANGED
|
@@ -5,9 +5,11 @@ export const baseSchema = z.object({
|
|
|
5
5
|
.describe("Programming language for the generated test (default: python)"),
|
|
6
6
|
framework: z
|
|
7
7
|
.string()
|
|
8
|
-
.
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
.describe("Testing framework to use (e.g., pytest for python, playwright for javascript and typescript, junit for java, etc.)"),
|
|
9
|
+
output: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Name of the output test file. Default value is empty string. If not provided, Skyramp will generate a default name for the test file."),
|
|
11
13
|
outputDir: z
|
|
12
14
|
.string()
|
|
13
15
|
.describe("MUST be absolute path to the directory where test files will be generated. If not provided, the CURRENT WORKING DIRECTORY will be used WITHOUT ANY SUBDIRECTORIES"),
|
|
@@ -47,6 +49,7 @@ export const baseSchema = z.object({
|
|
|
47
49
|
.boolean()
|
|
48
50
|
.default(false)
|
|
49
51
|
.describe("Whether to allow insecure SSL connections for HTTPS endpoints"),
|
|
52
|
+
prompt: z.string().describe("The prompt user provided to generate the test"),
|
|
50
53
|
});
|
|
51
54
|
export const baseTraceSchema = z.object({
|
|
52
55
|
...baseSchema.shape,
|
|
@@ -6,9 +6,10 @@ export function getModularizationPrompt() {
|
|
|
6
6
|
2. Parameterize the test function(s) with meaningful parameters to make it more flexible. Preserve the original order of code lines within each function
|
|
7
7
|
3. Do not change or remove any existing lines of code, variable names, function names, or function structures.
|
|
8
8
|
4. Only extract reusable logical sections into helper functions or parameterized structures where applicable.
|
|
9
|
-
5.
|
|
10
|
-
6.
|
|
11
|
-
7.
|
|
9
|
+
5. SEARCH REPOSITORY FOR CODE THAT CAN BE REUSED AND USE IT. WITHOUT BREAKING NEW OR EXISTING TESTS/FUNCTIONS/CODE.
|
|
10
|
+
6. Do not create any new test cases but only helper functions.
|
|
11
|
+
7. Make sure the logic is same and the test works as expected.
|
|
12
|
+
8. Do not add any new logic or classes or any other files.
|
|
12
13
|
|
|
13
14
|
Please refactor the code with these modularization principles. Respond with the complete, modularized code only.
|
|
14
15
|
`;
|
package/build/utils/utils.js
CHANGED
|
@@ -100,7 +100,7 @@ export function validateRequestData(value) {
|
|
|
100
100
|
if (value.includes("@")) {
|
|
101
101
|
return value;
|
|
102
102
|
}
|
|
103
|
-
//
|
|
103
|
+
// If value is valid JSON string return value
|
|
104
104
|
try {
|
|
105
105
|
JSON.parse(value);
|
|
106
106
|
return value;
|
|
@@ -110,7 +110,7 @@ export function validateRequestData(value) {
|
|
|
110
110
|
}
|
|
111
111
|
const isAbsolute = path.isAbsolute(value);
|
|
112
112
|
logger.debug("Path validation check", { value, isAbsolute });
|
|
113
|
-
//
|
|
113
|
+
// If value is path
|
|
114
114
|
if (isAbsolute) {
|
|
115
115
|
return "@" + value;
|
|
116
116
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.11.4",
|
|
45
|
-
"@skyramp/skyramp": "^1.2.
|
|
45
|
+
"@skyramp/skyramp": "^1.2.10",
|
|
46
46
|
"dockerode": "^4.0.6",
|
|
47
47
|
"zod": "^3.25.3"
|
|
48
48
|
},
|