@skyramp/mcp
Version:
Skyramp MCP (Model Context Protocol) Server - AI-powered test generation and execution
159 lines (158 loc) • 7.48 kB
JavaScript
import { z } from "zod";
export const SESSION_STORAGE_FILENAME = "skyramp_session_storage.json";
export var TestType;
(function (TestType) {
TestType["SMOKE"] = "smoke";
TestType["FUZZ"] = "fuzz";
TestType["CONTRACT"] = "contract";
TestType["LOAD"] = "load";
TestType["INTEGRATION"] = "integration";
TestType["E2E"] = "e2e";
TestType["UI"] = "ui";
})(TestType || (TestType = {}));
export const languageSchema = z.object({
language: z
.string()
.refine((val) => {
const validLanguages = ["python", "typescript", "javascript", "java"];
return validLanguages.includes(val.toLowerCase());
}, {
message: "Language must be one of: python, typescript, javascript, java",
})
.describe("Programming language for the generated test (default: python). Must be one of: python, typescript, javascript, java"),
framework: z
.string()
.describe("Testing framework to use (e.g., pytest for python, playwright for javascript and typescript, junit for java, etc.)"),
});
export const baseSchema = z.object({
...languageSchema.shape,
deployDashboard: z
.boolean()
.default(false)
.describe("Whether to deploy the Skyramp dashboard for test monitoring"),
runtime: z
.string()
.default("local")
.describe("Runtime environment (docker, kubernetes, local)"),
dockerNetwork: z
.string()
.default("")
.describe("Docker network name to use for containerized testing"),
dockerWorkerPort: z
.number()
.default(0)
.describe("Port number for the Docker worker service"),
k8sNamespace: z
.string()
.default("")
.describe("Kubernetes namespace for deployment"),
k8sConfig: z
.string()
.default("")
.describe("Path to Kubernetes configuration file"),
k8sContext: z.string().default("").describe("Kubernetes context to use"),
authHeader: z
.string()
.default("")
.describe("Authorization header value for authenticated requests"),
insecure: z
.boolean()
.default(false)
.describe("Whether to allow insecure SSL connections for HTTPS endpoints"),
output: z
.string()
.optional()
.refine((val) => {
if (!val || val === "")
return true; // Allow empty string or undefined
const validExtensions = [".py", ".ts", ".js", ".java"];
return validExtensions.some((ext) => val.endsWith(ext));
}, {
message: "Output file must have one of these extensions: .py, .ts, .js, .java",
})
.describe("Name of the output test file. Must have one of these extensions: .py, .ts, .js, .java. Default value is empty string. If not provided, Skyramp will generate a default name for the test file."),
outputDir: z
.string()
.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"),
force: z
.boolean()
.default(true)
.describe("Whether to overwrite existing files in the output directory"),
prompt: z.string().describe("The prompt user provided to generate the test"),
});
export const basePlaywrightSchema = z.object({
playwrightInput: z
.string()
.describe("MUST be absolute path to the playwright input file like /path/to/playwright-ui-test.zip and MUST be a zip file captured using start_trace_collection tool"),
playwrightStoragePath: z
.string()
.optional()
.describe("Path to LOAD existing playwright session storage for trace collection with playwright enabled. THE PATH MUST BE AN ABSOLUTE PATH LIKE /Users/<path>/<filename>.json"),
playwrightSaveStoragePath: z
.string()
.optional()
.describe(`Path to SAVE Playwright session storage after trace collection. ONLY provide this when user explicitly says 'with session storage', 'save session', or similar. If user specifies this without a path, defaults to '${SESSION_STORAGE_FILENAME}' in the outputDir. This SAVES authentication state (cookies, localStorage, sessionStorage) when the browser closes. To LOAD existing auth state, use playwrightStoragePath instead. Can be relative (e.g., 'auth.json') or absolute path.`),
playwrightViewportSize: z
.string()
.default("")
.describe("Viewport size for playwright browser. THE VALUE MUST BE IN THE FORMAT ['', 'hd', 'full-hd', '2k', 'x,y' e.g. '1920,1080' for 1920x1080 resolution]. DEFAULT VALUE IS ''. If set to '', the browser will use its default viewport size."),
});
export const baseTraceSchema = z.object({
trace: z
.string()
.describe("Absolute path to the trace file in JSON format (e.g., /path/to/trace.json). Must use .json extension only. Do not use .jsonl files."),
include: z
.array(z.string())
.default([])
.describe("List of endpoints or patterns to include in test generation."),
exclude: z
.array(z.string())
.default([])
.describe("List of endpoints or patterns to exclude from test generation."),
...baseSchema.shape,
});
// Base schema that all test tools share
export const baseTestSchema = {
endpointURL: z
.string()
.describe("The endpoint URL to test (e.g., https://demoshop.skyramp.dev/api/v1/products)"),
method: z
.string()
.default("")
.describe('HTTP method to use. DEFAULT: Use empty string ("") to test ALL available methods from OpenAPI schema (recommended). Only specify a specific method (GET, POST, PUT, DELETE, etc.) if user explicitly requests testing a single method only.'),
apiSchema: z
.string()
.default("")
.describe("MUST be absolute path(/path/to/openapi.json) to the OpenAPI/Swagger schema file or a URL to the OpenAPI/Swagger schema file(e.g. https://demoshop.skyramp.dev/openapi.json). DO NOT TRY TO ASSUME THE OPENAPI SCHEMA IF NOT PROVIDED. NOTE TO AI ASSISTANTS: You do not need to read the contents of this file - simply pass the file path as the backend will read and process it."),
pathParams: z
.string()
.default("")
.describe("MUST be string of comma separated values like 'id=1,name=John' for URL path parameters"),
queryParams: z
.string()
.default("")
.describe("MUST be string of comma separated values like 'id=1,name=John' for URL query parameters"),
formParams: z
.string()
.default("")
.describe("MUST be string of comma separated values like 'id=1,name=John' for form data parameters"),
requestData: z
.string()
.default("")
.describe("Sample request body data, provided either as an inline JSON/YAML string or as an absolute file path prefixed with '@' (e.g., @/absolute/path/to/file)."),
responseStatusCode: z
.string()
.default("")
.describe("Expected HTTP response status code (e.g., '200', '201', '404'). DO NOT ASSUME STATUS CODE IF NOT PROVIDED"),
...baseSchema.shape,
};
export const codeRefactoringSchema = z.object({
codeReuse: z
.boolean()
.default(false)
.describe("Whether to reuse existing code"),
modularizeCode: z
.boolean()
.default(false)
.describe("Whether to modularize the code"),
});