import type { StoredSession } from '@frontmcp/auth'; import { z } from '@frontmcp/lazy-zod'; import { type RequestId } from '@frontmcp/protocol'; import { FlowBase, httpInputSchema, httpOutputSchema, type FlowRunOptions, type ServerResponse } from '../../common'; export declare const plan: { readonly pre: ["parseInput", "router"]; readonly execute: ["onInitialize", "onMessage", "onElicitResult", "onSseListener", "onExtApps"]; readonly post: []; readonly finalize: ["cleanup"]; }; export declare const stateSchema: import("@frontmcp/lazy-zod").ZodObject<{ token: import("@frontmcp/lazy-zod").ZodString; session: import("@frontmcp/lazy-zod").ZodObject<{ id: import("@frontmcp/lazy-zod").ZodString; payload: import("@frontmcp/lazy-zod").ZodOptional>; isPublic: import("@frontmcp/lazy-zod").ZodOptional; platformType: import("@frontmcp/lazy-zod").ZodOptional>; }, import("zod/v4/core").$strip>>; }, import("zod/v4/core").$strip>; requestType: import("@frontmcp/lazy-zod").ZodOptional>; }, import("zod/v4/core").$strip>; type StreamableHttpSession = z.infer['session']; export type StreamableHttpRequestType = NonNullable['requestType']>; export declare function resolveStreamableHttpSession(params: { rawHeader: unknown; authorizationSession?: StreamableHttpSession; createSession: () => StreamableHttpSession; }): { responded404: boolean; session?: StreamableHttpSession; createdNew: boolean; }; export declare function classifyStreamableHttpRequest(params: { method: string; body: unknown; }): { requestType: StreamableHttpRequestType; } | { error: 'Invalid Request'; }; export declare function syncStreamableHttpAuthorizationSession(authorization: { session?: StreamableHttpSession; }, session: StreamableHttpSession): void; /** * Minimal structural view of a transport that can be re-initialized in place. * Implemented by `LocalTransporter` / `TransportStreamableHttpAdapter`. */ export interface ReinitializableTransport { readonly isInitialized: boolean; resetForReinitialization(): void; reregisterServer(): void; } /** * Reset an already-initialized streamable-HTTP transport so a fresh `initialize` * handshake is accepted under the same session id (idempotent re-initialization). * * An `initialize` request on a live, initialized transport must NOT dead-end with * the MCP SDK's `-32600 "Server already initialized"` (returned with `id: null`, * trapping the client). This is the recovery path for every legitimate re-init: * explicit DELETE-then-reconnect, a dev-server restart that recreated the session * from Redis, or a client that simply retries the handshake (#474). * * - Returns `true` when the transport is ready to (re-)initialize — either it was * never initialized, or the reset cleared its initialized state. * - Returns `false` when the transport STILL reports initialized after the reset * (e.g. an incompatible MCP SDK internal layout). The caller must then surface a * clear, actionable error instead of letting the SDK emit a bare `-32600`. * * `reregisterServer()` is called because a prior DELETE → `terminateSession` → * `unregisterServer` removed the server from the notification map; re-registering * an already-registered server is a harmless overwrite for the restart/retry case. */ export declare function resetInitializedTransportForReinit(transport: ReinitializableTransport): boolean; /** * Build the clear, actionable HTTP error returned when an initialized transport * could NOT be reset for re-initialization (#474). This replaces the MCP SDK's * bare `-32600 "Server already initialized" / id: null` — which traps the client * — with a `-32000` keyed to the request's JSON-RPC id and a recovery hint. */ export declare function buildReinitFailedResponse(sessionId: string, requestId: RequestId | null): { kind: "json"; status: number; body: any[] | Record | { [x: string]: unknown; }; contentType: string; headers?: Record | undefined; cookies?: { name: string; value: string; path: string; httpOnly: boolean; domain?: string | undefined; secure?: boolean | undefined; sameSite?: "strict" | "none" | "lax" | undefined; maxAge?: number | undefined; expires?: Date | undefined; }[] | undefined; }; export interface StreamableHttpTransport { handleRequest(request: unknown, response: unknown): Promise; } export interface StreamableHttpTransportLookupService { getTransporter(type: 'streamable-http', token: string, sessionId: string): Promise; getStoredSession(type: 'streamable-http', token: string, sessionId: string): Promise; recreateTransporter(type: 'streamable-http', token: string, sessionId: string, storedSession: StoredSession, response: ServerResponse): Promise; wasSessionCreatedAsync(type: 'streamable-http', token: string, sessionId: string): Promise; } export type StreamableHttpTransportLookupResult = { kind: 'transport'; source: 'memory' | 'redis'; transport: StreamableHttpTransport; } | { kind: 'session-expired'; recreationError?: unknown; } | { kind: 'session-not-initialized'; recreationError?: unknown; }; export declare function lookupStreamableHttpTransport(params: { transportService: StreamableHttpTransportLookupService; token: string; sessionId: string; response: ServerResponse; }): Promise; declare const name: "handle:streamable-http"; declare global { interface ExtendFlows { 'handle:streamable-http': FlowRunOptions; } } export default class HandleStreamableHttpFlow extends FlowBase { name: "handle:streamable-http"; parseInput(): Promise; router(): Promise; onInitialize(): Promise; onElicitResult(): Promise; onMessage(): Promise; onSseListener(): Promise; onExtApps(): Promise; } export {}; //# sourceMappingURL=handle.streamable-http.flow.d.ts.map