UNPKG

@launchdarkly/mcp-server

Version:

The local [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for [LaunchDarkly](https://launchdarkly.com/) federal and European Union (EU) environments.

151 lines • 5.7 kB
"use strict"; /* * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.main = main; const sse_js_1 = require("@modelcontextprotocol/sdk/server/sse.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const hostHeaderValidation_js_1 = require("@modelcontextprotocol/sdk/server/middleware/hostHeaderValidation.js"); const express_1 = __importDefault(require("express")); const console_logger_js_1 = require("../../console-logger.js"); const server_js_1 = require("../../server.js"); const sse_security_js_1 = require("./sse-security.js"); const tls_blocklist_js_1 = require("./tls-blocklist.js"); async function main(flags) { // INC-289: block the compromised eMudhra intermediates before any request. (0, tls_blocklist_js_1.installTlsBlocklist)(); const runtimeWarning = (0, tls_blocklist_js_1.unpatchedRuntimeWarning)(); if (runtimeWarning) { process.stderr.write(runtimeWarning); } flags.env?.forEach(([key, value]) => { process.env[key] = value; }); switch (flags.transport) { case "stdio": await startStdio(flags); break; case "sse": await startSSE(flags); break; default: throw new Error(`Invalid transport: ${flags.transport}`); } } async function startStdio(flags) { const logger = (0, console_logger_js_1.createConsoleLogger)(flags["log-level"]); const transport = new stdio_js_1.StdioServerTransport(); const server = (0, server_js_1.createMCPServer)({ logger, allowedTools: flags.tool, scopes: flags.scope, ...{ apiKey: flags["api-key"] ?? "" }, serverURL: flags["server-url"], serverIdx: flags["server-index"], }); await server.connect(transport); const abort = async () => { await server.close(); process.exit(0); }; process.on("SIGTERM", abort); process.on("SIGINT", abort); } async function startSSE(flags) { const logger = (0, console_logger_js_1.createConsoleLogger)(flags["log-level"]); const host = flags.host; const authToken = flags["auth-token"]; (0, sse_security_js_1.assertSafeSSEBind)(host, authToken); const app = (0, express_1.default)(); if ((0, sse_security_js_1.isLoopbackHost)(host)) { app.use((0, hostHeaderValidation_js_1.localhostHostValidation)()); } if (authToken) { app.use((0, sse_security_js_1.requireBearerToken)(authToken)); } const sessions = new Map(); const controller = new AbortController(); app.get("/sse", async (_req, res) => { const server = (0, server_js_1.createMCPServer)({ logger, allowedTools: flags.tool, scopes: flags.scope, ...{ apiKey: flags["api-key"] ?? "" }, serverURL: flags["server-url"], serverIdx: flags["server-index"], }); const transport = new sse_js_1.SSEServerTransport("/message", res); sessions.set(transport.sessionId, { transport, server }); res.on("close", () => { sessions.delete(transport.sessionId); void server.close(); }); try { await server.connect(transport); } catch (err) { logger.error("Failed to open SSE session", { error: err instanceof Error ? err.message : String(err), }); sessions.delete(transport.sessionId); void server.close(); if (!res.headersSent) { res.status(500).send("Internal Server Error"); } } }); app.post("/message", async (req, res) => { const sessionId = typeof req.query["sessionId"] === "string" ? req.query["sessionId"] : ""; const session = sessions.get(sessionId); if (!session) { res.status(404).send("Unknown session"); return; } try { await session.transport.handlePostMessage(req, res); } catch (err) { logger.error("Failed to handle SSE message", { error: err instanceof Error ? err.message : String(err), }); if (!res.headersSent) { res.status(500).send("Internal Server Error"); } } }); const httpServer = app.listen(flags.port, host, () => { const ha = httpServer.address(); const host = typeof ha === "string" ? ha : `${ha?.address}:${ha?.port}`; logger.info("MCP HTTP server started", { host }); }); let closing = false; controller.signal.addEventListener("abort", async () => { if (closing) { logger.info("Received second signal. Forcing shutdown."); process.exit(1); } closing = true; logger.info("Shutting down MCP servers"); await Promise.all([...sessions.values()].map(({ server }) => server.close())); logger.info("Shutting down HTTP server"); const timer = setTimeout(() => { logger.info("Forcing shutdown"); process.exit(1); }, 5000); httpServer.close(() => { clearTimeout(timer); logger.info("Graceful shutdown complete"); process.exit(0); }); }); const abort = () => controller.abort(); process.on("SIGTERM", abort); process.on("SIGINT", abort); } //# sourceMappingURL=impl.js.map