import express from "express";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { createMcpServer } from "./server.js";
import { randomUUID } from "node:crypto";
const args = process.argv.slice(2);
// Vercel sets the VERCEL environment variable to '1'
const isVercel = process.env.VERCEL === '1';
const mode = (isVercel || args.includes("http")) ? "http" : "stdio";
if (mode === "http") {
const app = express();
const transports: Record<string, StreamableHTTPServerTransport> = {};
app.use(express.json());
// Handle SSE (GET)
app.get("/mcp", async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string;
if (!sessionId || !transports[sessionId]) {
res.status(400).send("Invalid or missing session ID");
return;
}
const transport = transports[sessionId];
await transport.handleRequest(req, res);
});
// Handle Messages (POST)
app.post("/mcp", async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string;
let transport: StreamableHTTPServerTransport | undefined;
if (sessionId) {
transport = transports[sessionId];
}
if (!transport) {
// Check for initialization
const body = req.body;
// Simple check for initialize message
if (body && typeof body === 'object' && body.method === 'initialize') {
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (id) => {
if (transport) transports[id] = transport;
console.log(`Session initialized: ${id}`);
},
onsessionclosed: (id) => {
delete transports[id];
console.log(`Session closed: ${id}`);
}
});
const server = createMcpServer();
await server.connect(transport);
// Handle the request
await transport.handleRequest(req, res, body);
return;
}
}
if (!transport) {
res.status(400).json({
jsonrpc: "2.0",
error: { code: -32000, message: "Session not found. Send an 'initialize' request first." },
id: null
});
return;
}
await transport.handleRequest(req, res, req.body);
});
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`MCP Server running on http://localhost:${port}/mcp`);
console.log("Supports SSE and Streamable HTTP transports.");
});
} else {
// Stdio Mode
(async () => {
const server = createMcpServer();
const transport = new StdioServerTransport();
await server.connect(transport);
// console.log is intercepted by StdioTransport, so use console.error for logs
console.error("MCP Server running on stdio");
})();
}