/**
* Ask-Me MCP Server
*
* This server implements the Model Context Protocol with stdio transport,
* allowing MCP clients like Claude Code to interact with human input tools
* through standard input / output.
*/
import { createMCPServer, startMCPServer, setupGracefulShutdown } from './core/server.js';
import { RequestManager } from './core/request-manager.js';
import { startBrowserBridge } from './core/browser-bridge.js';
import { Logger } from './core/logger.js';
/**
* Parse command line arguments
*/
function parseArgs(): { port: number; help: boolean; portSpecified: boolean; exitAfterCommand: boolean; transport: 'stdio' | 'sse' } {
const args = process.argv.slice(2);
let port = 33333; // Default port
let help = false;
let portSpecified = false;
let exitAfterCommand = false;
let transport: 'stdio' | 'sse' = 'stdio'; // Default transport
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg === '--port' || arg === '-p') {
const portArg = args[i + 1];
if (!portArg || isNaN(Number(portArg))) {
Logger.error('[ask-me-mcp] Error: --port requires a valid port number');
process.exit(1);
}
port = Number(portArg);
if (port < 1 || port > 65535) {
Logger.error('[ask-me-mcp] Error: Port must be between 1 and 65535');
process.exit(1);
}
portSpecified = true;
i++; // Skip the next argument since it's the port value
} else if (arg === '--help' || arg === '-h') {
help = true;
} else if (arg === '--exit-after-command') {
exitAfterCommand = true;
} else if (arg === '--transport' || arg === '-t') {
const transportArg = args[i + 1];
if (!transportArg || (transportArg !== 'stdio' && transportArg !== 'sse')) {
Logger.error('[ask-me-mcp] Error: --transport requires "stdio" or "sse"');
process.exit(1);
}
transport = transportArg;
i++; // Skip the next argument since it's the transport value
} else if (arg.startsWith('-')) {
Logger.error(`[ask-me-mcp] Error: Unknown argument: ${arg}`);
Logger.error('[ask-me-mcp] Use --help for usage information');
process.exit(1);
}
}
return { port, help, portSpecified, exitAfterCommand, transport };
}
/**
* Display help message
*/
function showHelp(): void {
console.error(`
Ask-Me MCP Server - Human-in-the-Loop MCP Server
Usage: node main.js [options]
Options:
--port, -p <number> Port for the browser bridge HTTP server (default: 3000)
If not specified, auto-discovers available port starting from 3000
If specified, uses exact port (will fail if port is in use)
--transport, -t <type> MCP transport type: "stdio" or "sse" (default: stdio)
"stdio": MCP communication over standard input/output.
"sse": MCP communication over Server-Sent Events via the browser bridge.
--exit-after-command Exit server after handling first MCP command (debug only)
--help, -h Show this help message
Examples:
node main.js # Auto-discover port starting from 3000, stdio transport
node main.js --port 4711 # Use exact port 4711, stdio transport
node main.js -p 8080 --transport sse # Use exact port 8080, SSE transport
node main.js --exit-after-command # Exit after first MCP command (debug)
The server uses stdio transport for MCP communication and starts an HTTP server
for browser UI communication on the specified port.
`);
}
/**
* Main application entry point
*/
async function main() {
try {
// Parse command line arguments
const { port, help, portSpecified, exitAfterCommand, transport } = parseArgs();
Logger.info('Starting AskMeMCP server', { args: process.argv });
if (help) {
showHelp();
process.exit(0);
}
// Initialize request manager
const requestManager = new RequestManager();
// Server configuration
const serverConfig = {
name: 'ask-me-mcp',
version: '1.0.0',
description: 'Human-in-the-Loop MCP Server',
};
// Start the browser bridge HTTP server with specified port
// If transport is 'sse', enable SSE transport on the bridge
const httpServer = await startBrowserBridge(
requestManager,
serverConfig,
port,
portSpecified,
transport === 'sse'
);
// If transport is 'stdio', start the Stdio MCP server
// If transport is 'sse', the bridge handles MCP connections
let server;
if (transport === 'stdio') {
// Create and configure the MCP server
server = createMCPServer(
serverConfig,
requestManager,
exitAfterCommand
);
// Start the MCP server with stdio transport
await startMCPServer(server);
// Setup graceful shutdown handling
setupGracefulShutdown(server, httpServer);
} else {
Logger.info('[ask-me-mcp] Running in SSE mode - Stdio transport disabled');
// For SSE mode, we need to keep the process alive
// The HTTP server is already running
// Handle signals for graceful shutdown
const shutdown = async (signal: string) => {
Logger.info(`[ask-me-mcp] Received ${signal}, shutting down...`);
httpServer.close();
process.exit(0);
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
}
} catch (error) {
Logger.error('[ask-me-mcp] Fatal error:', error);
Logger.error('[ask-me-mcp] Stack trace:', error instanceof Error ? error.stack : 'No stack trace');
process.exit(1);
}
}
// Start the application
main();