{"version":3,"sources":["../src/mcp/index.ts","../src/types.ts","../src/mcp/definitions.ts","../src/errors.ts","../src/scanner/walk.ts","../src/mcp/paths.ts","../src/mcp/runtime.ts","../src/mcp/content.ts"],"sourcesContent":["export { prompt, resource, tool } from \"./definitions.js\"\n\nexport { error, HttpError, isHttpError } from \"../errors.js\"\n\nexport {\n  deriveMcpName,\n  deriveResourceUri,\n  isUriTemplate,\n  uriTemplateVariables,\n} from \"./paths.js\"\n\nexport { McpRuntime, MCP_SESSION_HEADER } from \"./runtime.js\"\nexport type { McpRuntimeOptions } from \"./runtime.js\"\n\nexport type {\n  InferInput,\n  InputSchema,\n  McpContent,\n  McpImageContent,\n  McpPrompt,\n  McpPromptDefinition,\n  McpPromptHandler,\n  McpPromptMessage,\n  McpPromptSpec,\n  McpResource,\n  McpResourceArgs,\n  McpResourceDefinition,\n  McpResourceHandler,\n  McpResourceSpec,\n  McpScan,\n  McpTextContent,\n  McpTool,\n  McpToolAnnotations,\n  McpToolArgs,\n  McpToolDefinition,\n  McpToolHandler,\n  McpToolMeta,\n  McpToolSpec,\n} from \"./types.js\"\n","import type { CloveRequest } from \"./http/request.js\"\nimport type { CloveResponse } from \"./http/response.js\"\n\n/**\n * The dependency injection context.\n *\n * This interface is intentionally empty in the framework itself. User projects\n * get it augmented by the generated `.clove/types.d.ts`, which declares one\n * property per file in `services/` and `di/`.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Ctx {}\n\n/** `ctx` as seen at runtime: the augmented interface plus arbitrary keys. */\nexport type RuntimeCtx = Ctx & Record<string, any>\n\nexport type Lifetime = \"singleton\" | \"session\" | \"request\"\n\nexport const KIND = Symbol.for(\"clovejs.kind\")\n\nexport type DefinitionKind =\n  | \"route\"\n  | \"middleware\"\n  | \"service\"\n  | \"di\"\n  | \"ws\"\n  | \"mcpTool\"\n  | \"mcpResource\"\n  | \"mcpPrompt\"\n\nexport interface Definition<K extends DefinitionKind> {\n  readonly [KIND]: K\n}\n\nexport type HttpMethod =\n  | \"GET\"\n  | \"POST\"\n  | \"PUT\"\n  | \"PATCH\"\n  | \"DELETE\"\n  | \"HEAD\"\n  | \"OPTIONS\"\n\n/** Hook registrar handed to service / di / ws factories. */\nexport interface LifecycleHooks {\n  onDestroy(fn: () => void | Promise<void>): void\n}\n\nexport type RouteHandlerFn = (\n  req: CloveRequest,\n  res: CloveResponse,\n  ctx: RuntimeCtx,\n) => unknown | Promise<unknown>\n\nexport interface RouteMeta {\n  /** Set `false` to disable the built-in JSON middleware for this route. */\n  json?: boolean\n  [key: string]: unknown\n}\n\nexport const META = Symbol.for(\"clovejs.meta\")\n\nexport interface RouteDefinition extends Definition<\"route\"> {\n  method: HttpMethod | \"ALL\"\n  handler: RouteHandlerFn\n  /** Collected metadata. Read by the scanner, written by `.meta()`. */\n  [META]: RouteMeta\n  /** Attach route metadata. Chainable; merges with any previous call. */\n  meta(meta: RouteMeta): RouteDefinition\n}\n\n/** A route as registered in the router, with its resolved path and origin. */\nexport interface Route {\n  method: HttpMethod | \"ALL\"\n  path: string\n  handler: RouteHandlerFn\n  meta: Readonly<RouteMeta>\n  /** Absolute path of the file this route came from. Used in error messages. */\n  file: string\n}\n\nexport interface MiddlewareArgs {\n  route: Route\n  handler: { execute(): Promise<unknown> }\n  req: CloveRequest\n  res: CloveResponse\n  ctx: RuntimeCtx\n}\n\nexport type MiddlewareFn = (args: MiddlewareArgs) => unknown | Promise<unknown>\n\nexport interface MiddlewareDefinition extends Definition<\"middleware\"> {\n  fn: MiddlewareFn\n}\n\n/**\n * A service factory.\n *\n * The return type is a bare `T` rather than `T | Promise<T>` on purpose: with a\n * union, `this` inside the returned object literal widens to include\n * `PromiseLike`, and calling a sibling method (`this.sign(user)`) stops\n * type-checking. Callers unwrap with `Awaited<T>` instead.\n */\nexport type ServiceFactory<T = any> = (\n  ctx: RuntimeCtx,\n  hooks: LifecycleHooks,\n) => T\n\nexport interface ServiceDefinition<T = any> extends Definition<\"service\"> {\n  factory: ServiceFactory<T>\n}\n\nexport type ValueFactory<T = any> = (ctx: RuntimeCtx, hooks: LifecycleHooks) => T\n\nexport interface DiSpec<T = any> {\n  lifetime: Lifetime\n  value: T | ValueFactory<T>\n}\n\nexport interface DiDefinition<T = any> extends Definition<\"di\"> {\n  lifetime: Lifetime\n  value: T | ValueFactory<T>\n  /** True when `value` was supplied as a factory function. */\n  isFactory: boolean\n}\n\nexport interface WsArgs {\n  onMessage(fn: (msg: string | Buffer) => void | Promise<void>): void\n  onClose(fn: () => void | Promise<void>): void\n  onDestroy(fn: () => void | Promise<void>): void\n  send(data: string | Buffer | object): void\n  close(code?: number, reason?: string): void\n  ctx: RuntimeCtx\n  req: CloveRequest\n  params: Record<string, string>\n}\n\nexport type WsHandlerFn = (args: WsArgs) => void | Promise<void>\n\nexport interface WsDefinition extends Definition<\"ws\"> {\n  handler: WsHandlerFn\n}\n\nexport type AnyDefinition =\n  | RouteDefinition\n  | MiddlewareDefinition\n  | ServiceDefinition\n  | DiDefinition\n  | WsDefinition\n  // MCP definitions are structurally identified the same way, but their shapes\n  // live in `src/mcp/` so the core never has to import the MCP SDK.\n  | Definition<\"mcpTool\">\n  | Definition<\"mcpResource\">\n  | Definition<\"mcpPrompt\">\n\nexport function isDefinition(value: unknown): value is AnyDefinition {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    KIND in (value as Record<PropertyKey, unknown>)\n  )\n}\n\nexport function definitionKind(value: unknown): DefinitionKind | null {\n  return isDefinition(value) ? value[KIND] : null\n}\n","import { KIND, META } from \"../types.js\"\nimport type {\n  InputSchema,\n  McpPromptDefinition,\n  McpPromptSpec,\n  McpResourceDefinition,\n  McpResourceSpec,\n  McpToolDefinition,\n  McpToolMeta,\n  McpToolSpec,\n} from \"./types.js\"\n\n/**\n * Declares an MCP tool — an action a model can invoke.\n *\n * The tool name comes from the filename (`mcp/tools/searchNotes.ts` becomes\n * `searchNotes`) unless `name` overrides it.\n *\n * ```ts\n * export default tool({\n *   description: \"Full-text search across the user's notes\",\n *   input: z.object({ query: z.string() }),\n *   async handler({ query }, ctx) {\n *     return ctx.notes.search(query)\n *   },\n * })\n * ```\n */\nexport function tool<S extends InputSchema | undefined = undefined, Result = unknown>(\n  spec: McpToolSpec<S, Result>,\n): McpToolDefinition {\n  const def: McpToolDefinition = {\n    [KIND]: \"mcpTool\",\n    [META]: {},\n    name: spec.name ?? null,\n    description: spec.description,\n    title: spec.title ?? null,\n    input: (spec.input ?? null) as InputSchema | null,\n    handler: spec.handler as McpToolDefinition[\"handler\"],\n    meta(meta: McpToolMeta) {\n      Object.assign(def[META], meta)\n      return def\n    },\n  }\n  return def\n}\n\n/**\n * Declares an MCP resource — data a client can read by URI.\n *\n * The URI comes from the file path: the first directory segment becomes the\n * scheme and the rest becomes the path, with `[param]` segments turning into\n * `{param}` template variables. `mcp/resources/notes/[id].ts` serves\n * `notes://{id}`. Pass `uri` to set it explicitly.\n */\nexport function resource<Result = unknown>(\n  spec: McpResourceSpec<Result>,\n): McpResourceDefinition {\n  return {\n    [KIND]: \"mcpResource\",\n    uri: spec.uri ?? null,\n    name: spec.name ?? null,\n    description: spec.description,\n    title: spec.title ?? null,\n    mimeType: spec.mimeType ?? null,\n    handler: spec.handler as McpResourceDefinition[\"handler\"],\n  }\n}\n\n/**\n * Declares an MCP prompt — a reusable, parameterised message template that a\n * user picks explicitly (unlike tools, which the model chooses).\n *\n * The name comes from the filename unless `name` overrides it. A handler may\n * return a string, a message object, or an array of messages.\n */\nexport function prompt<S extends InputSchema | undefined = undefined, Result = unknown>(\n  spec: McpPromptSpec<S, Result>,\n): McpPromptDefinition {\n  return {\n    [KIND]: \"mcpPrompt\",\n    name: spec.name ?? null,\n    description: spec.description,\n    title: spec.title ?? null,\n    input: (spec.input ?? null) as InputSchema | null,\n    handler: spec.handler as McpPromptDefinition[\"handler\"],\n  }\n}\n","/**\n * Brands HTTP errors so they are recognised across module copies.\n *\n * `instanceof` is not enough: a project can end up with more than one copy of\n * the framework loaded (ESM alongside CJS, or a hoisting miss), and an error\n * thrown by one copy must still be rendered by the other.\n */\nexport const HTTP_ERROR = Symbol.for(\"clovejs.HttpError\")\n\n/**\n * An HTTP error that the pipeline renders into a response instead of a 500.\n * Anything else thrown from a handler is treated as an unexpected failure.\n */\nexport class HttpError extends Error {\n  readonly status: number\n  readonly body: unknown\n  readonly expose = true;\n  readonly [HTTP_ERROR] = true\n\n  constructor(status: number, body?: unknown) {\n    const message =\n      typeof body === \"object\" && body !== null && \"message\" in body\n        ? String((body as { message: unknown }).message)\n        : typeof body === \"string\"\n          ? body\n          : `HTTP ${status}`\n    super(message)\n    this.name = \"HttpError\"\n    this.status = status\n    this.body = body === undefined ? { message } : body\n  }\n}\n\n/**\n * Creates an HTTP error to throw from a handler, middleware or service.\n *\n * ```ts\n * throw error(400, { message: \"username and password are required\" })\n * ```\n */\nexport function error(status: number, body?: unknown): HttpError {\n  return new HttpError(status, body)\n}\n\nexport function isHttpError(value: unknown): value is HttpError {\n  return (\n    value instanceof HttpError ||\n    (typeof value === \"object\" &&\n      value !== null &&\n      (value as Record<PropertyKey, unknown>)[HTTP_ERROR] === true)\n  )\n}\n\n/**\n * A failure detected while scanning and validating the project, before the\n * server starts. These always name the offending file so the user can act.\n */\nexport class CloveBootError extends Error {\n  readonly files: string[]\n\n  constructor(message: string, files: string[] = []) {\n    super(files.length ? `${message}\\n${files.map((f) => `  - ${f}`).join(\"\\n\")}` : message)\n    this.name = \"CloveBootError\"\n    this.files = files\n  }\n}\n","import { readdir } from \"node:fs/promises\"\nimport { join, relative, sep } from \"node:path\"\n\nexport const SOURCE_EXTENSIONS = [\".ts\", \".mts\", \".cts\", \".js\", \".mjs\", \".cjs\"]\n\nconst IGNORED_DIRS = new Set([\"node_modules\", \".git\", \".clove\", \"dist\", \"build\"])\n\n/** A source file found under one of the convention directories. */\nexport interface WalkedFile {\n  /** Absolute path on disk. */\n  absolute: string\n  /** Path relative to the scanned root, with forward slashes. */\n  relative: string\n}\n\n/**\n * Recursively collects source files under `root`. Returns an empty array when\n * the directory does not exist, since every convention directory is optional.\n */\nexport async function walkDir(root: string): Promise<WalkedFile[]> {\n  const out: WalkedFile[] = []\n\n  async function visit(dir: string): Promise<void> {\n    let entries\n    try {\n      entries = await readdir(dir, { withFileTypes: true })\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n      throw err\n    }\n    for (const entry of entries) {\n      if (entry.name.startsWith(\".\")) continue\n      const full = join(dir, entry.name)\n      if (entry.isDirectory()) {\n        if (IGNORED_DIRS.has(entry.name)) continue\n        await visit(full)\n      } else if (entry.isFile() && isSourceFile(entry.name)) {\n        out.push({ absolute: full, relative: relative(root, full).split(sep).join(\"/\") })\n      }\n    }\n  }\n\n  await visit(root)\n  return out.sort((a, b) => a.relative.localeCompare(b.relative))\n}\n\nexport function isSourceFile(name: string): boolean {\n  if (name.endsWith(\".d.ts\")) return false\n  if (/\\.(test|spec)\\.[cm]?[jt]s$/.test(name)) return false\n  return SOURCE_EXTENSIONS.some((ext) => name.endsWith(ext))\n}\n\n/** Strips a recognised source extension from a path. */\nexport function stripExtension(path: string): string {\n  for (const ext of SOURCE_EXTENSIONS) {\n    if (path.endsWith(ext)) return path.slice(0, -ext.length)\n  }\n  return path\n}\n","import { stripExtension } from \"../scanner/walk.js\"\n\n/**\n * Derives an MCP tool or prompt name from a file path relative to its\n * directory.\n *\n * Nested files flatten with camelCase, matching how `services/` and `di/`\n * derive their `ctx` keys — one rule for the whole framework:\n *\n * ```\n * searchNotes.ts        -> searchNotes\n * notes/search.ts       -> notesSearch\n * notes/index.ts        -> notes\n * ```\n */\nexport function deriveMcpName(relativePath: string): string {\n  const segments = stripExtension(relativePath).split(\"/\").filter(Boolean)\n  if (segments[segments.length - 1] === \"index\" && segments.length > 1) segments.pop()\n  return segments\n    .map((s, i) => (i === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1)))\n    .join(\"\")\n}\n\n/**\n * Derives a resource URI from a file path relative to `mcp/resources/`.\n *\n * The first segment becomes the URI scheme and the rest becomes the path;\n * `[param]` segments become `{param}` template variables:\n *\n * ```\n * notes/[id].ts         -> notes://{id}\n * config/app.ts         -> config://app\n * files/[...path].ts    -> files://{path}\n * db/users/[id]/tags.ts -> db://users/{id}/tags\n * config.ts             -> config://\n * ```\n */\nexport function deriveResourceUri(relativePath: string): string {\n  const segments = stripExtension(relativePath).split(\"/\").filter(Boolean)\n  if (segments[segments.length - 1] === \"index\" && segments.length > 1) segments.pop()\n\n  const [scheme, ...rest] = segments\n  if (!scheme) return \"\"\n  return `${templateSegment(scheme)}://${rest.map(templateSegment).join(\"/\")}`\n}\n\n/** Turns `[id]` into `{id}` and leaves literal segments alone. */\nfunction templateSegment(segment: string): string {\n  const match = /^\\[\\.{0,3}(.+)\\]$/.exec(segment)\n  return match ? `{${match[1]}}` : segment\n}\n\n/** The `{param}` variable names a URI template declares, in order. */\nexport function uriTemplateVariables(uri: string): string[] {\n  return [...uri.matchAll(/\\{([^}]+)\\}/g)].map((m) => m[1]!)\n}\n\n/** True when the URI carries at least one `{param}` variable. */\nexport function isUriTemplate(uri: string): boolean {\n  return uri.includes(\"{\")\n}\n","import { randomUUID } from \"node:crypto\"\nimport type { IncomingMessage, ServerResponse } from \"node:http\"\nimport type { Container } from \"../container/container.js\"\nimport type { Logger } from \"../container/logger.js\"\nimport { CloveBootError } from \"../errors.js\"\nimport type { SessionManager } from \"../session/index.js\"\nimport { errorText, isRecoverable, toPromptMessages, toResourceContents, toToolContent } from \"./content.js\"\nimport { isUriTemplate } from \"./paths.js\"\nimport type { McpScan, McpToolArgs } from \"./types.js\"\n\nexport const MCP_SESSION_HEADER = \"mcp-session-id\"\n\nexport interface McpRuntimeOptions {\n  scan: McpScan\n  root: Container\n  logger: Logger\n  sessions: SessionManager\n  /** Path the Streamable HTTP transport is served from. Defaults to `/mcp`. */\n  path?: string\n  /** Reported to clients during initialization. */\n  serverInfo?: { name: string; version: string }\n  /** Include the underlying message when a handler fails unexpectedly. */\n  exposeErrors?: boolean\n}\n\n/** The slice of the MCP SDK this runtime uses, resolved lazily. */\ninterface Sdk {\n  McpServer: any\n  ResourceTemplate: any\n  StreamableHTTPServerTransport: any\n  StdioServerTransport: any\n}\n\ninterface Live {\n  server: any\n  transport: any\n  /** Parent container for calls on this connection: session- or root-scoped. */\n  parent: Container\n  /** Set when `parent` is a session container that needs persisting. */\n  sessionId: string | null\n  /** Resolves once `parent` holds the session container for this connection. */\n  ready: Promise<void>\n}\n\n/**\n * Serves the project's `mcp/` directory as a Model Context Protocol server.\n *\n * The protocol itself is handled by `@modelcontextprotocol/sdk`; this class\n * owns the CloveJS half — scoping each connection to a session container,\n * each call to a request container, and mapping handler results and errors\n * onto MCP's wire shapes.\n */\nexport class McpRuntime {\n  readonly path: string\n  #options: McpRuntimeOptions & { exposeErrors: boolean }\n  #sdk: Sdk | null = null\n  #live = new Map<string, Live>()\n  /** The single connection used by stdio, which has no session ids. */\n  #standalone: Live | null = null\n\n  constructor(options: McpRuntimeOptions) {\n    this.#options = { exposeErrors: false, ...options }\n    this.path = options.path ?? \"/mcp\"\n  }\n\n  get empty(): boolean {\n    const { tools, resources, prompts } = this.#options.scan\n    return tools.length === 0 && resources.length === 0 && prompts.length === 0\n  }\n\n  get counts(): { tools: number; resources: number; prompts: number } {\n    const { tools, resources, prompts } = this.#options.scan\n    return { tools: tools.length, resources: resources.length, prompts: prompts.length }\n  }\n\n  /**\n   * Handles one MCP HTTP request. Returns false when the path does not match,\n   * so the caller can fall through to routes.\n   */\n  async handle(req: IncomingMessage, res: ServerResponse, body: unknown): Promise<boolean> {\n    if (this.empty) return false\n    const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`)\n    if (url.pathname !== this.path) return false\n\n    const sdk = await this.#load()\n    const existingId = headerValue(req, MCP_SESSION_HEADER)\n\n    if (existingId) {\n      const live = this.#live.get(existingId)\n      if (!live) {\n        writeJsonRpcError(res, 404, -32001, \"Unknown or expired MCP session\")\n        return true\n      }\n      await live.ready\n      await live.transport.handleRequest(req, res, body)\n      await this.#persist(live)\n      return true\n    }\n\n    if (req.method !== \"POST\") {\n      // GET opens the server-to-client stream and DELETE ends a session; both\n      // need a session that initialization already created.\n      writeJsonRpcError(res, 400, -32000, \"Missing Mcp-Session-Id header\")\n      return true\n    }\n\n    // No session id and a POST: this is an initialize request. The transport\n    // mints the id, and we attach a session container once it does.\n    const transport = new sdk.StreamableHTTPServerTransport({\n      sessionIdGenerator: () => randomUUID(),\n      onsessioninitialized: (sessionId: string) => {\n        // Registered synchronously, before any await: the client may send its\n        // first call the moment it has the id, and a lookup that missed here\n        // would 404 a session that is perfectly valid. `ready` is what makes\n        // the container available, and every path awaits it.\n        this.#live.set(sessionId, live)\n        this.#options.logger.debug(`MCP session opened: ${sessionId}`)\n\n        live.ready = (async () => {\n          if (!this.#options.sessions.needed) return\n          const { container } = await this.#options.sessions.acquireById(sessionId)\n          live.parent = container\n          live.sessionId = sessionId\n        })()\n        return live.ready\n      },\n      onsessionclosed: (sessionId: string) => {\n        void this.#closeSession(sessionId)\n      },\n    })\n\n    const live: Live = {\n      server: this.#buildServer(sdk, () => live.parent),\n      transport,\n      parent: this.#options.root,\n      sessionId: null,\n      ready: Promise.resolve(),\n    }\n\n    transport.onclose = () => {\n      const id = transport.sessionId\n      if (id) void this.#closeSession(id)\n    }\n\n    await live.server.connect(transport)\n    await transport.handleRequest(req, res, body)\n    await live.ready\n    await this.#persist(live)\n    return true\n  }\n\n  /**\n   * Serves the project over stdio, for clients that launch the server as a\n   * subprocess. Resolves when the client disconnects.\n   */\n  async serveStdio(): Promise<void> {\n    const sdk = await this.#load()\n    const transport = new sdk.StdioServerTransport()\n    const live: Live = {\n      server: this.#buildServer(sdk, () => this.#options.root),\n      transport,\n      parent: this.#options.root,\n      sessionId: null,\n      ready: Promise.resolve(),\n    }\n    this.#standalone = live\n    await live.server.connect(transport)\n    await new Promise<void>((resolve) => {\n      transport.onclose = () => resolve()\n    })\n  }\n\n  /** Builds an MCP server with every scanned tool, resource and prompt bound. */\n  #buildServer(sdk: Sdk, parent: () => Container): any {\n    const { scan, serverInfo } = this.#options\n    const server = new sdk.McpServer(\n      serverInfo ?? { name: \"clovejs\", version: \"0.1.1\" },\n      { capabilities: { logging: {} } },\n    )\n\n    for (const tool of scan.tools) {\n      const shape = tool.shape\n      const run = (input: unknown, extra: unknown) =>\n        this.#call(parent(), tool.file, extra, async (ctx, args) => ({\n          content: toToolContent(await tool.handler(input ?? {}, ctx, args)),\n        }), true)\n\n      server.registerTool(\n        tool.name,\n        {\n          description: tool.description,\n          ...(tool.title ? { title: tool.title } : {}),\n          ...(shape ? { inputSchema: shape } : {}),\n          ...annotationsOf(tool.meta),\n        },\n        // A tool without an input schema takes no arguments, so the SDK calls\n        // back with `(extra)` alone rather than `(input, extra)`.\n        shape\n          ? (input: unknown, extra: unknown) => run(input, extra)\n          : (extra: unknown) => run({}, extra),\n      )\n    }\n\n    for (const res of scan.resources) {\n      const target = isUriTemplate(res.uri)\n        ? new sdk.ResourceTemplate(res.uri, { list: undefined })\n        : res.uri\n\n      server.registerResource(\n        res.name,\n        target,\n        {\n          description: res.description,\n          ...(res.title ? { title: res.title } : {}),\n          ...(res.mimeType ? { mimeType: res.mimeType } : {}),\n        },\n        async (uri: URL, a: unknown, b?: unknown) => {\n          // Template reads pass (uri, variables, extra); static reads pass\n          // (uri, extra) — the variables argument simply is not there.\n          const variables = (isUriTemplate(res.uri) ? a : {}) as Record<string, unknown>\n          const extra = isUriTemplate(res.uri) ? b : a\n          return this.#call(parent(), res.file, extra, async (ctx, args) => ({\n            contents: toResourceContents(\n              await res.handler(stringParams(variables), ctx, { ...args, uri: uri.href }),\n              uri.href,\n              res.mimeType,\n            ),\n          }))\n        },\n      )\n    }\n\n    for (const p of scan.prompts) {\n      const shape = p.shape\n      const run = (input: unknown, extra: unknown) =>\n        this.#call(parent(), p.file, extra, async (ctx, args) => ({\n          messages: toPromptMessages(await p.handler(input ?? {}, ctx, args)),\n        }))\n\n      server.registerPrompt(\n        p.name,\n        {\n          description: p.description,\n          ...(p.title ? { title: p.title } : {}),\n          ...(shape ? { argsSchema: shape } : {}),\n        },\n        // As with tools, an argument-less prompt is called with `(extra)` only.\n        shape\n          ? (input: unknown, extra: unknown) => run(input, extra)\n          : (extra: unknown) => run({}, extra),\n      )\n    }\n\n    return server\n  }\n\n  /**\n   * Runs one handler in a fresh request-scoped container.\n   *\n   * A client error (4xx) is the model's problem — bad arguments, a missing\n   * record — so its message is passed through verbatim for the model to act\n   * on. Anything else is ours: it is logged in full and reported as a generic\n   * failure, so internal detail does not reach the client. That mirrors what\n   * the HTTP pipeline does with a 500, `exposeErrors` and all.\n   *\n   * Only tools can carry a failure in their result. Resources and prompts have\n   * no such field in the protocol, so for those the error is rethrown and the\n   * SDK turns it into a JSON-RPC error.\n   */\n  async #call<T>(\n    parent: Container,\n    file: string,\n    extra: any,\n    run: (ctx: any, args: McpToolArgs) => Promise<T>,\n    soft = false,\n  ): Promise<T | { content: Array<{ type: \"text\"; text: string }>; isError: true }> {\n    const container = parent.createChild(\"request\")\n    const args: McpToolArgs = {\n      ctx: container.ctx,\n      sessionId: typeof extra?.sessionId === \"string\" ? extra.sessionId : null,\n      signal: extra?.signal ?? new AbortController().signal,\n      log: (level, message) => {\n        void extra?.sendNotification?.({\n          method: \"notifications/message\",\n          params: { level, data: message },\n        })\n      },\n    }\n\n    try {\n      return await run(container.ctx, args)\n    } catch (err) {\n      const message = isRecoverable(err)\n        ? errorText(err)\n        : this.#reportInternal(err, file)\n      if (soft) return { content: [{ type: \"text\", text: message }], isError: true }\n      // Rethrown rather than propagated so the client sees `message` — which\n      // is redacted for anything that is not a 4xx — while the original stays\n      // attached for a server-side reader.\n      throw new Error(message, { cause: err })\n    } finally {\n      await container\n        .dispose()\n        .catch((err) => this.#options.logger.error(\"Error disposing MCP request scope:\", err))\n    }\n  }\n\n  /** Logs an unexpected failure and returns the message the client may see. */\n  #reportInternal(err: unknown, file: string): string {\n    this.#options.logger.error(`MCP handler failed (${file}):`, err)\n    return this.#options.exposeErrors && err instanceof Error\n      ? `Internal error: ${err.message}`\n      : \"Internal error\"\n  }\n\n  async #persist(live: Live): Promise<void> {\n    if (!live.sessionId) return\n    await this.#options.sessions\n      .persist(live.sessionId, live.parent)\n      .catch((err) => this.#options.logger.error(\"Failed to persist MCP session:\", err))\n  }\n\n  async #closeSession(sessionId: string): Promise<void> {\n    const live = this.#live.get(sessionId)\n    if (!live) return\n    this.#live.delete(sessionId)\n    this.#options.logger.debug(`MCP session closed: ${sessionId}`)\n    await live.server.close().catch(() => undefined)\n    if (live.sessionId) {\n      await this.#options.sessions.destroy(live.sessionId).catch(() => undefined)\n    }\n  }\n\n  /** Closes every open connection. */\n  async close(): Promise<void> {\n    const ids = [...this.#live.keys()]\n    await Promise.all(ids.map((id) => this.#closeSession(id)))\n    if (this.#standalone) {\n      await this.#standalone.server.close().catch(() => undefined)\n      this.#standalone = null\n    }\n  }\n\n  /**\n   * Imports the MCP SDK on first use.\n   *\n   * It is an optional peer dependency: a project with no `mcp/` directory\n   * never loads it, and never has to install it.\n   */\n  async #load(): Promise<Sdk> {\n    if (this.#sdk) return this.#sdk\n    try {\n      const [mcp, http, stdio] = await Promise.all([\n        import(\"@modelcontextprotocol/sdk/server/mcp.js\"),\n        import(\"@modelcontextprotocol/sdk/server/streamableHttp.js\"),\n        import(\"@modelcontextprotocol/sdk/server/stdio.js\"),\n      ])\n      this.#sdk = {\n        McpServer: mcp.McpServer,\n        ResourceTemplate: mcp.ResourceTemplate,\n        StreamableHTTPServerTransport: http.StreamableHTTPServerTransport,\n        StdioServerTransport: stdio.StdioServerTransport,\n      }\n      return this.#sdk\n    } catch (err) {\n      throw new CloveBootError(\n        `This project has an mcp/ directory, which needs the MCP SDK and zod:\\n\\n` +\n          `  npm install @modelcontextprotocol/sdk zod\\n\\n` +\n          `They are optional peer dependencies, so projects without MCP tools ` +\n          `do not carry them.\\n\\nUnderlying error: ${(err as Error).message}`,\n      )\n    }\n  }\n}\n\nfunction annotationsOf(meta: Readonly<Record<string, unknown>>): {\n  annotations?: Record<string, boolean>\n} {\n  const annotations: Record<string, boolean> = {}\n  if (typeof meta.readOnly === \"boolean\") annotations.readOnlyHint = meta.readOnly\n  if (typeof meta.destructive === \"boolean\") annotations.destructiveHint = meta.destructive\n  if (typeof meta.idempotent === \"boolean\") annotations.idempotentHint = meta.idempotent\n  if (typeof meta.openWorld === \"boolean\") annotations.openWorldHint = meta.openWorld\n  return Object.keys(annotations).length ? { annotations } : {}\n}\n\n/** URI template variables arrive as string or string[]; handlers want strings. */\nfunction stringParams(variables: Record<string, unknown>): Record<string, string> {\n  const out: Record<string, string> = {}\n  for (const [key, value] of Object.entries(variables ?? {})) {\n    out[key] = Array.isArray(value) ? value.join(\"/\") : String(value)\n  }\n  return out\n}\n\nfunction headerValue(req: IncomingMessage, name: string): string | undefined {\n  const raw = req.headers[name]\n  return Array.isArray(raw) ? raw[0] : raw\n}\n\nfunction writeJsonRpcError(\n  res: ServerResponse,\n  status: number,\n  code: number,\n  message: string,\n): void {\n  res.writeHead(status, { \"content-type\": \"application/json\" })\n  res.end(JSON.stringify({ jsonrpc: \"2.0\", error: { code, message }, id: null }))\n}\n","import { isHttpError } from \"../errors.js\"\nimport type { McpContent, McpPromptMessage } from \"./types.js\"\n\n/**\n * Normalises whatever a tool handler returned into MCP content blocks.\n *\n * The rules mirror the JSON middleware for HTTP routes: return a value and it\n * is serialised for you, or return content blocks when you need control.\n */\nexport function toToolContent(result: unknown): McpContent[] {\n  if (result === undefined || result === null) return []\n  if (typeof result === \"string\") return [{ type: \"text\", text: result }]\n\n  if (isContentBlock(result)) return [result]\n  if (Array.isArray(result) && result.length > 0 && result.every(isContentBlock)) {\n    return result\n  }\n\n  return [{ type: \"text\", text: stringify(result) }]\n}\n\n/**\n * Normalises a resource handler's return value into resource contents.\n *\n * Binary payloads (`Buffer`, `Uint8Array`, `ArrayBuffer`) become base64 blobs;\n * everything else becomes text, with objects serialised as JSON.\n */\nexport function toResourceContents(\n  result: unknown,\n  uri: string,\n  declaredMimeType: string | null,\n): Array<{ uri: string; mimeType?: string; text?: string; blob?: string }> {\n  if (result === undefined || result === null) return []\n\n  const binary = asBinary(result)\n  if (binary) {\n    return [\n      {\n        uri,\n        mimeType: declaredMimeType ?? \"application/octet-stream\",\n        blob: binary.toString(\"base64\"),\n      },\n    ]\n  }\n\n  if (typeof result === \"string\") {\n    return [{ uri, ...(declaredMimeType ? { mimeType: declaredMimeType } : {}), text: result }]\n  }\n\n  // An explicit `{ contents: [...] }` passes through untouched.\n  if (\n    typeof result === \"object\" &&\n    Array.isArray((result as { contents?: unknown }).contents)\n  ) {\n    return (result as { contents: Array<Record<string, unknown>> }).contents.map(\n      (entry) => ({ uri, ...entry }) as { uri: string },\n    )\n  }\n\n  return [\n    {\n      uri,\n      mimeType: declaredMimeType ?? \"application/json\",\n      text: stringify(result),\n    },\n  ]\n}\n\n/** Normalises a prompt handler's return value into MCP prompt messages. */\nexport function toPromptMessages(\n  result: unknown,\n): Array<{ role: \"user\" | \"assistant\"; content: McpContent }> {\n  if (result === undefined || result === null) return []\n\n  if (typeof result === \"string\") {\n    return [{ role: \"user\", content: { type: \"text\", text: result } }]\n  }\n\n  const list: unknown[] = Array.isArray(result) ? result : [result]\n  const messages: Array<{ role: \"user\" | \"assistant\"; content: McpContent }> = []\n\n  for (const entry of list) {\n    if (typeof entry === \"string\") {\n      messages.push({ role: \"user\", content: { type: \"text\", text: entry } })\n      continue\n    }\n    if (!isPromptMessage(entry)) {\n      messages.push({ role: \"user\", content: { type: \"text\", text: stringify(entry) } })\n      continue\n    }\n    // A message may carry several content blocks; MCP transports one block per\n    // message, so a multi-block message fans out into several.\n    for (const content of toToolContent(entry.content)) {\n      messages.push({ role: entry.role, content })\n    }\n  }\n  return messages\n}\n\n/**\n * Splits a thrown value into a result the model can read and recover from,\n * versus a protocol-level failure the client should surface as an error.\n *\n * Client errors (4xx) are the model's problem — bad arguments, a missing\n * record — so they come back as a normal tool result flagged `isError`, which\n * lets the model correct itself. Server errors are ours, and become JSON-RPC\n * errors instead.\n */\nexport function isRecoverable(err: unknown): boolean {\n  return isHttpError(err) && err.status >= 400 && err.status < 500\n}\n\n/** The message shown to the model for a recoverable error. */\nexport function errorText(err: unknown): string {\n  if (isHttpError(err)) {\n    const body = err.body\n    if (typeof body === \"string\") return body\n    if (body && typeof body === \"object\" && \"message\" in body) {\n      return String((body as { message: unknown }).message)\n    }\n    return err.message\n  }\n  return err instanceof Error ? err.message : String(err)\n}\n\nfunction isContentBlock(value: unknown): value is McpContent {\n  if (typeof value !== \"object\" || value === null) return false\n  const type = (value as { type?: unknown }).type\n  return (\n    (type === \"text\" && typeof (value as { text?: unknown }).text === \"string\") ||\n    (type === \"image\" && typeof (value as { data?: unknown }).data === \"string\")\n  )\n}\n\nfunction isPromptMessage(value: unknown): value is McpPromptMessage {\n  if (typeof value !== \"object\" || value === null) return false\n  const role = (value as { role?: unknown }).role\n  return (role === \"user\" || role === \"assistant\") && \"content\" in value\n}\n\nfunction asBinary(value: unknown): Buffer | null {\n  if (Buffer.isBuffer(value)) return value\n  if (value instanceof Uint8Array) return Buffer.from(value)\n  if (value instanceof ArrayBuffer) return Buffer.from(value)\n  return null\n}\n\nfunction stringify(value: unknown): string {\n  try {\n    return JSON.stringify(value, null, 2) ?? String(value)\n  } catch {\n    return String(value)\n  }\n}\n"],"mappings":"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","names":["live","tool"]}