import express from "express";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { HotAPI } from "./HotAPI";
import { ServerAuthorizationFunction } from "./HotRouteMethod";
import { HotLog } from "./HotLog";
/**
 * A tool definition for the MCP server.
 */
interface MCPToolDefinition {
    /**
     * The tool name.
     */
    name: string;
    /**
     * The tool description.
     */
    description: string;
    /**
     * The JSON Schema for the tool's input parameters.
     */
    inputSchema: {
        type: "object";
        properties: {
            [name: string]: any;
        };
        required?: string[];
    };
    /**
     * The HTTP method type for making the internal call.
     */
    httpMethod: string;
    /**
     * The internal URL path to call.
     */
    urlPath: string;
    /**
     * The route name (key in api.routes).
     */
    routeName: string;
    /**
     * The method name on the route.
     */
    methodName: string;
}
/**
 * Exposes a HotAPI as an MCP (Model Context Protocol) server using the
 * Streamable HTTP transport in stateless mode.
 *
 * This class walks all routes and methods on a HotAPI instance and registers
 * them as MCP tools. When a tool is called via MCP, it makes an internal
 * in-process call through the full HotStaq request pipeline and returns
 * the result.
 *
 * Each POST to the MCP route is self-contained: a fresh Server + transport
 * are created per request, authorization runs once, and cleanup fires when
 * the response closes. There is no long-lived session state — which means
 * no "Session not found" 404s when a reverse proxy reaps an idle SSE
 * stream.
 */
export declare class HotMCPServer {
    /**
     * The API instance to expose as MCP tools.
     */
    api: HotAPI;
    /**
     * The route prefix for the MCP endpoints.
     * @default "/mcp"
     */
    route: string;
    /**
     * The associated logger.
     */
    logger: HotLog;
    /**
     * The registered tool definitions.
     */
    tools: MCPToolDefinition[];
    /**
     * Executes when authorizing an incoming MCP request. The value returned
     * from here is stored as the connection's authorizedValue and passed
     * into tool call ServerRequests via bearerToken. Returning undefined
     * means authorization failed and the request will be rejected with 401.
     * If any exceptions are thrown, the request will be rejected with 401
     * and the exception message in the body.
     *
     * The bearer token from the request (Authorization header or `?token=`
     * query param) is passed via request.bearerToken.
     *
     * Set to null to skip authorization (default).
     *
     * Note on semantics change from pre-0.8.141: under the SSE transport
     * this ran once per long-lived connection. Under the Streamable HTTP
     * transport it runs once per tool-call request.
     */
    onServerAuthorize: ServerAuthorizationFunction;
    /**
     * Executes after a successful MCP request is authorized.
     *
     * Note on semantics change from pre-0.8.141: under the SSE transport
     * this ran once per long-lived connection. Under the Streamable HTTP
     * transport it runs once per tool-call request. The sessionId argument
     * is always a freshly-generated UUID for request tracing; it does not
     * persist across requests.
     */
    onSuccessfulConnection: ((sessionId: string, authorizedValue: any) => Promise<void>);
    /**
     * Executes right when a client connects before onServerAuthorize is called.
     * If this returns false, the request will be rejected with 403 Forbidden.
     * Use onServerAuthorize for authorization logic, not here.
     */
    onConnection: ((req: express.Request) => Promise<boolean>);
    /**
     * Executes after a request fails authorization.
     */
    onConnectionError: ((req: express.Request, errorMessage: string) => Promise<void>);
    constructor(api: HotAPI, route?: string);
    /**
     * Build MCP tool definitions from the API's routes and methods.
     */
    protected buildToolDefinitions(): void;
    /**
     * Create a fresh MCP Server instance with handlers registered for this
     * request. The authorizedValue (from onServerAuthorize or the raw bearer
     * token) and the raw connection-level bearer token are captured in closure
     * so tool calls can flow them through as connection-level auth.
     *
     * Both values are threaded because onServerAuthorize commonly returns a
     * non-string (e.g. a user object). When it does, the original bearer would
     * otherwise be unavailable to downstream tool-call route handlers and
     * write-tools would fail with "jwt must be provided".
     */
    protected createServerInstance(authorizedValue: any, connectionBearerToken?: string): Server;
    /**
     * Register the MCP request handlers for tools/list and tools/call on
     * the given Server instance. authorizedValue is the result of
     * onServerAuthorize (or the raw bearer if no callback is set). The
     * connectionBearerToken parameter is the raw Bearer string extracted from
     * the original HTTP request — used as a fallback bearer for tool calls
     * when a per-call _meta.authorization isn't supplied AND the
     * authorizedValue isn't a string.
     */
    protected registerHandlers(instance: Server, authorizedValue: any, connectionBearerToken?: string): void;
    /**
     * Execute a tool call by calling processRequest directly, going through
     * the full HotStaq sanitization pipeline (validation, authorization,
     * pre/post execute hooks, etc).
     *
     * Bearer-token resolution order (first non-empty wins):
     *   1. Per-call: `request.params._meta.authorization` from the MCP client.
     *   2. Connection-level raw Bearer captured before `onServerAuthorize` ran.
     *   3. Legacy fallback: `authorizedValue` if it happens to be a string.
     *
     * Step 2 is the fix for HS-1: when `onServerAuthorize` returns a non-string
     * (e.g. a user object) the legacy fallback in step 3 doesn't fire, and
     * before this change the route handler saw no JWT — every admin-only write
     * tool failed with "jwt must be provided" even though the connection-level
     * Bearer authenticated fine.
     */
    protected executeToolCall(tool: MCPToolDefinition, args: any, mcpRequest?: any, authorizedValue?: any, connectionBearerToken?: string): Promise<CallToolResult>;
    /**
     * Handle an incoming MCP POST request via the Streamable HTTP transport.
     *
     * Each request is fully self-contained: connection gate → bearer-token
     * extraction → onServerAuthorize → fresh Server + transport → tool call
     * → response → cleanup. No state persists between requests, so there's
     * no session map to invalidate and no long-lived connection to reap.
     */
    protected handleMCPRequest(req: express.Request, res: express.Response): Promise<void>;
    /**
     * Attach the MCP endpoints to an Express application.
     *
     * The server speaks the Streamable HTTP transport on a single POST
     * route. GET and DELETE on the same route return 405 Method Not
     * Allowed so misbehaving clients see a clear failure instead of a
     * quiet hang.
     */
    attach(app: express.Express): Promise<void>;
}
export {};
//# sourceMappingURL=HotMCPServer.d.ts.map