Skip to main content
Glama
mcp-server.ts4.91 kB
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { setupMCPServer } from "../../src/mcp-server-setup"; import express, { Request, Response } from "express"; import serverless from "serverless-http"; // Create Express app const app = express(); // Ensure body is parsed so we can pass it to the MCP transport under serverless-http app.use( express.json({ type: ["application/json", "application/*+json"], limit: "2mb", }) ); // MCP endpoint app.post("/mcp", async (req: Request, res: Response) => { // In stateless mode, create a new instance of transport and server for each request // to ensure complete isolation. A single instance would cause request ID collisions // when multiple clients connect concurrently. console.log("Received POST MCP request"); try { const server = setupMCPServer(); const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, }); await server.connect(transport); await transport.handleRequest(req as any, res as any, req.body); res.on("close", () => { console.log("Request closed"); transport.close(); server.close(); }); } 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, }); } } }); // OAuth-like authorize endpoint for clients (e.g., Goose) // This fakes a successful auth by redirecting back to the provided redirect_uri // with a mock code and preserved state. app.get("/authorize", async (req: Request, res: Response) => { try { const redirectUriRaw = (req.query?.redirect_uri ?? "") as string; const state = (req.query?.state ?? "") as string; if (!redirectUriRaw) { res.status(400).send("Missing redirect_uri"); return; } const mockCode = `mock_${Math.random().toString(36).slice(2, 10)}`; const url = new URL(redirectUriRaw); url.searchParams.set("code", mockCode); if (state) url.searchParams.set("state", state); res.redirect(302, url.toString()); } catch (err) { console.error("/authorize error:", err); res.status(500) .type("html") .send( "<html><body><h1>Authorization Error</h1><p>There was a problem handling the request. You can close this window.</p></body></html>" ); } }); app.get("/mcp", (_req: Request, res: Response) => { // For the stateless server, GET requests are used to initialize // SSE connections which are stateful. Therefore, we don't need // to handle GET requests but we can signal to the client this error. console.log("Received GET MCP request"); res.status(405).json({ jsonrpc: "2.0", error: { code: -32000, message: "Method not allowed.", }, id: null, }); }); app.delete("/mcp", (_req: Request, res: Response) => { console.log("Received DELETE MCP request"); res.status(405).json({ jsonrpc: "2.0", error: { code: -32000, message: "DELETE not supported. Use POST for all requests.", }, }); }); // Dev routes app.get("/", async (_req: Request, res: Response) => { const { getDevIndex } = await import("../../src/dev-routes.js"); res.type("html").send(getDevIndex()); }); app.get("/dev", async (_req: Request, res: Response) => { const { getDevIndex } = await import("../../src/dev-routes.js"); res.type("html").send(getDevIndex()); }); app.get("/dev/restaurants", async (req: Request, res: Response) => { const { handleDevRestaurants } = await import("../../src/dev-routes.js"); await handleDevRestaurants(req, res); }); app.get("/dev/restaurant/:id", async (req: Request, res: Response) => { const { handleDevRestaurant } = await import("../../src/dev-routes.js"); await handleDevRestaurant(req, res); }); app.get("/dev/menu/:id", async (req: Request, res: Response) => { const { handleDevMenu } = await import("../../src/dev-routes.js"); await handleDevMenu(req, res); }); app.get("/dev/order/:id", async (req: Request, res: Response) => { const { handleDevOrder } = await import("../../src/dev-routes.js"); await handleDevOrder(req, res); }); app.get("/dev/receipt/:id", async (req: Request, res: Response) => { const { handleDevReceipt } = await import("../../src/dev-routes.js"); await handleDevReceipt(req, res); }); export const handler = serverless(app);

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/aharvard/mcp_agentic-commerce'

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