UNPKG

mcp-ts-template

Version:

A production-grade TypeScript template for building robust Model Context Protocol (MCP) servers, featuring built-in observability with OpenTelemetry, advanced error handling, comprehensive utilities, and a modular architecture.

126 lines 5.3 kB
#!/usr/bin/env node /** * @fileoverview Main entry point for the MCP TypeScript Template application. * This script initializes the configuration, sets up the logger, starts the * MCP server (either via STDIO or HTTP transport), and handles graceful * shutdown on process signals or unhandled errors. * @module src/index */ // IMPORTANT: This line MUST be the first import to ensure OpenTelemetry is // initialized before any other modules are loaded. import { shutdownOpenTelemetry } from "./utils/telemetry/instrumentation.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import http from "http"; import { config, environment } from "./config/index.js"; import { initializeAndStartServer } from "./mcp-server/server.js"; import { requestContextService } from "./utils/index.js"; import { logger } from "./utils/internal/logger.js"; let mcpStdioServer; let actualHttpServer; const shutdown = async (signal) => { const shutdownContext = requestContextService.createRequestContext({ operation: "ServerShutdown", triggerEvent: signal, }); logger.info(`Received ${signal}. Initiating graceful shutdown...`, shutdownContext); try { // Shutdown OpenTelemetry first to ensure buffered telemetry is sent await shutdownOpenTelemetry(); let closePromise = Promise.resolve(); const transportType = config.mcpTransportType; if (transportType === "stdio" && mcpStdioServer) { logger.info("Attempting to close main MCP server (STDIO)...", shutdownContext); closePromise = mcpStdioServer.close(); } else if (transportType === "http" && actualHttpServer) { logger.info("Attempting to close HTTP server...", shutdownContext); closePromise = new Promise((resolve, reject) => { actualHttpServer.close((err) => { if (err) { logger.error("Error closing HTTP server.", err, shutdownContext); return reject(err); } logger.info("HTTP server closed successfully.", shutdownContext); resolve(); }); }); } await closePromise; logger.info("Graceful shutdown completed successfully. Exiting.", shutdownContext); process.exit(0); } catch (error) { logger.error("Critical error during shutdown process.", error, shutdownContext); process.exit(1); } }; const start = async () => { const validMcpLogLevels = [ "debug", "info", "notice", "warning", "error", "crit", "alert", "emerg", ]; const initialLogLevelConfig = config.logLevel; let validatedMcpLogLevel = "info"; if (validMcpLogLevels.includes(initialLogLevelConfig)) { validatedMcpLogLevel = initialLogLevelConfig; } else { if (process.stdout.isTTY) { console.warn(`[Startup Warning] Invalid MCP_LOG_LEVEL "${initialLogLevelConfig}". Defaulting to "info".`); } } await logger.initialize(validatedMcpLogLevel); logger.info(`Logger initialized. Effective MCP logging level: ${validatedMcpLogLevel}.`, requestContextService.createRequestContext({ operation: "LoggerInit" })); const transportType = config.mcpTransportType; const startupContext = requestContextService.createRequestContext({ operation: `ServerStartupSequence_${transportType}`, applicationName: config.mcpServerName, applicationVersion: config.mcpServerVersion, nodeEnvironment: environment, }); logger.info(`Starting ${config.mcpServerName} (Version: ${config.mcpServerVersion}, Transport: ${transportType}, Env: ${environment})...`, startupContext); try { const serverInstance = await initializeAndStartServer(); if (transportType === "stdio" && serverInstance instanceof McpServer) { mcpStdioServer = serverInstance; } else if (transportType === "http" && serverInstance instanceof http.Server) { actualHttpServer = serverInstance; } logger.info(`${config.mcpServerName} is now running and ready.`, startupContext); process.on("SIGTERM", () => shutdown("SIGTERM")); process.on("SIGINT", () => shutdown("SIGINT")); process.on("uncaughtException", (error) => { logger.fatal("FATAL: Uncaught exception detected.", error, startupContext); shutdown("uncaughtException"); }); process.on("unhandledRejection", (reason) => { logger.fatal("FATAL: Unhandled promise rejection detected.", reason, startupContext); shutdown("unhandledRejection"); }); } catch (error) { logger.fatal("CRITICAL ERROR DURING STARTUP.", error, startupContext); await shutdownOpenTelemetry(); // Attempt to flush any startup-related traces process.exit(1); } }; (async () => { try { await start(); } catch (error) { if (process.stdout.isTTY) { console.error("[GLOBAL CATCH] A fatal, unhandled error occurred:", error); } process.exit(1); } })(); //# sourceMappingURL=index.js.map