#!/usr/bin/env node
import { Command } from 'commander';
import chalk from 'chalk';
import { IncrementalImpactAnalyzer } from './IncrementalImpactAnalyzer.js';
import { ReportGenerator } from './ReportGenerator.js';
import fs from 'fs/promises';
const program = new Command();
const reportGenerator = new ReportGenerator();
program
.name('mcp-token-analyzer')
.description('Precise token counting and context efficiency analysis for MCP servers')
.version('1.0.0');
program
.command('analyze')
.description('Perform complete MCP token analysis')
.option('-o, --output <file>', 'Output file for detailed results (JSON)')
.option('-r, --report <file>', 'Output file for formatted report (TXT)')
.option('-c, --csv <file>', 'Output file for CSV data')
.option('-q, --quiet', 'Suppress console output except errors')
.option('-s, --summary', 'Show only quick summary')
.action(async (options) => {
try {
const analyzer = new IncrementalImpactAnalyzer();
if (!options.quiet) {
console.log(chalk.cyan.bold('š MCP Token Analyzer v1.0.0'));
console.log(chalk.gray('Analyzing MCP server token consumption...\n'));
}
// Perform analysis
const results = await analyzer.performCompleteAnalysis();
if (results.error) {
console.error(chalk.red('ā Analysis failed:'), results.error);
if (results.configPaths) {
console.log(chalk.gray('Checked configuration paths:'));
results.configPaths.forEach(path => console.log(chalk.gray(` ⢠${path}`)));
}
process.exit(1);
}
// Generate outputs
if (options.output) {
await fs.writeFile(options.output, JSON.stringify(results, null, 2));
if (!options.quiet) console.log(chalk.green(`š Detailed results saved to ${options.output}`));
}
if (options.report) {
const report = reportGenerator.generateCompleteReport(results);
await fs.writeFile(options.report, report);
if (!options.quiet) console.log(chalk.green(`š Report saved to ${options.report}`));
}
if (options.csv) {
const csvData = reportGenerator.generateCSVExport(results);
await fs.writeFile(options.csv, csvData);
if (!options.quiet) console.log(chalk.green(`š CSV data saved to ${options.csv}`));
}
// Console output
if (!options.quiet) {
if (options.summary) {
console.log('\n' + reportGenerator.generateQuickSummary(results));
} else {
console.log('\n' + reportGenerator.generateCompleteReport(results));
}
}
} catch (error) {
console.error(chalk.red('ā Analysis failed:'), error.message);
if (process.env.DEBUG) {
console.error(error.stack);
}
process.exit(1);
}
});
program
.command('config')
.description('Show MCP configuration information')
.action(async () => {
try {
const { MCPConfigurationAnalyzer } = await import('./MCPConfigurationAnalyzer.js');
const analyzer = new MCPConfigurationAnalyzer();
console.log(chalk.cyan.bold('š MCP Configuration Analysis\n'));
const config = await analyzer.analyzeConfiguration();
if (!config.hasConfiguration) {
console.log(chalk.yellow('ā ļø No MCP configuration found'));
console.log(chalk.gray('Checked paths:'));
analyzer.configPaths.forEach(path => console.log(chalk.gray(` ⢠${path}`)));
return;
}
console.log(chalk.green(`ā
Configuration found: ${config.configPath}`));
console.log(`Total servers: ${config.totalServers}`);
if (config.servers.length > 0) {
console.log('\n' + chalk.cyan('Configured Servers:'));
config.servers.forEach(server => {
const status = server.disabled ? chalk.red('DISABLED') : chalk.green('ACTIVE');
console.log(` ⢠${server.name} (${server.configType}) - ${status}`);
});
}
} catch (error) {
console.error(chalk.red('ā Configuration analysis failed:'), error.message);
process.exit(1);
}
});
program
.command('quick')
.description('Quick token estimation (no server connection)')
.action(async () => {
try {
const { MCPConfigurationAnalyzer } = await import('./MCPConfigurationAnalyzer.js');
const { TokenMeasurementEngine } = await import('./TokenMeasurementEngine.js');
const configAnalyzer = new MCPConfigurationAnalyzer();
const tokenEngine = new TokenMeasurementEngine();
console.log(chalk.cyan.bold('ā” Quick Token Estimation\n'));
const config = await configAnalyzer.analyzeConfiguration();
if (!config.hasConfiguration) {
console.log(chalk.yellow('ā ļø No MCP configuration found'));
return;
}
const activeServers = config.servers.filter(s => !s.disabled);
const baseline = tokenEngine.measureBaselineTokens();
// Rough estimation without connecting to servers
const estimatedTokensPerServer = 1500; // Conservative estimate based on research
const estimatedMcpTokens = activeServers.length * estimatedTokensPerServer;
const totalEstimated = baseline.totalBuiltInTokens + estimatedMcpTokens;
const percentageEstimated = (totalEstimated / 200000) * 100;
console.log(`Built-in tools: ${baseline.totalBuiltInTokens} tokens`);
console.log(`Active MCP servers: ${activeServers.length}`);
console.log(`Estimated MCP tokens: ${estimatedMcpTokens.toLocaleString()} tokens`);
console.log(`Total estimated overhead: ${totalEstimated.toLocaleString()} tokens`);
console.log(`Estimated context usage: ${percentageEstimated.toFixed(1)}%`);
if (percentageEstimated > 10) {
console.log(chalk.yellow('\nā ļø High estimated overhead detected'));
console.log(chalk.gray('Run full analysis for detailed recommendations'));
} else {
console.log(chalk.green('\nā
Overhead appears reasonable'));
}
} catch (error) {
console.error(chalk.red('ā Quick estimation failed:'), error.message);
process.exit(1);
}
});
program
.command('doctor')
.description('Validate analyzer setup and dependencies')
.action(async () => {
console.log(chalk.cyan.bold('𩺠MCP Token Analyzer Doctor\n'));
const checks = [];
// Check Node.js version
const nodeVersion = process.version;
checks.push({
name: 'Node.js Version',
status: true,
message: nodeVersion
});
// Check for MCP configuration
try {
const { MCPConfigurationAnalyzer } = await import('./MCPConfigurationAnalyzer.js');
const analyzer = new MCPConfigurationAnalyzer();
const config = await analyzer.analyzeConfiguration();
checks.push({
name: 'MCP Configuration',
status: config.hasConfiguration,
message: config.hasConfiguration ? `Found: ${config.configPath}` : 'Not found'
});
} catch (error) {
checks.push({
name: 'MCP Configuration',
status: false,
message: `Error: ${error.message}`
});
}
// Check write permissions
try {
await fs.writeFile('test-write.tmp', 'test');
await fs.unlink('test-write.tmp');
checks.push({
name: 'File System Access',
status: true,
message: 'Write permissions OK'
});
} catch (error) {
checks.push({
name: 'File System Access',
status: false,
message: `Cannot write files: ${error.message}`
});
}
// Display results
checks.forEach(check => {
const icon = check.status ? chalk.green('ā
') : chalk.red('ā');
console.log(`${icon} ${check.name}: ${check.message}`);
});
const allPassed = checks.every(check => check.status);
console.log('\n' + (allPassed ?
chalk.green('š All checks passed! Analyzer is ready to use.') :
chalk.yellow('ā ļø Some checks failed. See messages above.')
));
});
// Handle unknown commands
program.on('command:*', () => {
console.error(chalk.red('ā Unknown command. Use --help for available commands.'));
process.exit(1);
});
// Default action
if (process.argv.length === 2) {
program.help();
}
program.parse();