Skip to main content
Glama

CTS MCP Server

by EricA1019
suggest_refactoring.ts7.82 kB
/** * CTS Suggest Refactoring Tool * AI-powered refactoring suggestions for signal names * * NOTE: This tool currently uses TreeSitterBridge (native bindings). * Migration to WASM parser (utils/tree_sitter.ts) is planned for future releases. * See: docs/mcp_upgrade_plan.md Tier 1 Task 3 */ import { z } from 'zod'; import { ToolDefinition, ToolHandler } from '../types.js'; import { validateToolResponse, SuggestRefactoringResponseSchema } from '../schemas.js'; import { Errors } from '../errors.js'; import { TreeSitterBridge } from '../artifacts/parsers/tree_sitter_bridge.js'; import { ProjectScanner } from '../artifacts/scanner/index.js'; import { SignalGraphBuilder } from '../artifacts/graph/index.js'; import { SignalExtractor } from '../artifacts/parsers/signal_extractor.js'; import { RefactoringEngine } from '../artifacts/refactoring/index.js'; import { PerformanceMonitor } from '../artifacts/monitoring/index.js'; const SuggestRefactoringParamsSchema = z.object({ projectPath: z.string().describe('Path to Godot project directory'), minConfidence: z.number().min(0).max(1).default(0.95).describe('Minimum confidence threshold for suggestions'), maxSuggestions: z.number().min(1).max(100).default(20).describe('Maximum number of suggestions to return'), includeRename: z.boolean().default(true).describe('Include naming convention rename suggestions'), includeMerge: z.boolean().default(true).describe('Include signal merge suggestions'), includeDeprecate: z.boolean().default(false).describe('Include deprecation suggestions'), }); export const suggestRefactoringTool: ToolDefinition = { name: 'CTS_Suggest_Refactoring', description: 'Generate AI-powered refactoring suggestions for signal names using Levenshtein similarity detection and GDScript naming validation', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to Godot project directory', }, minConfidence: { type: 'number', description: 'Minimum confidence threshold (0.0-1.0) for suggestions', default: 0.95, minimum: 0.0, maximum: 1.0, }, maxSuggestions: { type: 'number', description: 'Maximum number of suggestions to return', default: 20, minimum: 1, maximum: 100, }, includeRename: { type: 'boolean', description: 'Include naming convention rename suggestions', default: true, }, includeMerge: { type: 'boolean', description: 'Include signal merge suggestions for similar names', default: true, }, includeDeprecate: { type: 'boolean', description: 'Include deprecation suggestions', default: false, }, }, required: ['projectPath'], }, }; /** * Create tool handler */ export function createSuggestRefactoringHandler(): ToolHandler { const monitor = new PerformanceMonitor(); // Simple cache: projectPath → { graph, timestamp } const graphCache = new Map<string, { graph: any; timestamp: number }>(); const CACHE_TTL = 5 * 60 * 1000; // 5 minutes return async (args: Record<string, unknown>) => { const startTime = Date.now(); const params = SuggestRefactoringParamsSchema.parse(args); console.error(`[CTS Refactor] Generating suggestions for ${params.projectPath}`); console.error(`[CTS Refactor] Min confidence: ${params.minConfidence}, Max suggestions: ${params.maxSuggestions}`); // Check cache const cached = graphCache.get(params.projectPath); const now = Date.now(); let graph; if (cached && (now - cached.timestamp) < CACHE_TTL) { console.error('[CTS Refactor] Using cached signal graph'); graph = cached.graph; } else { // Build graph console.error('[CTS Refactor] Building signal graph...'); const bridge = new TreeSitterBridge(); const extractor = new SignalExtractor(); const scanner = new ProjectScanner(bridge); const builder = new SignalGraphBuilder(extractor); const scanResult = await monitor.monitorOperation('refactor_scan', async () => { return await scanner.scanProject(params.projectPath); }); graph = await monitor.monitorOperation('refactor_graph', async () => { return await builder.buildFullGraph(scanResult); }); // Update cache graphCache.set(params.projectPath, { graph, timestamp: now }); console.error(`[CTS Refactor] Graph cached for ${params.projectPath}`); } // Generate suggestions console.error('[CTS Refactor] Generating refactoring suggestions...'); const engine = new RefactoringEngine(); const allSuggestions = await monitor.monitorOperation('generate_suggestions', async () => { return await engine.generateSuggestions(graph); }); // Filter by type and confidence let filteredSuggestions = allSuggestions.filter(s => s.confidence >= params.minConfidence); if (!params.includeRename) { filteredSuggestions = filteredSuggestions.filter(s => s.type !== 'rename'); } if (!params.includeMerge) { filteredSuggestions = filteredSuggestions.filter(s => s.type !== 'merge'); } if (!params.includeDeprecate) { filteredSuggestions = filteredSuggestions.filter(s => s.type !== 'deprecate'); } // Sort by confidence (descending) and limit const topSuggestions = filteredSuggestions .sort((a, b) => b.confidence - a.confidence) .slice(0, params.maxSuggestions); console.error(`[CTS Refactor] Generated ${topSuggestions.length} suggestions (filtered from ${allSuggestions.length})`); const totalDuration = Date.now() - startTime; // Format results using BaseToolResponse pattern const response = { success: true as const, timestamp: new Date().toISOString(), toolName: 'CTS_Suggest_Refactoring' as const, duration_ms: totalDuration, result: { projectPath: params.projectPath, suggestions: topSuggestions.map((s: any) => ({ type: s.type, target: s.target, replacement: s.replacement, confidence: s.confidence, reason: s.reason, affectedFiles: s.affectedFiles || [], estimatedImpact: s.estimatedImpact || 'medium', })), summary: { totalGenerated: allSuggestions.length, afterFiltering: filteredSuggestions.length, returned: topSuggestions.length, byType: { merge: allSuggestions.filter((s: any) => s.type === 'merge').length, rename: allSuggestions.filter((s: any) => s.type === 'rename').length, deprecate: allSuggestions.filter((s: any) => s.type === 'deprecate').length, }, avgConfidence: topSuggestions.length > 0 ? topSuggestions.reduce((sum: number, s: any) => sum + s.confidence, 0) / topSuggestions.length : 0, }, performance: { scanTime: monitor.getMetricsForOperation('refactor_scan')[0]?.duration || 0, graphTime: monitor.getMetricsForOperation('refactor_graph')[0]?.duration || 0, suggestionTime: monitor.getMetricsForOperation('generate_suggestions')[0]?.duration || 0, cacheHit: !!cached, }, }, }; // Validate response format const validation = validateToolResponse('CTS_Suggest_Refactoring', response); if (!validation.valid) { throw Errors.validationError( 'response', 'SuggestRefactoringResponse', validation.errors?.errors[0]?.message || 'Unknown validation error' ); } return response; }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EricA1019/CTS_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server