import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import cors from "cors";
import express, { Request, Response } from "express";
import eventBus from "./common/event-bus.js";
import { SERVER_INFO, createServer, server as mcpServer } from "./server.js";
const app = express();
const PORT = process.env.PORT || 3000;
// Debug logging function
const debug = (message: string, data?: any) => {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [DEBUG] ${message}`, data ? JSON.stringify(data, null, 2) : "");
};
// Configure CORS
app.use(
cors({
origin: "*",
methods: ["GET", "POST", "OPTIONS"],
allowedHeaders: ["Content-Type"],
})
);
app.use(express.json());
// Initialize MCP server if not already initialized
if (!mcpServer) {
debug("Initializing MCP server");
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { server: _server, version } = createServer();
debug("MCP Server initialized", { version });
}
// Set up Streamable HTTP Transport for MCP
debug("Setting up Streamable HTTP Transport");
const mcpTransport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
timeout: 0, // No timeout for long-lived SSE connections
});
// Connect MCP server to transport
if (mcpServer) {
try {
debug("Attempting to connect MCP server to transport");
mcpServer.connect(mcpTransport);
debug("MCP Server successfully connected to Streamable HTTP Transport");
} catch (error) {
debug("Failed to connect MCP server to transport", { error });
}
}
// Handle server info requests
app.get("/server-info", (req, res) => {
debug("Received server info request");
res.json(SERVER_INFO);
});
// Handle MCP transport requests
app.all("/mcp", (req, res) => {
debug("Received MCP request", {
method: req.method,
path: req.path,
headers: req.headers,
body: req.body,
});
if (!mcpServer) {
debug("MCP Server not initialized, returning error");
res.status(500).json({ error: "MCP Server not initialized" });
return;
}
// Set reasonable timeouts for MCP requests
req.setTimeout(60000); // 60 seconds
res.setTimeout(60000); // 60 seconds
// Handle request
try {
debug("Handling MCP request");
mcpTransport.handleRequest(req, res, req.body);
debug("MCP request handled successfully");
} catch (error) {
debug("Error handling MCP request", { error });
res.status(500).json({ error: "Failed to handle MCP request" });
}
});
// Handle SSE requests
app.all("/sse", (req: Request, res: Response) => {
debug("Received SSE request", {
method: req.method,
path: req.path,
headers: req.headers,
body: req.body,
});
if (!mcpServer) {
debug("MCP Server not initialized, returning error");
res.status(500).json({ error: "MCP Server not initialized" });
return;
}
// No timeouts for SSE - long-lived connections
req.setTimeout(0);
res.setTimeout(0);
// Handle client disconnect for SSE
req.on("close", () => {
debug("SSE client disconnected");
});
req.on("error", (error) => {
debug("SSE request error", { error });
});
res.on("error", (error) => {
debug("SSE response error", { error });
});
// Handle request using MCP transport
try {
debug("Handling SSE request");
// Let the SDK handle all headers and response setup
mcpTransport.handleRequest(req, res, req.body);
debug("SSE request handled successfully");
} catch (error) {
debug("Error handling SSE request", { error });
if (!res.headersSent) {
res.status(500).json({ error: "Failed to handle SSE request" });
}
}
});
// Listen for all events on the event bus and broadcast to SSE clients
const broadcast = (event: string, payload: any) => {
debug("Broadcasting event", { event, payload });
const message = {
jsonrpc: "2.0",
method: event,
params: {
...payload,
timestamp: new Date().toISOString(),
},
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _data = JSON.stringify(message);
// mcpTransport.broadcast(_data); // Removed because this method does not exist
// If you want to broadcast, use eventBus.emit or another mechanism
};
// Listen for all events
eventBus.on("broadcast", ({ event, payload }: { event: string; payload: any }) => {
broadcast(event, payload);
});
// Start the server
app.listen(PORT, () => {
debug(`HTTP server started on port ${PORT}`);
});