import { AuthInfo, JSONRPCMessage, McpHandlerRequestOptions, MessageExtraInfo, RequestId, Transport, WebStandardStreamableHTTPServerTransportOptions } from "@modelcontextprotocol/server";
import { IncomingMessage, ServerResponse } from "node:http";

//#region src/middleware/hostHeaderValidation.d.ts

/**
 * Node.js request guard for DNS rebinding protection.
 * Validates the `Host` header hostname (port-agnostic) against an allowed list.
 *
 * Unlike the framework adapters, plain `node:http` has no middleware chain, so
 * the guard returns whether the request may proceed: when it returns `false`
 * it has already answered the request with a `403` JSON-RPC error and the
 * caller must not handle it further.
 *
 * @param allowedHostnames - List of allowed hostnames (without ports).
 *   For IPv6, provide the address with brackets (e.g., `[::1]`).
 *
 * @example
 * ```ts
 * const validateHost = hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']);
 * http.createServer((req, res) => {
 *     if (!validateHost(req, res)) return;
 *     void transport.handleRequest(req, res);
 * });
 * ```
 */
declare function hostHeaderValidation(allowedHostnames: string[]): (req: IncomingMessage, res: ServerResponse) => boolean;
/**
 * Convenience guard for localhost DNS rebinding protection.
 * Allows only `localhost`, `127.0.0.1`, and `[::1]` (IPv6 localhost) hostnames.
 */
declare function localhostHostValidation(): (req: IncomingMessage, res: ServerResponse) => boolean;
//#endregion
//#region src/middleware/originValidation.d.ts
/**
 * Node.js request guard for Origin header validation.
 * Validates the `Origin` header hostname (port-agnostic) against an allowed list.
 *
 * Requests without an `Origin` header pass (non-browser MCP clients do not send
 * one); a present value that is not allowed, or that cannot be parsed, is
 * rejected with `403`. The guard returns whether the request may proceed: when
 * it returns `false` it has already answered the request and the caller must
 * not handle it further.
 *
 * @param allowedOriginHostnames - List of allowed origin hostnames (without scheme or port).
 *   For IPv6, provide the address with brackets (e.g., `[::1]`).
 *
 * @example
 * ```ts
 * const validateOrigin = originValidation(['localhost', '127.0.0.1', '[::1]']);
 * http.createServer((req, res) => {
 *     if (!validateOrigin(req, res)) return;
 *     void transport.handleRequest(req, res);
 * });
 * ```
 */
declare function originValidation(allowedOriginHostnames: string[]): (req: IncomingMessage, res: ServerResponse) => boolean;
/**
 * Convenience guard for localhost Origin validation.
 * Allows only origins whose hostname is `localhost`, `127.0.0.1`, or `[::1]` (IPv6 localhost).
 */
declare function localhostOriginValidation(): (req: IncomingMessage, res: ServerResponse) => boolean;
//#endregion
//#region src/streamableHttp.d.ts
/**
 * Configuration options for {@linkcode NodeStreamableHTTPServerTransport}
 *
 * This is an alias for {@linkcode WebStandardStreamableHTTPServerTransportOptions} for backward compatibility.
 */
type StreamableHTTPServerTransportOptions = WebStandardStreamableHTTPServerTransportOptions;
/**
 * Server transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
 * It supports both SSE streaming and direct HTTP responses.
 *
 * This is a wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides Node.js HTTP compatibility.
 * It uses the `@hono/node-server` library to convert between Node.js HTTP and Web Standard APIs.
 *
 * In stateful mode:
 * - Session ID is generated and included in response headers
 * - Session ID is always included in initialization responses
 * - Requests with invalid session IDs are rejected with `404 Not Found`
 * - Non-initialization requests without a session ID are rejected with `400 Bad Request`
 * - State is maintained in-memory (connections, message history)
 *
 * In stateless mode:
 * - No Session ID is included in any responses
 * - No session validation is performed
 *
 * @example Stateful setup
 * ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateful"
 * const server = new McpServer({ name: 'my-server', version: '1.0.0' });
 *
 * const transport = new NodeStreamableHTTPServerTransport({
 *     sessionIdGenerator: () => randomUUID()
 * });
 *
 * await server.connect(transport);
 * ```
 *
 * @example Stateless setup
 * ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateless"
 * const transport = new NodeStreamableHTTPServerTransport({
 *     sessionIdGenerator: undefined
 * });
 * ```
 *
 * @example Using with a pre-parsed request body (e.g. Express)
 * ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_express"
 * app.post('/mcp', (req, res) => {
 *     transport.handleRequest(req, res, req.body);
 * });
 * ```
 */
