/** * Entry point for the Competitor Research MCP server. * * Supports two transport modes: * - Streamable HTTP (default): `npm run serve` * - stdio: `npm run serve -- --stdio` * * @module main */ import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import cors from "cors"; import type { Request, Response } from "express"; import { createServer } from "./server.js"; /** * Start the MCP server with Streamable HTTP transport (stateless mode). * * Each incoming request gets a fresh McpServer instance, matching the * pattern used by other ext-apps examples. */ export async function startStreamableHTTPServer( factory: () => McpServer, ): Promise { const port = parseInt(process.env.PORT ?? "3001", 10); const app = createMcpExpressApp({ host: "0.0.0.0" }); app.use(cors()); app.all("/mcp", async (req: Request, res: Response) => { const server = factory(); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, }); res.on("close", () => { transport.close().catch(() => {}); server.close().catch(() => {}); }); try { await server.connect(transport); await transport.handleRequest(req, res, req.body); } catch (error) { console.error("[main] MCP error:", error); if (!res.headersSent) { res.status(500).json({ jsonrpc: "2.0", error: { code: -32603, message: "Internal server error" }, id: null, }); } } }); const httpServer = app.listen(port, (err) => { if (err) { console.error("Failed to start server:", err); process.exit(1); } console.log(`🔍 Competitor Research MCP server listening on http://localhost:${port}/mcp`); }); const shutdown = () => { console.log("\nShutting down..."); httpServer.close(() => process.exit(0)); }; process.on("SIGINT", shutdown); process.on("SIGTERM", shutdown); } /** * Start the MCP server with stdio transport. */ export async function startStdioServer( factory: () => McpServer, ): Promise { await factory().connect(new StdioServerTransport()); } async function main() { if (process.argv.includes("--stdio")) { await startStdioServer(createServer); } else { await startStreamableHTTPServer(createServer); } } main().catch((e) => { console.error(e); process.exit(1); });