@skyramp/mcp
Version:
Skyramp MCP (Model Context Protocol) Server - AI-powered test generation and execution
119 lines (113 loc) • 4.26 kB
JavaScript
import path from "path";
import { logger } from "./logger.js";
export const OUTPUT_DIR_FIELD_NAME = "outputDir";
export const TRACE_OUTPUT_FILE_FIELD_NAME = "traceOutputFile";
export const PLAYWRIGHT_OUTPUT_FILE_FIELD_NAME = "playwrightOutput";
export const PATH_PARAMS_FIELD_NAME = "pathParams";
export const QUERY_PARAMS_FIELD_NAME = "queryParams";
export const FORM_PARAMS_FIELD_NAME = "formParams";
export const TELEMETRY_entrypoint_FIELD_NAME = "mcp";
export function IsValidKeyValueList(input) {
// Regular expression to match a comma-separated list of key:value pairs
const regex = /^([a-zA-Z0-9_-]+)(,([a-zA-Z0-9_-]+))*$/;
return regex.test(input);
}
export function getPathParameterValidationError(requiredPathParams) {
if (requiredPathParams.split(",").length > 1) {
return (`Please specify values for the following required path parameters: \n` +
`${requiredPathParams
.split(",")
.map((param, index) => `${index + 1}. \`${param.trim()}\``)
.join("\n")}\n\n`);
}
else {
return (`Please specify value for the following required path parameter:\n` +
`${requiredPathParams
.split(",")
.map((param, index) => `- \`${param.trim()}\``)
.join("\n")}\n\n`);
}
}
export function validatePath(dir, fieldName) {
if (dir !== "" && !path.isAbsolute(dir)) {
return {
content: [
{
type: "text",
text: `Error: Relative path provided for ${fieldName}: "${dir}"
**Root Cause:** This tool requires absolute paths, but a relative path was provided.
**Solution:** Use the appropriate Skyramp prompt first to resolve relative paths to absolute paths:
- For trace collection: Use "skyramp_stop_trace_collection_prompt"
- For test generation: Provide absolute paths directly
**How prompts work:**
1. Prompts take your relative paths + current working directory from your IDE
2. They resolve relative paths to absolute paths
3. They provide the exact absolute paths to use with tools
**Alternative:** Provide absolute paths directly (e.g., "/Users/username/project/output.json")
Current working directory context is required when using relative paths.`,
},
],
isError: true,
};
}
return null;
}
export function validateParams(params, fieldName) {
const trimmedParams = params.trim();
// Reject JSON-like input
if (trimmedParams.startsWith("{") && trimmedParams.endsWith("}")) {
return {
content: [
{
type: "text",
text: `Error: ${fieldName} must be a comma-separated string in the format key=value or key1=value1,key2=value2 — not a JSON object.`,
},
],
isError: true,
};
}
// Allow empty input
if (!trimmedParams)
return null;
// Validate comma-separated key=value pairs
const pairs = trimmedParams.split(",");
for (const pair of pairs) {
const [key, value] = pair.split("=");
if (!key ||
value === undefined ||
key.trim() === "" ||
value.trim() === "") {
return {
content: [
{
type: "text",
text: `Error: Each entry in ${fieldName} must be in the format key=value. Invalid entry: "${pair}".`,
},
],
isError: true,
};
}
}
return null;
}
// check if the value is a path and if it a relative throw an error else return path appended with `@`
export function validateRequestData(value) {
if (value.includes("@")) {
return value;
}
// If value is valid JSON string return value
try {
JSON.parse(value);
return value;
}
catch (e) {
logger.warning("Request data is not a valid JSON string", { value });
}
const isAbsolute = path.isAbsolute(value);
logger.debug("Path validation check", { value, isAbsolute });
// If value is path
if (isAbsolute) {
return "@" + value;
}
return null;
}