Skip to main content
Glama

XcodeBuildMCP

update-tools-docs.ts8.29 kB
#!/usr/bin/env node /** * XcodeBuildMCP Tools Documentation Updater * * Automatically updates docs/TOOLS.md with current tool and workflow information * using static AST analysis. Ensures documentation always reflects the actual codebase. * * Usage: * npx tsx scripts/update-tools-docs.ts [--dry-run] [--verbose] * * Options: * --dry-run, -d Show what would be updated without making changes * --verbose, -v Show detailed information about the update process * --help, -h Show this help message */ import * as fs from 'fs'; import * as path from 'path'; import { fileURLToPath } from 'url'; import { getStaticToolAnalysis, type StaticAnalysisResult, type WorkflowInfo, } from './analysis/tools-analysis.js'; // Get project paths const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const projectRoot = path.resolve(__dirname, '..'); const docsPath = path.join(projectRoot, 'docs', 'TOOLS.md'); // CLI options const args = process.argv.slice(2); const options = { dryRun: args.includes('--dry-run') || args.includes('-d'), verbose: args.includes('--verbose') || args.includes('-v'), help: args.includes('--help') || args.includes('-h'), }; const colors = { reset: '\x1b[0m', bright: '\x1b[1m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', cyan: '\x1b[36m', magenta: '\x1b[35m', } as const; if (options.help) { console.log(` ${colors.bright}${colors.blue}XcodeBuildMCP Tools Documentation Updater${colors.reset} Automatically updates docs/TOOLS.md with current tool and workflow information. ${colors.bright}Usage:${colors.reset} npx tsx scripts/update-tools-docs.ts [options] ${colors.bright}Options:${colors.reset} --dry-run, -d Show what would be updated without making changes --verbose, -v Show detailed information about the update process --help, -h Show this help message ${colors.bright}Examples:${colors.reset} ${colors.cyan}npx tsx scripts/update-tools-docs.ts${colors.reset} # Update docs/TOOLS.md ${colors.cyan}npx tsx scripts/update-tools-docs.ts --dry-run${colors.reset} # Preview changes ${colors.cyan}npx tsx scripts/update-tools-docs.ts --verbose${colors.reset} # Show detailed progress `); process.exit(0); } /** * Generate the workflow section content */ function generateWorkflowSection(workflow: WorkflowInfo): string { const canonicalTools = workflow.tools.filter((tool) => tool.isCanonical); const toolCount = canonicalTools.length; let content = `### ${workflow.displayName} (\`${workflow.name}\`)\n`; content += `**Purpose**: ${workflow.description} (${toolCount} tools)\n\n`; // List each tool with its description for (const tool of canonicalTools.sort((a, b) => a.name.localeCompare(b.name))) { // Clean up the description for documentation const cleanDescription = tool.description .replace(/IMPORTANT:.*?Example:.*?\)/g, '') // Remove IMPORTANT sections .replace(/\s+/g, ' ') // Normalize whitespace .trim(); content += `- \`${tool.name}\` - ${cleanDescription}\n`; } return content; } /** * Generate the complete TOOLS.md content */ function generateToolsDocumentation(analysis: StaticAnalysisResult): string { const { workflows, stats } = analysis; // Sort workflows by display name for consistent ordering const sortedWorkflows = workflows.sort((a, b) => a.displayName.localeCompare(b.displayName)); const content = `# XcodeBuildMCP Tools Reference XcodeBuildMCP provides ${stats.canonicalTools} tools organized into ${stats.workflowCount} workflow groups for comprehensive Apple development workflows. ## Workflow Groups ${sortedWorkflows.map((workflow) => generateWorkflowSection(workflow)).join('')} ## Summary Statistics - **Total Tools**: ${stats.canonicalTools} canonical tools + ${stats.reExportTools} re-exports = ${stats.totalTools} total - **Workflow Groups**: ${stats.workflowCount} --- *This documentation is automatically generated by \`scripts/update-tools-docs.ts\` using static analysis. Last updated: ${new Date().toISOString().split('T')[0]}* `; return content; } /** * Compare old and new content to show what changed */ function showDiff(oldContent: string, newContent: string): void { if (!options.verbose) return; console.log(`${colors.bright}${colors.cyan}📄 Content Comparison:${colors.reset}`); console.log('─'.repeat(50)); const oldLines = oldContent.split('\n'); const newLines = newContent.split('\n'); const maxLength = Math.max(oldLines.length, newLines.length); let changes = 0; for (let i = 0; i < maxLength; i++) { const oldLine = oldLines[i] || ''; const newLine = newLines[i] || ''; if (oldLine !== newLine) { changes++; if (changes <= 10) { // Show first 10 changes console.log(`${colors.red}- Line ${i + 1}: ${oldLine}${colors.reset}`); console.log(`${colors.green}+ Line ${i + 1}: ${newLine}${colors.reset}`); } } } if (changes > 10) { console.log(`${colors.yellow}... and ${changes - 10} more changes${colors.reset}`); } console.log(`${colors.blue}Total changes: ${changes} lines${colors.reset}\n`); } /** * Main execution function */ async function main(): Promise<void> { try { console.log( `${colors.bright}${colors.blue}🔧 XcodeBuildMCP Tools Documentation Updater${colors.reset}`, ); if (options.dryRun) { console.log( `${colors.yellow}🔍 Running in dry-run mode - no files will be modified${colors.reset}`, ); } console.log(`${colors.cyan}📊 Analyzing tools...${colors.reset}`); // Get current tool analysis const analysis = await getStaticToolAnalysis(); if (options.verbose) { console.log( `${colors.green}✓ Found ${analysis.stats.canonicalTools} canonical tools in ${analysis.stats.workflowCount} workflows${colors.reset}`, ); console.log( `${colors.green}✓ Found ${analysis.stats.reExportTools} re-export files${colors.reset}`, ); } // Generate new documentation content console.log(`${colors.cyan}📝 Generating documentation...${colors.reset}`); const newContent = generateToolsDocumentation(analysis); // Read current content for comparison let oldContent = ''; if (fs.existsSync(docsPath)) { oldContent = fs.readFileSync(docsPath, 'utf-8'); } // Check if content has changed if (oldContent === newContent) { console.log(`${colors.green}✅ Documentation is already up to date!${colors.reset}`); return; } // Show differences if verbose if (oldContent && options.verbose) { showDiff(oldContent, newContent); } if (options.dryRun) { console.log( `${colors.yellow}📋 Dry run completed. Documentation would be updated with:${colors.reset}`, ); console.log(` - ${analysis.stats.canonicalTools} canonical tools`); console.log(` - ${analysis.stats.workflowCount} workflow groups`); console.log(` - ${newContent.split('\n').length} lines total`); if (!options.verbose) { console.log(`\n${colors.cyan}💡 Use --verbose to see detailed changes${colors.reset}`); } return; } // Write new content console.log(`${colors.cyan}✏️ Writing updated documentation...${colors.reset}`); fs.writeFileSync(docsPath, newContent, 'utf-8'); console.log( `${colors.green}✅ Successfully updated ${path.relative(projectRoot, docsPath)}!${colors.reset}`, ); if (options.verbose) { console.log(`\n${colors.bright}📈 Update Summary:${colors.reset}`); console.log( ` Tools: ${analysis.stats.canonicalTools} canonical + ${analysis.stats.reExportTools} re-exports = ${analysis.stats.totalTools} total`, ); console.log(` Workflows: ${analysis.stats.workflowCount}`); console.log(` File size: ${(newContent.length / 1024).toFixed(1)}KB`); console.log(` Lines: ${newContent.split('\n').length}`); } } catch (error) { console.error(`${colors.red}❌ Error: ${(error as Error).message}${colors.reset}`); process.exit(1); } } // Run the updater 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