UNPKG

@skyramp/mcp

Version:

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

159 lines (153 loc) 6.59 kB
import { z } from "zod"; import { StateManager } from "../../utils/AnalysisStateManager.js"; import { logger } from "../../utils/logger.js"; import { AnalyticsService } from "../../services/AnalyticsService.js"; const TOOL_NAME = "skyramp_state_cleanup"; /** * Register the state file cleanup tool with the MCP server * * This tool helps manage state files created during test analysis workflows. * It can list existing state files and clean up old ones to save disk space. */ export function registerStateCleanupTool(server) { server.registerTool(TOOL_NAME, { description: `Manage and cleanup Skyramp state files. **WHAT IT DOES:** - List all existing state files with details (size, age, session ID, type) - Delete state files older than specified age - Show disk space usage by state files **STATE TYPES MANAGED:** - analysis: Test maintenance workflow (discovery, drift, execution, health) - recommendation: Test recommendation workflow (analyze repo, map tests, recommend) **WHEN TO USE:** - Periodically to clean up old analysis sessions - To check current state files in the system - To free up disk space from temporary analysis data **OPTIONS:** - action: "list" - Show all state files - action: "cleanup" - Delete old state files - maxAgeHours: How old files must be before deletion (default: 24 hours) **Output:** Information about state files and cleanup results.`, inputSchema: { action: z .enum(["list", "cleanup"]) .describe('Action to perform: "list" shows all state files, "cleanup" deletes old files'), maxAgeHours: z .number() .optional() .default(24) .describe("For cleanup action: delete files older than this many hours (default: 24)"), }, }, async (args) => { let errorResult; try { logger.info(`State file ${args.action} requested`); if (args.action === "list") { // List all state files (analysis, recommendation) const stateFiles = await StateManager.listStateFiles(); if (stateFiles.length === 0) { return { content: [ { type: "text", text: JSON.stringify({ message: "No state files found", totalFiles: 0, totalSize: 0, }, null, 2), }, ], }; } const totalSize = stateFiles.reduce((sum, file) => sum + file.size, 0); const formatSize = (bytes) => { if (bytes === 0) return "0 B"; const k = 1024; const sizes = ["B", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`; }; const fileDetails = stateFiles.map((file) => ({ sessionId: file.sessionId, stateType: file.stateType, path: file.path, size: formatSize(file.size), sizeBytes: file.size, createdAt: file.createdAt.toISOString(), modifiedAt: file.modifiedAt.toISOString(), ageHours: ((Date.now() - file.modifiedAt.getTime()) / (1000 * 60 * 60)).toFixed(1), })); logger.info(`Found ${stateFiles.length} state files, total size: ${formatSize(totalSize)}`); return { content: [ { type: "text", text: JSON.stringify({ totalFiles: stateFiles.length, totalSize: formatSize(totalSize), totalSizeBytes: totalSize, files: fileDetails, }, null, 2), }, ], }; } else if (args.action === "cleanup") { // Cleanup old state files (all types: analysis, recommendation) const maxAgeHours = args.maxAgeHours || 24; const deletedCount = await StateManager.cleanupOldStateFiles(maxAgeHours); logger.info(`Cleaned up ${deletedCount} state files older than ${maxAgeHours} hours`); // Get remaining files const remainingFiles = await StateManager.listStateFiles(); return { content: [ { type: "text", text: JSON.stringify({ deletedCount, maxAgeHours, remainingFiles: remainingFiles.length, message: deletedCount > 0 ? `Successfully deleted ${deletedCount} state file(s) older than ${maxAgeHours} hours` : `No state files found older than ${maxAgeHours} hours`, }, null, 2), }, ], }; } errorResult = { content: [ { type: "text", text: JSON.stringify({ error: "Invalid action", }, null, 2), }, ], isError: true, }; return errorResult; } catch (error) { logger.error(`State cleanup failed: ${error.message}`, error); errorResult = { content: [ { type: "text", text: JSON.stringify({ error: error.message, }, null, 2), }, ], isError: true, }; return errorResult; } finally { AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {}); } }); }