UNPKG

mcp-proxy

Version:

A TypeScript SSE proxy for MCP servers that use stdio transport.

1,120 lines (1,110 loc) 90 kB
import { C as NEVER, S as _coercedNumber, T as AuthenticationMiddleware, _ as looseObject, a as startHTTPServer, b as string, c as LATEST_PROTOCOL_VERSION, d as isJSONRPCResponse, f as ZodNumber, g as literal, h as boolean, i as Client, l as isInitializedNotification, m as array, n as serializeMessage, o as proxyServer, p as any, r as Server, s as JSONRPCMessageSchema, t as ReadBuffer, u as isJSONRPCRequest, v as number$1, w as InMemoryEventStore, x as url, y as object } from "./stdio-DBuYn6eo.mjs"; import process from "node:process"; //#region node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/compat.js /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */ const ZodIssueCode = { invalid_type: "invalid_type", too_big: "too_big", too_small: "too_small", invalid_format: "invalid_format", not_multiple_of: "not_multiple_of", unrecognized_keys: "unrecognized_keys", invalid_union: "invalid_union", invalid_key: "invalid_key", invalid_element: "invalid_element", invalid_value: "invalid_value", custom: "custom" }; //#endregion //#region node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/coerce.js function number(params) { return _coercedNumber(ZodNumber, params); } //#endregion //#region node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.js var ParseError = class extends Error { constructor(message, options) { super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line; } }; function noop(_arg) {} function createParser(callbacks) { if (typeof callbacks == "function") throw new TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"); const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks; let incompleteLine = "", isFirstChunk = !0, id, data = "", eventType = ""; function feed(newChunk) { const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`); for (const line of complete) parseLine(line); incompleteLine = incomplete, isFirstChunk = !1; } function parseLine(line) { if (line === "") { dispatchEvent(); return; } if (line.startsWith(":")) { onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1)); return; } const fieldSeparatorIndex = line.indexOf(":"); if (fieldSeparatorIndex !== -1) { const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1; processField(field, line.slice(fieldSeparatorIndex + offset), line); return; } processField(line, "", line); } function processField(field, value, line) { switch (field) { case "event": eventType = value; break; case "data": data = `${data}${value} `; break; case "id": id = value.includes("\0") ? void 0 : value; break; case "retry": /^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(new ParseError(`Invalid \`retry\` value: "${value}"`, { type: "invalid-retry", value, line })); break; default: onError(new ParseError(`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`, { type: "unknown-field", field, value, line })); break; } } function dispatchEvent() { data.length > 0 && onEvent({ id, event: eventType || void 0, data: data.endsWith(` `) ? data.slice(0, -1) : data }), id = void 0, data = "", eventType = ""; } function reset(options = {}) { incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = !0, id = void 0, data = "", eventType = "", incompleteLine = ""; } return { feed, reset }; } function splitLines(chunk) { const lines = []; let incompleteLine = "", searchIndex = 0; for (; searchIndex < chunk.length;) { const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(` `, searchIndex); let lineEnd = -1; if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) { incompleteLine = chunk.slice(searchIndex); break; } else { const line = chunk.slice(searchIndex, lineEnd); lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === ` ` && searchIndex++; } } return [lines, incompleteLine]; } //#endregion //#region node_modules/.pnpm/eventsource@3.0.7/node_modules/eventsource/dist/index.js var ErrorEvent = class extends Event { /** * Constructs a new `ErrorEvent` instance. This is typically not called directly, * but rather emitted by the `EventSource` object when an error occurs. * * @param type - The type of the event (should be "error") * @param errorEventInitDict - Optional properties to include in the error event */ constructor(type, errorEventInitDict) { var _a, _b; super(type), this.code = (_a = errorEventInitDict == null ? void 0 : errorEventInitDict.code) != null ? _a : void 0, this.message = (_b = errorEventInitDict == null ? void 0 : errorEventInitDict.message) != null ? _b : void 0; } /** * Node.js "hides" the `message` and `code` properties of the `ErrorEvent` instance, * when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging, * we explicitly include the properties in the `inspect` method. * * This is automatically called by Node.js when you `console.log` an instance of this class. * * @param _depth - The current depth * @param options - The options passed to `util.inspect` * @param inspect - The inspect function to use (prevents having to import it from `util`) * @returns A string representation of the error */ [Symbol.for("nodejs.util.inspect.custom")](_depth, options, inspect) { return inspect(inspectableError(this), options); } /** * Deno "hides" the `message` and `code` properties of the `ErrorEvent` instance, * when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging, * we explicitly include the properties in the `inspect` method. * * This is automatically called by Deno when you `console.log` an instance of this class. * * @param inspect - The inspect function to use (prevents having to import it from `util`) * @param options - The options passed to `Deno.inspect` * @returns A string representation of the error */ [Symbol.for("Deno.customInspect")](inspect, options) { return inspect(inspectableError(this), options); } }; function syntaxError(message) { const DomException = globalThis.DOMException; return typeof DomException == "function" ? new DomException(message, "SyntaxError") : new SyntaxError(message); } function flattenError(err) { return err instanceof Error ? "errors" in err && Array.isArray(err.errors) ? err.errors.map(flattenError).join(", ") : "cause" in err && err.cause instanceof Error ? `${err}: ${flattenError(err.cause)}` : err.message : `${err}`; } function inspectableError(err) { return { type: err.type, message: err.message, code: err.code, defaultPrevented: err.defaultPrevented, cancelable: err.cancelable, timeStamp: err.timeStamp }; } var __typeError = (msg) => { throw TypeError(msg); }, __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg), __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)), __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value), __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value), __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method), _readyState, _url, _redirectUrl, _withCredentials, _fetch, _reconnectInterval, _reconnectTimer, _lastEventId, _controller, _parser, _onError, _onMessage, _onOpen, _EventSource_instances, connect_fn, _onFetchResponse, _onFetchError, getRequestOptions_fn, _onEvent, _onRetryChange, failConnection_fn, scheduleReconnect_fn, _reconnect; var EventSource = class extends EventTarget { constructor(url$1, eventSourceInitDict) { var _a, _b; super(), __privateAdd(this, _EventSource_instances), this.CONNECTING = 0, this.OPEN = 1, this.CLOSED = 2, __privateAdd(this, _readyState), __privateAdd(this, _url), __privateAdd(this, _redirectUrl), __privateAdd(this, _withCredentials), __privateAdd(this, _fetch), __privateAdd(this, _reconnectInterval), __privateAdd(this, _reconnectTimer), __privateAdd(this, _lastEventId, null), __privateAdd(this, _controller), __privateAdd(this, _parser), __privateAdd(this, _onError, null), __privateAdd(this, _onMessage, null), __privateAdd(this, _onOpen, null), __privateAdd(this, _onFetchResponse, async (response) => { var _a2; __privateGet(this, _parser).reset(); const { body, redirected, status, headers } = response; if (status === 204) { __privateMethod(this, _EventSource_instances, failConnection_fn).call(this, "Server sent HTTP 204, not reconnecting", 204), this.close(); return; } if (redirected ? __privateSet(this, _redirectUrl, new URL(response.url)) : __privateSet(this, _redirectUrl, void 0), status !== 200) { __privateMethod(this, _EventSource_instances, failConnection_fn).call(this, `Non-200 status code (${status})`, status); return; } if (!(headers.get("content-type") || "").startsWith("text/event-stream")) { __privateMethod(this, _EventSource_instances, failConnection_fn).call(this, "Invalid content type, expected \"text/event-stream\"", status); return; } if (__privateGet(this, _readyState) === this.CLOSED) return; __privateSet(this, _readyState, this.OPEN); const openEvent = new Event("open"); if ((_a2 = __privateGet(this, _onOpen)) == null || _a2.call(this, openEvent), this.dispatchEvent(openEvent), typeof body != "object" || !body || !("getReader" in body)) { __privateMethod(this, _EventSource_instances, failConnection_fn).call(this, "Invalid response body, expected a web ReadableStream", status), this.close(); return; } const decoder = new TextDecoder(), reader = body.getReader(); let open = !0; do { const { done, value } = await reader.read(); value && __privateGet(this, _parser).feed(decoder.decode(value, { stream: !done })), done && (open = !1, __privateGet(this, _parser).reset(), __privateMethod(this, _EventSource_instances, scheduleReconnect_fn).call(this)); } while (open); }), __privateAdd(this, _onFetchError, (err) => { __privateSet(this, _controller, void 0), !(err.name === "AbortError" || err.type === "aborted") && __privateMethod(this, _EventSource_instances, scheduleReconnect_fn).call(this, flattenError(err)); }), __privateAdd(this, _onEvent, (event) => { typeof event.id == "string" && __privateSet(this, _lastEventId, event.id); const messageEvent = new MessageEvent(event.event || "message", { data: event.data, origin: __privateGet(this, _redirectUrl) ? __privateGet(this, _redirectUrl).origin : __privateGet(this, _url).origin, lastEventId: event.id || "" }); __privateGet(this, _onMessage) && (!event.event || event.event === "message") && __privateGet(this, _onMessage).call(this, messageEvent), this.dispatchEvent(messageEvent); }), __privateAdd(this, _onRetryChange, (value) => { __privateSet(this, _reconnectInterval, value); }), __privateAdd(this, _reconnect, () => { __privateSet(this, _reconnectTimer, void 0), __privateGet(this, _readyState) === this.CONNECTING && __privateMethod(this, _EventSource_instances, connect_fn).call(this); }); try { if (url$1 instanceof URL) __privateSet(this, _url, url$1); else if (typeof url$1 == "string") __privateSet(this, _url, new URL(url$1, getBaseURL())); else throw new Error("Invalid URL"); } catch { throw syntaxError("An invalid or illegal string was specified"); } __privateSet(this, _parser, createParser({ onEvent: __privateGet(this, _onEvent), onRetry: __privateGet(this, _onRetryChange) })), __privateSet(this, _readyState, this.CONNECTING), __privateSet(this, _reconnectInterval, 3e3), __privateSet(this, _fetch, (_a = eventSourceInitDict == null ? void 0 : eventSourceInitDict.fetch) != null ? _a : globalThis.fetch), __privateSet(this, _withCredentials, (_b = eventSourceInitDict == null ? void 0 : eventSourceInitDict.withCredentials) != null ? _b : !1), __privateMethod(this, _EventSource_instances, connect_fn).call(this); } /** * Returns the state of this EventSource object's connection. It can have the values described below. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/readyState) * * Note: typed as `number` instead of `0 | 1 | 2` for compatibility with the `EventSource` interface, * defined in the TypeScript `dom` library. * * @public */ get readyState() { return __privateGet(this, _readyState); } /** * Returns the URL providing the event stream. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/url) * * @public */ get url() { return __privateGet(this, _url).href; } /** * Returns true if the credentials mode for connection requests to the URL providing the event stream is set to "include", and false otherwise. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/withCredentials) */ get withCredentials() { return __privateGet(this, _withCredentials); } /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/error_event) */ get onerror() { return __privateGet(this, _onError); } set onerror(value) { __privateSet(this, _onError, value); } /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/message_event) */ get onmessage() { return __privateGet(this, _onMessage); } set onmessage(value) { __privateSet(this, _onMessage, value); } /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/open_event) */ get onopen() { return __privateGet(this, _onOpen); } set onopen(value) { __privateSet(this, _onOpen, value); } addEventListener(type, listener, options) { const listen = listener; super.addEventListener(type, listen, options); } removeEventListener(type, listener, options) { const listen = listener; super.removeEventListener(type, listen, options); } /** * Aborts any instances of the fetch algorithm started for this EventSource object, and sets the readyState attribute to CLOSED. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventSource/close) * * @public */ close() { __privateGet(this, _reconnectTimer) && clearTimeout(__privateGet(this, _reconnectTimer)), __privateGet(this, _readyState) !== this.CLOSED && (__privateGet(this, _controller) && __privateGet(this, _controller).abort(), __privateSet(this, _readyState, this.CLOSED), __privateSet(this, _controller, void 0)); } }; _readyState = /* @__PURE__ */ new WeakMap(), _url = /* @__PURE__ */ new WeakMap(), _redirectUrl = /* @__PURE__ */ new WeakMap(), _withCredentials = /* @__PURE__ */ new WeakMap(), _fetch = /* @__PURE__ */ new WeakMap(), _reconnectInterval = /* @__PURE__ */ new WeakMap(), _reconnectTimer = /* @__PURE__ */ new WeakMap(), _lastEventId = /* @__PURE__ */ new WeakMap(), _controller = /* @__PURE__ */ new WeakMap(), _parser = /* @__PURE__ */ new WeakMap(), _onError = /* @__PURE__ */ new WeakMap(), _onMessage = /* @__PURE__ */ new WeakMap(), _onOpen = /* @__PURE__ */ new WeakMap(), _EventSource_instances = /* @__PURE__ */ new WeakSet(), connect_fn = function() { __privateSet(this, _readyState, this.CONNECTING), __privateSet(this, _controller, new AbortController()), __privateGet(this, _fetch)(__privateGet(this, _url), __privateMethod(this, _EventSource_instances, getRequestOptions_fn).call(this)).then(__privateGet(this, _onFetchResponse)).catch(__privateGet(this, _onFetchError)); }, _onFetchResponse = /* @__PURE__ */ new WeakMap(), _onFetchError = /* @__PURE__ */ new WeakMap(), getRequestOptions_fn = function() { var _a; const init = { mode: "cors", redirect: "follow", headers: { Accept: "text/event-stream", ...__privateGet(this, _lastEventId) ? { "Last-Event-ID": __privateGet(this, _lastEventId) } : void 0 }, cache: "no-store", signal: (_a = __privateGet(this, _controller)) == null ? void 0 : _a.signal }; return "window" in globalThis && (init.credentials = this.withCredentials ? "include" : "same-origin"), init; }, _onEvent = /* @__PURE__ */ new WeakMap(), _onRetryChange = /* @__PURE__ */ new WeakMap(), failConnection_fn = function(message, code) { var _a; __privateGet(this, _readyState) !== this.CLOSED && __privateSet(this, _readyState, this.CLOSED); const errorEvent = new ErrorEvent("error", { code, message }); (_a = __privateGet(this, _onError)) == null || _a.call(this, errorEvent), this.dispatchEvent(errorEvent); }, scheduleReconnect_fn = function(message, code) { var _a; if (__privateGet(this, _readyState) === this.CLOSED) return; __privateSet(this, _readyState, this.CONNECTING); const errorEvent = new ErrorEvent("error", { code, message }); (_a = __privateGet(this, _onError)) == null || _a.call(this, errorEvent), this.dispatchEvent(errorEvent), __privateSet(this, _reconnectTimer, setTimeout(__privateGet(this, _reconnect), __privateGet(this, _reconnectInterval))); }, _reconnect = /* @__PURE__ */ new WeakMap(), EventSource.CONNECTING = 0, EventSource.OPEN = 1, EventSource.CLOSED = 2; function getBaseURL() { const doc = "document" in globalThis ? globalThis.document : void 0; return doc && typeof doc == "object" && "baseURI" in doc && typeof doc.baseURI == "string" ? doc.baseURI : void 0; } //#endregion //#region node_modules/.pnpm/@modelcontextprotocol+sdk@1.24.3_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.js /** * Normalizes HeadersInit to a plain Record<string, string> for manipulation. * Handles Headers objects, arrays of tuples, and plain objects. */ function normalizeHeaders(headers) { if (!headers) return {}; if (headers instanceof Headers) return Object.fromEntries(headers.entries()); if (Array.isArray(headers)) return Object.fromEntries(headers); return { ...headers }; } /** * Creates a fetch function that includes base RequestInit options. * This ensures requests inherit settings like credentials, mode, headers, etc. from the base init. * * @param baseFetch - The base fetch function to wrap (defaults to global fetch) * @param baseInit - The base RequestInit to merge with each request * @returns A wrapped fetch function that merges base options with call-specific options */ function createFetchWithInit(baseFetch = fetch, baseInit) { if (!baseInit) return baseFetch; return async (url$1, init) => { return baseFetch(url$1, { ...baseInit, ...init, headers: (init === null || init === void 0 ? void 0 : init.headers) ? { ...normalizeHeaders(baseInit.headers), ...normalizeHeaders(init.headers) } : baseInit.headers }); }; } //#endregion //#region node_modules/.pnpm/pkce-challenge@5.0.0/node_modules/pkce-challenge/dist/index.node.js let crypto; crypto = globalThis.crypto?.webcrypto ?? globalThis.crypto ?? import("node:crypto").then((m) => m.webcrypto); /** * Creates an array of length `size` of random bytes * @param size * @returns Array of random ints (0 to 255) */ async function getRandomValues(size) { return (await crypto).getRandomValues(new Uint8Array(size)); } /** Generate cryptographically strong random string * @param size The desired length of the string * @returns The random string */ async function random(size) { const mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"; let result = ""; const randomUints = await getRandomValues(size); for (let i = 0; i < size; i++) { const randomIndex = randomUints[i] % 66; result += mask[randomIndex]; } return result; } /** Generate a PKCE challenge verifier * @param length Length of the verifier * @returns A random verifier `length` characters long */ async function generateVerifier(length) { return await random(length); } /** Generate a PKCE code challenge from a code verifier * @param code_verifier * @returns The base64 url encoded code challenge */ async function generateChallenge(code_verifier) { const buffer = await (await crypto).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier)); return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, ""); } /** Generate a PKCE challenge pair * @param length Length of the verifer (between 43-128). Defaults to 43. * @returns PKCE challenge pair */ async function pkceChallenge(length) { if (!length) length = 43; if (length < 43 || length > 128) throw `Expected a length between 43 and 128. Received ${length}.`; const verifier = await generateVerifier(length); return { code_verifier: verifier, code_challenge: await generateChallenge(verifier) }; } //#endregion //#region node_modules/.pnpm/@modelcontextprotocol+sdk@1.24.3_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js /** * Reusable URL validation that disallows javascript: scheme */ const SafeUrlSchema = url().superRefine((val, ctx) => { if (!URL.canParse(val)) { ctx.addIssue({ code: ZodIssueCode.custom, message: "URL must be parseable", fatal: true }); return NEVER; } }).refine((url$1) => { const u = new URL(url$1); return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:"; }, { message: "URL cannot use javascript:, data:, or vbscript: scheme" }); /** * RFC 9728 OAuth Protected Resource Metadata */ const OAuthProtectedResourceMetadataSchema = looseObject({ resource: string().url(), authorization_servers: array(SafeUrlSchema).optional(), jwks_uri: string().url().optional(), scopes_supported: array(string()).optional(), bearer_methods_supported: array(string()).optional(), resource_signing_alg_values_supported: array(string()).optional(), resource_name: string().optional(), resource_documentation: string().optional(), resource_policy_uri: string().url().optional(), resource_tos_uri: string().url().optional(), tls_client_certificate_bound_access_tokens: boolean().optional(), authorization_details_types_supported: array(string()).optional(), dpop_signing_alg_values_supported: array(string()).optional(), dpop_bound_access_tokens_required: boolean().optional() }); /** * RFC 8414 OAuth 2.0 Authorization Server Metadata */ const OAuthMetadataSchema = looseObject({ issuer: string(), authorization_endpoint: SafeUrlSchema, token_endpoint: SafeUrlSchema, registration_endpoint: SafeUrlSchema.optional(), scopes_supported: array(string()).optional(), response_types_supported: array(string()), response_modes_supported: array(string()).optional(), grant_types_supported: array(string()).optional(), token_endpoint_auth_methods_supported: array(string()).optional(), token_endpoint_auth_signing_alg_values_supported: array(string()).optional(), service_documentation: SafeUrlSchema.optional(), revocation_endpoint: SafeUrlSchema.optional(), revocation_endpoint_auth_methods_supported: array(string()).optional(), revocation_endpoint_auth_signing_alg_values_supported: array(string()).optional(), introspection_endpoint: string().optional(), introspection_endpoint_auth_methods_supported: array(string()).optional(), introspection_endpoint_auth_signing_alg_values_supported: array(string()).optional(), code_challenge_methods_supported: array(string()).optional(), client_id_metadata_document_supported: boolean().optional() }); /** * OpenID Connect Discovery 1.0 Provider Metadata * see: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata */ const OpenIdProviderMetadataSchema = looseObject({ issuer: string(), authorization_endpoint: SafeUrlSchema, token_endpoint: SafeUrlSchema, userinfo_endpoint: SafeUrlSchema.optional(), jwks_uri: SafeUrlSchema, registration_endpoint: SafeUrlSchema.optional(), scopes_supported: array(string()).optional(), response_types_supported: array(string()), response_modes_supported: array(string()).optional(), grant_types_supported: array(string()).optional(), acr_values_supported: array(string()).optional(), subject_types_supported: array(string()), id_token_signing_alg_values_supported: array(string()), id_token_encryption_alg_values_supported: array(string()).optional(), id_token_encryption_enc_values_supported: array(string()).optional(), userinfo_signing_alg_values_supported: array(string()).optional(), userinfo_encryption_alg_values_supported: array(string()).optional(), userinfo_encryption_enc_values_supported: array(string()).optional(), request_object_signing_alg_values_supported: array(string()).optional(), request_object_encryption_alg_values_supported: array(string()).optional(), request_object_encryption_enc_values_supported: array(string()).optional(), token_endpoint_auth_methods_supported: array(string()).optional(), token_endpoint_auth_signing_alg_values_supported: array(string()).optional(), display_values_supported: array(string()).optional(), claim_types_supported: array(string()).optional(), claims_supported: array(string()).optional(), service_documentation: string().optional(), claims_locales_supported: array(string()).optional(), ui_locales_supported: array(string()).optional(), claims_parameter_supported: boolean().optional(), request_parameter_supported: boolean().optional(), request_uri_parameter_supported: boolean().optional(), require_request_uri_registration: boolean().optional(), op_policy_uri: SafeUrlSchema.optional(), op_tos_uri: SafeUrlSchema.optional(), client_id_metadata_document_supported: boolean().optional() }); /** * OpenID Connect Discovery metadata that may include OAuth 2.0 fields * This schema represents the real-world scenario where OIDC providers * return a mix of OpenID Connect and OAuth 2.0 metadata fields */ const OpenIdProviderDiscoveryMetadataSchema = object({ ...OpenIdProviderMetadataSchema.shape, ...OAuthMetadataSchema.pick({ code_challenge_methods_supported: true }).shape }); /** * OAuth 2.1 token response */ const OAuthTokensSchema = object({ access_token: string(), id_token: string().optional(), token_type: string(), expires_in: number().optional(), scope: string().optional(), refresh_token: string().optional() }).strip(); /** * OAuth 2.1 error response */ const OAuthErrorResponseSchema = object({ error: string(), error_description: string().optional(), error_uri: string().optional() }); /** * Optional version of SafeUrlSchema that allows empty string for retrocompatibility on tos_uri and logo_uri */ const OptionalSafeUrlSchema = SafeUrlSchema.optional().or(literal("").transform(() => void 0)); /** * RFC 7591 OAuth 2.0 Dynamic Client Registration metadata */ const OAuthClientMetadataSchema = object({ redirect_uris: array(SafeUrlSchema), token_endpoint_auth_method: string().optional(), grant_types: array(string()).optional(), response_types: array(string()).optional(), client_name: string().optional(), client_uri: SafeUrlSchema.optional(), logo_uri: OptionalSafeUrlSchema, scope: string().optional(), contacts: array(string()).optional(), tos_uri: OptionalSafeUrlSchema, policy_uri: string().optional(), jwks_uri: SafeUrlSchema.optional(), jwks: any().optional(), software_id: string().optional(), software_version: string().optional(), software_statement: string().optional() }).strip(); /** * RFC 7591 OAuth 2.0 Dynamic Client Registration client information */ const OAuthClientInformationSchema = object({ client_id: string(), client_secret: string().optional(), client_id_issued_at: number$1().optional(), client_secret_expires_at: number$1().optional() }).strip(); /** * RFC 7591 OAuth 2.0 Dynamic Client Registration full response (client information plus metadata) */ const OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema); /** * RFC 7591 OAuth 2.0 Dynamic Client Registration error response */ const OAuthClientRegistrationErrorSchema = object({ error: string(), error_description: string().optional() }).strip(); /** * RFC 7009 OAuth 2.0 Token Revocation request */ const OAuthTokenRevocationRequestSchema = object({ token: string(), token_type_hint: string().optional() }).strip(); //#endregion //#region node_modules/.pnpm/@modelcontextprotocol+sdk@1.24.3_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth-utils.js /** * Utilities for handling OAuth resource URIs. */ /** * Converts a server URL to a resource URL by removing the fragment. * RFC 8707 section 2 states that resource URIs "MUST NOT include a fragment component". * Keeps everything else unchanged (scheme, domain, port, path, query). */ function resourceUrlFromServerUrl(url$1) { const resourceURL = typeof url$1 === "string" ? new URL(url$1) : new URL(url$1.href); resourceURL.hash = ""; return resourceURL; } /** * Checks if a requested resource URL matches a configured resource URL. * A requested resource matches if it has the same scheme, domain, port, * and its path starts with the configured resource's path. * * @param requestedResource The resource URL being requested * @param configuredResource The resource URL that has been configured * @returns true if the requested resource matches the configured resource, false otherwise */ function checkResourceAllowed({ requestedResource, configuredResource }) { const requested = typeof requestedResource === "string" ? new URL(requestedResource) : new URL(requestedResource.href); const configured = typeof configuredResource === "string" ? new URL(configuredResource) : new URL(configuredResource.href); if (requested.origin !== configured.origin) return false; if (requested.pathname.length < configured.pathname.length) return false; const requestedPath = requested.pathname.endsWith("/") ? requested.pathname : requested.pathname + "/"; const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/"; return requestedPath.startsWith(configuredPath); } //#endregion //#region node_modules/.pnpm/@modelcontextprotocol+sdk@1.24.3_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js /** * Base class for all OAuth errors */ var OAuthError = class extends Error { constructor(message, errorUri) { super(message); this.errorUri = errorUri; this.name = this.constructor.name; } /** * Converts the error to a standard OAuth error response object */ toResponseObject() { const response = { error: this.errorCode, error_description: this.message }; if (this.errorUri) response.error_uri = this.errorUri; return response; } get errorCode() { return this.constructor.errorCode; } }; /** * Invalid request error - The request is missing a required parameter, * includes an invalid parameter value, includes a parameter more than once, * or is otherwise malformed. */ var InvalidRequestError = class extends OAuthError {}; InvalidRequestError.errorCode = "invalid_request"; /** * Invalid client error - Client authentication failed (e.g., unknown client, no client * authentication included, or unsupported authentication method). */ var InvalidClientError = class extends OAuthError {}; InvalidClientError.errorCode = "invalid_client"; /** * Invalid grant error - The provided authorization grant or refresh token is * invalid, expired, revoked, does not match the redirection URI used in the * authorization request, or was issued to another client. */ var InvalidGrantError = class extends OAuthError {}; InvalidGrantError.errorCode = "invalid_grant"; /** * Unauthorized client error - The authenticated client is not authorized to use * this authorization grant type. */ var UnauthorizedClientError = class extends OAuthError {}; UnauthorizedClientError.errorCode = "unauthorized_client"; /** * Unsupported grant type error - The authorization grant type is not supported * by the authorization server. */ var UnsupportedGrantTypeError = class extends OAuthError {}; UnsupportedGrantTypeError.errorCode = "unsupported_grant_type"; /** * Invalid scope error - The requested scope is invalid, unknown, malformed, or * exceeds the scope granted by the resource owner. */ var InvalidScopeError = class extends OAuthError {}; InvalidScopeError.errorCode = "invalid_scope"; /** * Access denied error - The resource owner or authorization server denied the request. */ var AccessDeniedError = class extends OAuthError {}; AccessDeniedError.errorCode = "access_denied"; /** * Server error - The authorization server encountered an unexpected condition * that prevented it from fulfilling the request. */ var ServerError = class extends OAuthError {}; ServerError.errorCode = "server_error"; /** * Temporarily unavailable error - The authorization server is currently unable to * handle the request due to a temporary overloading or maintenance of the server. */ var TemporarilyUnavailableError = class extends OAuthError {}; TemporarilyUnavailableError.errorCode = "temporarily_unavailable"; /** * Unsupported response type error - The authorization server does not support * obtaining an authorization code using this method. */ var UnsupportedResponseTypeError = class extends OAuthError {}; UnsupportedResponseTypeError.errorCode = "unsupported_response_type"; /** * Unsupported token type error - The authorization server does not support * the requested token type. */ var UnsupportedTokenTypeError = class extends OAuthError {}; UnsupportedTokenTypeError.errorCode = "unsupported_token_type"; /** * Invalid token error - The access token provided is expired, revoked, malformed, * or invalid for other reasons. */ var InvalidTokenError = class extends OAuthError {}; InvalidTokenError.errorCode = "invalid_token"; /** * Method not allowed error - The HTTP method used is not allowed for this endpoint. * (Custom, non-standard error) */ var MethodNotAllowedError = class extends OAuthError {}; MethodNotAllowedError.errorCode = "method_not_allowed"; /** * Too many requests error - Rate limit exceeded. * (Custom, non-standard error based on RFC 6585) */ var TooManyRequestsError = class extends OAuthError {}; TooManyRequestsError.errorCode = "too_many_requests"; /** * Invalid client metadata error - The client metadata is invalid. * (Custom error for dynamic client registration - RFC 7591) */ var InvalidClientMetadataError = class extends OAuthError {}; InvalidClientMetadataError.errorCode = "invalid_client_metadata"; /** * Insufficient scope error - The request requires higher privileges than provided by the access token. */ var InsufficientScopeError = class extends OAuthError {}; InsufficientScopeError.errorCode = "insufficient_scope"; /** * Invalid target error - The requested resource is invalid, missing, unknown, or malformed. * (Custom error for resource indicators - RFC 8707) */ var InvalidTargetError = class extends OAuthError {}; InvalidTargetError.errorCode = "invalid_target"; /** * A full list of all OAuthErrors, enabling parsing from error responses */ const OAUTH_ERRORS = { [InvalidRequestError.errorCode]: InvalidRequestError, [InvalidClientError.errorCode]: InvalidClientError, [InvalidGrantError.errorCode]: InvalidGrantError, [UnauthorizedClientError.errorCode]: UnauthorizedClientError, [UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError, [InvalidScopeError.errorCode]: InvalidScopeError, [AccessDeniedError.errorCode]: AccessDeniedError, [ServerError.errorCode]: ServerError, [TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError, [UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError, [UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError, [InvalidTokenError.errorCode]: InvalidTokenError, [MethodNotAllowedError.errorCode]: MethodNotAllowedError, [TooManyRequestsError.errorCode]: TooManyRequestsError, [InvalidClientMetadataError.errorCode]: InvalidClientMetadataError, [InsufficientScopeError.errorCode]: InsufficientScopeError, [InvalidTargetError.errorCode]: InvalidTargetError }; //#endregion //#region node_modules/.pnpm/@modelcontextprotocol+sdk@1.24.3_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js var UnauthorizedError = class extends Error { constructor(message) { super(message !== null && message !== void 0 ? message : "Unauthorized"); } }; function isClientAuthMethod(method) { return [ "client_secret_basic", "client_secret_post", "none" ].includes(method); } const AUTHORIZATION_CODE_RESPONSE_TYPE = "code"; const AUTHORIZATION_CODE_CHALLENGE_METHOD = "S256"; /** * Determines the best client authentication method to use based on server support and client configuration. * * Priority order (highest to lowest): * 1. client_secret_basic (if client secret is available) * 2. client_secret_post (if client secret is available) * 3. none (for public clients) * * @param clientInformation - OAuth client information containing credentials * @param supportedMethods - Authentication methods supported by the authorization server * @returns The selected authentication method */ function selectClientAuthMethod(clientInformation, supportedMethods) { const hasClientSecret = clientInformation.client_secret !== void 0; if (supportedMethods.length === 0) return hasClientSecret ? "client_secret_post" : "none"; if ("token_endpoint_auth_method" in clientInformation && clientInformation.token_endpoint_auth_method && isClientAuthMethod(clientInformation.token_endpoint_auth_method) && supportedMethods.includes(clientInformation.token_endpoint_auth_method)) return clientInformation.token_endpoint_auth_method; if (hasClientSecret && supportedMethods.includes("client_secret_basic")) return "client_secret_basic"; if (hasClientSecret && supportedMethods.includes("client_secret_post")) return "client_secret_post"; if (supportedMethods.includes("none")) return "none"; return hasClientSecret ? "client_secret_post" : "none"; } /** * Applies client authentication to the request based on the specified method. * * Implements OAuth 2.1 client authentication methods: * - client_secret_basic: HTTP Basic authentication (RFC 6749 Section 2.3.1) * - client_secret_post: Credentials in request body (RFC 6749 Section 2.3.1) * - none: Public client authentication (RFC 6749 Section 2.1) * * @param method - The authentication method to use * @param clientInformation - OAuth client information containing credentials * @param headers - HTTP headers object to modify * @param params - URL search parameters to modify * @throws {Error} When required credentials are missing */ function applyClientAuthentication(method, clientInformation, headers, params) { const { client_id, client_secret } = clientInformation; switch (method) { case "client_secret_basic": applyBasicAuth(client_id, client_secret, headers); return; case "client_secret_post": applyPostAuth(client_id, client_secret, params); return; case "none": applyPublicAuth(client_id, params); return; default: throw new Error(`Unsupported client authentication method: ${method}`); } } /** * Applies HTTP Basic authentication (RFC 6749 Section 2.3.1) */ function applyBasicAuth(clientId, clientSecret, headers) { if (!clientSecret) throw new Error("client_secret_basic authentication requires a client_secret"); const credentials = btoa(`${clientId}:${clientSecret}`); headers.set("Authorization", `Basic ${credentials}`); } /** * Applies POST body authentication (RFC 6749 Section 2.3.1) */ function applyPostAuth(clientId, clientSecret, params) { params.set("client_id", clientId); if (clientSecret) params.set("client_secret", clientSecret); } /** * Applies public client authentication (RFC 6749 Section 2.1) */ function applyPublicAuth(clientId, params) { params.set("client_id", clientId); } /** * Parses an OAuth error response from a string or Response object. * * If the input is a standard OAuth2.0 error response, it will be parsed according to the spec * and an instance of the appropriate OAuthError subclass will be returned. * If parsing fails, it falls back to a generic ServerError that includes * the response status (if available) and original content. * * @param input - A Response object or string containing the error response * @returns A Promise that resolves to an OAuthError instance */ async function parseErrorResponse(input) { const statusCode = input instanceof Response ? input.status : void 0; const body = input instanceof Response ? await input.text() : input; try { const { error, error_description, error_uri } = OAuthErrorResponseSchema.parse(JSON.parse(body)); return new (OAUTH_ERRORS[error] || ServerError)(error_description || "", error_uri); } catch (error) { return new ServerError(`${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error}. Raw body: ${body}`); } } /** * Orchestrates the full auth flow with a server. * * This can be used as a single entry point for all authorization functionality, * instead of linking together the other lower-level functions in this module. */ async function auth(provider, options) { var _a, _b; try { return await authInternal(provider, options); } catch (error) { if (error instanceof InvalidClientError || error instanceof UnauthorizedClientError) { await ((_a = provider.invalidateCredentials) === null || _a === void 0 ? void 0 : _a.call(provider, "all")); return await authInternal(provider, options); } else if (error instanceof InvalidGrantError) { await ((_b = provider.invalidateCredentials) === null || _b === void 0 ? void 0 : _b.call(provider, "tokens")); return await authInternal(provider, options); } throw error; } } async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) { var _a, _b; let resourceMetadata; let authorizationServerUrl; try { resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl }, fetchFn); if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) authorizationServerUrl = resourceMetadata.authorization_servers[0]; } catch (_c) {} /** * If we don't get a valid authorization server metadata from protected resource metadata, * fallback to the legacy MCP spec's implementation (version 2025-03-26): MCP server base URL acts as the Authorization server. */ if (!authorizationServerUrl) authorizationServerUrl = new URL("/", serverUrl); const resource = await selectResourceURL(serverUrl, provider, resourceMetadata); const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn }); let clientInformation = await Promise.resolve(provider.clientInformation()); if (!clientInformation) { if (authorizationCode !== void 0) throw new Error("Existing OAuth client information is required when exchanging an authorization code"); const supportsUrlBasedClientId = (metadata === null || metadata === void 0 ? void 0 : metadata.client_id_metadata_document_supported) === true; const clientMetadataUrl = provider.clientMetadataUrl; if (clientMetadataUrl && !isHttpsUrl(clientMetadataUrl)) throw new InvalidClientMetadataError(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${clientMetadataUrl}`); if (supportsUrlBasedClientId && clientMetadataUrl) { clientInformation = { client_id: clientMetadataUrl }; await ((_a = provider.saveClientInformation) === null || _a === void 0 ? void 0 : _a.call(provider, clientInformation)); } else { if (!provider.saveClientInformation) throw new Error("OAuth client information must be saveable for dynamic registration"); const fullInformation = await registerClient(authorizationServerUrl, { metadata, clientMetadata: provider.clientMetadata, fetchFn }); await provider.saveClientInformation(fullInformation); clientInformation = fullInformation; } } const nonInteractiveFlow = !provider.redirectUrl; if (authorizationCode !== void 0 || nonInteractiveFlow) { const tokens$1 = await fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn }); await provider.saveTokens(tokens$1); return "AUTHORIZED"; } const tokens = await provider.tokens(); if (tokens === null || tokens === void 0 ? void 0 : tokens.refresh_token) try { const newTokens = await refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken: tokens.refresh_token, resource, addClientAuthentication: provider.addClientAuthentication, fetchFn }); await provider.saveTokens(newTokens); return "AUTHORIZED"; } catch (error) { if (!(error instanceof OAuthError) || error instanceof ServerError) {} else throw error; } const state = provider.state ? await provider.state() : void 0; const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, { metadata, clientInformation, state, redirectUrl: provider.redirectUrl, scope: scope || ((_b = resourceMetadata === null || resourceMetadata === void 0 ? void 0 : resourceMetadata.scopes_supported) === null || _b === void 0 ? void 0 : _b.join(" ")) || provider.clientMetadata.scope, resource }); await provider.saveCodeVerifier(codeVerifier); await provider.redirectToAuthorization(authorizationUrl); return "REDIRECT"; } /** * SEP-991: URL-based Client IDs * Validate that the client_id is a valid URL with https scheme */ function isHttpsUrl(value) { if (!value) return false; try { const url$1 = new URL(value); return url$1.protocol === "https:" && url$1.pathname !== "/"; } catch (_a) { return false; } } async function selectResourceURL(serverUrl, provider, resourceMetadata) { const defaultResource = resourceUrlFromServerUrl(serverUrl); if (provider.validateResourceURL) return await provider.validateResourceURL(defaultResource, resourceMetadata === null || resourceMetadata === void 0 ? void 0 : resourceMetadata.resource); if (!resourceMetadata) return; if (!checkResourceAllowed({ requestedResource: defaultResource, configuredResource: resourceMetadata.resource })) throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`); return new URL(resourceMetadata.resource); } /** * Extract resource_metadata, scope, and error from WWW-Authenticate header. */ function extractWWWAuthenticateParams(res) { const authenticateHeader = res.headers.get("WWW-Authenticate"); if (!authenticateHeader) return {}; const [type, scheme] = authenticateHeader.split(" "); if (type.toLowerCase() !== "bearer" || !scheme) return {}; const resourceMetadataMatch = extractFieldFromWwwAuth(res, "resource_metadata") || void 0; let resourceMetadataUrl; if (resourceMetadataMatch) try { resourceMetadataUrl = new URL(resourceMetadataMatch); } catch (_a) {} const scope = extractFieldFromWwwAuth(res, "scope") || void 0; const error = extractFieldFromWwwAuth(res, "error") || void 0; return { resourceMetadataUrl, scope, error }; } /** * Extracts a specific field's value from the WWW-Authenticate header string. * * @param response The HTTP response object containing the headers. * @param fieldName The name of the field to extract (e.g., "realm", "nonce"). * @returns The field value */ function extractFieldFromWwwAuth(response, fieldName) { const wwwAuthHeader = response.headers.get("WWW-Authenticate"); if (!wwwAuthHeader) return null; const pattern = /* @__PURE__ */ new RegExp(`${fieldName}=(?:"([^"]+)"|([^\\s,]+))`); const match = wwwAuthHeader.match(pattern); if (match) return match[1] || match[2]; return null; } /** * Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata. * * If the server returns a 404 for the well-known endpoint, this function will * return `undefined`. Any other errors will be thrown as exceptions. */ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) { var _a, _b; const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, { protocolVersion: opts === null || opts === void 0 ? void 0 : opts.protocolVersion, metadataUrl: opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl }); if (!response || response.status === 404) { await ((_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.cancel()); throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`); } if (!response.ok) { await ((_b = response.body) === null || _b === void 0 ? void 0 : _b.cancel()); throw new Error(`HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`); } return OAuthProtectedResourceMetadataSchema.parse(await response.json()); } /** * Helper function to handle fetch with CORS retry logic */ async function fetchWithCorsRetry(url$1, headers, fetchFn = fetch) { try { return await fetchFn(url$1, { headers }); } catch (error) { if (error instanceof TypeError) if (headers) return fetchWithCorsRetry(url$1, void 0, fetchFn); else return; throw error; } } /** * Constructs the well-known path for auth-related metadata discovery */ function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) { if (pathname.endsWith("/")) pathname = pathname.slice(0, -1); return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`; } /** * Tries to discover OAuth metadata at a specific URL */ async function tryM