diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index c0d5b81..1015784 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "@next-ai-drawio/mcp-server", - "version": "0.1.10", + "version": "0.1.11", "description": "MCP server for Next AI Draw.io - AI-powered diagram generation with real-time browser preview", "type": "module", "main": "dist/index.js", diff --git a/packages/mcp-server/src/http-server.ts b/packages/mcp-server/src/http-server.ts index 95ff6b2..6721599 100644 --- a/packages/mcp-server/src/http-server.ts +++ b/packages/mcp-server/src/http-server.ts @@ -127,7 +127,12 @@ function cleanupExpiredSessions(): void { } } -setInterval(cleanupExpiredSessions, 5 * 60 * 1000) +const cleanupIntervalId = setInterval(cleanupExpiredSessions, 5 * 60 * 1000) + +export function shutdown(): void { + clearInterval(cleanupIntervalId) + stopHttpServer() +} export function getServerPort(): number { return serverPort diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 785071a..8c6f576 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -39,6 +39,7 @@ import { getState, requestSync, setState, + shutdown, startHttpServer, waitForSync, } from "./http-server.js" @@ -618,6 +619,31 @@ server.registerTool( }, ) +// Graceful shutdown handler +let isShuttingDown = false +function gracefulShutdown(reason: string) { + if (isShuttingDown) return + isShuttingDown = true + log.info(`Shutting down: ${reason}`) + shutdown() + process.exit(0) +} + +// Handle stdin close (primary method - works on all platforms including Windows) +process.stdin.on("close", () => gracefulShutdown("stdin closed")) +process.stdin.on("end", () => gracefulShutdown("stdin ended")) + +// Handle signals (may not work reliably on Windows) +process.on("SIGINT", () => gracefulShutdown("SIGINT")) +process.on("SIGTERM", () => gracefulShutdown("SIGTERM")) + +// Handle broken pipe (writing to closed stdout) +process.stdout.on("error", (err) => { + if (err.code === "EPIPE" || err.code === "ERR_STREAM_DESTROYED") { + gracefulShutdown("stdout error") + } +}) + // Start the MCP server async function main() { log.info("Starting MCP server for Next AI Draw.io (embedded mode)...")