import { Hono } from "hono"; import { buildWwwAuthenticateHeader, type OAuthConfig } from "../auth.js"; import { type Logger } from "../logger.js"; /** * Streamable HTTP transport (MCP spec 2025-11-25 §transports). * * Shape: * POST /mcp — JSON-RPC request/response, delegated to the SDK transport * which enforces the dual-Accept header, Content-Type, and * `MCP-Protocol-Version`. * GET /mcp — 405 (V1 is stateless with no server-initiated notifications). * DELETE /mcp — 405 (V1 is stateless; `Mcp-Session-Id` is never issued). * GET /health — Fly.io health probe. * GET /.well-known/oauth-protected-resource — RFC 9728 PRM stub (required * by spec §Authorization for spec-conformant clients to discover how * to authenticate). * * Per-request server: every POST builds a fresh `McpServer` bound to that * request's bearer. This is the standard stateless pattern — it isolates * per-key auth state and avoids cross-bearer leakage. It is NOT a performance * mistake. If profiling ever shows `McpServer` construction is a hot spot, the * fix is to hoist tool registration to module scope (tool definitions are * static) and only rebuild the per-request auth/client binding — **do not** * share a mutable server across requests with different bearers. Not a v1 * optimization. */ export interface CreateHttpAppOptions { /** Optional upstream override (otherwise resolved from env). */ baseUrl?: string; /** * Allowlist for the `Origin` header (DNS rebinding protection, spec * §transports line 104). Requests without an `Origin` header pass (non- * browser clients like `curl` / `npx` don't set it). */ allowedOrigins: string[]; /** * Public base URL of the PRM document — scheme + host + `PRM_PATH`. * * NOT used verbatim: only its origin is load-bearing. The URL actually * advertised in `WWW-Authenticate` is rebuilt from that origin plus the * resource identifier's path suffix (RFC 9728 §3.1), so a trailing slash or a * stale path here cannot produce an advertised URL that this server doesn't * serve. See `resourceMetadataFor`. */ protectedResourceMetadataUrl: string; /** * OAuth 2.1 configuration. When set: * - non-`mt_live_` bearers are verified as JWTs against `jwksUrl` * - PRM advertises `issuer` in `authorization_servers` * When unset, only `mt_live_…` keys are accepted (pre-OAuth deployments). */ oauth?: OAuthConfig; /** Optional fetch override for tests. Threaded into `buildServer`. */ fetchImpl?: typeof fetch; /** Optional logger override (tests use a sink that captures lines). */ logger?: Logger; } export declare const HEALTH_PATH = "/health"; export declare const MCP_PATH = "/mcp"; export declare const PRM_PATH = "/.well-known/oauth-protected-resource"; /** Resolved identity of this resource server, derived from a single config value. */ export interface ResourceMetadata { /** RFC 8707 resource identifier — byte-identical to what the AS binds as `aud`. */ resource: string; /** Every path the PRM document is served from. */ paths: string[]; /** URL advertised in `WWW-Authenticate: … resource_metadata=…`. */ canonicalUrl: string; } /** * Resolve the resource identifier and where its metadata lives. * * `resource` is read from `oauth.audience` — the config value that already * holds this string — rather than kept as a second hand-authored copy. Two * independently-maintained spellings of it is exactly the defect this replaces: * the PRM advertised the bare origin while the server validated `aud` with a * `/mcp` path, so any client that used the advertised value as its RFC 8707 * resource indicator was rejected by the authorization server. * * NOTE the `resource == aud` equality is a fact about THIS deployment, not a * general rule — RFC 8707 §2 lets an AS map a resource indicator to a different * or abstract audience, and `aud` may be an array while `resource` is always a * single string. * * Every step is total. This runs at app construction, so a throw here becomes * `process.exit(1)` and a crash-looping deploy — an outage caused by a metadata * value, which is a much worse failure than serving a slightly odd document. */ export declare function resourceMetadataFor(options: CreateHttpAppOptions): ResourceMetadata; export declare function createHttpApp(options: CreateHttpAppOptions): Hono; /** * Default value for `protectedResourceMetadataUrl` when `MEERTRACK_MCP_PRM_URL` * is unset — derived from the public host. This is the *base*: the URL actually * advertised on 401s is `resourceMetadataFor().canonicalUrl`, which appends the * resource identifier's path suffix per RFC 9728 §3.1. Only the origin of this * value survives that rebuild. */ export declare function defaultProtectedResourceMetadataUrl(host: string, protocol?: "http" | "https"): string; export { buildWwwAuthenticateHeader }; //# sourceMappingURL=http.d.ts.map