| | |
| | |
| | |
| |
|
| | import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; |
| | import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
| | import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; |
| | import cors from "cors"; |
| | import type { Request, Response } from "express"; |
| |
|
| | export interface ServerOptions { |
| | port: number; |
| | name?: string; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | export async function startServer( |
| | createServer: () => McpServer, |
| | options: ServerOptions, |
| | ): Promise<void> { |
| | const { port, name = "MCP Server" } = options; |
| |
|
| | const app = createMcpExpressApp({ host: "0.0.0.0" }); |
| | app.use(cors()); |
| |
|
| | app.all("/mcp", async (req: Request, res: Response) => { |
| | const server = createServer(); |
| | 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("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, () => { |
| | console.log(`${name} 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); |
| | } |
| |
|