Skip to main content
Glama

XcodeBuildMCP

check-code-patterns.js37.3 kB
#!/usr/bin/env node /** * XcodeBuildMCP Code Pattern Violations Checker * * Validates that all code files follow XcodeBuildMCP-specific architectural patterns. * This script focuses on domain-specific rules that ESLint cannot express. * * USAGE: * node scripts/check-code-patterns.js [--pattern=vitest|execsync|handler|handler-testing|all] * node scripts/check-code-patterns.js --help * * ARCHITECTURAL RULES ENFORCED: * 1. NO vitest mocking patterns (vi.mock, vi.fn, .mockResolvedValue, etc.) * 2. NO execSync usage in production code (use CommandExecutor instead) * 3. ONLY dependency injection with createMockExecutor() and createMockFileSystemExecutor() * 4. NO handler signature violations (handlers must have exact MCP SDK signatures) * 5. NO handler testing violations (test logic functions, not handlers directly) * * For comprehensive code quality documentation, see docs/CODE_QUALITY.md * * Note: General code quality rules (TypeScript, ESLint) are handled by other tools. * This script only enforces XcodeBuildMCP-specific architectural patterns. */ import { readFileSync, readdirSync, statSync } from 'fs'; import { join, relative } from 'path'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const projectRoot = join(__dirname, '..'); // Parse command line arguments const args = process.argv.slice(2); const patternFilter = args.find(arg => arg.startsWith('--pattern='))?.split('=')[1] || 'all'; const showHelp = args.includes('--help') || args.includes('-h'); if (showHelp) { console.log(` XcodeBuildMCP Code Pattern Violations Checker USAGE: node scripts/check-code-patterns.js [options] OPTIONS: --pattern=TYPE Check specific pattern type (vitest|execsync|handler|handler-testing|server-typing|all) [default: all] --help, -h Show this help message PATTERN TYPES: vitest Check only vitest mocking violations (vi.mock, vi.fn, etc.) execsync Check only execSync usage in production code handler Check only handler signature violations handler-testing Check only handler testing violations (testing handlers instead of logic functions) server-typing Check only improper server typing violations (Record<string, unknown> casts) all Check all pattern violations (default) Note: General code quality (TypeScript, etc.) is handled by ESLint EXAMPLES: node scripts/check-code-patterns.js node scripts/check-code-patterns.js --pattern=vitest node scripts/check-code-patterns.js --pattern=handler node scripts/check-code-patterns.js --pattern=handler-testing node scripts/check-code-patterns.js --pattern=server-typing `); process.exit(0); } // Patterns for execSync usage in production code (FORBIDDEN) // Note: execSync is allowed in test files for mocking, but not in production code const EXECSYNC_PATTERNS = [ /\bexecSync\s*\(/, // Direct execSync usage /\bexecSyncFn\s*[=:]/, // execSyncFn parameter or assignment /^import\s+(?!type\s)[^}]*from\s+['"]child_process['"]/m, // Importing from child_process (except type-only imports) /^import\s+{[^}]*(?:exec|spawn|execSync)[^}]*}\s+from\s+['"](?:node:)?child_process['"]/m, // Named imports of functions ]; // CRITICAL: ALL VITEST MOCKING PATTERNS ARE COMPLETELY FORBIDDEN // ONLY dependency injection with approved mock utilities is allowed const VITEST_GENERIC_PATTERNS = [ /vi\.mock\s*\(/, // vi.mock() - BANNED /vi\.fn\s*\(/, // vi.fn() - BANNED /vi\.mocked\s*\(/, // vi.mocked() - BANNED /vi\.spyOn\s*\(/, // vi.spyOn() - BANNED /vi\.clearAllMocks\s*\(/, // vi.clearAllMocks() - BANNED /\.mockResolvedValue/, // .mockResolvedValue - BANNED /\.mockRejectedValue/, // .mockRejectedValue - BANNED /\.mockReturnValue/, // .mockReturnValue - BANNED /\.mockImplementation/, // .mockImplementation - BANNED /\.mockClear/, // .mockClear - BANNED /\.mockReset/, // .mockReset - BANNED /\.mockRestore/, // .mockRestore - BANNED /\.toHaveBeenCalled/, // .toHaveBeenCalled - BANNED /\.toHaveBeenCalledWith/, // .toHaveBeenCalledWith - BANNED /MockedFunction/, // MockedFunction type - BANNED /as MockedFunction/, // Type casting to MockedFunction - BANNED /\bexecSync\b/, // execSync usage - BANNED (use executeCommand instead) /\bexecSyncFn\b/, // execSyncFn usage - BANNED (use executeCommand instead) ]; // APPROVED mock utilities - ONLY these are allowed const APPROVED_MOCK_PATTERNS = [ /\bcreateMockExecutor\b/, /\bcreateMockFileSystemExecutor\b/, /\bcreateNoopExecutor\b/, /\bcreateNoopFileSystemExecutor\b/, /\bcreateCommandMatchingMockExecutor\b/, /\bcreateMockEnvironmentDetector\b/, ]; // REFINED PATTERNS - Only flag ACTUAL vitest violations, not approved dependency injection patterns // Manual executors and mock objects are APPROVED when used for dependency injection const UNAPPROVED_MOCK_PATTERNS = [ // ONLY ACTUAL VITEST PATTERNS (vi.* usage) - Everything else is approved /\bmock[A-Z][a-zA-Z0-9]*\s*=\s*vi\./, // mockSomething = vi.fn() - vitest assignments only // No other patterns - manual executors and mock objects are approved for dependency injection ]; // Function to check if a line contains unapproved mock patterns function hasUnapprovedMockPattern(line) { // Skip lines that contain approved patterns const hasApprovedPattern = APPROVED_MOCK_PATTERNS.some(pattern => pattern.test(line)); if (hasApprovedPattern) { return false; } // Check for unapproved patterns return UNAPPROVED_MOCK_PATTERNS.some(pattern => pattern.test(line)); } // Combined pattern checker for backward compatibility const VITEST_MOCKING_PATTERNS = VITEST_GENERIC_PATTERNS; // CRITICAL: ARCHITECTURAL VIOLATIONS - Utilities bypassing CommandExecutor (BANNED) const UTILITY_BYPASS_PATTERNS = [ /spawn\s*\(/, // Direct Node.js spawn usage in utilities - BANNED /exec\s*\(/, // Direct Node.js exec usage in utilities - BANNED /execSync\s*\(/, // Direct Node.js execSync usage in utilities - BANNED /child_process\./, // Direct child_process module usage in utilities - BANNED ]; // TypeScript patterns are now handled by ESLint - removed from domain-specific checks // ESLint has comprehensive TypeScript rules with proper test file exceptions // CRITICAL: HANDLER SIGNATURE VIOLATIONS ARE FORBIDDEN // MCP SDK requires handlers to have exact signatures: // Tools: (args: Record<string, unknown>) => Promise<ToolResponse> // Resources: (uri: URL) => Promise<{ contents: Array<{ text: string }> }> const HANDLER_SIGNATURE_VIOLATIONS = [ /async\s+handler\s*\([^)]*:\s*[^,)]+,\s*[^)]+\s*:/ms, // Handler with multiple parameters separated by comma - BANNED /async\s+handler\s*\(\s*args\?\s*:/ms, // Handler with optional args parameter - BANNED (should be required) /async\s+handler\s*\([^)]*,\s*[^)]*CommandExecutor/ms, // Handler with CommandExecutor parameter - BANNED /async\s+handler\s*\([^)]*,\s*[^)]*FileSystemExecutor/ms, // Handler with FileSystemExecutor parameter - BANNED /async\s+handler\s*\([^)]*,\s*[^)]*Dependencies/ms, // Handler with Dependencies parameter - BANNED /async\s+handler\s*\([^)]*,\s*[^)]*executor\s*:/ms, // Handler with executor parameter - BANNED /async\s+handler\s*\([^)]*,\s*[^)]*dependencies\s*:/ms, // Handler with dependencies parameter - BANNED ]; // CRITICAL: HANDLER TESTING IN TESTS IS FORBIDDEN // Tests must ONLY call logic functions with dependency injection, NEVER handlers directly // Handlers are thin wrappers for MCP SDK - testing them violates dependency injection architecture const HANDLER_TESTING_VIOLATIONS = [ /\.handler\s*\(/, // Direct handler calls in tests - BANNED /await\s+\w+\.handler\s*\(/, // Awaited handler calls - BANNED /const\s+result\s*=\s*await\s+\w+\.handler/, // Handler result assignment - BANNED /expect\s*\(\s*await\s+\w+\.handler/, // Handler expectation calls - BANNED ]; // CRITICAL: IMPROPER SERVER TYPING PATTERNS ARE FORBIDDEN // Server instances must use proper MCP SDK types, not generic Record<string, unknown> casts const IMPROPER_SERVER_TYPING_VIOLATIONS = [ /as Record<string, unknown>.*server/, // Casting server to Record - BANNED /server.*as Record<string, unknown>/, // Casting server to Record - BANNED /mcpServer\?\s*:\s*Record<string, unknown>/, // Typing server as Record - BANNED /server\.server\?\?\s*server.*as Record/, // Complex server casting - BANNED /interface\s+MCPServerInterface\s*{/, // Custom MCP interfaces when SDK types exist - BANNED ]; // ALLOWED PATTERNS for cleanup (not mocking) const ALLOWED_CLEANUP_PATTERNS = [ // All cleanup patterns removed - no exceptions allowed ]; // Patterns that indicate TRUE dependency injection approach const DEPENDENCY_INJECTION_PATTERNS = [ /createMockExecutor/, // createMockExecutor usage /createMockFileSystemExecutor/, // createMockFileSystemExecutor usage /executor\?\s*:\s*CommandExecutor/, // executor?: CommandExecutor parameter ]; function findTestFiles(dir) { const testFiles = []; function traverse(currentDir) { const items = readdirSync(currentDir); for (const item of items) { const fullPath = join(currentDir, item); const stat = statSync(fullPath); if (stat.isDirectory()) { // Skip node_modules and other non-relevant directories if (!item.startsWith('.') && item !== 'node_modules' && item !== 'dist' && item !== 'build') { traverse(fullPath); } } else if (item.endsWith('.test.ts') || item.endsWith('.test.js')) { testFiles.push(fullPath); } } } traverse(dir); return testFiles; } function findToolAndResourceFiles(dir) { const toolFiles = []; function traverse(currentDir) { const items = readdirSync(currentDir); for (const item of items) { const fullPath = join(currentDir, item); const stat = statSync(fullPath); if (stat.isDirectory()) { // Skip test directories and other non-relevant directories if (!item.startsWith('.') && item !== '__tests__' && item !== 'node_modules' && item !== 'dist' && item !== 'build') { traverse(fullPath); } } else if ((item.endsWith('.ts') || item.endsWith('.js')) && !item.includes('.test.') && item !== 'index.ts' && item !== 'index.js') { toolFiles.push(fullPath); } } } traverse(dir); return toolFiles; } function findUtilityFiles(dir) { const utilityFiles = []; function traverse(currentDir) { const items = readdirSync(currentDir); for (const item of items) { const fullPath = join(currentDir, item); const stat = statSync(fullPath); if (stat.isDirectory()) { // Skip test directories and other non-relevant directories if (!item.startsWith('.') && item !== '__tests__' && item !== 'node_modules' && item !== 'dist' && item !== 'build') { traverse(fullPath); } } else if ((item.endsWith('.ts') || item.endsWith('.js')) && !item.includes('.test.') && item !== 'index.ts' && item !== 'index.js') { // Only include key utility files that should use CommandExecutor // Exclude command.ts itself as it's the core implementation that is allowed to use spawn() if (fullPath.includes('/utils/') && ( fullPath.includes('log_capture.ts') || fullPath.includes('build.ts') || fullPath.includes('simctl.ts') ) && !fullPath.includes('command.ts')) { utilityFiles.push(fullPath); } } } } traverse(dir); return utilityFiles; } // Helper function to determine if a file is a test file function isTestFile(filePath) { return filePath.includes('__tests__') || filePath.endsWith('.test.ts') || filePath.endsWith('.test.js'); } // Helper function to determine if a file is a production file function isProductionFile(filePath) { return !isTestFile(filePath) && (filePath.endsWith('.ts') || filePath.endsWith('.js')); } // Helper function to determine if a file is allowed to use child_process function isAllowedChildProcessFile(filePath) { // These files need direct child_process access for their core functionality return filePath.includes('command.ts') || // Core CommandExecutor implementation filePath.includes('swift_package_run.ts'); // Needs spawn for background process management } function analyzeTestFile(filePath) { try { const content = readFileSync(filePath, 'utf8'); const relativePath = relative(projectRoot, filePath); // Check for vitest mocking patterns using new robust approach const vitestMockingDetails = []; const lines = content.split('\n'); // 1. Check generic vi.* patterns (always violations) lines.forEach((line, index) => { VITEST_GENERIC_PATTERNS.forEach(pattern => { if (pattern.test(line)) { vitestMockingDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source, type: 'vitest-generic' }); } }); // 2. Check for unapproved mock patterns if (hasUnapprovedMockPattern(line)) { // Find which specific pattern matched for better reporting const matchedPattern = UNAPPROVED_MOCK_PATTERNS.find(pattern => pattern.test(line)); vitestMockingDetails.push({ line: index + 1, content: line.trim(), pattern: matchedPattern ? matchedPattern.source : 'unapproved mock pattern', type: 'unapproved-mock' }); } }); const hasVitestMockingPatterns = vitestMockingDetails.length > 0; // TypeScript patterns now handled by ESLint const hasTypescriptAntipatterns = false; // Check for handler testing violations (FORBIDDEN - ARCHITECTURAL VIOLATION) const hasHandlerTestingViolations = HANDLER_TESTING_VIOLATIONS.some(pattern => pattern.test(content)); // Check for improper server typing violations (FORBIDDEN - ARCHITECTURAL VIOLATION) const hasImproperServerTypingViolations = IMPROPER_SERVER_TYPING_VIOLATIONS.some(pattern => pattern.test(content)); // Check for dependency injection patterns (TRUE DI) const hasDIPatterns = DEPENDENCY_INJECTION_PATTERNS.some(pattern => pattern.test(content)); // Extract specific pattern occurrences for details const execSyncDetails = []; // Not applicable to test files const typescriptAntipatternDetails = []; // Unused - TypeScript handled by ESLint const handlerTestingDetails = []; const improperServerTypingDetails = []; lines.forEach((line, index) => { // TypeScript anti-patterns now handled by ESLint - removed from domain checks HANDLER_TESTING_VIOLATIONS.forEach(pattern => { if (pattern.test(line)) { handlerTestingDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source }); } }); IMPROPER_SERVER_TYPING_VIOLATIONS.forEach(pattern => { if (pattern.test(line)) { improperServerTypingDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source }); } }); }); return { filePath: relativePath, hasExecSyncPatterns: false, // Not applicable to test files hasVitestMockingPatterns, hasTypescriptAntipatterns, hasHandlerTestingViolations, hasImproperServerTypingViolations, hasDIPatterns, execSyncDetails, vitestMockingDetails, typescriptAntipatternDetails, handlerTestingDetails, improperServerTypingDetails, needsConversion: hasVitestMockingPatterns || hasHandlerTestingViolations || hasImproperServerTypingViolations, isConverted: hasDIPatterns && !hasVitestMockingPatterns && !hasHandlerTestingViolations && !hasImproperServerTypingViolations, isMixed: (hasVitestMockingPatterns || hasHandlerTestingViolations || hasImproperServerTypingViolations) && hasDIPatterns }; } catch (error) { console.error(`Error reading file ${filePath}: ${error.message}`); return null; } } function analyzeToolOrResourceFile(filePath) { try { const content = readFileSync(filePath, 'utf8'); const relativePath = relative(projectRoot, filePath); // Check for execSync patterns in production code (excluding allowed files) const hasExecSyncPatterns = isProductionFile(filePath) && !isAllowedChildProcessFile(filePath) && EXECSYNC_PATTERNS.some(pattern => pattern.test(content)); // Check for vitest mocking patterns using new robust approach const vitestMockingDetails = []; const lines = content.split('\n'); // 1. Check generic vi.* patterns (always violations) lines.forEach((line, index) => { VITEST_GENERIC_PATTERNS.forEach(pattern => { if (pattern.test(line)) { vitestMockingDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source, type: 'vitest-generic' }); } }); // 2. Check for unapproved mock patterns if (hasUnapprovedMockPattern(line)) { // Find which specific pattern matched for better reporting const matchedPattern = UNAPPROVED_MOCK_PATTERNS.find(pattern => pattern.test(line)); vitestMockingDetails.push({ line: index + 1, content: line.trim(), pattern: matchedPattern ? matchedPattern.source : 'unapproved mock pattern', type: 'unapproved-mock' }); } }); const hasVitestMockingPatterns = vitestMockingDetails.length > 0; // TypeScript patterns now handled by ESLint const hasTypescriptAntipatterns = false; // Check for dependency injection patterns (TRUE DI) const hasDIPatterns = DEPENDENCY_INJECTION_PATTERNS.some(pattern => pattern.test(content)); // Check for handler signature violations (FORBIDDEN) const hasHandlerSignatureViolations = HANDLER_SIGNATURE_VIOLATIONS.some(pattern => pattern.test(content)); // Check for improper server typing violations (FORBIDDEN - ARCHITECTURAL VIOLATION) const hasImproperServerTypingViolations = IMPROPER_SERVER_TYPING_VIOLATIONS.some(pattern => pattern.test(content)); // Check for utility bypass patterns (ARCHITECTURAL VIOLATION) const hasUtilityBypassPatterns = UTILITY_BYPASS_PATTERNS.some(pattern => pattern.test(content)); // Extract specific pattern occurrences for details const execSyncDetails = []; const typescriptAntipatternDetails = []; // Unused - TypeScript handled by ESLint const handlerSignatureDetails = []; const improperServerTypingDetails = []; const utilityBypassDetails = []; lines.forEach((line, index) => { if (isProductionFile(filePath) && !isAllowedChildProcessFile(filePath)) { EXECSYNC_PATTERNS.forEach(pattern => { if (pattern.test(line)) { execSyncDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source }); } }); } // TypeScript anti-patterns now handled by ESLint - removed from domain checks IMPROPER_SERVER_TYPING_VIOLATIONS.forEach(pattern => { if (pattern.test(line)) { improperServerTypingDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source }); } }); UTILITY_BYPASS_PATTERNS.forEach(pattern => { if (pattern.test(line)) { utilityBypassDetails.push({ line: index + 1, content: line.trim(), pattern: pattern.source }); } }); }); if (hasHandlerSignatureViolations) { // Use regex to find the violation and its line number const lines = content.split('\n'); const fullContent = content; HANDLER_SIGNATURE_VIOLATIONS.forEach(pattern => { let match; const globalPattern = new RegExp(pattern.source, pattern.flags + 'g'); while ((match = globalPattern.exec(fullContent)) !== null) { // Find which line this match is on const beforeMatch = fullContent.substring(0, match.index); const lineNumber = beforeMatch.split('\n').length; handlerSignatureDetails.push({ line: lineNumber, content: match[0].replace(/\s+/g, ' ').trim(), pattern: pattern.source }); } }); } return { filePath: relativePath, hasExecSyncPatterns, hasVitestMockingPatterns, hasTypescriptAntipatterns, hasDIPatterns, hasHandlerSignatureViolations, hasImproperServerTypingViolations, hasUtilityBypassPatterns, execSyncDetails, vitestMockingDetails, typescriptAntipatternDetails, handlerSignatureDetails, improperServerTypingDetails, utilityBypassDetails, needsConversion: hasExecSyncPatterns || hasVitestMockingPatterns || hasHandlerSignatureViolations || hasImproperServerTypingViolations || hasUtilityBypassPatterns, isConverted: hasDIPatterns && !hasExecSyncPatterns && !hasVitestMockingPatterns && !hasHandlerSignatureViolations && !hasImproperServerTypingViolations && !hasUtilityBypassPatterns, isMixed: (hasExecSyncPatterns || hasVitestMockingPatterns || hasHandlerSignatureViolations || hasImproperServerTypingViolations || hasUtilityBypassPatterns) && hasDIPatterns }; } catch (error) { console.error(`Error reading file ${filePath}: ${error.message}`); return null; } } function main() { console.log('🔍 XcodeBuildMCP Code Pattern Violations Checker\n'); console.log(`🎯 Checking pattern type: ${patternFilter.toUpperCase()}\n`); console.log('CODE GUIDELINES ENFORCED:'); console.log('✅ ONLY ALLOWED: createMockExecutor() and createMockFileSystemExecutor()'); console.log('❌ BANNED: vitest mocking patterns (vi.mock, vi.fn, .mockResolvedValue, etc.)'); console.log('❌ BANNED: execSync usage in production code (use CommandExecutor instead)'); console.log('ℹ️ TypeScript patterns: Handled by ESLint with proper test exceptions'); console.log('❌ BANNED: handler signature violations (handlers must have exact MCP SDK signatures)'); console.log('❌ BANNED: handler testing violations (test logic functions, not handlers directly)'); console.log('❌ BANNED: improper server typing (use McpServer type, not Record<string, unknown>)\n'); const testFiles = findTestFiles(join(projectRoot, 'src')); const testResults = testFiles.map(analyzeTestFile).filter(Boolean); // Also check tool and resource files for TypeScript anti-patterns AND handler signature violations const toolFiles = findToolAndResourceFiles(join(projectRoot, 'src', 'mcp', 'tools')); const resourceFiles = findToolAndResourceFiles(join(projectRoot, 'src', 'mcp', 'resources')); const allToolAndResourceFiles = [...toolFiles, ...resourceFiles]; const toolResults = allToolAndResourceFiles.map(analyzeToolOrResourceFile).filter(Boolean); // Check utility files for architectural violations (bypassing CommandExecutor) const utilityFiles = findUtilityFiles(join(projectRoot, 'src')); const utilityResults = utilityFiles.map(analyzeToolOrResourceFile).filter(Boolean); // Combine test, tool, and utility file results for analysis const results = [...testResults, ...toolResults, ...utilityResults]; const handlerResults = toolResults; const utilityBypassResults = utilityResults.filter(r => r.hasUtilityBypassPatterns); // Filter results based on pattern type let filteredResults; let filteredHandlerResults = []; switch (patternFilter) { case 'vitest': filteredResults = results.filter(r => r.hasVitestMockingPatterns); console.log(`Filtering to show only vitest mocking violations (${filteredResults.length} files)`); break; case 'execsync': filteredResults = results.filter(r => r.hasExecSyncPatterns); console.log(`Filtering to show only execSync violations (${filteredResults.length} files)`); break; // TypeScript case removed - now handled by ESLint case 'handler': filteredResults = []; filteredHandlerResults = handlerResults.filter(r => r.hasHandlerSignatureViolations); console.log(`Filtering to show only handler signature violations (${filteredHandlerResults.length} files)`); break; case 'handler-testing': filteredResults = results.filter(r => r.hasHandlerTestingViolations); console.log(`Filtering to show only handler testing violations (${filteredResults.length} files)`); break; case 'server-typing': filteredResults = results.filter(r => r.hasImproperServerTypingViolations); console.log(`Filtering to show only improper server typing violations (${filteredResults.length} files)`); break; case 'all': default: filteredResults = results.filter(r => r.needsConversion); filteredHandlerResults = handlerResults.filter(r => r.hasHandlerSignatureViolations); console.log(`Showing all pattern violations (${filteredResults.length} test files + ${filteredHandlerResults.length} handler files)`); break; } const needsConversion = filteredResults; const converted = results.filter(r => r.isConverted); const mixed = results.filter(r => r.isMixed); const execSyncOnly = results.filter(r => r.hasExecSyncPatterns && !r.hasVitestMockingPatterns && true && !r.hasHandlerTestingViolations && !r.hasImproperServerTypingViolations && !r.hasDIPatterns); const vitestMockingOnly = results.filter(r => r.hasVitestMockingPatterns && !r.hasExecSyncPatterns && true && !r.hasHandlerTestingViolations && !r.hasImproperServerTypingViolations && !r.hasDIPatterns); const typescriptOnly = results.filter(r => r.false && !r.hasExecSyncPatterns && !r.hasVitestMockingPatterns && !r.hasHandlerTestingViolations && !r.hasImproperServerTypingViolations && !r.hasDIPatterns); const handlerTestingOnly = results.filter(r => r.hasHandlerTestingViolations && !r.hasExecSyncPatterns && !r.hasVitestMockingPatterns && true && !r.hasImproperServerTypingViolations && !r.hasDIPatterns); const improperServerTypingOnly = results.filter(r => r.hasImproperServerTypingViolations && !r.hasExecSyncPatterns && !r.hasVitestMockingPatterns && !r.hasHandlerTestingViolations && !r.hasDIPatterns); const noPatterns = results.filter(r => !r.hasExecSyncPatterns && !r.hasVitestMockingPatterns && true && !r.hasHandlerTestingViolations && !r.hasImproperServerTypingViolations && !r.hasDIPatterns); console.log(`📊 CODE PATTERN VIOLATION ANALYSIS`); console.log(`=================================`); console.log(`Total files analyzed: ${results.length}`); console.log(`🚨 FILES WITH VIOLATIONS: ${needsConversion.length}`); console.log(` └─ execSync production violations: ${execSyncOnly.length}`); console.log(` └─ vitest mocking violations: ${vitestMockingOnly.length}`); // TypeScript anti-patterns now handled by ESLint console.log(` └─ handler testing violations: ${handlerTestingOnly.length}`); console.log(` └─ improper server typing violations: ${improperServerTypingOnly.length}`); console.log(`🚨 ARCHITECTURAL VIOLATIONS: ${utilityBypassResults.length}`); console.log(`✅ COMPLIANT (best practices): ${converted.length}`); console.log(`⚠️ MIXED VIOLATIONS: ${mixed.length}`); console.log(`📝 No patterns detected: ${noPatterns.length}`); console.log(''); if (needsConversion.length > 0) { console.log(`❌ FILES THAT NEED CONVERSION (${needsConversion.length}):`); console.log(`=====================================`); needsConversion.forEach((result, index) => { console.log(`${index + 1}. ${result.filePath}`); if (result.execSyncDetails && result.execSyncDetails.length > 0) { console.log(` 🚨 EXECSYNC PATTERNS (${result.execSyncDetails.length}):`); result.execSyncDetails.slice(0, 2).forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); if (result.execSyncDetails.length > 2) { console.log(` ... and ${result.execSyncDetails.length - 2} more execSync patterns`); } console.log(` 🔧 FIX: Replace execSync with CommandExecutor dependency injection`); } if (result.vitestMockingDetails.length > 0) { console.log(` 🧪 VITEST MOCKING PATTERNS (${result.vitestMockingDetails.length}):`); result.vitestMockingDetails.slice(0, 2).forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); if (result.vitestMockingDetails.length > 2) { console.log(` ... and ${result.vitestMockingDetails.length - 2} more vitest patterns`); } } // TypeScript violations now handled by ESLint - removed from domain checks if (result.handlerTestingDetails && result.handlerTestingDetails.length > 0) { console.log(` 🚨 HANDLER TESTING VIOLATIONS (${result.handlerTestingDetails.length}):`); result.handlerTestingDetails.slice(0, 2).forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); if (result.handlerTestingDetails.length > 2) { console.log(` ... and ${result.handlerTestingDetails.length - 2} more handler testing violations`); } console.log(` 🔧 FIX: Replace handler calls with logic function calls using dependency injection`); } if (result.improperServerTypingDetails && result.improperServerTypingDetails.length > 0) { console.log(` 🔧 IMPROPER SERVER TYPING VIOLATIONS (${result.improperServerTypingDetails.length}):`); result.improperServerTypingDetails.slice(0, 2).forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); if (result.improperServerTypingDetails.length > 2) { console.log(` ... and ${result.improperServerTypingDetails.length - 2} more server typing violations`); } console.log(` 🔧 FIX: Import McpServer from SDK and use proper typing instead of Record<string, unknown>`); } console.log(''); }); } // Utility bypass violations reporting if (utilityBypassResults.length > 0) { console.log(`🚨 CRITICAL: UTILITY ARCHITECTURAL VIOLATIONS (${utilityBypassResults.length}):`); console.log(`=======================================================`); console.log('⚠️ These utilities bypass CommandExecutor and break our testing architecture!'); console.log(''); utilityBypassResults.forEach((result, index) => { console.log(`${index + 1}. ${result.filePath}`); if (result.utilityBypassDetails.length > 0) { console.log(` 🚨 BYPASS PATTERNS (${result.utilityBypassDetails.length}):`); result.utilityBypassDetails.forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); } console.log(' 🔧 FIX: Refactor to accept CommandExecutor and use it instead of direct spawn/exec calls'); console.log(''); }); } // Handler signature violations reporting if (filteredHandlerResults.length > 0) { console.log(`🚨 HANDLER SIGNATURE VIOLATIONS (${filteredHandlerResults.length}):`); console.log(`===========================================`); filteredHandlerResults.forEach((result, index) => { console.log(`${index + 1}. ${result.filePath}`); if (result.handlerSignatureDetails.length > 0) { console.log(` 🛠️ HANDLER VIOLATIONS (${result.handlerSignatureDetails.length}):`); result.handlerSignatureDetails.forEach(detail => { console.log(` Line ${detail.line}: ${detail.content}`); }); } console.log(''); }); } if (mixed.length > 0) { console.log(`⚠️ FILES WITH MIXED PATTERNS (${mixed.length}):`); console.log(`===================================`); mixed.forEach((result, index) => { console.log(`${index + 1}. ${result.filePath}`); console.log(` ⚠️ Contains both setTimeout and dependency injection patterns`); console.log(''); }); } if (converted.length > 0) { console.log(`✅ SUCCESSFULLY CONVERTED FILES (${converted.length}):`); console.log(`====================================`); converted.forEach((result, index) => { console.log(`${index + 1}. ${result.filePath}`); }); console.log(''); } // Summary for next steps const hasViolations = needsConversion.length > 0 || filteredHandlerResults.length > 0 || utilityBypassResults.length > 0; if (needsConversion.length > 0) { console.log(`🚨 CRITICAL ACTION REQUIRED (TEST FILES):`); console.log(`=======================================`); console.log(`1. IMMEDIATELY remove ALL vitest mocking from ${needsConversion.length} files`); console.log(`2. BANNED: vi.mock(), vi.fn(), .mockResolvedValue(), .toHaveBeenCalled(), etc.`); console.log(`3. BANNED: Testing handlers directly (.handler()) - test logic functions with dependency injection`); console.log(`4. ONLY ALLOWED: createMockExecutor() and createMockFileSystemExecutor()`); console.log(`4. Update plugin implementations to accept executor?: CommandExecutor parameter`); console.log(`5. Run this script again after each fix to track progress`); console.log(''); // Show top files by total violation count const sortedByPatterns = needsConversion .sort((a, b) => { const totalA = (a.execSyncDetails?.length || 0) + a.vitestMockingDetails.length + (a.handlerTestingDetails?.length || 0) + (a.improperServerTypingDetails?.length || 0); const totalB = (b.execSyncDetails?.length || 0) + b.vitestMockingDetails.length + (b.handlerTestingDetails?.length || 0) + (b.improperServerTypingDetails?.length || 0); return totalB - totalA; }) .slice(0, 5); console.log(`🚨 TOP 5 FILES WITH MOST VIOLATIONS:`); sortedByPatterns.forEach((result, index) => { const totalPatterns = (result.execSyncDetails?.length || 0) + result.vitestMockingDetails.length + (result.handlerTestingDetails?.length || 0) + (result.improperServerTypingDetails?.length || 0); console.log(`${index + 1}. ${result.filePath} (${totalPatterns} violations: ${result.execSyncDetails?.length || 0} execSync + ${result.vitestMockingDetails.length} vitest + ${result.handlerTestingDetails?.length || 0} handler + ${result.improperServerTypingDetails?.length || 0} server)`); }); console.log(''); } if (utilityBypassResults.length > 0) { console.log(`🚨 CRITICAL ACTION REQUIRED (UTILITY FILES):`); console.log(`==========================================`); console.log(`1. IMMEDIATELY fix ALL architectural violations in ${utilityBypassResults.length} files`); console.log(`2. Refactor utilities to accept CommandExecutor parameter`); console.log(`3. Replace direct spawn/exec calls with executor calls`); console.log(`4. These violations break our entire testing strategy`); console.log(`5. Run this script again after each fix to track progress`); console.log(''); } if (filteredHandlerResults.length > 0) { console.log(`🚨 CRITICAL ACTION REQUIRED (HANDLER FILES):`); console.log(`==========================================`); console.log(`1. IMMEDIATELY fix ALL handler signature violations in ${filteredHandlerResults.length} files`); console.log(`2. Tools: Handler must be: async handler(args: Record<string, unknown>): Promise<ToolResponse>`); console.log(`3. Resources: Handler must be: async handler(uri: URL): Promise<{ contents: Array<{ text: string }> }>`); console.log(`4. Inject dependencies INSIDE handler body: const executor = getDefaultCommandExecutor()`); console.log(`5. Run this script again after each fix to track progress`); console.log(''); } if (!hasViolations && mixed.length === 0) { console.log(`🎉 ALL FILES COMPLY WITH PROJECT STANDARDS!`); console.log(`==========================================`); console.log(`✅ All files use ONLY createMockExecutor() and createMockFileSystemExecutor()`); console.log(`✅ All files follow TypeScript best practices (no unsafe casts)`); console.log(`✅ All handler signatures comply with MCP SDK requirements`); console.log(`✅ All utilities properly use CommandExecutor dependency injection`); console.log(`✅ No violations detected!`); } // Exit with appropriate code process.exit(hasViolations || mixed.length > 0 ? 1 : 0); } main();

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/cameroncooke/XcodeBuildMCP'

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