141 lines
4.3 KiB
JavaScript
141 lines
4.3 KiB
JavaScript
#!/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');
|