import {
  createMcpServer
} from "./chunk-HRFQAFPR.js";
import "./chunk-CAY57CKF.js";
import {
  getConfig,
  runWithConfig
} from "./chunk-KOO5733S.js";

// src/http-server.ts
import express from "express";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { randomUUID, createHash } from "crypto";
var oauthTokens = /* @__PURE__ */ new Map();
function extractBearerToken(req) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith("Bearer ")) return null;
  const token = authHeader.slice(7) || null;
  if (!token) return null;
  const oauthEntry = oauthTokens.get(token);
  if (oauthEntry) {
    if (Date.now() < oauthEntry.expiresAt) {
      return oauthEntry.apiKey;
    }
    oauthTokens.delete(token);
    return null;
  }
  return token;
}
function generateAccessToken() {
  return createHash("sha256").update(randomUUID()).digest("hex");
}
async function handleWithSessionConfig(apiKey, fn) {
  const baseConfig = getConfig();
  return runWithConfig({ ...baseConfig, apiKey }, fn);
}
async function startHttpServer({
  port
}) {
  const app = express();
  app.set("trust proxy", true);
  app.use(express.json());
  app.use((_req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header(
      "Access-Control-Allow-Methods",
      "GET, POST, DELETE, OPTIONS"
    );
    res.header(
      "Access-Control-Allow-Headers",
      "Content-Type, Authorization, mcp-session-id, MCP-Protocol-Version"
    );
    if (_req.method === "OPTIONS") {
      res.sendStatus(200);
      return;
    }
    next();
  });
  app.get("/health", (_req, res) => {
    res.json({ status: "ok" });
  });
  app.get(
    "/.well-known/oauth-authorization-server",
    (_req, res) => {
      const baseUrl = `${_req.protocol}://${_req.get("host")}`;
      res.json({
        issuer: baseUrl,
        token_endpoint: `${baseUrl}/oauth/token`,
        token_endpoint_auth_methods_supported: ["client_secret_post"],
        grant_types_supported: ["client_credentials"],
        response_types_supported: [],
        scopes_supported: ["mcp:tools"]
      });
    }
  );
  app.post(
    "/oauth/token",
    express.urlencoded({ extended: false }),
    (req, res) => {
      const grantType = req.body.grant_type;
      if (grantType !== "client_credentials") {
        res.status(400).json({
          error: "unsupported_grant_type",
          error_description: "Only client_credentials grant type is supported"
        });
        return;
      }
      const clientSecret = req.body.client_secret;
      if (!clientSecret || typeof clientSecret !== "string") {
        res.status(400).json({
          error: "invalid_request",
          error_description: "client_secret is required (use your LangWatch API key)"
        });
        return;
      }
      const expiresIn = 3600;
      const accessToken = generateAccessToken();
      oauthTokens.set(accessToken, {
        apiKey: clientSecret,
        expiresAt: Date.now() + expiresIn * 1e3
      });
      res.json({
        access_token: accessToken,
        token_type: "Bearer",
        expires_in: expiresIn,
        scope: "mcp:tools"
      });
    }
  );
  const sessions = {};
  app.post("/mcp", async (req, res) => {
    const sessionId = req.headers["mcp-session-id"];
    if (sessionId && sessions[sessionId]) {
      const session = sessions[sessionId];
      await handleWithSessionConfig(
        session.apiKey,
        () => session.transport.handleRequest(req, res, req.body)
      );
      return;
    }
    if (!sessionId && isInitializeRequest(req.body)) {
      const apiKey = extractBearerToken(req);
      if (!apiKey) {
        res.status(401).json({
          error: "Authorization: Bearer <LANGWATCH_API_KEY> header required"
        });
        return;
      }
      const transport = new StreamableHTTPServerTransport({
        sessionIdGenerator: () => randomUUID(),
        onsessioninitialized: (id) => {
          sessions[id] = { transport, apiKey };
        }
      });
      transport.onclose = () => {
        if (transport.sessionId) {
          delete sessions[transport.sessionId];
        }
      };
      const sessionServer = createMcpServer();
      await handleWithSessionConfig(
        apiKey,
        () => sessionServer.connect(transport)
      );
      await handleWithSessionConfig(
        apiKey,
        () => transport.handleRequest(req, res, req.body)
      );
      return;
    }
    res.status(400).json({
      error: "Invalid request \u2014 no session ID or not an initialize request"
    });
  });
  app.get("/mcp", async (req, res) => {
    const sessionId = req.headers["mcp-session-id"];
    if (sessionId && sessions[sessionId]) {
      const session = sessions[sessionId];
      await handleWithSessionConfig(
        session.apiKey,
        () => session.transport.handleRequest(req, res)
      );
    } else {
      res.status(400).json({ error: "Invalid request \u2014 no valid session ID" });
    }
  });
  app.delete("/mcp", async (req, res) => {
    const sessionId = req.headers["mcp-session-id"];
    if (sessionId && sessions[sessionId]) {
      const session = sessions[sessionId];
      await session.transport.close();
      delete sessions[sessionId];
      res.status(200).json({ status: "session closed" });
    } else {
      res.status(404).json({ error: "Session not found" });
    }
  });
  const sseSessions = {};
  app.get("/sse", async (req, res) => {
    const apiKey = extractBearerToken(req) || // lgtm[js/sensitive-get-query]
    req.query["apiKey"] || null;
    if (!apiKey) {
      res.status(401).json({
        error: "Authorization: Bearer <LANGWATCH_API_KEY> header or ?apiKey= query parameter required"
      });
      return;
    }
    const transport = new SSEServerTransport("/messages", res);
    sseSessions[transport.sessionId] = { transport, apiKey };
    const sessionServer = createMcpServer();
    res.on("close", () => {
      delete sseSessions[transport.sessionId];
    });
    await handleWithSessionConfig(
      apiKey,
      () => sessionServer.connect(transport)
    );
  });
  const handleSseMessage = async (req, res) => {
    const sessionId = req.query["sessionId"];
    if (!sessionId || !sseSessions[sessionId]) {
      res.status(400).json({ error: "Invalid or missing session ID" });
      return;
    }
    const session = sseSessions[sessionId];
    await handleWithSessionConfig(
      session.apiKey,
      () => session.transport.handlePostMessage(req, res, req.body)
    );
  };
  app.post("/messages", handleSseMessage);
  app.post("/sse/messages", handleSseMessage);
  return new Promise((resolve) => {
    const server = app.listen(port, "0.0.0.0", () => {
      const addr = server.address();
      const resolvedPort = typeof addr === "object" && addr ? addr.port : port;
      resolve({ server, port: resolvedPort });
    });
  });
}
export {
  startHttpServer
};
//# sourceMappingURL=http-server-GXVEDA7G.js.map