const require_chunk = require('./chunk-Bnu9O96Y.cjs'); const require_src = require('./src-BhnGYybN.cjs'); let _modelcontextprotocol_server__shims = require("@modelcontextprotocol/server/_shims"); let _modelcontextprotocol_core_internal = require("@modelcontextprotocol/core/internal"); //#region src/server/completable.ts const COMPLETABLE_SYMBOL = Symbol.for("mcp.completable"); /** * Wraps a schema to provide autocompletion capabilities. Useful for, e.g., prompt arguments in MCP. * * @example * ```ts source="./completable.examples.ts#completable_basicUsage" * server.registerPrompt( * 'review-code', * { * title: 'Code Review', * argsSchema: z.object({ * language: completable(z.string().describe('Programming language'), value => * ['typescript', 'javascript', 'python', 'rust', 'go'].filter(lang => lang.startsWith(value)) * ) * }) * }, * ({ language }) => ({ * messages: [ * { * role: 'user' as const, * content: { * type: 'text' as const, * text: `Review this ${language} code.` * } * } * ] * }) * ); * ``` * * @see {@linkcode server/mcp.McpServer.registerPrompt | McpServer.registerPrompt} for using completable schemas in prompt argument definitions */ function completable(schema, complete) { Object.defineProperty(schema, COMPLETABLE_SYMBOL, { value: { complete }, enumerable: false, writable: false, configurable: false }); return schema; } /** * Checks if a schema is completable (has completion metadata). */ function isCompletable(schema) { return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema; } /** * Gets the completer callback from a completable schema, if it exists. */ function getCompleter(schema) { return schema[COMPLETABLE_SYMBOL]?.complete; } //#endregion //#region src/server/sseKeepAlive.ts /** Default interval between SSE keep-alive comment frames. */ const DEFAULT_SSE_KEEP_ALIVE_MS = 15e3; const MAX_TIMER_DELAY_MS = 2 ** 31 - 1; /** Arms an unref'd timer, or disables keep-alive for invalid delays. */ function armSseKeepAlive(intervalMs, onTick) { if (!Number.isFinite(intervalMs) || intervalMs < 1) return; const timer = setInterval(onTick, Math.min(intervalMs, MAX_TIMER_DELAY_MS)); timer.unref?.(); return timer; } //#endregion //#region src/server/serverEventBus.ts /** * A `ServerEventBus` backed by an in-process listener set. * * `publish()` delivers synchronously to the live listener set (a listener * unsubscribing itself mid-dispatch is safe; the entry's listen-router * listeners never unsubscribe peers). A throwing listener does not stop * delivery to the others. */ var InMemoryServerEventBus = class { _listeners = /* @__PURE__ */ new Set(); /** * @param onerror - Optional callback for errors thrown by listeners * during dispatch. */ constructor(onerror) { this.onerror = onerror; } publish(event) { for (const listener of this._listeners) try { listener(event); } catch (error) { this.onerror?.(error instanceof Error ? error : new Error(String(error))); } } subscribe(listener) { this._listeners.add(listener); let live = true; return () => { if (!live) return; live = false; this._listeners.delete(listener); }; } /** The number of currently registered listeners (test/introspection only — the routers track capacity via their own open-subscription set). */ get listenerCount() { return this._listeners.size; } }; /** Build a {@linkcode ServerNotifier} over a bus. */ function createServerNotifier(bus) { return { toolsChanged: () => bus.publish({ kind: "tools_list_changed" }), promptsChanged: () => bus.publish({ kind: "prompts_list_changed" }), resourcesChanged: () => bus.publish({ kind: "resources_list_changed" }), resourceUpdated: (uri) => bus.publish({ kind: "resource_updated", uri }) }; } /** * Whether a `subscriptions/listen` filter accepts a given change event. * * Pure: no I/O, no mutation. The filter governs ONLY the four * subscription-gated change types — non-gated notifications never reach the * bus and are not modeled here. * * `resource_updated` matches only when `resourceSubscriptions` is present and * contains the event's URI exactly (per the spec: "for these resource URIs"). */ function listenFilterAccepts(filter, event) { switch (event.kind) { case "tools_list_changed": return filter.toolsListChanged === true; case "prompts_list_changed": return filter.promptsListChanged === true; case "resources_list_changed": return filter.resourcesListChanged === true; case "resource_updated": return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri); } } /** * The honored subset of a requested filter: keeps only the fields the client * explicitly opted in to (drops `false` and absent fields), narrowed against * the server's declared capabilities when supplied. The serving entry sends * this back in `notifications/subscriptions/acknowledged` so the ack reflects * what the server can actually deliver. * * - `toolsListChanged` is honored only when `capabilities.tools.listChanged` * is advertised; likewise `promptsListChanged` / `resourcesListChanged`. * - `resourceSubscriptions` is honored only when * `capabilities.resources.subscribe` is advertised. * * `capabilities` is optional on this pure helper for test convenience only — * both wired routers REQUIRE capabilities at the call site (the HTTP router's * `serve()` takes a required parameter; `StdioListenRouter.serve()` throws * before `setServerCapabilities()` was called), so the fail-open * `undefined → honor everything` branch is never reachable on a wired entry. */ function honoredSubset(requested, capabilities) { const honored = {}; const allow = (bit) => capabilities === void 0 || bit === true; if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true; if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true; if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true; if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions]; return honored; } /** Map a {@linkcode ServerEvent} onto its wire notification `{method, params}`. */ function serverEventToNotification(event) { switch (event.kind) { case "tools_list_changed": return { method: "notifications/tools/list_changed" }; case "prompts_list_changed": return { method: "notifications/prompts/list_changed" }; case "resources_list_changed": return { method: "notifications/resources/list_changed" }; case "resource_updated": return { method: "notifications/resources/updated", params: { uri: event.uri } }; } } //#endregion //#region src/server/listenRouter.ts /** Default capacity guard: refuse a new subscription when this many are already open. */ const DEFAULT_MAX_SUBSCRIPTIONS = 1024; function jsonRpcError(id, code, message) { return Response.json({ jsonrpc: "2.0", error: { code, message }, id }, { status: 200 }); } /** Stamp the subscription id onto a notification's `_meta`. Non-mutating. */ function stampSubscriptionId(notification, subscriptionId) { return { method: notification.method, params: { ...notification.params, _meta: { ...notification.params?._meta, [_modelcontextprotocol_core_internal.SUBSCRIPTION_ID_META_KEY]: subscriptionId } } }; } /** * Read the requested filter off a `subscriptions/listen` request body. * Returns the validated filter, or `undefined` when `params.notifications` * is absent or fails the schema (the caller answers `-32602` — the spec * marks `notifications` REQUIRED on the listen request). */ function parseListenFilter(message) { const outcome = require_src.codecForVersion(require_src.MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message); return outcome.ok ? outcome.value.params?.notifications : void 0; } function createListenRouter(options) { const { bus, onerror } = options; const maxSubscriptions = options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS; const keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS; const open = /* @__PURE__ */ new Set(); function serve(message, signal, capabilities, serverInfo) { if (open.size >= maxSubscriptions) { onerror?.(/* @__PURE__ */ new Error(`subscriptions/listen refused: subscription limit reached (${maxSubscriptions})`)); return jsonRpcError(message.id, -32603, "Subscription limit reached"); } const filter = parseListenFilter(message); if (filter === void 0) return jsonRpcError(message.id, -32602, "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"); const honored = honoredSubset(filter, capabilities); const subscriptionId = message.id; const encoder = new TextEncoder(); let controller; let closed = false; let unsubscribe; let keepAliveTimer; let abortCleanup; const writeFrame = (frame) => { if (closed) return; try { controller.enqueue(encoder.encode(frame)); } catch (error) { onerror?.(error instanceof Error ? error : new Error(String(error))); } }; const writeNotification = (method, params) => { writeFrame(`event: message\ndata: ${JSON.stringify({ jsonrpc: "2.0", method, params })}\n\n`); }; const teardown = (graceful) => { if (closed) return; if (graceful) writeFrame(`event: message\ndata: ${JSON.stringify({ jsonrpc: "2.0", id: subscriptionId, result: { resultType: "complete", _meta: { [_modelcontextprotocol_core_internal.SUBSCRIPTION_ID_META_KEY]: subscriptionId, [_modelcontextprotocol_core_internal.SERVER_INFO_META_KEY]: serverInfo } } })}\n\n`); closed = true; try { unsubscribe?.(); } catch (error) { onerror?.(error instanceof Error ? error : new Error(String(error))); } if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer); abortCleanup?.(); open.delete(teardown); try { controller.close(); } catch {} }; const readable = new ReadableStream({ start(streamController) { controller = streamController; const ack = stampSubscriptionId({ method: "notifications/subscriptions/acknowledged", params: { notifications: honored } }, subscriptionId); writeNotification(ack.method, ack.params); if (Object.keys(honored).length === 0) { teardown(true); return; } unsubscribe = bus.subscribe((event) => { if (closed || !listenFilterAccepts(honored, event)) return; const note = stampSubscriptionId(serverEventToNotification(event), subscriptionId); writeNotification(note.method, note.params); }); keepAliveTimer = armSseKeepAlive(keepAliveMs, () => writeFrame(": keepalive\n\n")); open.add(teardown); }, cancel() { teardown(false); } }); if (signal !== void 0) if (signal.aborted) teardown(false); else { const onAbort = () => teardown(false); signal.addEventListener("abort", onAbort, { once: true }); abortCleanup = () => signal.removeEventListener("abort", onAbort); } return new Response(readable, { status: 200, headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache, no-transform", Connection: "keep-alive", "X-Accel-Buffering": "no" } }); } return { serve, closeAll() { for (const teardown of open) teardown(true); }, get openCount() { return open.size; } }; } const CHANGE_NOTIFICATION_METHODS = new Set([ "notifications/tools/list_changed", "notifications/prompts/list_changed", "notifications/resources/list_changed", "notifications/resources/updated" ]); /** * Per-connection listen state for the stdio entry. One instance is held by * `serveStdio` for the connection lifetime; it routes inbound * `subscriptions/listen` / `notifications/cancelled` and rewrites outbound * change notifications onto the active subscriptions. No bus — the long-lived * pinned instance's existing `send*ListChanged()` calls feed straight into * `routeOutbound()`. */ var StdioListenRouter = class { /** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */ _subs = /* @__PURE__ */ new Map(); /** * The serving instance's declared capabilities. Filled in by the entry * once the modern instance is constructed (the router is created before * the instance exists), so the acknowledged filter is narrowed against * what the server can actually deliver. */ _serverCapabilities; /** * The serving instance's identity, stamped onto the graceful-close * results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends * `ResultMetaObject`). Handed over together with the capabilities. */ _serverInfo; constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) { this._maxSubscriptions = _maxSubscriptions; this._serverCapabilities = serverCapabilities; this._serverInfo = serverInfo; } /** * Record the serving instance's declared capabilities and identity once * it has been constructed. Called by `serveStdio`'s connect path; * subsequent `serve()` calls narrow the honored filter against the * capabilities, and `teardownAll()` stamps the identity. */ setServerCapabilities(capabilities, serverInfo) { this._serverCapabilities = capabilities; if (serverInfo !== void 0) this._serverInfo = serverInfo; } /** Whether `id` is an active listen subscription on this connection. */ has(id) { return this._subs.has(id); } /** * Serve one inbound `subscriptions/listen` request: registers the * subscription and returns the stamped acknowledged notification (or, on * capacity / params rejection, the in-band JSON-RPC error response). * * @throws when called before {@linkcode setServerCapabilities} (or the * constructor) has supplied the serving instance's capabilities. Honoring a * filter without knowing the server's advertised capabilities would fail * open (deliver unadvertised types); the entry guarantees capabilities are * set before any listen request is routed here. */ serve(message) { if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities"); if (this._subs.size >= this._maxSubscriptions) return { jsonrpc: "2.0", id: message.id, error: { code: -32603, message: "Subscription limit reached" } }; const filter = parseListenFilter(message); if (filter === void 0) return { jsonrpc: "2.0", id: message.id, error: { code: -32602, message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter" } }; const honored = honoredSubset(filter, this._serverCapabilities); this._subs.set(message.id, honored); return stampSubscriptionId({ method: "notifications/subscriptions/acknowledged", params: { notifications: honored } }, message.id); } /** * Tear down one subscription (inbound `notifications/cancelled`). Returns * `true` when a subscription was removed. After this call NOTHING further * is delivered for that subscription id (the post-cancel hardening). */ cancel(id) { return this._subs.delete(id); } /** * Route an outbound notification through the active subscriptions. * * - For a subscription-gated change notification, returns one stamped copy * per subscription that opted in to it (an empty array means it is * dropped — the modern era never delivers an un-requested change type). * - For any other outbound message, returns `'passthrough'` (the entry * forwards it as-is). */ routeOutbound(message) { if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough"; const uriParam = message.params?.["uri"]; const uri = typeof uriParam === "string" ? uriParam : void 0; const event = notificationToServerEvent(message.method, uri); const out = []; for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({ method: message.method, params: message.params ?? {} }, subscriptionId)); return out; } /** * Server-side graceful teardown of every active subscription: returns the * empty `subscriptions/listen` JSON-RPC result for each subscription id — * the spec's graceful-close signal, `_meta` carrying the subscription id * and the serving instance's identity — for the entry to emit before * closing the wire. Clears the set so nothing further is delivered. */ teardownAll() { const out = []; for (const id of this._subs.keys()) out.push({ jsonrpc: "2.0", id, result: { resultType: "complete", _meta: { [_modelcontextprotocol_core_internal.SUBSCRIPTION_ID_META_KEY]: id, ...this._serverInfo !== void 0 && { [_modelcontextprotocol_core_internal.SERVER_INFO_META_KEY]: this._serverInfo } } } }); this._subs.clear(); return out; } }; function notificationToServerEvent(method, uri) { switch (method) { case "notifications/tools/list_changed": return { kind: "tools_list_changed" }; case "notifications/prompts/list_changed": return { kind: "prompts_list_changed" }; case "notifications/resources/list_changed": return { kind: "resources_list_changed" }; default: return { kind: "resource_updated", uri: uri ?? "" }; } } //#endregion //#region src/server/middleware/bearerAuth.ts function comparableResource(value) { const text = String(value); const hash = text.indexOf("#"); return (hash === -1 ? text : text.slice(0, hash)).replace(/\/$/, ""); } function sameResource(reported, expected) { if (!reported) return false; return comparableResource(reported) === comparableResource(expected); } function headerQuotedValue(value) { return value.replaceAll(/[\\"]/g, String.raw`\$&`).replaceAll(/[^\u0020-\u007E]/g, " "); } /** * Build a `WWW-Authenticate: Bearer …` challenge header value (RFC 6750). * * The single formatter behind every challenge this package emits — the * bearer-auth 401/403 answers and the per-operation scope-challenge 403 — so * all challenges from one server agree on parameter order and quoting. Every * parameter value is emitted as an HTTP quoted-string with `\` and `"` * escaped and non-printable characters replaced. */ function buildWwwAuthenticateHeader(errorCode, description, requiredScopes, resourceMetadataUrl) { let header = `Bearer error="${headerQuotedValue(errorCode)}", error_description="${headerQuotedValue(description)}"`; if (requiredScopes.length > 0) header += `, scope="${headerQuotedValue(requiredScopes.join(" "))}"`; if (resourceMetadataUrl) header += `, resource_metadata="${headerQuotedValue(resourceMetadataUrl)}"`; return header; } /** * Validate a raw `Authorization` header value as a Bearer token and return * the verified {@link AuthInfo}. * * The runtime-neutral core of Bearer authentication: it parses the header, * runs the verifier, compares the token's resource with `expectedResource`, * enforces `requiredScopes`, and rejects tokens without an * expiration or past it. On any failure it throws an {@link OAuthError} — * pass that to {@link bearerAuthChallengeResponse} for the matching HTTP * answer, or use {@link requireBearerAuth} to get both steps as one call. * * Framework adapters build on this: `requireBearerAuth` from * `@modelcontextprotocol/express` feeds it `req.headers.authorization`. */ async function verifyBearerToken(authorizationHeader, options) { const { verifier, requiredScopes = [], expectedResource } = options; if (!authorizationHeader) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Missing Authorization header"); const [type, token] = authorizationHeader.split(" "); if (type?.toLowerCase() !== "bearer" || !token) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Invalid Authorization header format, expected 'Bearer TOKEN'"); const authInfo = await verifier.verifyAccessToken(token); if (expectedResource !== void 0 && !sameResource(authInfo.resource, expectedResource)) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Token was not issued for this resource"); if (requiredScopes.length > 0) { if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new require_src.OAuthError(require_src.OAuthErrorCode.InsufficientScope, "Insufficient scope"); } if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Token has no expiration time"); else if (authInfo.expiresAt < Date.now() / 1e3) throw new require_src.OAuthError(require_src.OAuthErrorCode.InvalidToken, "Token has expired"); if (options.resourceMetadataUrl !== void 0 && authInfo.resourceMetadataUrl === void 0) return { ...authInfo, resourceMetadataUrl: options.resourceMetadataUrl }; return authInfo; } /** * Build the HTTP answer for a Bearer authentication failure. * * Maps an {@link OAuthError} to its status — `401` for `invalid_token` and * `403` for `insufficient_scope` (both carrying the `WWW-Authenticate: Bearer …` * challenge, with `resource_metadata` when configured so clients can discover * the Authorization Server), `500` for `server_error`, `400` for anything * else. A non-`OAuthError` value answers `500 server_error`. The body is the * OAuth error JSON. */ function bearerAuthChallengeResponse(error, options) { const { requiredScopes = [], resourceMetadataUrl } = options ?? {}; if (!(error instanceof require_src.OAuthError)) { const serverError = new require_src.OAuthError(require_src.OAuthErrorCode.ServerError, "Internal Server Error"); return Response.json(serverError.toResponseObject(), { status: 500 }); } switch (error.code) { case require_src.OAuthErrorCode.InvalidToken: { const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl); return Response.json(error.toResponseObject(), { status: 401, headers: { "WWW-Authenticate": challenge } }); } case require_src.OAuthErrorCode.InsufficientScope: { const challenge = buildWwwAuthenticateHeader(error.code, error.message, requiredScopes, resourceMetadataUrl); return Response.json(error.toResponseObject(), { status: 403, headers: { "WWW-Authenticate": challenge } }); } case require_src.OAuthErrorCode.ServerError: return Response.json(error.toResponseObject(), { status: 500 }); default: return Response.json(error.toResponseObject(), { status: 400 }); } } /** * Require a valid Bearer token on web-standard requests. * * The framework-free counterpart of `requireBearerAuth` from * `@modelcontextprotocol/express`, for hosts whose HTTP surface is a * `fetch(request)` handler — Cloudflare Workers, Deno, Bun, Hono. The * returned gate resolves to the verified {@link AuthInfo}, or to the * ready-to-return challenge `Response` when the request must be refused. * * @example * ```ts source="./bearerAuth.examples.ts#requireBearerAuth_fetchGate" * const gate = requireBearerAuth({ verifier, requiredScopes: ['mcp'] }); * * async function fetchHandler(request: Request): Promise { * const auth: AuthInfo | Response = await gate(request); * if (auth instanceof Response) return auth; * return handler.fetch(request, { authInfo: auth }); * } * ``` */ function requireBearerAuth(options) { const { verifier, requiredScopes = [], resourceMetadataUrl, expectedResource } = options; const resolved = { verifier, requiredScopes, resourceMetadataUrl, expectedResource }; return async (request) => { const [authorizationHeader] = (request.headers.get("authorization") ?? "").split(","); try { return await verifyBearerToken(authorizationHeader || void 0, resolved); } catch (error) { return bearerAuthChallengeResponse(error, resolved); } }; } //#endregion //#region src/server/middleware/oauthMetadata.ts function checkIssuerUrl(issuer, allowInsecure) { if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1" && !allowInsecure) throw new Error("Issuer URL must be HTTPS"); if (issuer.hash) throw new Error(`Issuer URL must not have a fragment: ${issuer}`); if (issuer.search) throw new Error(`Issuer URL must not have a query string: ${issuer}`); } /** * Derive the RFC 9728 Protected Resource Metadata document from * {@link AuthMetadataOptions}, validating the Authorization Server issuer URL * (HTTPS required outside localhost) in the process. * * `oauthMetadataResponse` and the Express `mcpAuthMetadataRouter` both build * on this; use it directly when serving the document through your own * routing — or call it once at startup to fail fast on a misconfigured * issuer before any request arrives. */ function buildOAuthProtectedResourceMetadata(options) { checkIssuerUrl(new URL(options.oauthMetadata.issuer), options.dangerouslyAllowInsecureIssuerUrl); return { resource: options.resourceServerUrl.href, authorization_servers: [options.oauthMetadata.issuer], scopes_supported: options.scopesSupported, resource_name: options.resourceName, resource_documentation: options.serviceDocumentationUrl?.href }; } /** * Builds the RFC 9728 Protected Resource Metadata URL for a given MCP server * URL by inserting `/.well-known/oauth-protected-resource` ahead of the path. * * @example * ```ts * getOAuthProtectedResourceMetadataUrl(new URL('https://api.example.com/mcp')) * // → 'https://api.example.com/.well-known/oauth-protected-resource/mcp' * ``` */ function getOAuthProtectedResourceMetadataUrl(serverUrl) { const metadataUrl = new URL(serverUrl); metadataUrl.pathname = protectedResourceMetadataPath(serverUrl); metadataUrl.hash = ""; return metadataUrl.href; } /** The RFC 9728 path-aware well-known path for a resource URL. */ function protectedResourceMetadataPath(resourceServerUrl) { const rsPath = stripTrailingSlash(resourceServerUrl.pathname); return `/.well-known/oauth-protected-resource${rsPath === "/" ? "" : rsPath}`; } function stripTrailingSlash(path) { return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path; } const ALLOWED_METHODS = "GET, HEAD, OPTIONS"; function metadataDocumentResponse(request, metadata) { if (request.method === "OPTIONS") { const requestedHeaders = request.headers.get("access-control-request-headers"); return new Response(null, { status: 204, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": ALLOWED_METHODS, ...requestedHeaders === null ? {} : { "Access-Control-Allow-Headers": requestedHeaders, Vary: "Access-Control-Request-Headers" } } }); } if (request.method !== "GET" && request.method !== "HEAD") { const error = new require_src.OAuthError(require_src.OAuthErrorCode.MethodNotAllowed, `The method ${request.method} is not allowed for this endpoint`); return Response.json(error.toResponseObject(), { status: 405, headers: { Allow: ALLOWED_METHODS, "Access-Control-Allow-Origin": "*" } }); } const response = Response.json(metadata, { headers: { "Access-Control-Allow-Origin": "*" } }); return request.method === "HEAD" ? new Response(null, { status: response.status, headers: response.headers }) : response; } /** * Serve the two OAuth discovery documents an MCP server acting as a Resource * Server exposes, from a web-standard `fetch(request)` handler: * * - `/.well-known/oauth-protected-resource[/]` — RFC 9728 Protected * Resource Metadata, derived from the supplied options (path-aware: the * resource URL's path is reflected in the route). * - `/.well-known/oauth-authorization-server` — RFC 8414 Authorization * Server Metadata, passed through verbatim. * * Returns the matched document `Response` (JSON with permissive CORS, `405` * with an `Allow` header for non-GET methods, `204` for CORS preflight), or * `undefined` when the request path is neither well-known route — fall * through to your own routing. The framework-free counterpart of * `mcpAuthMetadataRouter` from `@modelcontextprotocol/express`; pair it with * `requireBearerAuth` and `getOAuthProtectedResourceMetadataUrl` so * unauthenticated clients can discover the AS from the `401` challenge. * * @example * ```ts source="./oauthMetadata.examples.ts#oauthMetadataResponse_fetchHandler" * async function fetchHandler(request: Request): Promise { * return oauthMetadataResponse(request, options) ?? serveMcp(request); * } * ``` */ function oauthMetadataResponse(request, options) { const requestPath = stripTrailingSlash(new URL(request.url).pathname); if (requestPath === protectedResourceMetadataPath(options.resourceServerUrl)) return metadataDocumentResponse(request, buildOAuthProtectedResourceMetadata(options)); if (requestPath === "/.well-known/oauth-authorization-server") { buildOAuthProtectedResourceMetadata(options); return metadataDocumentResponse(request, options.oauthMetadata); } } //#endregion //#region src/server/scopeChallenge.ts /** @internal */ function supportsScopeChallengeResolver(transport) { return typeof transport === "object" && transport !== null && "setScopeChallengeResolver" in transport && typeof transport.setScopeChallengeResolver === "function"; } function assertScope(scope, location) { if (typeof scope !== "string" || !/^[\u0021\u0023-\u005B\u005D-\u007E]+$/.test(scope)) throw new TypeError(`${location} must satisfy the OAuth scope-token grammar`); } function validateScopeChallenge(challenge) { if (challenge === null || typeof challenge !== "object" || !Array.isArray(challenge.scopes) || challenge.scopes.length === 0) throw new TypeError("scope challenge must contain at least one scope"); for (const [index, scope] of challenge.scopes.entries()) assertScope(scope, `scope challenge scopes[${index}]`); if (challenge.errorDescription !== void 0 && typeof challenge.errorDescription !== "string") throw new TypeError("scope challenge errorDescription must be a string"); if (challenge.errorDescription !== void 0 && !/^[\u0020-\u0021\u0023-\u005B\u005D-\u007E]+$/.test(challenge.errorDescription)) throw new TypeError("scope challenge errorDescription must satisfy the RFC 6750 error-description grammar"); return challenge; } /** * Creates a handler that requires every supplied scope exactly. * * Requests without authentication are left to the server's authentication gate. */ function requireScopes(...scopes) { if (scopes.length === 0) throw new TypeError("requireScopes must contain at least one scope"); for (const [index, scope] of scopes.entries()) assertScope(scope, `requireScopes scope[${index}]`); const requiredScopes = [...scopes]; return ({ authInfo }) => { if (authInfo === void 0) return; const activeScopes = new Set(authInfo.scopes); if (requiredScopes.every((scope) => activeScopes.has(scope))) return; return { scopes: requiredScopes }; }; } /** @internal */ async function findScopeChallenge(requests, authInfo, resolve) { for (const request of requests) { const challenge = await resolve({ request, ...authInfo !== void 0 && { authInfo } }); if (challenge !== void 0) return validateScopeChallenge(challenge); } } /** * The RFC 9728 Protected Resource Metadata URL to advertise on a scope * challenge, derived from the verified {@link AuthInfo}: the URL the * authentication gate stamped (`authInfo.resourceMetadataUrl`, set by the * bearer-auth helpers from their `resourceMetadataUrl` option), falling back * to the well-known location for an HTTP(S) RFC 8707 `resource` identifier, or * `undefined` when neither is available (the `resource_metadata` parameter is * then omitted, matching the bearer-auth challenges). * * @internal */ function scopeChallengeResourceMetadataUrl(authInfo) { if (authInfo?.resourceMetadataUrl !== void 0) return authInfo.resourceMetadataUrl; if (authInfo?.resource?.protocol === "https:" || authInfo?.resource?.protocol === "http:") return getOAuthProtectedResourceMetadataUrl(authInfo.resource); } /** @internal */ function createScopeChallengeResponse(challenge, resourceMetadataUrl) { return bearerAuthChallengeResponse(new require_src.OAuthError(require_src.OAuthErrorCode.InsufficientScope, challenge.errorDescription ?? "Insufficient scope"), { requiredScopes: [...challenge.scopes], resourceMetadataUrl }); } //#endregion //#region src/server/legacyInputRequiredShim.ts /** * Default handler re-entries per originating request — tighter than the * client driver's 10 because the shim holds a live wire request open. */ const DEFAULT_LEGACY_SHIM_MAX_ROUNDS = 8; /** Default per-leg timeout: legs are human-paced, so the 60s protocol default is wrong. */ const DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS = 6e5; /** Resolves and validates `ServerOptions.inputRequired`, failing loudly at construction time. */ function resolveLegacyShimOptions(options) { if (options?.maxRounds !== void 0 && (!Number.isInteger(options.maxRounds) || options.maxRounds < 1)) throw new RangeError(`inputRequired.maxRounds must be a positive integer (got ${options.maxRounds})`); if (options?.roundTimeoutMs !== void 0 && (!Number.isFinite(options.roundTimeoutMs) || options.roundTimeoutMs <= 0)) throw new RangeError(`inputRequired.roundTimeoutMs must be a positive number (got ${options.roundTimeoutMs})`); return { maxRounds: options?.maxRounds ?? DEFAULT_LEGACY_SHIM_MAX_ROUNDS, roundTimeoutMs: options?.roundTimeoutMs ?? DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS, legacyShim: options?.legacyShim ?? true }; } /** * Validates one `inputRequests` entry: malformed or unknown kinds are server * bugs and fail loudly on both eras. Shared by the modern seam's capability * check and the shim's gate. */ function coerceEmbeddedInputRequest(method, key, entry) { if (entry === null || typeof entry !== "object" || typeof entry.method !== "string") throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an invalid input request '${key}': each inputRequests entry must be an embedded elicitation/create, sampling/createMessage, or roots/list request`); const embedded = entry; const required = require_src.requiredClientCapabilitiesForInputRequest(embedded); if (required === void 0) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input request '${key}' of kind '${embedded.method}', which is not an embedded request the 2026-07-28 revision defines`); return { embedded, required }; } /** * The 2025-11-25 URL-mode wire shape requires an `elicitationId`; the 2026 * in-band shape has none, so URL legs mint one (CSPRNG-backed, with a * getRandomValues fallback for runtimes without `randomUUID`). */ function syntheticElicitationId() { const webCrypto = globalThis.crypto; if (webCrypto?.randomUUID !== void 0) return webCrypto.randomUUID(); const bytes = new Uint8Array(16); webCrypto.getRandomValues(bytes); bytes[6] = bytes[6] & 15 | 64; bytes[8] = bytes[8] & 63 | 128; const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join(""); return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; } /** Per-family surfacing: tools/call → isError result (the 2025 idiom); prompts/resources → JSON-RPC error. */ function legacyShimFailure(method, message) { if (method === "tools/call") return { content: [{ type: "text", text: message }], isError: true }; throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, message); } /** The fulfilment loop — see the module doc for the contract. */ var LegacyInputRequiredShim = class { constructor(_host) { this._host = _host; } async fulfill(method, handler, request, ctx, firstResult) { const { maxRounds, roundTimeoutMs } = this._host; const outerSignal = ctx.mcpReq.signal; let current = firstResult; let round = 0; while (true) { round += 1; if (round > maxRounds) return legacyShimFailure(method, require_src.inputRequiredRoundsExceededMessage(method, maxRounds)); const inputRequests = current.inputRequests; const hasInputRequests = inputRequests != null && Object.keys(inputRequests).length > 0; const requestState = typeof current.requestState === "string" ? current.requestState : void 0; if (!hasInputRequests && requestState === void 0) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result with neither inputRequests nor requestState (every InputRequiredResult must include at least one of the two)`); let responses; if (hasInputRequests) { const declared = this._host.resolvedClientCapabilities(ctx); const coerced = []; for (const [key, entry] of Object.entries(inputRequests)) { const { embedded, required } = coerceEmbeddedInputRequest(method, key, entry); if (embedded.method !== "roots/list" && embedded.params === void 0) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input request '${key}' of kind '${embedded.method}' without params`); if (require_src.missingClientCapabilities(required, declared) !== void 0) return legacyShimFailure(method, `Cannot request input '${key}' (${embedded.method}): the client on this 2025-era connection did not declare the required capability${declared === void 0 ? " (no client capabilities are available on this connection — per-request legacy serving cannot receive server-to-client requests)" : ""}`); coerced.push([key, embedded]); } const roundAbort = require_src.linkedRoundAbort(outerSignal); try { const legOptions = { relatedRequestId: ctx.mcpReq.id, timeout: roundTimeoutMs, resetTimeoutOnProgress: true, onprogress: () => {}, signal: roundAbort.signal }; const fulfilled = await Promise.all(coerced.map(async ([key, embedded]) => { try { return [key, await this._dispatchLeg(embedded, legOptions)]; } catch (error) { roundAbort.abort(error); throw error; } })); responses = Object.fromEntries(fulfilled); } catch (error) { if (outerSignal.aborted) throw error; return legacyShimFailure(method, `Fulfilling input required by '${method}' failed: ${error instanceof Error ? error.message : String(error)}`); } finally { roundAbort.dispose(); } } else await require_src.sleep(require_src.REQUEST_STATE_ONLY_LEG_PACING_MS, outerSignal); let ctxNext = { ...ctx, mcpReq: { ...ctx.mcpReq, inputResponses: responses, droppedInputResponseKeys: void 0, requestState: require_src.requestStateAccessor(requestState) } }; if (requestState !== void 0) { const decoded = await this._host.verifyRequestState(requestState, ctxNext, method); if (decoded !== void 0) ctxNext = require_src.withRequestStateValue(ctxNext, decoded); } const next = await handler(request, ctxNext); if (!require_src.isInputRequiredResult(next)) return next; current = next; } } /** Routes one embedded request through the host's existing 2025-era senders (gate already ran). */ async _dispatchLeg(embedded, options) { switch (embedded.method) { case "elicitation/create": { let params = embedded.params; if (params.mode === "url" && params.elicitationId === void 0) params = { ...params, elicitationId: syntheticElicitationId() }; return await this._host.sendElicitation(params, options); } case "sampling/createMessage": return await this._host.sendSampling(embedded.params, options); case "roots/list": return await this._host.listRoots(embedded.params, options); } } }; //#endregion //#region src/server/server.ts /** * The request methods whose 2026-07-28 result vocabulary includes * `input_required` (the multi round-trip methods). Returning an * input-required result from any other handler is a server bug. */ const INPUT_REQUIRED_CAPABLE_METHODS = new Set([ "tools/call", "prompts/get", "resources/read" ]); let writeClientIdentity; let installDiscoverHandler; let readServerIdentity; /** * Package-internal: backfills the connection-scoped client-identity fields of a * per-request server instance from the request's validated `_meta` envelope, so the * (deprecated) {@linkcode Server.getClientCapabilities} / {@linkcode Server.getClientVersion} * accessors keep answering on instances that never see an `initialize` handshake. * Not public API. */ function seedClientIdentityFromEnvelope(server, identity) { writeClientIdentity(server, identity); } /** * Package-internal: installs the modern-only `server/discover` handler on an instance * the HTTP entry has marked as serving the 2026-07-28 era, and makes sure the modern * revisions the entry serves appear in the instance's supported-versions list (so the * discover advertisement and version-mismatch errors name them). Idempotent. * Hand-constructed instances are unaffected: nothing else calls this, so they keep * answering `-32601` unless their own supported-versions list opts into a modern * revision. Not public API. */ function installModernOnlyHandlers(server, servedModernVersions) { installDiscoverHandler(server, servedModernVersions); } /** * Package-internal: the instance's implementation identity, for the serving * entries to stamp onto entry-built results (the `subscriptions/listen` * graceful-close result — built outside the encode seam, but the spec's * `SubscriptionsListenResultMetaObject` extends `ResultMetaObject`, so it carries * the serverInfo SHOULD like every other result). Not public API. */ function serverIdentityOf(server) { return readServerIdentity(server); } /** * An MCP server on top of a pluggable transport. * * This server will automatically respond to the initialization flow as initiated from the client. * * @deprecated Use {@linkcode server/mcp.McpServer | McpServer} instead for the high-level API. Only use `Server` for advanced use cases. */ var Server = class extends require_src.Protocol { _clientCapabilities; _clientVersion; static { writeClientIdentity = (server, identity) => { if (identity.clientCapabilities !== void 0) server._clientCapabilities = identity.clientCapabilities; if (identity.clientInfo !== void 0) server._clientVersion = identity.clientInfo; }; installDiscoverHandler = (server, servedModernVersions) => { const missing = servedModernVersions.filter((version) => !server._supportedProtocolVersions.includes(version)); if (missing.length > 0) server._supportedProtocolVersions = [...server._supportedProtocolVersions, ...missing]; server.setRequestHandler("server/discover", () => server._ondiscover()); }; readServerIdentity = (server) => server._serverInfo; } _capabilities; _instructions; _jsonSchemaValidator; _cacheHints; _requestStateVerify; _inputRequiredServing; _legacyShim; /** Lazily-built legacy shim; the loop lives in legacyInputRequiredShim.ts behind a narrow host contract. */ _legacyInputRequiredShim() { return this._legacyShim ??= new LegacyInputRequiredShim({ maxRounds: this._inputRequiredServing.maxRounds, roundTimeoutMs: this._inputRequiredServing.roundTimeoutMs, resolvedClientCapabilities: (ctx) => this._inputRequestCapabilityView(ctx), verifyRequestState: (state, ctx, method) => this._verifyRequestState(state, ctx, method), sendElicitation: (params, options) => this._sendElicitationLeg(params, options, { validateAcceptedContent: false }), sendSampling: (params, options) => this.createMessage(params, options), listRoots: (params, options) => this.listRoots(params, options) }); } /** * Callback for when initialization has fully completed (i.e., the client has sent an `notifications/initialized` notification). */ oninitialized; /** * Initializes this server with the given name and version information. */ constructor(_serverInfo, options) { super(options); this._serverInfo = _serverInfo; this._capabilities = options?.capabilities ? { ...options.capabilities } : {}; this._instructions = options?.instructions; this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new _modelcontextprotocol_server__shims.DefaultJsonSchemaValidator(); this._requestStateVerify = options?.requestState?.verify; this._inputRequiredServing = resolveLegacyShimOptions(options?.inputRequired); if (options?.cacheHints !== void 0) { for (const [operation, hint] of Object.entries(options.cacheHints)) if (hint !== void 0) require_src.assertValidCacheHint(hint, `cacheHints['${operation}']`); this._cacheHints = options.cacheHints; } this.setRequestHandler("initialize", (request) => this._oninitialize(request)); this.setNotificationHandler("notifications/initialized", () => this.oninitialized?.()); if (require_src.modernProtocolVersions(this._supportedProtocolVersions).length > 0) this.setRequestHandler("server/discover", () => this._ondiscover()); if (this._capabilities.logging) this._registerLoggingHandler(); } /** Attaches to the given transport; rejects while this instance is connected to another one. */ async connect(transport) { if (this.transport !== void 0) throw new require_src.SdkError(require_src.SdkErrorCode.AlreadyConnected, "Use a separate Server instance per connection: this instance is already connected to a transport. To connect it to a new transport, call close() first."); await super.connect(transport); } /** * Registers the built-in `logging/setLevel` request handler. * * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577). * Remains functional during the deprecation window (at least twelve months). * Migrate to stderr logging (STDIO servers) or OpenTelemetry. */ _registerLoggingHandler() { this.setRequestHandler("logging/setLevel", async (request, ctx) => { const transportSessionId = ctx.sessionId || ctx.http?.req?.headers.get("mcp-session-id") || void 0; const { level } = request.params; const parseResult = require_src.parseSchema(_modelcontextprotocol_core_internal.LoggingLevelSchema, level); if (parseResult.success) this._loggingLevels.set(transportSessionId, parseResult.data); return {}; }); } buildContext(ctx, transportInfo) { const hasHttpInfo = ctx.http || transportInfo?.request || transportInfo?.closeSSEStream || transportInfo?.closeStandaloneSSEStream; return { ...ctx, mcpReq: { ...ctx.mcpReq, log: (level, data, logger) => { if (!this._capabilities.logging) return Promise.resolve(); let threshold; if (this._servedModernEra()) { threshold = ctx.mcpReq.envelope?.[_modelcontextprotocol_core_internal.LOG_LEVEL_META_KEY]; if (threshold === void 0) return Promise.resolve(); } else threshold = this._loggingLevels.get(ctx.sessionId) ?? this._loggingLevels.get(void 0); if (threshold !== void 0 && this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(threshold)) return Promise.resolve(); return ctx.mcpReq.notify({ method: "notifications/message", params: { level, data, logger } }); }, elicitInput: (params, options) => this.elicitInput(params, options), requestSampling: (params, options) => this.createMessage(params, options) }, http: hasHttpInfo ? { ...ctx.http, req: transportInfo?.request, closeSSE: transportInfo?.closeSSEStream, closeStandaloneSSE: transportInfo?.closeStandaloneSSEStream } : void 0 }; } _loggingLevels = /* @__PURE__ */ new Map(); LOG_LEVEL_SEVERITY = new Map(_modelcontextprotocol_core_internal.LoggingLevelSchema.options.map((level, index) => [level, index])); isMessageIgnored = (level, sessionId) => { const currentLevel = this._loggingLevels.get(sessionId); return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false; }; /** * Registers new capabilities. This can only be called before connecting to a transport. * * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization). */ registerCapabilities(capabilities) { if (this.transport) throw new require_src.SdkError(require_src.SdkErrorCode.AlreadyConnected, "Cannot register capabilities after connecting to transport"); const hadLogging = !!this._capabilities.logging; this._capabilities = require_src.mergeCapabilities(this._capabilities, capabilities); if (!hadLogging && this._capabilities.logging) this._registerLoggingHandler(); } /** * Enforces server-side validation for `tools/call` results regardless of how the * handler was registered, attaches the configured per-operation cache hint * (when one exists) so the 2026-07-28 encode seam can fill `ttlMs`/`cacheScope` * for results that do not provide their own, and owns the multi-round-trip * seam: on the methods whose 2026-07-28 result vocabulary includes * `input_required` (`tools/call`, `prompts/get`, `resources/read`) an * input-required return skips result-schema validation and is checked * against the served era, the at-least-one rule, and the request's own * declared client capabilities; on every other method an input-required * return is a server bug and fails loudly. The hint rides a symbol-keyed * property that is never serialized, so 2025-era responses are unaffected. */ _wrapHandler(method, handler) { if (method !== "tools/call") { const cacheHint = this._cacheHints?.[method]; const isInputRequiredCapable = INPUT_REQUIRED_CAPABLE_METHODS.has(method); if (cacheHint === void 0 && !isInputRequiredCapable) return async (request, ctx) => { const result = await handler(request, ctx); if (require_src.isInputRequiredResult(result)) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but only tools/call, prompts/get and resources/read support input_required (protocol revision 2026-07-28)`); return result; }; return async (request, ctx) => { const result = isInputRequiredCapable ? await this._invokeInputRequiredCapableHandler(method, handler, request, ctx) : await handler(request, ctx); if (require_src.isInputRequiredResult(result)) { if (!isInputRequiredCapable) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but only tools/call, prompts/get and resources/read support input_required (protocol revision 2026-07-28)`); return result; } return cacheHint === void 0 ? result : require_src.attachCacheHintFallback(result, cacheHint); }; } return async (request, ctx) => { const codec = require_src.codecForVersion(this._negotiatedProtocolVersion); const validatedRequest = codec.validateRequest("tools/call", request); if (!validatedRequest.ok) throw new require_src.ProtocolError(validatedRequest.reason === "not-in-era" ? require_src.ProtocolErrorCode.InternalError : require_src.ProtocolErrorCode.InvalidParams, validatedRequest.reason === "not-in-era" ? "No wire schema for tools/call in the resolved era" : `Invalid tools/call request: ${validatedRequest.message}`); const result = await this._invokeInputRequiredCapableHandler("tools/call", handler, request, ctx); if (require_src.isInputRequiredResult(result)) return result; const normalizedResult = require_src.normalizeContentlessToolResult(result); const validationResult = codec.validateResult("tools/call", normalizedResult); if (!validationResult.ok) throw new require_src.ProtocolError(validationResult.reason === "not-in-era" ? require_src.ProtocolErrorCode.InternalError : require_src.ProtocolErrorCode.InvalidParams, validationResult.reason === "not-in-era" ? "No wire schema for tools/call in the resolved era" : `Invalid tools/call result: ${validationResult.message}`); return validationResult.value; }; } /** * Whether this instance is bound to a 2026-07-28-or-later protocol * revision. Era is instance state — a serving entry (`createMcpHandler`, * `serveStdio`) marks the instance modern at construction; a 2025-era * `initialize` handshake binds it legacy. The multi-round-trip seam reads * this directly: there is no per-request era consult. */ _servedModernEra() { return this._negotiatedProtocolVersion !== void 0 && require_src.isModernProtocolVersion(this._negotiatedProtocolVersion); } /** * Invokes a handler for one of the multi-round-trip methods and applies * the input-required seam: * * - a `UrlElicitationRequiredError` (or any 2025-style server→client * request idiom) escaping the handler on a request served on the * 2026-07-28 era fails LOUDLY with a clear steer to * `inputRequired.elicitUrl(...)` — the `-32042` error never reaches the * 2026-07-28 wire and the throw is not silently converted. Requests * served on the 2025 era keep today's `-32042` behavior byte-exact (the * error is rethrown unchanged). * - an input-required RETURN toward a 2026-07-28 request must satisfy * the at-least-one rule, and every embedded request must be covered by * the capabilities declared on the request's envelope (violations * answer the typed `-32021` error). Toward a 2025-era request the * return is fulfilled by the default-on legacy shim, whose own gate * consults the initialize-declared capabilities and surfaces * violations per family; `inputRequired.legacyShim: false` restores * the pre-shim loud failure. */ async _invokeInputRequiredCapableHandler(method, handler, request, ctx) { const servedModern = this._servedModernEra(); const rawRequestState = ctx.mcpReq.requestState(); if (rawRequestState !== void 0 && typeof rawRequestState !== "string") throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, "Invalid or expired requestState", { reason: "invalid_request_state" }); let ctxForHandler = ctx; if (typeof rawRequestState === "string") { const decoded = await this._verifyRequestState(rawRequestState, ctx, method); if (decoded !== void 0) ctxForHandler = require_src.withRequestStateValue(ctx, decoded); } let result; try { result = await handler(request, ctxForHandler); } catch (error) { if (error instanceof require_src.ProtocolError && error.code === require_src.ProtocolErrorCode.UrlElicitationRequired) { if (!servedModern) throw error; throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `URL elicitation cannot be signalled by throwing UrlElicitationRequiredError on protocol revision ${this._negotiatedProtocolVersion}: return inputRequired({ inputRequests: { …: inputRequired.elicitUrl(...) } }) from the handler instead. The urlElicitationRequired error (-32042) of earlier revisions is not available on this revision.`); } throw error; } if (!require_src.isInputRequiredResult(result)) return result; if (!servedModern) { if (!this._inputRequiredServing.legacyShim) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but this request is served on protocol revision ${this._negotiatedProtocolVersion ?? _modelcontextprotocol_core_internal.LATEST_PROTOCOL_VERSION}, which has no input_required vocabulary`); return await this._legacyInputRequiredShim().fulfill(method, handler, request, ctxForHandler, result); } const inputRequests = result.inputRequests; const hasInputRequests = inputRequests != null && Object.keys(inputRequests).length > 0; const hasRequestState = typeof result.requestState === "string"; if (!hasInputRequests && !hasRequestState) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result with neither inputRequests nor requestState (every InputRequiredResult must include at least one of the two)`); if (hasInputRequests) { const declared = this._inputRequestCapabilityView(ctx); for (const [key, entry] of Object.entries(inputRequests)) { const { embedded, required } = coerceEmbeddedInputRequest(method, key, entry); const missing = require_src.missingClientCapabilities(required, declared); if (missing !== void 0) throw new require_src.MissingRequiredClientCapabilityError({ requiredCapabilities: missing }, `Cannot request input '${key}' (${embedded.method}): the request's client capabilities do not declare the required capability`); } } return result; } /** * Runs the configured `requestState.verify` hook and returns its * resolved value (`undefined` when unconfigured or the hook returns * nothing). Deny-on-error: any hook failure answers the frozen `-32602`; * the reason goes to `onerror` only. */ async _verifyRequestState(state, ctx, method) { if (this._requestStateVerify === void 0) return; try { return await this._requestStateVerify(state, ctx); } catch (error) { this.onerror?.(/* @__PURE__ */ new Error(`requestState verification rejected ${method}: ${error instanceof Error ? error.message : String(error)}`)); throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, "Invalid or expired requestState", { reason: "invalid_request_state" }); } } /** * The per-request resolved client-capabilities view: the request's own * `_meta` envelope on the 2026 era; the `initialize`-declared state on a * 2025-era connection. Per-request instances that never saw an * initialize (stateless legacy) hold nothing, so gates refuse there. */ _inputRequestCapabilityView(ctx) { return this._servedModernEra() ? ctx.mcpReq.envelope?.[_modelcontextprotocol_core_internal.CLIENT_CAPABILITIES_META_KEY] : this._clientCapabilities; } /** * Guard for the push-style server→client request APIs ({@linkcode createMessage}, * {@linkcode elicitInput}, {@linkcode listRoots}, {@linkcode ping}) on a * modern-era instance: the 2026-07-28 revision has no server→client request * channel, so the call fails before any wire traffic with a typed error * whose message steers to `inputRequired(...)`. The base era gate would * also reject it; this guard runs first to carry the steer. */ _assertPushApiInServedEra(method) { if (this._servedModernEra()) throw new require_src.SdkError(require_src.SdkErrorCode.MethodNotSupportedByProtocolVersion, `Server-to-client requests are not available on protocol revision ${this._negotiatedProtocolVersion}: '${method}' cannot be sent while serving a request on that revision. Return inputRequired({ ... }) from the handler instead — the client fulfils the embedded requests and retries the original request (multi round-trip requests).`, { method, era: "2026-07-28" }); } assertCapabilityForMethod(method) { switch (method) { case "sampling/createMessage": if (!this._clientCapabilities?.sampling) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Client does not support sampling (required for ${method})`); break; case "elicitation/create": if (!this._clientCapabilities?.elicitation) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Client does not support elicitation (required for ${method})`); break; case "roots/list": if (!this._clientCapabilities?.roots) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Client does not support listing roots (required for ${method})`); break; case "ping": break; } } assertNotificationCapability(method) { switch (method) { case "notifications/message": if (!this._capabilities.logging) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`); break; case "notifications/resources/updated": case "notifications/resources/list_changed": if (!this._capabilities.resources) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support notifying about resources (required for ${method})`); break; case "notifications/tools/list_changed": if (!this._capabilities.tools) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support notifying of tool list changes (required for ${method})`); break; case "notifications/prompts/list_changed": if (!this._capabilities.prompts) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support notifying of prompt list changes (required for ${method})`); break; case "notifications/elicitation/complete": if (!this._clientCapabilities?.elicitation?.url) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Client does not support URL elicitation (required for ${method})`); break; case "notifications/cancelled": break; case "notifications/progress": break; } } assertRequestHandlerCapability(method) { switch (method) { case "completion/complete": if (!this._capabilities.completions) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support completions (required for ${method})`); break; case "logging/setLevel": if (!this._capabilities.logging) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`); break; case "prompts/get": case "prompts/list": if (!this._capabilities.prompts) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support prompts (required for ${method})`); break; case "resources/list": case "resources/templates/list": case "resources/read": if (!this._capabilities.resources) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support resources (required for ${method})`); break; case "tools/call": case "tools/list": if (!this._capabilities.tools) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, `Server does not support tools (required for ${method})`); break; case "ping": case "initialize": break; } } async _oninitialize(request) { const requestedVersion = request.params.protocolVersion; this._clientCapabilities = request.params.capabilities; this._clientVersion = request.params.clientInfo; const legacyVersions = require_src.legacyProtocolVersions(this._supportedProtocolVersions); const protocolVersion = legacyVersions.includes(requestedVersion) ? requestedVersion : legacyVersions[0] ?? _modelcontextprotocol_core_internal.LATEST_PROTOCOL_VERSION; this._negotiatedProtocolVersion = protocolVersion; this.transport?.setProtocolVersion?.(protocolVersion); return { protocolVersion, capabilities: this.getCapabilities(), serverInfo: this._serverInfo, ...this._instructions && { instructions: this._instructions } }; } /** * Answers `server/discover` (protocol revision 2026-07-28). `supportedVersions` * lists only modern revisions (2025-era versions are negotiated via `initialize`); * the capabilities are advertised as-is, listChanged/subscribe bits included * (see {@linkcode discoverAdvertisedCapabilities}). */ _ondiscover() { return { supportedVersions: require_src.modernProtocolVersions(this._supportedProtocolVersions), capabilities: discoverAdvertisedCapabilities(this.getCapabilities()), ...this._instructions && { instructions: this._instructions } }; } /** * The identity the 2026-era encode seam stamps into every outbound * result's `_meta` under `io.modelcontextprotocol/serverInfo` (spec PR * #3002: servers SHOULD identify themselves on every response). */ _outboundServerInfo() { return this._serverInfo; } /** * After initialization has completed, this will be populated with the client's reported capabilities. * * @deprecated Read client identity from the per-request handler context instead: on * 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's * declared capabilities, while on 2025-era connections this accessor keeps returning the * `initialize`-scoped value. The accessor remains functional — instances serving the * 2026-07-28 era are backfilled per request from the validated envelope. */ getClientCapabilities() { return this._clientCapabilities; } /** * After initialization has completed, this will be populated with information about the client's name and version. * * @deprecated Read client identity from the per-request handler context instead: on * 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's * name and version, while on 2025-era connections this accessor keeps returning the * `initialize`-scoped value. The accessor remains functional — instances serving the * 2026-07-28 era are backfilled per request from the validated envelope. */ getClientVersion() { return this._clientVersion; } /** * After initialization has completed, this will be populated with the protocol version negotiated * with the client (the version the server responded with during the initialize handshake), or * `undefined` before initialization. * * @deprecated Read the protocol revision from the per-request handler context instead: on * 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` names the revision the * request was sent for, while on 2025-era connections this accessor keeps returning the * `initialize`-negotiated version. The accessor remains functional — instances serving the * 2026-07-28 era report that revision. */ getNegotiatedProtocolVersion() { return this._negotiatedProtocolVersion; } /** * Project a `tools/call` result through this instance's negotiated wire * codec — the era-agnostic SEP-2106 §4.3 TextContent auto-append, plus on * the 2025 era the `{result:…}` wrap when `structuredContent` is a * non-object value or the advertised `outputSchema` had a non-object root. * Identity for object-shaped `structuredContent` on the 2026 era. * * `McpServer`'s built-in `tools/call` handler routes through this method. * Low-level `setRequestHandler('tools/call', …)` authors call it * themselves so the projection lives in one place (the codec) and the * server-side handler stays era-blind. * * This is the only codec function exposed on `Server` — the full * `WireCodec` is intentionally not part of the public surface. */ projectCallToolResult(result, advertisedOutputSchema) { return this._wireCodec().projectCallToolResult(result, advertisedOutputSchema); } /** * Returns the current server capabilities. */ getCapabilities() { return this._capabilities; } /** * Sends a `ping` request to the connected client. * * @deprecated The 2026-07-28 protocol removed ping; it throws on a 2026-07-28-era instance. * If your factory serves both eras, this only works on the legacy path. */ async ping() { this._assertPushApiInServedEra("ping"); return this.request({ method: "ping" }); } async createMessage(params, options) { this._assertPushApiInServedEra("sampling/createMessage"); if ((params.tools || params.toolChoice) && !this._clientCapabilities?.sampling?.tools) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, "Client does not support sampling tools capability."); if (params.messages.length > 0) { const lastMessage = params.messages.at(-1); const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content]; const hasToolResults = lastContent.some((c) => c.type === "tool_result"); const previousMessage = params.messages.length > 1 ? params.messages.at(-2) : void 0; const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : []; const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use"); if (hasToolResults) { if (lastContent.some((c) => c.type !== "tool_result")) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, "The last message must contain only tool_result content if any is present"); if (!hasPreviousToolUse) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, "tool_result blocks are not matching any tool_use from the previous message"); } if (hasPreviousToolUse) { const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id)); const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId)); if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, "ids of tool_result blocks and tool_use blocks from previous message do not match"); } } const hasTools = Boolean(params.tools || params.toolChoice); const wide = await this.request({ method: "sampling/createMessage", params }, options); const outcome = this._wireCodec().samplingResultVariant(hasTools, wide); if (!outcome.ok) throw new require_src.SdkError(require_src.SdkErrorCode.InvalidResult, `Invalid sampling/createMessage result: ${outcome.reason === "invalid" ? outcome.message : outcome.reason}`); return outcome.value; } /** * Creates an elicitation request for the given parameters. * For backwards compatibility, `mode` may be omitted for form requests and will default to `"form"`. * @param params The parameters for the elicitation request. * @param options Optional request options. * @returns The result of the elicitation request. * * @deprecated Throws on a 2026-07-28-era request — use {@link index.inputRequired | inputRequired} (multi-round-trip) * instead. The 2025 push-style server-to-client request model is replaced by input_required * results in the 2026-07-28 protocol. If your factory serves both eras, this only works on the * legacy path. */ async elicitInput(params, options) { this._assertPushApiInServedEra("elicitation/create"); switch (params.mode ?? "form") { case "url": if (!this._clientCapabilities?.elicitation?.url) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, "Client does not support url elicitation."); break; case "form": if (!this._clientCapabilities?.elicitation?.form) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, "Client does not support form elicitation."); break; } return this._sendElicitationLeg(params, options); } /** * The capability-check-free core of {@linkcode elicitInput}. The shim * uses it because its gate differs from the public checks: a bare * `elicitation: {}` counts as form support (the pre-mode rule), and * accepted content passes through unvalidated for parity with the * modern client driver (handlers validate via the schema-aware * `acceptedContent` overload and can re-ask). */ async _sendElicitationLeg(params, options, behavior) { const mode = params.mode ?? "form"; const validateAcceptedContent = behavior?.validateAcceptedContent ?? true; switch (mode) { case "url": { const urlParams = params; return this.request({ method: "elicitation/create", params: urlParams }, options); } case "form": { const formParams = params.mode === "form" ? params : { ...params, mode: "form" }; const result = await this.request({ method: "elicitation/create", params: formParams }, options); if (validateAcceptedContent && result.action === "accept" && result.content && formParams.requestedSchema) try { const validationResult = this._jsonSchemaValidator.getValidator(formParams.requestedSchema)(result.content); if (!validationResult.valid) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Elicitation response content does not match requested schema: ${validationResult.errorMessage}`); } catch (error) { if (error instanceof require_src.ProtocolError) throw error; throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InternalError, `Error validating elicitation response: ${error instanceof Error ? error.message : String(error)}`); } return result; } } } /** * Creates a reusable callback that, when invoked, will send a `notifications/elicitation/complete` * notification for the specified elicitation ID. * * The notification (and the `elicitationId` it references) exists only on protocol revision * 2025-11-25 — the 2026-07-28 revision removed both. On a connection negotiated at 2026-07-28 the * returned callback rejects with a typed local error before anything reaches the transport * (the method is not part of that revision's wire registry). * * @param elicitationId The ID of the elicitation to mark as complete. * @param options Optional notification options. Useful when the completion notification should be related to a prior request. * @returns A function that emits the completion notification when awaited. */ createElicitationCompletionNotifier(elicitationId, options) { if (!this._clientCapabilities?.elicitation?.url) throw new require_src.SdkError(require_src.SdkErrorCode.CapabilityNotSupported, "Client does not support URL elicitation (required for notifications/elicitation/complete)"); return () => this.notification({ method: "notifications/elicitation/complete", params: { elicitationId } }, options); } /** * Requests the list of roots from the client. * * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577). * Throws on a 2026-07-28-era request — use {@link index.inputRequired | inputRequired} (multi-round-trip) instead, * or migrate to passing paths via tool parameters, resource URIs, or configuration. The 2025 * push-style server-to-client request model is replaced by input_required results in the * 2026-07-28 protocol. If your factory serves both eras, this only works on the legacy path. */ async listRoots(params, options) { this._assertPushApiInServedEra("roots/list"); return this.request({ method: "roots/list", params }, options); } /** * Sends a logging message to the client, if connected. * Note: You only need to send the parameters object, not the entire JSON-RPC message. * @see {@linkcode LoggingMessageNotification} * @param params * @param sessionId Optional for stateless transports and backward compatibility. * * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577). * Remains functional during the deprecation window (at least twelve months). * Migrate to stderr logging (STDIO servers) or OpenTelemetry. */ async sendLoggingMessage(params, sessionId) { if (this._capabilities.logging && !this.isMessageIgnored(params.level, sessionId)) return this.notification({ method: "notifications/message", params }); } async sendResourceUpdated(params) { return this.notification({ method: "notifications/resources/updated", params }); } async sendResourceListChanged() { return this.notification({ method: "notifications/resources/list_changed" }); } async sendToolListChanged() { return this.notification({ method: "notifications/tools/list_changed" }); } async sendPromptListChanged() { return this.notification({ method: "notifications/prompts/list_changed" }); } }; /** * The capability set a server advertises on `server/discover`. Pure — never * mutates the input; the legacy `initialize` advertisement is untouched. * * The serving entries serve `subscriptions/listen` themselves, so the * `listChanged` and `resources.subscribe` capability bits are advertised * as-is: a modern-era client uses them to decide which notification types to * request on its listen filter. */ function discoverAdvertisedCapabilities(capabilities) { return { ...capabilities }; } //#endregion //#region src/server/mcp.ts function toolInputElementCount(value, max) { let count = 0; const stack = [value]; while (stack.length > 0) { const node = stack.pop(); if (node === null || typeof node !== "object") continue; if (Array.isArray(node)) for (const child of node) { if (++count > max) return count; if (child !== null && typeof child === "object") stack.push(child); } else for (const key in node) { if (!Object.prototype.hasOwnProperty.call(node, key)) continue; if (++count > max) return count; const child = node[key]; if (child !== null && typeof child === "object") stack.push(child); } } return count; } function resolveMaxToolInputElements(value) { if (value === void 0 || value === Infinity) return void 0; if (typeof value !== "number" || Number.isNaN(value) || value < 1) throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`); return value; } /** * High-level MCP server that provides a simpler API for working with resources, tools, and prompts. * For advanced usage (like sending notifications or setting custom request handlers), use the underlying * {@linkcode Server} instance available via the {@linkcode McpServer.server | server} property. * * @example * ```ts source="./mcp.examples.ts#McpServer_basicUsage" * const server = new McpServer({ * name: 'my-server', * version: '1.0.0' * }); * ``` */ var McpServer = class { /** * The underlying {@linkcode Server} instance, useful for advanced operations like sending notifications. */ server; _maxToolInputElements; _registeredResources = {}; _registeredResourceTemplates = {}; _registeredTools = {}; _registeredPrompts = {}; /** Per-tool JSON-converted `inputSchema`, filled on first use by `toolInputSchemaJson()`. */ _toolInputSchemaJson = {}; /** * The JSON-serialized `inputSchema` of a registered tool, or `undefined` * when no such tool is registered. Used by the HTTP entry's pre-dispatch * SEP-2243 `Mcp-Param-*` validation step (which needs the same JSON Schema * `tools/list` would emit, before dispatch reaches the handler). * * @internal */ toolInputSchemaJson(name) { const tool = this._registeredTools[name]; if (tool === void 0 || !tool.enabled) return void 0; if (Object.hasOwn(this._toolInputSchemaJson, name)) return this._toolInputSchemaJson[name]; if (tool.inputSchema === void 0) return EMPTY_OBJECT_JSON_SCHEMA; try { const json = require_src.standardSchemaToJsonSchema(tool.inputSchema, "input"); this._toolInputSchemaJson[name] = json; return json; } catch { return; } } constructor(serverInfo, options) { this.server = new Server(serverInfo, options); this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements); if (options?.capabilities?.tools) this.setToolRequestHandlers(); if (options?.capabilities?.resources) this.setResourceRequestHandlers(); if (options?.capabilities?.prompts) this.setPromptRequestHandlers(); } /** * Attaches to the given transport, starts it, and starts listening for messages. * * The `server` object assumes ownership of the {@linkcode Transport}, replacing any callbacks that have already been set, and expects that it is the only user of the {@linkcode Transport} instance going forward. * * @example * ```ts source="./mcp.examples.ts#McpServer_connect_stdio" * const server = new McpServer({ name: 'my-server', version: '1.0.0' }); * const transport = new StdioServerTransport(); * await server.connect(transport); * ``` */ async connect(transport) { if (supportsScopeChallengeResolver(transport)) transport.setScopeChallengeResolver((context) => this.resolveScopeChallenge(context)); return await this.server.connect(transport); } /** * Closes the connection. */ async close() { await this.server.close(); } /** @internal */ resolveScopeChallenge = (context) => { switch (context.request.method) { case "tools/call": { const toolName = context.request.params?.name; if (typeof toolName !== "string") return; const tool = this._registeredTools[toolName]; if (tool === void 0 || !tool.enabled) return; return tool.scopeChallenge?.(context); } case "resources/read": { const resourceUri = context.request.params?.uri; if (typeof resourceUri !== "string") return; let uri; try { uri = new URL(resourceUri); } catch { return; } const resource = this._registeredResources[uri.toString()]; if (resource !== void 0) return resource.enabled ? resource.scopeChallenge?.(context) : void 0; for (const template of Object.values(this._registeredResourceTemplates)) if (template.resourceTemplate.uriTemplate.match(uri.toString())) return template.enabled ? template.scopeChallenge?.(context) : void 0; return; } case "prompts/get": { const promptName = context.request.params?.name; if (typeof promptName !== "string") return; const prompt = this._registeredPrompts[promptName]; if (prompt === void 0 || !prompt.enabled) return; return prompt.scopeChallenge?.(context); } default: return; } }; _toolHandlersInitialized = false; setToolRequestHandlers() { if (this._toolHandlersInitialized) return; this.server.assertCanSetRequestHandler("tools/list"); this.server.assertCanSetRequestHandler("tools/call"); this.server.registerCapabilities({ tools: { listChanged: this.server.getCapabilities().tools?.listChanged ?? true } }); this.server.setRequestHandler("tools/list", () => ({ tools: Object.entries(this._registeredTools).filter(([, tool]) => tool.enabled).map(([name, tool]) => { const toolDefinition = { name, title: tool.title, description: tool.description, inputSchema: tool.inputSchema ? convertListedInputSchema(name, tool.inputSchema) : EMPTY_OBJECT_JSON_SCHEMA, annotations: tool.annotations, icons: tool.icons, execution: tool.execution, _meta: tool._meta }; if (tool.outputSchema) toolDefinition.outputSchema = require_src.standardSchemaToJsonSchema(tool.outputSchema, "output"); return toolDefinition; }) })); this.server.setRequestHandler("tools/call", async (request, ctx) => { const tool = this._registeredTools[request.params.name]; if (!tool) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Tool ${request.params.name} not found`); if (!tool.enabled) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Tool ${request.params.name} disabled`); try { const args = await this.validateToolInput(tool, request.params.arguments, request.params.name); const result = await this.executeToolHandler(tool, args, ctx); await this.validateToolOutput(tool, result, request.params.name); if (require_src.isInputRequiredResult(result)) return result; return this.server.projectCallToolResult(result, tool.outputSchemaJson); } catch (error) { if (error instanceof require_src.ProtocolError && error.code === require_src.ProtocolErrorCode.UrlElicitationRequired) throw error; return this.createToolError(error instanceof Error ? error.message : String(error)); } }); this._toolHandlersInitialized = true; } /** * Creates a tool error result. * * @param errorMessage - The error message. * @returns The tool error result. */ createToolError(errorMessage) { return { content: [{ type: "text", text: errorMessage }], isError: true }; } /** * Validates tool input arguments against the tool's input schema. */ async validateToolInput(tool, args, toolName) { if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`); if (!tool.inputSchema) return; const parseResult = await require_src.validateStandardSchema(tool.inputSchema, args ?? {}); if (!parseResult.success) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${parseResult.error}`); return parseResult.data; } /** * Validates tool output against the tool's output schema. */ async validateToolOutput(tool, result, toolName) { if (!tool.outputSchema) return; if (require_src.isInputRequiredResult(result)) return; if (result.isError) return; if (result.structuredContent === void 0) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Output validation error: Tool ${toolName} has an output schema but no structured content was provided`); const parseResult = await require_src.validateStandardSchema(tool.outputSchema, result.structuredContent); if (!parseResult.success) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${parseResult.error}`); } /** * Executes a tool handler. */ async executeToolHandler(tool, args, ctx) { return tool.executor(args, ctx); } _completionHandlerInitialized = false; setCompletionRequestHandler() { if (this._completionHandlerInitialized) return; this.server.assertCanSetRequestHandler("completion/complete"); this.server.registerCapabilities({ completions: {} }); this.server.setRequestHandler("completion/complete", async (request) => { switch (request.params.ref.type) { case "ref/prompt": require_src.assertCompleteRequestPrompt(request); return this.handlePromptCompletion(request, request.params.ref); case "ref/resource": require_src.assertCompleteRequestResourceTemplate(request); return this.handleResourceCompletion(request, request.params.ref); default: throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Invalid completion reference: ${request.params.ref}`); } }); this._completionHandlerInitialized = true; } async handlePromptCompletion(request, ref) { const prompt = this._registeredPrompts[ref.name]; if (!prompt) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} not found`); if (!prompt.enabled) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} disabled`); if (!prompt.argsSchema) return EMPTY_COMPLETION_RESULT; const field = unwrapOptionalSchema(getSchemaShape(prompt.argsSchema)?.[request.params.argument.name]); if (!isCompletable(field)) return EMPTY_COMPLETION_RESULT; const completer = getCompleter(field); if (!completer) return EMPTY_COMPLETION_RESULT; return createCompletionResult(await completer(request.params.argument.value, request.params.context)); } async handleResourceCompletion(request, ref) { const template = Object.values(this._registeredResourceTemplates).find((t) => t.resourceTemplate.uriTemplate.toString() === ref.uri); if (!template) { if (this._registeredResources[ref.uri]) return EMPTY_COMPLETION_RESULT; throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Resource template ${request.params.ref.uri} not found`); } const completer = template.resourceTemplate.completeCallback(request.params.argument.name); if (!completer) return EMPTY_COMPLETION_RESULT; return createCompletionResult(await completer(request.params.argument.value, request.params.context)); } _resourceHandlersInitialized = false; setResourceRequestHandlers() { if (this._resourceHandlersInitialized) return; this.server.assertCanSetRequestHandler("resources/list"); this.server.assertCanSetRequestHandler("resources/templates/list"); this.server.assertCanSetRequestHandler("resources/read"); this.server.registerCapabilities({ resources: { listChanged: this.server.getCapabilities().resources?.listChanged ?? true } }); this.server.setRequestHandler("resources/list", async (_request, ctx) => { const resources = Object.entries(this._registeredResources).filter(([_, resource]) => resource.enabled).map(([uri, resource]) => ({ uri, name: resource.name, ...resource.metadata })); const templateResources = []; for (const template of Object.values(this._registeredResourceTemplates)) { if (!template.resourceTemplate.listCallback) continue; const result = await template.resourceTemplate.listCallback(ctx); for (const resource of result.resources) templateResources.push({ ...template.metadata, ...resource }); } return { resources: [...resources, ...templateResources] }; }); this.server.setRequestHandler("resources/templates/list", async () => { return { resourceTemplates: Object.entries(this._registeredResourceTemplates).map(([name, template]) => ({ name, uriTemplate: template.resourceTemplate.uriTemplate.toString(), ...template.metadata })) }; }); this.server.setRequestHandler("resources/read", async (request, ctx) => { let uri; try { uri = new URL(request.params.uri); } catch { throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Resource URI ${request.params.uri} is invalid`, { uri: request.params.uri, reason: "invalid_uri" }); } const resource = this._registeredResources[uri.toString()]; if (resource) { if (!resource.enabled) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Resource ${uri} disabled`); return require_src.attachCacheHintFallback(await resource.readCallback(uri, ctx), resource.cacheHint); } for (const template of Object.values(this._registeredResourceTemplates)) { const variables = template.resourceTemplate.uriTemplate.match(uri.toString()); if (variables) { if (!template.enabled) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Resource template ${template.resourceTemplate.uriTemplate} disabled`); return require_src.attachCacheHintFallback(await template.readCallback(uri, variables, ctx), template.cacheHint); } } throw new require_src.ResourceNotFoundError(request.params.uri); }); this._resourceHandlersInitialized = true; } _promptHandlersInitialized = false; setPromptRequestHandlers() { if (this._promptHandlersInitialized) return; this.server.assertCanSetRequestHandler("prompts/list"); this.server.assertCanSetRequestHandler("prompts/get"); this.server.registerCapabilities({ prompts: { listChanged: this.server.getCapabilities().prompts?.listChanged ?? true } }); this.server.setRequestHandler("prompts/list", () => ({ prompts: Object.entries(this._registeredPrompts).filter(([, prompt]) => prompt.enabled).map(([name, prompt]) => { return { name, title: prompt.title, description: prompt.description, arguments: prompt.argsSchema ? require_src.promptArgumentsFromStandardSchema(prompt.argsSchema) : void 0, icons: prompt.icons, _meta: prompt._meta }; }) })); this.server.setRequestHandler("prompts/get", async (request, ctx) => { const prompt = this._registeredPrompts[request.params.name]; if (!prompt) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Prompt ${request.params.name} not found`); if (!prompt.enabled) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Prompt ${request.params.name} disabled`); return prompt.handler(request.params.arguments, ctx); }); this._promptHandlersInitialized = true; } registerResource(name, uriOrTemplate, config, readCallback) { const { cacheHint, scopeChallenge, ...resourceMetadata } = config; const metadata = resourceMetadata; if (cacheHint !== void 0) require_src.assertValidCacheHint(cacheHint, `resource ${name}`); if (typeof uriOrTemplate === "string") { if (this._registeredResources[uriOrTemplate]) throw new Error(`Resource ${uriOrTemplate} is already registered`); const registeredResource = this._createRegisteredResource(name, config.title, uriOrTemplate, metadata, scopeChallenge, readCallback); if (cacheHint !== void 0) registeredResource.cacheHint = cacheHint; this.setResourceRequestHandlers(); this.sendResourceListChanged(); return registeredResource; } else { if (this._registeredResourceTemplates[name]) throw new Error(`Resource template ${name} is already registered`); const registeredResourceTemplate = this._createRegisteredResourceTemplate(name, config.title, uriOrTemplate, metadata, scopeChallenge, readCallback); if (cacheHint !== void 0) registeredResourceTemplate.cacheHint = cacheHint; this.setResourceRequestHandlers(); this.sendResourceListChanged(); return registeredResourceTemplate; } } _createRegisteredResource(name, title, uri, metadata, scopeChallenge, readCallback) { const registeredResource = { name, title, metadata, readCallback, scopeChallenge, enabled: true, disable: () => registeredResource.update({ enabled: false }), enable: () => registeredResource.update({ enabled: true }), remove: () => registeredResource.update({ uri: null }), update: (updates) => { if (updates.uri !== void 0 && updates.uri !== uri) { delete this._registeredResources[uri]; if (updates.uri) this._registeredResources[updates.uri] = registeredResource; } if (updates.name !== void 0) registeredResource.name = updates.name; if (updates.title !== void 0) registeredResource.title = updates.title; if (updates.metadata !== void 0) registeredResource.metadata = updates.metadata; if (updates.callback !== void 0) registeredResource.readCallback = updates.callback; if (updates.scopeChallenge !== void 0) registeredResource.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge; if (updates.enabled !== void 0) registeredResource.enabled = updates.enabled; this.sendResourceListChanged(); } }; this._registeredResources[uri] = registeredResource; return registeredResource; } _createRegisteredResourceTemplate(name, title, template, metadata, scopeChallenge, readCallback) { const registeredResourceTemplate = { resourceTemplate: template, title, metadata, readCallback, scopeChallenge, enabled: true, disable: () => registeredResourceTemplate.update({ enabled: false }), enable: () => registeredResourceTemplate.update({ enabled: true }), remove: () => registeredResourceTemplate.update({ name: null }), update: (updates) => { if (updates.name !== void 0 && updates.name !== name) { delete this._registeredResourceTemplates[name]; if (updates.name) this._registeredResourceTemplates[updates.name] = registeredResourceTemplate; } if (updates.title !== void 0) registeredResourceTemplate.title = updates.title; if (updates.template !== void 0) registeredResourceTemplate.resourceTemplate = updates.template; if (updates.metadata !== void 0) registeredResourceTemplate.metadata = updates.metadata; if (updates.callback !== void 0) registeredResourceTemplate.readCallback = updates.callback; if (updates.scopeChallenge !== void 0) registeredResourceTemplate.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge; if (updates.enabled !== void 0) registeredResourceTemplate.enabled = updates.enabled; this.sendResourceListChanged(); } }; this._registeredResourceTemplates[name] = registeredResourceTemplate; const variableNames = template.uriTemplate.variableNames; if (Array.isArray(variableNames) && variableNames.some((v) => !!template.completeCallback(v))) this.setCompletionRequestHandler(); return registeredResourceTemplate; } _createRegisteredPrompt(name, title, description, argsSchema, callback, icons, scopeChallenge, _meta) { let currentArgsSchema = argsSchema; let currentCallback = callback; const registeredPrompt = { title, description, argsSchema, icons, scopeChallenge, _meta, handler: createPromptHandler(name, argsSchema, callback), enabled: true, disable: () => registeredPrompt.update({ enabled: false }), enable: () => registeredPrompt.update({ enabled: true }), remove: () => registeredPrompt.update({ name: null }), update: (updates) => { if (updates.name !== void 0 && updates.name !== name) { delete this._registeredPrompts[name]; if (updates.name) this._registeredPrompts[updates.name] = registeredPrompt; } if (updates.title !== void 0) registeredPrompt.title = updates.title; if (updates.description !== void 0) registeredPrompt.description = updates.description; if (updates.icons !== void 0) registeredPrompt.icons = updates.icons; if (updates.scopeChallenge !== void 0) registeredPrompt.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge; if (updates._meta !== void 0) registeredPrompt._meta = updates._meta; let needsHandlerRegen = false; if (updates.argsSchema !== void 0) { registeredPrompt.argsSchema = updates.argsSchema; currentArgsSchema = updates.argsSchema; needsHandlerRegen = true; } if (updates.callback !== void 0) { currentCallback = updates.callback; needsHandlerRegen = true; } if (needsHandlerRegen) registeredPrompt.handler = createPromptHandler(name, currentArgsSchema, currentCallback); if (updates.enabled !== void 0) registeredPrompt.enabled = updates.enabled; this.sendPromptListChanged(); } }; this._registeredPrompts[name] = registeredPrompt; if (argsSchema) { const shape = getSchemaShape(argsSchema); if (shape) { if (Object.values(shape).some((field) => { return isCompletable(unwrapOptionalSchema(field)); })) this.setCompletionRequestHandler(); } } return registeredPrompt; } _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, scopeChallenge, _meta, handler) { require_src.validateAndWarnToolName(name); let currentHandler = handler; let outputSchemaJson; const registeredTool = { title, description, inputSchema, outputSchema, get outputSchemaJson() { return outputSchemaJson ??= convertOutputSchemaJson(registeredTool.outputSchema); }, set outputSchemaJson(value) { outputSchemaJson = value; }, annotations, icons, execution, scopeChallenge, _meta, handler, executor: createToolExecutor(inputSchema, handler), enabled: true, disable: () => registeredTool.update({ enabled: false }), enable: () => registeredTool.update({ enabled: true }), remove: () => registeredTool.update({ name: null }), update: (updates) => { if (updates.name !== void 0 && updates.name !== name) { if (typeof updates.name === "string") require_src.validateAndWarnToolName(updates.name); delete this._registeredTools[name]; delete this._toolInputSchemaJson[name]; if (updates.name) { delete this._toolInputSchemaJson[updates.name]; this._registeredTools[updates.name] = registeredTool; name = updates.name; } } if (updates.title !== void 0) registeredTool.title = updates.title; if (updates.description !== void 0) registeredTool.description = updates.description; let needsExecutorRegen = false; if (updates.paramsSchema !== void 0) { registeredTool.inputSchema = updates.paramsSchema; delete this._toolInputSchemaJson[name]; needsExecutorRegen = true; } if (updates.callback !== void 0) { registeredTool.handler = updates.callback; currentHandler = updates.callback; needsExecutorRegen = true; } if (needsExecutorRegen) registeredTool.executor = createToolExecutor(registeredTool.inputSchema, currentHandler); if (updates.outputSchema !== void 0) { registeredTool.outputSchema = updates.outputSchema; registeredTool.outputSchemaJson = convertOutputSchemaJson(updates.outputSchema); } if (updates.annotations !== void 0) registeredTool.annotations = updates.annotations; if (updates.icons !== void 0) registeredTool.icons = updates.icons; if (updates.scopeChallenge !== void 0) registeredTool.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge; if (updates._meta !== void 0) registeredTool._meta = updates._meta; if (updates.enabled !== void 0) registeredTool.enabled = updates.enabled; this.sendToolListChanged(); } }; this._registeredTools[name] = registeredTool; this.setToolRequestHandlers(); this.sendToolListChanged(); return registeredTool; } registerTool(name, config, cb) { if (this._registeredTools[name]) throw new Error(`Tool ${name} is already registered`); const { title, description, inputSchema, outputSchema, annotations, icons, scopeChallenge, _meta } = config; return this._createRegisteredTool(name, title, description, require_src.normalizeRawShapeSchema(inputSchema), require_src.normalizeRawShapeSchema(outputSchema), annotations, icons, void 0, scopeChallenge, _meta, cb); } registerPrompt(name, config, cb) { if (this._registeredPrompts[name]) throw new Error(`Prompt ${name} is already registered`); const { title, description, argsSchema, icons, scopeChallenge, _meta } = config; const registeredPrompt = this._createRegisteredPrompt(name, title, description, require_src.normalizeRawShapeSchema(argsSchema), cb, icons, scopeChallenge, _meta); this.setPromptRequestHandlers(); this.sendPromptListChanged(); return registeredPrompt; } /** * Checks if the server is connected to a transport. * @returns `true` if the server is connected */ isConnected() { return this.server.transport !== void 0; } /** * Sends a logging message to the client, if connected. * Note: You only need to send the parameters object, not the entire JSON-RPC message. * @see {@linkcode LoggingMessageNotification} * @param params * @param sessionId Optional for stateless transports and backward compatibility. * * @example * ```ts source="./mcp.examples.ts#McpServer_sendLoggingMessage_basic" * await server.sendLoggingMessage({ * level: 'info', * data: 'Processing complete' * }); * ``` * * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577). * Remains functional during the deprecation window (at least twelve months). * Migrate to stderr logging (STDIO servers) or OpenTelemetry. */ async sendLoggingMessage(params, sessionId) { return this.server.sendLoggingMessage(params, sessionId); } /** * Sends a resource list changed event to the client, if connected. */ sendResourceListChanged() { if (this.isConnected()) this.server.sendResourceListChanged(); } /** * Sends a tool list changed event to the client, if connected. */ sendToolListChanged() { if (this.isConnected()) this.server.sendToolListChanged(); } /** * Sends a prompt list changed event to the client, if connected. */ sendPromptListChanged() { if (this.isConnected()) this.server.sendPromptListChanged(); } }; /** * A resource template combines a URI pattern with optional functionality to enumerate * all resources matching that pattern. */ var ResourceTemplate = class { _uriTemplate; constructor(uriTemplate, _callbacks) { this._callbacks = _callbacks; this._uriTemplate = typeof uriTemplate === "string" ? new require_src.UriTemplate(uriTemplate) : uriTemplate; } /** * Gets the URI template pattern. */ get uriTemplate() { return this._uriTemplate; } /** * Gets the list callback, if one was provided. */ get listCallback() { return this._callbacks.list; } /** * Gets the callback for completing a specific URI template variable, if one was provided. */ completeCallback(variable) { return this._callbacks.complete?.[variable]; } }; /** * Creates an executor that invokes the handler with the appropriate arguments. * When `inputSchema` is defined, the handler is called with `(args, ctx)`. * When `inputSchema` is undefined, the handler is called with just `(ctx)`. */ function createToolExecutor(inputSchema, handler) { if (inputSchema) { const callback$1 = handler; return async (args, ctx) => callback$1(args, ctx); } const callback = handler; return async (_args, ctx) => callback(ctx); } const EMPTY_OBJECT_JSON_SCHEMA = { type: "object", properties: {} }; /** Converts a tool's `inputSchema` for `tools/list` and warns on an invalid SEP-2243 `x-mcp-header` declaration. */ function convertListedInputSchema(name, inputSchema) { const json = require_src.standardSchemaToJsonSchema(inputSchema, "input"); const scan = require_src.scanXMcpHeaderDeclarations(json); if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`); return json; } /** * Convert a registered `outputSchema` to JSON Schema, memoised on {@link RegisteredTool.outputSchemaJson} * so `tools/call` passes the SAME advertised schema to the wire codec's `projectCallToolResult` that * `tools/list` emits (and that the 2025 codec's `encodeResult('tools/list', …)` may wrap). A conversion * failure yields `undefined` so the failure surfaces where it always has (`tools/list`). */ function convertOutputSchemaJson(outputSchema) { if (outputSchema === void 0) return void 0; try { return require_src.standardSchemaToJsonSchema(outputSchema, "output"); } catch { return; } } /** * Creates a type-safe prompt handler that captures the schema and callback in a closure. * This eliminates the need for type assertions at the call site. */ function createPromptHandler(name, argsSchema, callback) { if (argsSchema) { const typedCallback = callback; return async (args, ctx) => { const parseResult = await require_src.validateStandardSchema(argsSchema, args ?? {}); if (!parseResult.success) throw new require_src.ProtocolError(require_src.ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`); return typedCallback(parseResult.data, ctx); }; } else { const typedCallback = callback; return async (_args, ctx) => { return typedCallback(ctx); }; } } function createCompletionResult(suggestions) { return { completion: { values: suggestions.map(String).slice(0, 100), total: suggestions.length, hasMore: suggestions.length > 100 } }; } const EMPTY_COMPLETION_RESULT = { completion: { values: [], hasMore: false } }; /** @internal Gets the shape of a Zod object schema */ function getSchemaShape(schema) { const candidate = schema; if (candidate.shape && typeof candidate.shape === "object") return candidate.shape; } /** @internal Checks if a Zod schema is optional */ function isOptionalSchema(schema) { return schema?.type === "optional"; } /** @internal Unwraps an optional Zod schema */ function unwrapOptionalSchema(schema) { if (!isOptionalSchema(schema)) return schema; return schema.def?.innerType ?? schema; } //#endregion Object.defineProperty(exports, 'DEFAULT_MAX_SUBSCRIPTIONS', { enumerable: true, get: function () { return DEFAULT_MAX_SUBSCRIPTIONS; } }); Object.defineProperty(exports, 'DEFAULT_SSE_KEEP_ALIVE_MS', { enumerable: true, get: function () { return DEFAULT_SSE_KEEP_ALIVE_MS; } }); Object.defineProperty(exports, 'InMemoryServerEventBus', { enumerable: true, get: function () { return InMemoryServerEventBus; } }); Object.defineProperty(exports, 'McpServer', { enumerable: true, get: function () { return McpServer; } }); Object.defineProperty(exports, 'ResourceTemplate', { enumerable: true, get: function () { return ResourceTemplate; } }); Object.defineProperty(exports, 'Server', { enumerable: true, get: function () { return Server; } }); Object.defineProperty(exports, 'StdioListenRouter', { enumerable: true, get: function () { return StdioListenRouter; } }); Object.defineProperty(exports, 'armSseKeepAlive', { enumerable: true, get: function () { return armSseKeepAlive; } }); Object.defineProperty(exports, 'bearerAuthChallengeResponse', { enumerable: true, get: function () { return bearerAuthChallengeResponse; } }); Object.defineProperty(exports, 'buildOAuthProtectedResourceMetadata', { enumerable: true, get: function () { return buildOAuthProtectedResourceMetadata; } }); Object.defineProperty(exports, 'completable', { enumerable: true, get: function () { return completable; } }); Object.defineProperty(exports, 'createListenRouter', { enumerable: true, get: function () { return createListenRouter; } }); Object.defineProperty(exports, 'createScopeChallengeResponse', { enumerable: true, get: function () { return createScopeChallengeResponse; } }); Object.defineProperty(exports, 'createServerNotifier', { enumerable: true, get: function () { return createServerNotifier; } }); Object.defineProperty(exports, 'findScopeChallenge', { enumerable: true, get: function () { return findScopeChallenge; } }); Object.defineProperty(exports, 'getOAuthProtectedResourceMetadataUrl', { enumerable: true, get: function () { return getOAuthProtectedResourceMetadataUrl; } }); Object.defineProperty(exports, 'installModernOnlyHandlers', { enumerable: true, get: function () { return installModernOnlyHandlers; } }); Object.defineProperty(exports, 'isCompletable', { enumerable: true, get: function () { return isCompletable; } }); Object.defineProperty(exports, 'oauthMetadataResponse', { enumerable: true, get: function () { return oauthMetadataResponse; } }); Object.defineProperty(exports, 'requireBearerAuth', { enumerable: true, get: function () { return requireBearerAuth; } }); Object.defineProperty(exports, 'requireScopes', { enumerable: true, get: function () { return requireScopes; } }); Object.defineProperty(exports, 'scopeChallengeResourceMetadataUrl', { enumerable: true, get: function () { return scopeChallengeResourceMetadataUrl; } }); Object.defineProperty(exports, 'seedClientIdentityFromEnvelope', { enumerable: true, get: function () { return seedClientIdentityFromEnvelope; } }); Object.defineProperty(exports, 'serverIdentityOf', { enumerable: true, get: function () { return serverIdentityOf; } }); Object.defineProperty(exports, 'verifyBearerToken', { enumerable: true, get: function () { return verifyBearerToken; } }); //# sourceMappingURL=mcp-BumlNux0.cjs.map