declare class NodeStreamableHTTPServerTransport implements Transport {
  private _webStandardTransport;
  private _requestListener;
  private _requestContext;
  constructor(options?: StreamableHTTPServerTransportOptions);
  /**
   * Gets the session ID for this transport instance.
   */
  get sessionId(): string | undefined;
  /**
   * Sets callback for when the transport is closed.
   */
  set onclose(handler: (() => void) | undefined);
  get onclose(): (() => void) | undefined;
  /**
   * Sets callback for transport errors.
   */
  set onerror(handler: ((error: Error) => void) | undefined);
  get onerror(): ((error: Error) => void) | undefined;
  /**
   * Sets callback for incoming messages.
   */
  set onmessage(handler: ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined);
  get onmessage(): ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined;
  /**
   * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op
   * for the Streamable HTTP transport as connections are managed per-request.
   */
  start(): Promise<void>;
  /**
   * Closes the transport and all active connections.
   */
  close(): Promise<void>;
  /**
   * Sends a JSON-RPC message through the transport.
   */
  send(message: JSONRPCMessage, options?: {
    relatedRequestId?: RequestId;
  }): Promise<void>;
  /**
   * Forwards the supported protocol versions to the wrapped Web Standard
   * transport for `MCP-Protocol-Version` header validation. Called by the
   * protocol layer during connect; without this delegation a server's
   * `supportedProtocolVersions` option never reached the Node adapter's
   * header validation.
   */
  setSupportedProtocolVersions(versions: string[]): void;
  /**
   * Handles an incoming HTTP request, whether `GET` or `POST`.
   *
   * This method converts Node.js HTTP objects to Web Standard Request/Response
   * and delegates to the underlying {@linkcode WebStandardStreamableHTTPServerTransport}.
   *
   * @param req - Node.js `IncomingMessage`, optionally with `auth` property from middleware
   * @param res - Node.js `ServerResponse`
   * @param parsedBody - Optional pre-parsed body from body-parser middleware
   */
  handleRequest(req: IncomingMessage & {
    auth?: AuthInfo;
  }, res: ServerResponse, parsedBody?: unknown): Promise<void>;
  /**
   * Close an SSE stream for a specific request, triggering client reconnection.
   * Use this to implement polling behavior during long-running operations -
   * client will reconnect after the retry interval specified in the priming event.
   */
  closeSSEStream(requestId: RequestId): void;
  /**
   * Close the standalone GET SSE stream, triggering client reconnection.
   * Use this to implement polling behavior for server-initiated notifications.
   */
  closeStandaloneSSEStream(): void;
}
//#endregion
//#region src/toNodeHandler.d.ts
/**
 * Minimal duck-typed shape of a Node.js `IncomingMessage` accepted by
 * {@linkcode toNodeHandler}. Kept structural so the adapter stays free of
 * `node:` imports.
 */
