Skip to main content
Glama

CTS MCP Server

by EricA1019
analyze_project.jsโ€ข11 kB
/** * CTS Analyze Project Tool * Comprehensive signal intelligence analysis using Phase 3 components * * 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 { validateToolResponse } 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 { UnusedDetector } from '../artifacts/analysis/index.js'; import { HierarchicalClusterer } from '../artifacts/clustering/index.js'; import { PerformanceMonitor } from '../artifacts/monitoring/index.js'; const AnalyzeProjectParamsSchema = z.object({ projectPath: z.string().describe('Path to Godot project directory'), detectUnused: z.boolean().default(true).describe('Detect unused signals'), buildHierarchy: z.boolean().default(true).describe('Build hierarchical signal clusters'), minClusterSize: z.number().min(2).default(5).describe('Minimum signals per sub-cluster'), performanceBaseline: z.boolean().default(false).describe('Establish performance baseline'), }); export const analyzeProjectTool = { name: 'CTS_Analyze_Project', description: 'Analyze entire Godot project for comprehensive signal intelligence including unused detection, hierarchical clustering, and performance monitoring', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to Godot project directory', }, detectUnused: { type: 'boolean', description: 'Detect unused signals (orphans, dead emitters, isolated)', default: true, }, buildHierarchy: { type: 'boolean', description: 'Build hierarchical signal clusters with TF-IDF labels', default: true, }, minClusterSize: { type: 'number', description: 'Minimum signals per sub-cluster (2-10)', default: 5, minimum: 2, maximum: 10, }, performanceBaseline: { type: 'boolean', description: 'Establish performance baseline for future comparisons', default: false, }, }, required: ['projectPath'], }, }; /** * Create tool handler */ export function createAnalyzeProjectHandler() { const monitor = new PerformanceMonitor(); return async (args) => { const startTime = Date.now(); const params = AnalyzeProjectParamsSchema.parse(args); console.error(`[CTS Analyze] Starting analysis of ${params.projectPath}`); console.error(`[CTS Analyze] Options: detectUnused=${params.detectUnused}, buildHierarchy=${params.buildHierarchy}`); // Initialize components const bridge = new TreeSitterBridge(); const extractor = new SignalExtractor(); const scanner = new ProjectScanner(bridge); const builder = new SignalGraphBuilder(extractor); // Phase 1: Scan project console.error('[CTS Analyze] Phase 1: Scanning project...'); const scanResult = await monitor.monitorOperation('project_scan', async () => { return await scanner.scanProject(params.projectPath); }); console.error(`[CTS Analyze] Scanned ${scanResult.length} files`); // Phase 2: Build signal graph console.error('[CTS Analyze] Phase 2: Building signal graph...'); const graph = await monitor.monitorOperation('graph_build', async () => { return await builder.buildFullGraph(scanResult); }); const totalEmissions = Array.from(graph.emissions.values()).reduce((sum, arr) => sum + arr.length, 0); const totalConnections = Array.from(graph.connections.values()).reduce((sum, arr) => sum + arr.length, 0); console.error(`[CTS Analyze] Graph: ${graph.definitions.size} signals, ${totalEmissions} emissions, ${totalConnections} connections`); const results = { projectPath: params.projectPath, scanStats: { filesScanned: scanResult.length, totalSignals: graph.definitions.size, totalEmissions, totalConnections, scanTime: monitor.getMetricsForOperation('project_scan')[0]?.duration || 0, graphBuildTime: monitor.getMetricsForOperation('graph_build')[0]?.duration || 0, }, performance: { overheadMs: monitor.getStats().avgOverhead, alertsGenerated: monitor.getStats().alertsGenerated, baselineEstablished: false, }, }; // Phase 3: Unused signal detection (optional) if (params.detectUnused) { console.error('[CTS Analyze] Phase 3: Detecting unused signals...'); const detector = new UnusedDetector(); const allUnused = await monitor.monitorOperation('unused_detection', async () => { return await detector.detectUnused(graph); }); // Separate by pattern const orphans = allUnused.filter(u => u.pattern === 'orphan'); const deadEmitters = allUnused.filter(u => u.pattern === 'dead_emitter'); const isolated = allUnused.filter(u => u.pattern === 'isolated'); const highConfidenceCount = allUnused.filter(item => item.confidence >= 0.95).length; results.unused = { orphanSignals: orphans.map((o) => ({ signal: o.signalName, file: o.locations[0]?.file || 'unknown', confidence: o.confidence, reason: o.reason || 'Orphan signal: defined but never emitted', })), deadEmitters: deadEmitters.map((d) => ({ signal: d.signalName, file: d.locations[0]?.file || 'unknown', confidence: d.confidence, reason: d.reason || 'Dead emitter: emitted but never connected', })), isolatedSignals: isolated.map((i) => ({ signal: i.signalName, file: i.locations[0]?.file || 'unknown', confidence: i.confidence, reason: i.reason || 'Isolated signal: neither emitted nor connected', })), summary: { totalOrphans: orphans.length, totalDeadEmitters: deadEmitters.length, totalIsolated: isolated.length, highConfidenceCount, }, }; console.error(`[CTS Analyze] Found ${highConfidenceCount} high-confidence unused signals`); } // Phase 4: Hierarchical clustering (optional) if (params.buildHierarchy) { console.error('[CTS Analyze] Phase 4: Building hierarchical clusters...'); const clusterer = new HierarchicalClusterer(); const hierarchy = await monitor.monitorOperation('hierarchical_clustering', async () => { return await clusterer.clusterHierarchical(graph, 2, params.minClusterSize); }); let totalSubclusters = 0; const topLevel = Array.from(hierarchy.topLevel.clusters.values()).map((cluster) => { // Check if there are subclusters for this parent cluster const parentSubClusters = hierarchy.subClusters?.get(cluster.id); let subclusters; if (parentSubClusters) { subclusters = Array.from(parentSubClusters.clusters.entries()).map(([subId, signals]) => { totalSubclusters++; return { id: `${cluster.id}.${subId}`, label: `Sub-cluster ${subId}`, size: signals.size, signals: Array.from(signals), }; }); } return { id: cluster.id.toString(), label: cluster.label, size: cluster.signals.size, subclusters: subclusters && subclusters.length > 0 ? subclusters : undefined, }; }); const clusterSizes = Array.from(hierarchy.topLevel.clusters.values()).map((c) => c.signals.size); const avgClusterSize = clusterSizes.length > 0 ? clusterSizes.reduce((sum, size) => sum + size, 0) / clusterSizes.length : 0; results.clusters = { topLevel, summary: { totalClusters: hierarchy.topLevel.clusters.size, totalSubclusters, avgClusterSize, labelingMethod: 'TF-IDF', }, }; console.error(`[CTS Analyze] Created ${hierarchy.topLevel.clusters.size} top-level clusters with ${totalSubclusters} subclusters`); } // Establish baseline if requested if (params.performanceBaseline) { console.error('[CTS Analyze] Establishing performance baseline...'); for (const operation of ['project_scan', 'graph_build', 'unused_detection', 'hierarchical_clustering']) { const baseline = monitor.calculateBaseline(operation); if (baseline) { monitor.setBaseline(operation, baseline); console.error(`[CTS Analyze] Baseline set for ${operation}: ${baseline.avgDuration.toFixed(2)}ms`); } } results.performance.baselineEstablished = true; } console.error('[CTS Analyze] Analysis complete'); const totalDuration = Date.now() - startTime; // Format response using BaseToolResponse pattern const response = { success: true, timestamp: new Date().toISOString(), toolName: 'CTS_Analyze_Project', duration_ms: totalDuration, result: results, }; // Validate response format const validation = validateToolResponse('CTS_Analyze_Project', response); if (!validation.valid) { throw Errors.validationError('response', 'AnalyzeProjectResponse', validation.errors?.errors[0]?.message || 'Unknown validation error'); } return response; }; } //# sourceMappingURL=analyze_project.js.map

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