2026-02-04 23:01:37 -05:00

108 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
/**
* MCP Factory — Batch Discovery
* Runs mcp-jest discover on all 30 servers, generates test configs.
* Uses dummy env vars so servers start without real API keys.
*/
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
import { execSync } from 'child_process';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const FACTORY_ROOT = resolve(__dirname, '..');
const registry = JSON.parse(readFileSync(resolve(FACTORY_ROOT, 'server-registry.json'), 'utf-8'));
const SERVERS_ROOT = resolve(FACTORY_ROOT, registry.servers_root);
// Output dirs
const CONFIGS_DIR = resolve(FACTORY_ROOT, 'test-configs');
const REPORTS_DIR = resolve(FACTORY_ROOT, 'reports');
mkdirSync(CONFIGS_DIR, { recursive: true });
mkdirSync(REPORTS_DIR, { recursive: true });
const results = { passed: [], failed: [], total: 0 };
for (const [name, meta] of Object.entries(registry.servers)) {
results.total++;
const serverDir = resolve(SERVERS_ROOT, name);
const distEntry = resolve(serverDir, 'dist/index.js');
if (!existsSync(distEntry)) {
console.log(`⚠️ ${name}: No dist/index.js — needs build`);
results.failed.push({ name, reason: 'no dist' });
continue;
}
// Build env object with dummy values
const env = {};
for (const envVar of meta.env) {
env[envVar] = 'factory_discovery_dummy';
}
// Create test config
const config = {
server: {
command: 'node',
args: [distEntry],
env
}
};
const configPath = resolve(CONFIGS_DIR, `${name}.json`);
writeFileSync(configPath, JSON.stringify(config, null, 2));
try {
console.log(`🔍 Discovering ${name}...`);
const output = execSync(`mcp-jest discover --config "${configPath}"`, {
timeout: 30000,
encoding: 'utf-8',
cwd: CONFIGS_DIR,
stdio: ['pipe', 'pipe', 'pipe']
});
// Move generated config
const generatedPath = resolve(CONFIGS_DIR, 'mcp-jest.generated.json');
if (existsSync(generatedPath)) {
const generated = JSON.parse(readFileSync(generatedPath, 'utf-8'));
// Merge env into generated config
generated.server.env = env;
writeFileSync(resolve(CONFIGS_DIR, `${name}-tests.json`), JSON.stringify(generated, null, 2));
execSync(`rm "${generatedPath}"`);
const toolCount = Object.keys(generated.tests?.tools || {}).length;
console.log(`${name}: ${toolCount} test cases generated`);
results.passed.push({ name, tools: toolCount });
}
} catch (err) {
const stderr = err.stderr?.toString() || err.message;
console.log(`${name}: ${stderr.split('\n')[0]}`);
results.failed.push({ name, reason: stderr.split('\n')[0] });
}
}
// Summary
console.log('\n' + '═'.repeat(60));
console.log(' MCP FACTORY — DISCOVERY REPORT');
console.log('═'.repeat(60));
console.log(`\nTotal: ${results.total}`);
console.log(`Passed: ${results.passed.length}`);
console.log(`Failed: ${results.failed.length}`);
if (results.passed.length > 0) {
const totalTools = results.passed.reduce((sum, r) => sum + r.tools, 0);
console.log(`\nTotal test cases generated: ${totalTools}`);
}
if (results.failed.length > 0) {
console.log('\nFailed servers:');
for (const f of results.failed) {
console.log(` - ${f.name}: ${f.reason}`);
}
}
// Write report
const reportPath = resolve(REPORTS_DIR, `discovery-${new Date().toISOString().split('T')[0]}.json`);
writeFileSync(reportPath, JSON.stringify(results, null, 2));
console.log(`\nReport saved: ${reportPath}`);