UNPKG

@skyramp/mcp

Version:

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

119 lines (113 loc) 4.26 kB
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; }