@skyramp/mcp 0.0.1 → 0.0.3
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/build/index.js
CHANGED
|
@@ -15,6 +15,8 @@ import { registerContractTestTool } from "./tools/generateContractRestTool.js";
|
|
|
15
15
|
import { registerLoadTestTool } from "./tools/generateLoadRestTool.js";
|
|
16
16
|
import { registerIntegrationTestTool } from "./tools/generateIntegrationRestTool.js";
|
|
17
17
|
import { registerEndtoEndTestTool } from "./tools/generateE2ERestTool.js";
|
|
18
|
+
import { registerLoginTool } from "./tools/loginTool.js";
|
|
19
|
+
import { registerLogoutTool } from "./tools/logoutTool.js";
|
|
18
20
|
const server = new McpServer({
|
|
19
21
|
name: "Skyramp MCP Server",
|
|
20
22
|
version: "1.0.0",
|
|
@@ -37,6 +39,8 @@ registerIntegrationTestTool(server);
|
|
|
37
39
|
registerEndtoEndTestTool(server);
|
|
38
40
|
registerUITestTool(server);
|
|
39
41
|
// Register other Skyramp tools
|
|
42
|
+
registerLoginTool(server);
|
|
43
|
+
registerLogoutTool(server);
|
|
40
44
|
registerExecuteSkyrampTestTool(server);
|
|
41
45
|
registerTraceTool(server);
|
|
42
46
|
registerTraceStopTool(server);
|
|
@@ -24,8 +24,21 @@ export class TestGenerationService {
|
|
|
24
24
|
type: "text",
|
|
25
25
|
text: `${result}
|
|
26
26
|
|
|
27
|
-
If the test
|
|
28
|
-
|
|
27
|
+
If the test was successfully created, I can help refactor your test code to make it more modular and reusable.
|
|
28
|
+
Would you like to proceed with this step?
|
|
29
|
+
|
|
30
|
+
Reply "yes" to continue or "no" to skip.
|
|
31
|
+
|
|
32
|
+
If you reply "yes", I will:
|
|
33
|
+
|
|
34
|
+
Parameterize the test functions into logical groups (e.g., login) to enable reusability for other test scenarios.
|
|
35
|
+
|
|
36
|
+
NOT alter any existing logic, test scenarios, or test cases.
|
|
37
|
+
|
|
38
|
+
NOT add any new logic or classes.
|
|
39
|
+
|
|
40
|
+
Only restructure the code for better modularity and reusability.
|
|
41
|
+
`,
|
|
29
42
|
},
|
|
30
43
|
],
|
|
31
44
|
isError: false,
|
|
@@ -3,13 +3,22 @@ import Docker from "dockerode";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { Writable } from "stream";
|
|
5
5
|
import { logger } from "../utils/logger.js";
|
|
6
|
+
// Configuration for language-specific file paths
|
|
7
|
+
const LANGUAGE_PATHS = {
|
|
8
|
+
python: "/tmp",
|
|
9
|
+
javascript: "/tmp",
|
|
10
|
+
typescript: "/tmp",
|
|
11
|
+
java: "/app/src",
|
|
12
|
+
};
|
|
6
13
|
export function registerExecuteSkyrampTestTool(server) {
|
|
7
14
|
server.registerTool("skyramp_execute_test", {
|
|
8
|
-
description:
|
|
15
|
+
description: `Execute a Skyramp test to validate your application using isolated containerized environments.
|
|
16
|
+
Before I can execute the test for you, I need to confirm the following information:
|
|
17
|
+
Authentication: Please provide me with your authentication token (by default we assume a Bearer Token). If you don't require any token for your service please just say: 'No token required'`,
|
|
9
18
|
inputSchema: {
|
|
10
19
|
language: z
|
|
11
20
|
.string()
|
|
12
|
-
.describe("Programming language of the test file to execute (e.g., python, javascript, typescript, java)
|
|
21
|
+
.describe("Programming language of the test file to execute (e.g., python, javascript, typescript, java)"),
|
|
13
22
|
testType: z
|
|
14
23
|
.string()
|
|
15
24
|
.describe("Type of the test to execute (e.g., integration, contract, smoke, fuzz, load, e2e, ui). TEST TYPE MUST BE FROM [integration, contract, smoke, fuzz, load, e2e, ui]."),
|
|
@@ -18,19 +27,32 @@ export function registerExecuteSkyrampTestTool(server) {
|
|
|
18
27
|
.describe("ALWAYS USE ABSOLUTE PATH to the test file to execute"),
|
|
19
28
|
token: z
|
|
20
29
|
.string()
|
|
21
|
-
.describe("Skyramp authentication token for test execution"),
|
|
30
|
+
.describe("Skyramp authentication token for test execution. Use '' when user confirms 'No token required'"),
|
|
22
31
|
},
|
|
23
32
|
annotations: {
|
|
24
33
|
keywords: ["run test", "execute test"],
|
|
25
34
|
},
|
|
26
35
|
}, async (params) => {
|
|
27
36
|
var docker = new Docker();
|
|
28
|
-
var image = "public.ecr.aws/skyramp/rampup/runner:mcp-v0.0.
|
|
29
|
-
|
|
37
|
+
var image = "public.ecr.aws/skyramp/rampup/runner:mcp-v0.0.3";
|
|
38
|
+
// Use path.basename for safer filename extraction
|
|
39
|
+
const filename = path.basename(params.testFile);
|
|
40
|
+
if (!filename) {
|
|
41
|
+
throw new Error("Invalid test file path: could not extract filename");
|
|
42
|
+
}
|
|
43
|
+
// Use configurable language paths with fallback
|
|
44
|
+
const basePath = LANGUAGE_PATHS[params.language] || "/tmp";
|
|
45
|
+
const filePath = path.join(basePath, filename);
|
|
46
|
+
var command = [
|
|
47
|
+
"./root/runner.sh",
|
|
48
|
+
params.language,
|
|
49
|
+
filePath,
|
|
50
|
+
params.testType,
|
|
51
|
+
];
|
|
30
52
|
const hostConfig = {
|
|
31
53
|
Mounts: [
|
|
32
54
|
{
|
|
33
|
-
Target:
|
|
55
|
+
Target: filePath,
|
|
34
56
|
Source: path.resolve(params.testFile),
|
|
35
57
|
Type: "bind",
|
|
36
58
|
},
|
|
@@ -50,6 +72,24 @@ export function registerExecuteSkyrampTestTool(server) {
|
|
|
50
72
|
var stream = new DockerStream();
|
|
51
73
|
try {
|
|
52
74
|
var statusCode = 0;
|
|
75
|
+
// check if image exists
|
|
76
|
+
const images = await docker.listImages();
|
|
77
|
+
const imageExists = images.some((img) => (img.RepoTags && img.RepoTags.includes(image)) ||
|
|
78
|
+
(img.RepoDigests && img.RepoDigests.includes(image)));
|
|
79
|
+
if (!imageExists) {
|
|
80
|
+
// Pull the image if it does not exist
|
|
81
|
+
await new Promise((resolve, reject) => {
|
|
82
|
+
docker.pull(image, (err, stream) => {
|
|
83
|
+
if (err)
|
|
84
|
+
return reject(err);
|
|
85
|
+
docker.modem.followProgress(stream, (err, res) => {
|
|
86
|
+
if (err)
|
|
87
|
+
return reject(err);
|
|
88
|
+
resolve(res);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
53
93
|
await docker
|
|
54
94
|
.run(image, command, stream, { Env: env, HostConfig: hostConfig })
|
|
55
95
|
.then(function (data) {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
|
+
import { logger } from "../utils/logger.js";
|
|
3
|
+
export function registerLoginTool(server) {
|
|
4
|
+
server.registerTool("skyramp_login", {
|
|
5
|
+
description: "Login to Skyramp platform",
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
annotations: {
|
|
8
|
+
keywords: ["login", "authenticate", "skyramp login"],
|
|
9
|
+
},
|
|
10
|
+
}, async () => {
|
|
11
|
+
const client = new SkyrampClient();
|
|
12
|
+
try {
|
|
13
|
+
logger.info("Attempting to login to Skyramp...");
|
|
14
|
+
const result = await client.login();
|
|
15
|
+
// Strip ANSI codes if result contains them
|
|
16
|
+
const cleanResult = result.replace(/\u001b\[[0-9;]*m/g, "");
|
|
17
|
+
logger.info("Skyramp login successful");
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
type: "text",
|
|
22
|
+
text: cleanResult,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const errorMessage = `Login to Skyramp failed: ${error.message}`;
|
|
29
|
+
logger.error("Skyramp login failed", {
|
|
30
|
+
error: error.message,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: "text",
|
|
36
|
+
text: errorMessage,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
isError: true,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
|
+
import { logger } from "../utils/logger.js";
|
|
3
|
+
export function registerLogoutTool(server) {
|
|
4
|
+
server.registerTool("skyramp_logout", {
|
|
5
|
+
description: "Logout from Skyramp platform",
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
annotations: {
|
|
8
|
+
keywords: ["logout", "sign out", "skyramp logout"],
|
|
9
|
+
},
|
|
10
|
+
}, async () => {
|
|
11
|
+
const client = new SkyrampClient();
|
|
12
|
+
try {
|
|
13
|
+
logger.info("Attempting to logout from Skyramp...");
|
|
14
|
+
const result = await client.logout();
|
|
15
|
+
// Strip ANSI codes if result contains them
|
|
16
|
+
const cleanResult = result.replace(/\u001b\[[0-9;]*m/g, "");
|
|
17
|
+
logger.info("Skyramp logout successful");
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
type: "text",
|
|
22
|
+
text: cleanResult,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const errorMessage = `Logout from Skyramp failed: ${error.message}`;
|
|
29
|
+
logger.error("Skyramp logout failed", {
|
|
30
|
+
error: error.message,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: "text",
|
|
36
|
+
text: errorMessage,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
isError: true,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
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.9",
|
|
46
46
|
"dockerode": "^4.0.6",
|
|
47
47
|
"zod": "^3.25.3"
|
|
48
48
|
},
|
|
@@ -58,4 +58,4 @@
|
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=18"
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
}
|