Skip to main content
Glama
CLIHandler.ts5.43 kB
import { CLICommand, CLIOptions, CLIError } from './types.js'; import { OutputFormatter } from './OutputFormatter.js'; import { Logger } from '../utils/logger.js'; export class CLIHandler { private commands = new Map<string, CLICommand>(); private formatter = new OutputFormatter(); private logger = Logger.getInstance(); registerCommand(command: CLICommand): void { this.commands.set(command.name, command); } async execute(args: string[]): Promise<void> { try { if (args.length === 0) { this.showHelp(); return; } // Handle global options first if (args.includes('--help') || args.includes('-h')) { if (args.length === 1) { this.showHelp(); } else { const commandName = args.find(arg => !arg.startsWith('-')); if (commandName) { this.showCommandHelp(commandName); } else { this.showHelp(); } } return; } if (args.includes('--version') || args.includes('-v')) { this.showVersion(); return; } const [commandName, ...commandArgs] = args; const options = this.parseOptions(commandArgs); // Find and execute command const command = this.commands.get(commandName); if (!command) { throw new CLIError(`Unknown command: ${commandName}. Use --help for available commands.`); } await command.execute(commandArgs, options); } catch (error) { this.handleError(error); } } private parseOptions(args: string[]): CLIOptions { const options: CLIOptions = {}; const remainingArgs: string[] = []; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--')) { const [key, value] = arg.slice(2).split('='); if (value !== undefined) { options[key] = this.parseValue(value); } else if (i + 1 < args.length && !args[i + 1].startsWith('-')) { options[key] = this.parseValue(args[++i]); } else { options[key] = true; } } else if (arg.startsWith('-') && arg.length > 1) { // Handle short options const flags = arg.slice(1); for (const flag of flags) { options[flag] = true; } } else { remainingArgs.push(arg); } } // Add remaining args as positional arguments if (remainingArgs.length > 0) { options._args = remainingArgs; } return options; } private parseValue(value: string): any { // Try to parse as number if (/^\d+$/.test(value)) { return parseInt(value, 10); } // Try to parse as boolean if (value === 'true') return true; if (value === 'false') return false; // Return as string return value; } private showHelp(): void { const packageJson = this.getPackageInfo(); console.log(`${packageJson.name} v${packageJson.version}`); console.log(`${packageJson.description}\n`); console.log('Usage:'); console.log(' npx npm-dev-mcp [command] [options]\n'); console.log('Available Commands:'); this.commands.forEach(command => { console.log(` ${command.name.padEnd(12)} ${command.description}`); }); console.log('\nGlobal Options:'); console.log(' --help, -h Show help information'); console.log(' --version, -v Show version information'); console.log(' --json Output in JSON format'); console.log('\nExamples:'); console.log(' npx npm-dev-mcp scan # Scan for projects'); console.log(' npx npm-dev-mcp start # Start dev server'); console.log(' npx npm-dev-mcp status --json # Get status in JSON'); console.log(' npx npm-dev-mcp logs 100 --follow # Follow last 100 logs'); } private showCommandHelp(commandName: string): void { const command = this.commands.get(commandName); if (!command) { console.log(`Unknown command: ${commandName}`); this.showHelp(); return; } console.log(`${commandName} - ${command.description}\n`); console.log(`Usage: ${command.usage}\n`); if (command.options.length > 0) { console.log('Options:'); command.options.forEach(option => { const shortFlag = option.short ? `-${option.short}, ` : ' '; const longFlag = `--${option.long}`; const defaultValue = option.default ? ` (default: ${option.default})` : ''; console.log(` ${shortFlag}${longFlag.padEnd(20)} ${option.description}${defaultValue}`); }); } } private showVersion(): void { const packageJson = this.getPackageInfo(); console.log(packageJson.version); } private getPackageInfo(): any { // This would typically read from package.json // For now, return hardcoded values return { name: 'npm-dev-mcp', version: '1.0.0', description: 'MCP server for managing npm run dev processes' }; } private handleError(error: any): void { if (error instanceof CLIError) { console.error(`❌ ${error.message}`); process.exit(error.exitCode); } this.logger.error('Unexpected CLI error', { error }); console.error(`💥 Unexpected error: ${error.message}`); process.exit(1); } getAvailableCommands(): string[] { return Array.from(this.commands.keys()); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/masamunet/npm-dev-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server