#!/usr/bin/env node
/**
* @fileoverview DeepSource MCP Server entry point.
*
* This is the main entry point for the DeepSource MCP server when run
* as a standalone application. It uses the modular MCP server implementation
* for better separation of concerns.
*
* @packageDocumentation
*/
import { createLogger } from './utils/logging/logger.js';
import { DeepSourceMCPServer } from './server/mcp-server.js';
import { VERSION, getVersion } from './version.js';
import { getFeatureFlags, logFeatureFlags } from './config/features.js';
import { getEnvironmentConfig } from './config/default.js';
// Create logger instance for index.ts
const logger = createLogger('DeepSourceMCP:index');
// Internal mutable reference
let _mcpServer: DeepSourceMCPServer | undefined;
// Export an immutable getter for backward compatibility
export const mcpServer = {
get current(): DeepSourceMCPServer {
if (!_mcpServer) {
throw new Error('MCP server not initialized. Call initializeServer() first.');
}
return _mcpServer;
},
};
// Initialize the DeepSource MCP server
export async function initializeServer(): Promise<void> {
try {
logger.info('Initializing DeepSource MCP Server');
// Get feature flags and configuration
const features = getFeatureFlags();
const config = getEnvironmentConfig();
// Log feature flags in development
if (process.env.NODE_ENV === 'development' || features.enhancedLogging) {
logFeatureFlags(logger.debug.bind(logger));
}
// Create server with configuration
_mcpServer = await DeepSourceMCPServer.create({
autoRegisterTools: true,
autoStart: false,
// Pass discovery config if tool discovery is enabled
...(features.toolDiscovery && {
discoveryConfig: config.discovery,
}),
});
// If tool discovery is enabled, perform discovery
if (features.toolDiscovery && _mcpServer) {
logger.info('Tool discovery enabled, scanning for additional tools...');
const discoveredTools = await _mcpServer.discoverTools(
config.discovery as unknown as Record<string, unknown>
);
if (discoveredTools.length > 0) {
logger.info(`Discovered ${discoveredTools.length} additional tools`, {
tools: discoveredTools,
});
}
}
logger.info('DeepSource MCP Server initialized successfully', {
tools: _mcpServer.getRegisteredTools(),
features: Object.entries(features)
.filter(([, enabled]) => enabled)
.map(([name]) => name),
});
} catch (error) {
logger.error('Failed to initialize DeepSource MCP Server', error);
throw error;
}
}
// Export functions for backward compatibility
export function getMcpServer() {
return mcpServer.current.getMcpServer();
}
// CLI argument handler for testing
export function handleCliArgs(args: string[]): boolean {
// Check for version flag before anything else
if (args.includes('--version') || args.includes('-v')) {
const features = getFeatureFlags();
const enabledFeatures = Object.entries(features)
.filter(([, enabled]) => enabled)
.map(([name]) => name);
// eslint-disable-next-line no-console
console.log(`deepsource-mcp-server version ${VERSION}`);
if (enabledFeatures.length > 0) {
// eslint-disable-next-line no-console
console.log(`Enabled features: ${enabledFeatures.join(', ')}`);
}
return true;
}
// Check for help flag
if (args.includes('--help') || args.includes('-h')) {
/* eslint-disable no-console */
console.log(`DeepSource MCP Server v${VERSION}`);
console.log('\nUsage: deepsource-mcp-server [options]');
console.log('\nOptions:');
console.log(' -v, --version Display version information');
console.log(' -h, --help Display this help message');
console.log('\nEnvironment Variables:');
console.log(' DEEPSOURCE_API_KEY DeepSource API key (required)');
console.log(' LOG_FILE Path to log file (optional)');
console.log(
' LOG_LEVEL Minimum log level: DEBUG, INFO, WARN, ERROR (optional)'
);
console.log('\nFeature Flags:');
console.log(' FEATURE_TOOL_DISCOVERY Enable automatic tool discovery (optional)');
console.log(' FEATURE_ENHANCED_LOGGING Enable enhanced logging (optional)');
console.log(' FEATURE_METRICS Enable metrics collection (optional)');
console.log(' FEATURE_CACHE Enable caching layer (optional)');
/* eslint-enable no-console */
return true;
}
return false;
}
// Main entry point
async function main(): Promise<void> {
const args = process.argv.slice(2);
// Handle CLI args and exit if needed
if (handleCliArgs(args)) {
process.exit(0);
}
try {
// Log startup with version and features
const features = getFeatureFlags();
const enabledFeatures = Object.entries(features)
.filter(([, enabled]) => enabled)
.map(([name]) => name);
logger.info(`Starting DeepSource MCP Server v${VERSION}`, {
version: VERSION,
node: process.version,
platform: process.platform,
features: enabledFeatures,
});
// Initialize the server
await initializeServer();
// Start the server if not in test mode
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'test') {
logger.info('Starting MCP server connection...');
await mcpServer.current.start();
logger.info('MCP server started successfully', { version: getVersion() });
}
} catch (error) {
logger.error('Failed to start MCP server', error);
process.exit(1);
}
}
// Run the main function only when not in test mode and when executed directly
/* istanbul ignore if */
// Check if this file is being run directly (ESM compatible)
const isMainModule =
import.meta.url === `file://${process.argv[1]}` ||
import.meta.url === `file://${process.argv[1]}.ts` ||
import.meta.url === `file://${process.argv[1]}.js`;
if (process.env.NODE_ENV !== 'test' && isMainModule) {
main().catch((error) => {
logger.error('Unhandled error in main', error);
process.exit(1);
});
} else if (process.env.NODE_ENV === 'test') {
// In test mode, just initialize the server without starting it
initializeServer().catch((error) => {
logger.error('Failed to initialize server in test mode', error);
});
}
// Export for backward compatibility with modules that import from index-registry
export { validateEnvironment, createAndConfigureToolRegistry } from './compatibility.js';