1// Streamable HTTP MCP, authless. Localhost only in a checkout; on the2// hosted box (MOSAIC_PUBLIC=1) any host is served.3import { createMcpHandler } from "@modelcontextprotocol/server";4import { define } from "../utils.ts";5import { createServer, requestScope } from "../lib/mcp.ts";67function isLocal(req: Request): boolean {8 if (Deno.env.get("MOSAIC_PUBLIC") === "1") return true;9 const host = req.headers.get("Host")?.split(":")[0];10 return host === "localhost" || host === "127.0.0.1" || host === "[::1]";11}1213const mcp = createMcpHandler(() => createServer(), {14 legacy: "stateless",15 responseMode: "json",16 onerror(error: Error) {17 console.error(18 JSON.stringify({ message: "MCP request failed", error: error.message }),19 );20 },21});2223function serve(req: Request): Promise<Response> | Response {24 if (!isLocal(req)) {25 return Response.json({ error: "Invalid Host header." }, { status: 403 });26 }27 // the bearer token (join) travels to the tool handlers through a28 // request scope: the SDK's stateless mode gives handlers no request29 return requestScope.run(30 { authorization: req.headers.get("authorization") },31 () => mcp.fetch(req),32 );33}3435export const handler = define.handlers({36 GET: (ctx) => serve(ctx.req),37 POST: (ctx) => serve(ctx.req),38 DELETE: (ctx) => serve(ctx.req),39});