clawdbot-workspace/audit-localbosses-mcps.js

141 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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');