Skip to main content
Glama
http-server.ts5.32 kB
#!/usr/bin/env node import { Request, Response } from "express"; import { randomUUID } from "node:crypto"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; import { isInitializeRequest, } from "@modelcontextprotocol/sdk/types.js"; import { registerTools } from "./server-tools.js"; import { loadConfig } from "./config.js"; /** * MCP Server with Streamable HTTP transport */ // Create MCP server instance using high-level API const getServer = () => { const server = new McpServer({ name: "error-tracker-mcp", version: "1.0.0", }); // Register all tools registerTools(server); return server; }; /** * Start HTTP server */ async function main() { const config = loadConfig(); const PORT = config.server.httpPort; const app = createMcpExpressApp(); // Store transports by session ID const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {}; // MCP POST endpoint app.post("/mcp", async (req: Request, res: Response) => { const sessionId = req.headers["mcp-session-id"] as string | undefined; if (sessionId) { console.error(`Received MCP request for session: ${sessionId}`); } try { let transport: StreamableHTTPServerTransport; if (sessionId && transports[sessionId]) { // Reuse existing transport for this session transport = transports[sessionId]; } else if (!sessionId && isInitializeRequest(req.body)) { // New initialization request - create new transport transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (sessionId) => { console.error(`New session initialized: ${sessionId}`); transports[sessionId] = transport; }, onsessionclosed: (sessionId) => { console.error(`Session closed: ${sessionId}`); delete transports[sessionId]; }, }); // Set up cleanup on transport close transport.onclose = () => { const sid = transport.sessionId; if (sid && transports[sid]) { console.error(`Transport closed for session ${sid}, cleaning up`); delete transports[sid]; } }; // Connect server to transport const server = getServer(); await server.connect(transport); } else { res.status(400).json({ jsonrpc: "2.0", error: { code: -32600, message: "Invalid request: missing session ID or not an initialize request", }, id: null, }); return; } // Handle the request with the transport await transport.handleRequest(req, res, req.body); } catch (error) { console.error("Error handling MCP request:", error); if (!res.headersSent) { res.status(500).json({ jsonrpc: "2.0", error: { code: -32603, message: "Internal server error", }, id: null, }); } } }); // Handle GET requests for SSE streams app.get("/mcp", async (req: Request, res: Response) => { const sessionId = req.headers["mcp-session-id"] as string | undefined; if (!sessionId || !transports[sessionId]) { res.status(400).send("Invalid or missing session ID"); return; } console.error(`Establishing SSE stream for session ${sessionId}`); const transport = transports[sessionId]; await transport.handleRequest(req, res); }); // Handle DELETE requests for session termination app.delete("/mcp", async (req: Request, res: Response) => { const sessionId = req.headers["mcp-session-id"] as string | undefined; if (!sessionId || !transports[sessionId]) { res.status(400).send("Invalid or missing session ID"); return; } console.error(`Received session termination request for session ${sessionId}`); try { const transport = transports[sessionId]; await transport.handleRequest(req, res); } catch (error) { console.error("Error handling session termination:", error); if (!res.headersSent) { res.status(500).send("Error processing session termination"); } } }); // Start the server app.listen(PORT, () => { console.error(`Error Tracker MCP HTTP Server listening on port ${PORT}`); console.error(`Server URL: http://localhost:${PORT}/mcp`); }); // Handle server shutdown process.on("SIGINT", async () => { console.error("Shutting down server..."); // Close all active transports for (const sessionId in transports) { try { console.error(`Closing transport for session ${sessionId}`); await transports[sessionId].close(); delete transports[sessionId]; } catch (error) { console.error(`Error closing transport for session ${sessionId}:`, error); } } console.error("Server shutdown complete"); process.exit(0); }); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wycCome/mcp-error-tracing'

If you have feedback or need assistance with the MCP directory API, please join our Discord server