338 lines · 14.1 KB
import { env, waitUntil } from "cloudflare:workers";
import { HttpError } from "../errors";
import { limitMcpRequest } from "./audit";
import { recordToolUsage } from "./usage";
import { authenticate, agentIdentity, unauthorizedResponse } from "./caller";
import type { Authenticated } from "./caller";
import { dispatch, finishResult, initializeResult, negotiateLegacyVersion } from "./dispatch";
import { sessionHub } from "./hub-do";
import type { SessionInfo } from "./hub-session";
import { sseFrame } from "./hub-session";
import { openListenStream } from "./listen";
import {
  isObject,
  META,
  toJsonText,
  MODERN_VERSION,
  notification,
  RPC,
  rpcError,
  RpcError,
  rpcResult,
  SUPPORTED_VERSIONS,
} from "./protocol";
import type { JsonObject, JsonRpcId, JsonRpcMessage, McpCaller } from "./protocol";

const MAX_BODY_BYTES = 4 * 1024 * 1024;
const HTTP_OK = 200;
const HTTP_BAD_REQUEST = 400;
const HTTP_TOO_LARGE = 413;
const SESSION_HEADER = "mcp-session-id";
const NAMED_METHODS: Record<string, string> = { "tools/call": "name", "prompts/get": "name", "resources/read": "uri" };
const encoder = new TextEncoder();

function jsonResponse(message: JsonRpcMessage, status = 200, headers: Record<string, string> = {}): Response {
  return Response.json(message, { status, headers: { "cache-control": "no-store", ...headers } });
}

function errorResponse(
  id: JsonRpcId | null,
  error: RpcError,