interface NodeIncomingMessageLike extends AsyncIterable<unknown> {
  method?: string;
  url?: string;
  headers: Record<string, string | string[] | undefined>;
  /** Validated authentication info attached by upstream middleware (pass-through). */
  auth?: AuthInfo;
}
/** Minimal duck-typed shape of a Node.js `ServerResponse` accepted by {@linkcode toNodeHandler}. */
interface NodeServerResponseLike {
  writeHead(statusCode: number, headers?: Record<string, string>): unknown;
  write(chunk: string | Uint8Array): unknown;
  end(chunk?: string | Uint8Array): unknown;
  on(event: string, listener: (...args: unknown[]) => void): unknown;
  destroyed?: boolean;
}
/**
 * The web-standard fetch face of an `McpHttpHandler` (or any
 * fetch-shaped MCP handler) — the only surface {@linkcode toNodeHandler}
 * touches. Accepting the face structurally keeps the adapter usable with
 * hand-wired compositions that route over `isLegacyRequest` and produce a
 * `Response` directly.
 */
interface FetchLikeMcpHandler {
  fetch: (request: Request, options?: McpHandlerRequestOptions) => Promise<Response>;
}
/**
 * A Node.js `(req, res, parsedBody?)` request handler produced by
 * {@linkcode toNodeHandler}. The third argument is an optional pre-parsed body
 * (`req.body` from `express.json()`); a function third argument (Express's
 * `next` when the handler is mounted as middleware) is ignored.
 */
type NodeMcpRequestHandler = (req: NodeIncomingMessageLike, res: NodeServerResponseLike, parsedBody?: unknown) => Promise<void>;
/** Options for {@linkcode toNodeHandler}. */
interface ToNodeHandlerOptions {
  /**
   * Called when the adapter answers `500` because request conversion or
   * `handler.fetch` itself threw (e.g. a closed handler). Restores the
   * observability the removed `.node` face had via the entry's own
   * `onerror` — entry-internal failures are still reported through
   * `handler.fetch` and surface via the entry's `onerror` option as before.
   */
  onerror?: (error: Error) => void;
}
/**
 * Adapts a web-standard MCP handler (`handler.fetch`) to a Node.js
 * `(req, res, parsedBody?)` request handler. The returned function converts the
 * Node request to a web-standard `Request`, calls `handler.fetch`, then writes
 * the `Response` back to `res` (honoring write backpressure for streamed SSE
 * responses).
 *
 * `req.auth` is forwarded as the handler's pass-through `authInfo`. A function
 * third argument (Express's `next`) is ignored, never treated as a body.
 *
 * Pass `{ onerror }` to observe the adapter-level error fallback (request
 * conversion / `handler.fetch` throw) before the `500` response is written.
 */
declare function toNodeHandler(handler: FetchLikeMcpHandler, opts?: ToNodeHandlerOptions): NodeMcpRequestHandler;
/** Options for {@linkcode toWebRequest}. */
interface ToWebRequestOptions {
  /** An `AbortSignal` to attach to the constructed `Request` (`request.signal`). */
  signal?: AbortSignal;
}
/**
 * Convert a Node.js `IncomingMessage` (duck-typed — an Express `req` works) to
 * the web-standard `Request` that `handler.fetch()` and `isLegacyRequest()`
 * take. This is the conversion {@linkcode toNodeHandler} performs internally,
 * exported for hand-wired compositions:
 *
 * ```ts
 * const probe = await toWebRequest(req, req.body);
 * await ((await isLegacyRequest(probe)) ? legacy(req, res) : modern(req, res, req.body));
 * ```
 *
 * With no `parsedBody` the Node stream is read to completion — read the body
 * from the returned `Request` afterwards, not from `req`. When a body parser
 * already consumed the stream (`express.json()`), pass the parsed value as
 * `parsedBody` and nothing is read from `req`.
 */
declare function toWebRequest(req: NodeIncomingMessageLike, parsedBody?: unknown, options?: ToWebRequestOptions): Promise<Request>;
//#endregion
export { type FetchLikeMcpHandler, type NodeIncomingMessageLike, type NodeMcpRequestHandler, type NodeServerResponseLike, NodeStreamableHTTPServerTransport, StreamableHTTPServerTransportOptions, type ToNodeHandlerOptions, type ToWebRequestOptions, hostHeaderValidation, localhostHostValidation, localhostOriginValidation, originValidation, toNodeHandler, toWebRequest };
//# sourceMappingURL=index.d.mts.map