@uplinq/mcp-vitest
Version:
MCP server for Vitest with watch-mode support for fast test feedback
126 lines • 5.09 kB
JavaScript
import { detectTransport, getTransportDescription } from './utils/transport-detector.js';
import { createVitestMCPServer } from './server.js';
import { program } from 'commander';
import packageJson from '../package.json' with { type: 'json' };
import { log, error, setStdioTransport } from './utils/logger.js';
/**
* Main entry point for the MCP Vitest server
*/
async function main() {
// Setup CLI
program
.name('@uplinq/mcp-vitest')
.description('MCP server for Vitest with watch-mode support')
.version(packageJson.version, '-v, --version', 'display version number')
.option('--stdio', 'force stdio transport (default)')
.option('--sse <port>', 'use SSE transport on specified port')
.option('--http <port>', 'use HTTP stream transport on specified port')
.parse();
const options = program.opts();
try {
// Detect transport configuration
let transportConfig;
if (options.stdio) {
transportConfig = { transportType: 'stdio' };
}
else if (options.sse) {
const port = parseInt(options.sse);
if (isNaN(port)) {
error('Error: SSE port must be a valid number');
process.exit(1);
}
transportConfig = { transportType: 'sse', sse: { port } };
}
else if (options.http) {
const port = parseInt(options.http);
if (isNaN(port)) {
error('Error: HTTP port must be a valid number');
process.exit(1);
}
transportConfig = { transportType: 'httpStream', httpStream: { port } };
}
else {
// Auto-detect from environment
transportConfig = await detectTransport();
}
// Set stdio transport flag for logger
setStdioTransport(transportConfig.transportType === 'stdio');
log(`Starting MCP Vitest server with ${getTransportDescription(transportConfig)}...`);
// Create the FastMCP server
const server = await createVitestMCPServer(transportConfig.transportType);
// Start the server with the detected transport configuration
log('Starting server...');
switch (transportConfig.transportType) {
case 'sse':
if (!transportConfig.sse?.port) {
error('Error: SSE port not configured');
process.exit(1);
}
await server.start({
transportType: 'sse',
sse: {
port: transportConfig.sse.port,
endpoint: '/sse'
}
});
log(`🚀 MCP Vitest server running on SSE port ${transportConfig.sse.port}`);
break;
case 'httpStream':
if (!transportConfig.httpStream?.port) {
error('Error: HTTP Stream port not configured');
process.exit(1);
}
await server.start({
transportType: 'httpStream',
httpStream: {
port: transportConfig.httpStream.port,
endpoint: '/stream'
}
});
log(`🚀 MCP Vitest server running on HTTP Stream port ${transportConfig.httpStream.port}`);
break;
case 'stdio':
default:
await server.start({
transportType: 'stdio'
});
log('🚀 MCP Vitest server running on stdio');
break;
}
// Log helpful information
log('');
log('Available MCP tools:');
log(' • get_test_status - Get comprehensive test results');
log(' • get_failing_tests - Get detailed information about failing tests');
log(' • get_vitest_status - Get Vitest manager status');
log('');
log('Server is now ready to accept connections...');
// Keep the process alive - the server is now running and will handle transport communication
// No need for manual process.keepAlive since server.start() handles this
}
catch (err) {
error('Failed to start server:', err);
process.exit(1);
}
}
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
// Handle uncaught exceptions
process.on('uncaughtException', (err) => {
error('Uncaught Exception:', err);
process.exit(1);
});
// Start the server
// Check if this module is being executed directly (works with npm bin wrappers)
const isMainModule = process.argv[1].endsWith('/mcp-vitest') || import.meta.url === `file://${process.argv[1]}`;
if (isMainModule) {
main().catch((err) => {
error('Fatal error:', err);
process.exit(1);
});
}
//# sourceMappingURL=index.js.map