ntfy-mcp-server
Version:
An MCP (Model Context Protocol) server designed to interact with the ntfy push notification service. It enables LLMs and AI agents to send notifications to your devices with extensive customization options.
109 lines (108 loc) • 3.94 kB
JavaScript
/**
* Ntfy MCP Server - Main Entry Point
*
* This is the main entry point for the Ntfy MCP server. It initializes the
* server, sets up signal handlers for graceful shutdown, and manages the
* application lifecycle.
*/
import { config } from "./config/index.js";
import { createMcpServer } from "./mcp-server/server.js";
import { logger } from "./utils/logger.js";
import { createRequestContext } from "./utils/requestContext.js";
// Create main application logger
const appLogger = logger.createChildLogger({
module: 'NtfyMcpServer',
service: 'NtfyMcpServer',
component: 'Main',
environment: config.environment
});
/**
* Graceful shutdown handler
* @param signal The signal that triggered the shutdown
*/
const shutdown = async (signal) => {
appLogger.info(`Shutting down due to ${signal} signal...`);
try {
if (mcpServer) {
appLogger.info('Closing MCP server...');
await mcpServer.close();
appLogger.info('MCP server closed successfully');
}
appLogger.info('Shutdown complete. Exiting process.');
process.exit(0);
}
catch (error) {
appLogger.error('Error during shutdown', {
error: error instanceof Error ? error.message : String(error),
signal
});
process.exit(1);
}
};
// Variable to hold server instance
let mcpServer;
/**
* Main startup function
*/
const start = async () => {
// Create startup context
const startupContext = createRequestContext({
operation: "ServerStartup",
appName: "ntfy-mcp-server",
environment: config.environment,
});
appLogger.info("Starting ntfy-mcp-server...", {
environment: config.environment,
logLevel: config.logLevel,
requestId: startupContext.requestId
});
try {
// Validate ntfy configuration
const ntfyConfig = config.ntfy;
if (!ntfyConfig.baseUrl) {
appLogger.warn("Ntfy base URL not configured. Using default https://ntfy.sh");
}
if (!ntfyConfig.defaultTopic) {
appLogger.warn("No default ntfy topic configured. Some functionality may be limited.");
}
// Create main MCP server
appLogger.info("Creating MCP server...");
mcpServer = await createMcpServer();
appLogger.info("MCP server created and connected successfully");
// Register signal handlers for graceful shutdown
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));
// Handle uncaught exceptions
process.on("uncaughtException", (error) => {
appLogger.error("Uncaught exception", {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
});
// Handle unhandled promise rejections
process.on("unhandledRejection", (reason) => {
appLogger.error("Unhandled promise rejection", {
reason: reason instanceof Error ? reason.message : String(reason),
stack: reason instanceof Error ? reason.stack : undefined
});
});
appLogger.info("Server startup complete. Ready to handle requests.");
}
catch (error) {
appLogger.error("Failed to start server", {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
// Exit with non-zero code to indicate error
process.exit(1);
}
};
// Start the application
start().catch((error) => {
appLogger.error("Fatal error during startup", {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
process.exit(1);
});