@moikas/code-audit-mcp
Version:
AI-powered code auditing via MCP using local Ollama models for security, performance, and quality analysis
213 lines (212 loc) • 8.73 kB
JavaScript
/**
* Main CLI interface for Code Audit MCP
*/
import { Command } from 'commander';
import chalk from 'chalk';
import updateNotifier from 'update-notifier';
import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
// Import commands
import { startCommand } from './commands/start.js';
import { stopCommand } from './commands/stop.js';
import { setupCommand } from './commands/setup.js';
import { updateCommand } from './commands/update.js';
import { modelsCommand } from './commands/models.js';
import { healthCommand } from './commands/health.js';
import { configCommand } from './commands/config.js';
import { mcpCommand } from './commands/mcp.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Get package information
*/
function getPackageInfo() {
try {
const packagePath = join(__dirname, '../../package.json');
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
return packageJson;
}
catch {
return { name: 'code-audit-mcp', version: '1.0.0' };
}
}
/**
* Check for updates
*/
function checkForUpdates(pkg) {
const notifier = updateNotifier({
pkg,
updateCheckInterval: 1000 * 60 * 60 * 24, // 24 hours
});
if (notifier.update) {
console.log(chalk.yellow(`
┌─────────────────────────────────────────────────────────────┐
│ │
│ Update available: ${chalk.green(notifier.update.latest)} │
│ Current version: ${chalk.red(notifier.update.current)} │
│ │
│ Run ${chalk.cyan('npm install -g code-audit-mcp')} to update │
│ │
└─────────────────────────────────────────────────────────────┘
`));
}
}
/**
* Main CLI function
*/
export async function cli() {
const pkg = getPackageInfo();
// Check for updates (non-blocking)
checkForUpdates(pkg);
const program = new Command();
// Configure the main program
program
.name('code-audit')
.description('AI-powered code auditing via MCP using local Ollama models')
.version(pkg.version, '-v, --version', 'Show version number')
.helpOption('-h, --help', 'Show help information');
// Add global options
program
.option('--verbose', 'Enable verbose output')
.option('--config <path>', 'Path to config file')
.option('--no-color', 'Disable colored output');
// Register commands
program
.command('start')
.description('Start the MCP server')
.option('-d, --daemon', 'Run as daemon process')
.option('-p, --port <port>', 'Port for HTTP transport (optional)')
.option('--stdio', 'Use stdio transport (default)')
.action(startCommand);
program
.command('stop')
.description('Stop the running MCP server')
.action(stopCommand);
program
.command('setup')
.description('Interactive setup wizard')
.option('--force', 'Force re-setup even if already configured')
.option('--minimal', 'Minimal setup with essential models only')
.option('--comprehensive', 'Full setup with all recommended models')
.option('--claude-desktop', 'Configure Claude Desktop MCP server')
.option('--claude-code', 'Configure Claude Code global MCP server')
.option('--project', 'Configure Claude Code project MCP server')
.option('--auto', 'Auto-configure all available Claude environments')
.action(setupCommand);
program
.command('update')
.description('Check for and install updates')
.option('--check', "Only check for updates, don't install")
.option('--force', 'Force update even if no new version')
.action(updateCommand);
program
.command('models')
.description('Manage AI models')
.option('--list', 'List installed models')
.option('--pull <model>', 'Pull a specific model')
.option('--remove <model>', 'Remove a specific model')
.option('--update', 'Update all models to latest versions')
.action(modelsCommand);
program
.command('health')
.description('Check system health')
.option('--detailed', 'Show detailed health information')
.option('--json', 'Output as JSON')
.action(healthCommand);
program
.command('config')
.description('Manage configuration')
.option('--show', 'Show current configuration')
.option('--reset', 'Reset to default configuration')
.option('--set <key=value>', 'Set a configuration value')
.option('--get <key>', 'Get a configuration value')
.action(configCommand);
program
.command('mcp [subcommand]')
.description('Manage MCP server configurations in Claude')
.option('--environment <env>', 'Target specific environment (desktop, code-global, project)')
.option('--force', 'Skip confirmation prompts')
.option('--restore <file>', 'Backup file to restore from')
.action((subcommand, options) => {
mcpCommand(subcommand, options);
});
// Add example usage
program.addHelpText('after', `
Examples:
$ code-audit setup Interactive setup wizard
$ code-audit start Start MCP server
$ code-audit start --daemon Start as background daemon
$ code-audit health Check system health
$ code-audit models --list List installed models
$ code-audit mcp status Show MCP configuration status
$ code-audit mcp configure Configure MCP servers in Claude
$ code-audit update Check for updates
For more information, visit: https://github.com/warrengates/code-audit-mcp
`);
// Handle global error cases
program.exitOverride();
try {
await program.parseAsync(process.argv);
}
catch (error) {
// Type guard for Commander.js errors
const isCommanderError = (err) => {
return (typeof err === 'object' &&
err !== null &&
'code' in err &&
'message' in err);
};
// Type guard for Error objects
const isError = (err) => {
return err instanceof Error;
};
if (isCommanderError(error)) {
if (error.code === 'commander.version') {
// Version flag was used, exit normally
process.exit(0);
}
else if (error.code === 'commander.help') {
// Help flag was used, exit normally
process.exit(0);
}
else if (error.code === 'commander.unknownCommand') {
console.error(chalk.red(`Unknown command: ${error.message}`));
console.log(chalk.gray('Run "code-audit --help" for available commands.'));
process.exit(1);
}
}
if (isError(error)) {
// Check if this is a help-related error that shouldn't be displayed
if (error.message && error.message.includes('outputHelp')) {
// Help was displayed, exit normally
process.exit(0);
}
console.error(chalk.red('An error occurred:'), error.message);
if (program.opts().verbose) {
console.error(error.stack);
}
}
else {
// Check for help-related strings in the error
const errorStr = String(error);
if (errorStr.includes('outputHelp') || errorStr === '(outputHelp)') {
// Help was displayed, exit normally
process.exit(0);
}
console.error(chalk.red('An unknown error occurred:'), errorStr);
}
process.exit(1);
}
}
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
console.error(chalk.red('Unhandled Rejection at:'), promise, chalk.red('reason:'), reason);
process.exit(1);
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
console.error(chalk.red('Uncaught Exception:'), error);
process.exit(1);
});
//# sourceMappingURL=index.js.map