UNPKG

@skyramp/mcp

Version:

Skyramp MCP (Model Context Protocol) Server - AI-powered test generation and execution

171 lines (164 loc) 7.1 kB
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, }; } }); }