@skyramp/mcp
Version:
Skyramp MCP (Model Context Protocol) Server - AI-powered test generation and execution
159 lines (153 loc) • 6.59 kB
JavaScript
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, {});
}
});
}