@skyramp/mcp
Version:
Skyramp MCP (Model Context Protocol) Server - AI-powered test generation and execution
171 lines (164 loc) • 7.1 kB
JavaScript
import { z } from "zod";
import Docker from "dockerode";
import path from "path";
import { Writable } from "stream";
import { logger } from "../utils/logger.js";
// Configuration for language-specific file paths
const LANGUAGE_PATHS = {
python: "/tmp",
javascript: "/tmp",
typescript: "/tmp",
java: "/app/src",
};
export function registerExecuteSkyrampTestTool(server) {
server.registerTool("skyramp_execute_test", {
description: `Execute a Skyramp-generated test in isolated containerized environments for reliable, deterministic testing.
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.
KEY FEATURES:
• Isolated Execution: Tests run in containerized environments for consistency
• Multi-Language Support: Execute tests written in Python, Java, JavaScript, or TypeScript
• Out-of-the-Box Execution: Generated tests work immediately without modification
REQUIRED PARAMETERS:
- language: Programming language of your test file (python, javascript, typescript, java)
- testType: Type of test to execute (smoke, contract, fuzz, integration, load, ui, e2e)
- testFile: Absolute path to the generated test file to execute
- token: Authentication token for your service (use empty string if no authentication required)
AUTHENTICATION:
Provide your authentication token (typically a Bearer token) for services that require authentication. Use an empty string for services that don't require authentication.
IMPORTANT NOTES:
- First-time usage may take longer as Docker images are downloaded
- Tests run in isolated containers for maximum reliability
- Generated tests are designed to work out-of-the-box without modification
- Results include detailed execution logs and test outcomes
For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
inputSchema: {
language: z
.string()
.describe("Programming language of the test file to execute (e.g., python, javascript, typescript, java)"),
testType: z
.string()
.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]."),
testFile: z
.string()
.describe("ALWAYS USE ABSOLUTE PATH to the test file to execute"),
token: z
.string()
.describe("Skyramp authentication token for test execution. USE EMPTY STRING WHEN USER CONFIRMS 'No token required'"),
},
annotations: {
keywords: ["run test", "execute test"],
},
}, async (params) => {
var docker = new Docker();
var image = "public.ecr.aws/skyramp/rampup/runner:mcp-v0.0.3";
// Use path.basename for safer filename extraction
const filename = path.basename(params.testFile);
if (!filename) {
throw new Error("Invalid test file path: could not extract filename");
}
// Use configurable language paths with fallback
const basePath = LANGUAGE_PATHS[params.language] || "/tmp";
const filePath = path.join(basePath, filename);
var command = [
"./root/runner.sh",
params.language,
filePath,
params.testType,
];
const hostConfig = {
Mounts: [
{
Target: filePath,
Source: path.resolve(params.testFile),
Type: "bind",
},
],
};
const env = [
"SKYRAMP_TEST_TOKEN=" + params.token,
"SKYRAMP_IN_DOCKER=true",
];
var output = "";
class DockerStream extends Writable {
_write(data, encode, cb) {
output += data.toString();
cb();
}
}
var stream = new DockerStream();
try {
var statusCode = 0;
// check if image exists
const images = await docker.listImages();
const imageExists = images.some((img) => (img.RepoTags && img.RepoTags.includes(image)) ||
(img.RepoDigests && img.RepoDigests.includes(image)));
if (!imageExists) {
// Pull the image if it does not exist
await new Promise((resolve, reject) => {
docker.pull(image, (err, stream) => {
if (err)
return reject(err);
docker.modem.followProgress(stream, (err, res) => {
if (err)
return reject(err);
resolve(res);
});
});
});
}
await docker
.run(image, command, stream, { Env: env, HostConfig: hostConfig })
.then(function (data) {
var result = data[0];
var container = data[1];
stream.end();
statusCode = result.StatusCode;
logger.debug("Docker container execution completed");
return container.remove();
})
.then(function (data) {
logger.debug("Docker container removed successfully");
})
.catch(function (err) {
logger.error("Docker container execution failed", {
error: err.message,
});
throw err;
});
logger.info("Test execution completed", {
output: output.substring(0, 200) + (output.length > 200 ? "..." : ""),
statusCode,
});
if (statusCode !== 0) {
return {
content: [
{
type: "text",
text: `Test execution failed: ${output}
**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.**`,
},
],
};
}
return {
content: [
{
type: "text",
text: `Test execution result: ${output}`,
},
],
};
}
catch (err) {
return {
content: [
{
type: "text",
text: `Test execution failed: ${err.message}`,
},
],
isError: true,
};
}
});
}