#!/usr/bin/env node /** * Audit the 7 LocalBosses MCPs for: * 1. Build status (dist/ exists, compiled) * 2. _meta labels present * 3. Argument descriptions * 4. MCP Apps properly configured */ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const MCPs = [ { name: 'n8n', path: '/Users/jakeshore/.clawdbot/workspace/n8n-mcp-apps' }, { name: 'ghl', path: '/Users/jakeshore/.clawdbot/workspace/mcp-diagrams/GoHighLevel-MCP' }, { name: 'google-ads', path: '/Users/jakeshore/.clawdbot/workspace/mcp-diagrams/google-ads-mcp' }, { name: 'meta-ads', path: '/Users/jakeshore/.clawdbot/workspace/meta-ads-mcp' }, { name: 'google-console', path: '/Users/jakeshore/.clawdbot/workspace/google-console-mcp' }, { name: 'competitor-research', path: '/Users/jakeshore/.clawdbot/workspace/competitor-research-mcp' }, { name: 'twilio', path: '/Users/jakeshore/.clawdbot/workspace/twilio-mcp' }, ]; console.log('\nšŸ” Auditing LocalBosses MCPs...\n'); const results = {}; for (const mcp of MCPs) { console.log(`\nšŸ“¦ ${mcp.name.toUpperCase()}`); console.log(` Path: ${mcp.path}`); const result = { exists: fs.existsSync(mcp.path), hasPackageJson: false, hasDist: false, hasServer: false, built: false, issues: [], }; if (!result.exists) { result.issues.push('āŒ Directory does not exist'); results[mcp.name] = result; console.log(' āŒ Directory does not exist'); continue; } // Check package.json const packageJsonPath = path.join(mcp.path, 'package.json'); result.hasPackageJson = fs.existsSync(packageJsonPath); if (result.hasPackageJson) { console.log(' āœ… package.json found'); } else { result.issues.push('āŒ No package.json'); console.log(' āŒ No package.json'); } // Check dist/ const distPath = path.join(mcp.path, 'dist'); result.hasDist = fs.existsSync(distPath); if (result.hasDist) { const distFiles = fs.readdirSync(distPath); result.built = distFiles.length > 0; console.log(` āœ… dist/ exists (${distFiles.length} files)`); } else { result.issues.push('āŒ No dist/ directory - needs build'); console.log(' āŒ No dist/ directory'); } // Check for server file const serverPaths = [ path.join(mcp.path, 'src/server.ts'), path.join(mcp.path, 'src/index.ts'), path.join(mcp.path, 'server.ts'), path.join(mcp.path, 'index.ts'), ]; for (const serverPath of serverPaths) { if (fs.existsSync(serverPath)) { result.hasServer = true; console.log(` āœ… Server file: ${path.basename(serverPath)}`); // Check file content for _meta const content = fs.readFileSync(serverPath, 'utf-8'); const hasMeta = content.includes('_meta'); if (hasMeta) { console.log(' āœ… Contains _meta labels'); } else { result.issues.push('āš ļø No _meta labels found in server file'); console.log(' āš ļø No _meta labels found'); } // Check for MCP Apps patterns const hasApps = content.includes('resourceUri') || content.includes('ui://'); if (hasApps) { console.log(' āœ… MCP Apps configured'); } else { console.log(' ā„¹ļø No MCP Apps detected'); } break; } } if (!result.hasServer) { result.issues.push('āŒ No server file found'); console.log(' āŒ No server file found'); } // Summary if (result.issues.length === 0) { console.log(' ✨ Status: READY'); } else { console.log(` āš ļø Status: NEEDS ATTENTION (${result.issues.length} issues)`); result.issues.forEach(issue => console.log(` ${issue}`)); } results[mcp.name] = result; } // Overall summary console.log('\n\nšŸ“Š SUMMARY\n'); const ready = Object.values(results).filter(r => r.issues.length === 0).length; const needsWork = Object.values(results).filter(r => r.issues.length > 0).length; console.log(` āœ… Ready: ${ready}/7`); console.log(` āš ļø Needs work: ${needsWork}/7`); console.log('\nšŸ“ Action Items:\n'); Object.entries(results).forEach(([name, result]) => { if (result.issues.length > 0) { console.log(` ${name}:`); result.issues.forEach(issue => console.log(` - ${issue}`)); } }); console.log('\n');