@earendil-works/pi-mcp 0.99.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.1] - 2026-10-03
4
+
5
+ ### Breaking Changes
6
+
7
+ - `OAuthClientProvider.clientMetadataUrl` is replaced by `clientMetadataDocument(metadata)`, which returns the document URL and its redirect URI per authorization server, or `undefined` to register dynamically. It is called whenever no client information is stored, also when the server does not advertise support, and the document is no longer stored as client information ([#10302](https://github.com/earendil-works/pi/issues/10302))
8
+
9
+ ### Added
10
+
11
+ - `McpOAuthProviderOptions.clientMetadataDocument`, `OAuthCallbackServerOptions.extraPaths`, and a `path` argument for `OAuthCallbackServer.waitForCallback` that rejects responses on other paths ([#10302](https://github.com/earendil-works/pi/issues/10302))
12
+
13
+ ## [1.0.0] - 2026-10-01
14
+
15
+ ### Added
16
+
17
+ - Added an `authorizationServerMetadataUrl` option to `authorizeMcp()` to use a configured authorization server metadata document instead of discovery ([#10172](https://github.com/earendil-works/pi/issues/10172)).
18
+ - Added an `iss` option to `authorizeMcp()`. The authorization code is only exchanged when `iss` names the flow's authorization server, or is absent and the server's metadata does not set `authorization_response_iss_parameter_supported` (RFC 9207).
19
+ - Added `stepUpScope()`, which combines the scopes of an `insufficient_scope` challenge with the scopes granted so far.
20
+
21
+ ### Fixed
22
+
23
+ - Fixed OAuth token and client registration responses with an empty or `null` optional field (such as `"scope": ""`) failing with `Invalid scope` and similar errors; such fields are now treated as absent ([#10266](https://github.com/earendil-works/pi/issues/10266)).
24
+ - Fixed `expires_in: null` in a token response marking the access token as already expired.
25
+ - Fixed invalid URLs in protected resource metadata aborting OAuth discovery instead of falling back to the MCP server's origin.
26
+ - Fixed an empty requested scope, from `scope=""` in a `WWW-Authenticate` challenge or an empty `scopes_supported`, overriding the next scope source.
27
+ - Fixed list pagination failing with a duplicate cursor error when a server ends pagination with `nextCursor: ""` or `null`.
28
+ - Fixed step-up authorization in `adaptOAuthProvider()` requesting only the scopes of the `insufficient_scope` challenge. The new token lost the scopes granted before, so other requests failed with `insufficient_scope` again. Tokens now record their granted scope, which is the requested scope when the token response omits `scope`.
29
+
3
30
  ## [0.99.2] - 2026-09-30
4
31
 
5
32
  ### Fixed
package/dist/client.js CHANGED
@@ -26,10 +26,11 @@ function validateListPage(method, key, value, isItem) {
26
26
  if (!isObject(item) || !isItem(item))
27
27
  throw invalid(`Invalid entry in MCP ${method} result`);
28
28
  }
29
- if (value.nextCursor !== undefined && typeof value.nextCursor !== "string") {
29
+ // Some servers end pagination with `null` or `""` instead of omitting the cursor.
30
+ const nextCursor = value.nextCursor === null || value.nextCursor === "" ? undefined : value.nextCursor;
31
+ if (nextCursor !== undefined && typeof nextCursor !== "string")
30
32
  throw invalid(`Invalid MCP ${method} cursor`);
31
- }
32
- return { items, ...(value.nextCursor === undefined ? {} : { nextCursor: value.nextCursor }) };
33
+ return { items, ...(nextCursor === undefined ? {} : { nextCursor }) };
33
34
  }
34
35
  const isTool = (tool) => typeof tool.name === "string" && isObject(tool.inputSchema);
35
36
  // `name` is required by the spec, but some servers omit it; the URI stands in.
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CallToolResult } from \"./protocol/content.ts\";\nimport {\n\tisJsonRpcId,\n\tisJsonRpcNotification,\n\tisJsonRpcRequest,\n\tisJsonRpcResponse,\n\tisObject,\n\tJSON_RPC_ERROR_CODES,\n\ttype JsonRpcId,\n\ttype JsonRpcMessage,\n\ttype JsonRpcRequest,\n\ttype JsonRpcResponse,\n\tMcpAbortError,\n\tMcpConnectionClosedError,\n\tMcpError,\n\tMcpTimeoutError,\n\ttoError,\n} from \"./protocol/jsonrpc.ts\";\nimport {\n\ttype ClientCapabilities,\n\ttype Implementation,\n\ttype InitializeResult,\n\tLATEST_PROTOCOL_VERSION,\n\ttype ListResourcesResult,\n\ttype ListResourceTemplatesResult,\n\ttype ProgressNotification,\n\ttype ReadResourceResult,\n\ttype Resource,\n\ttype ResourceTemplate,\n\ttype Root,\n\ttype ServerCapabilities,\n\tSUPPORTED_PROTOCOL_VERSIONS,\n\ttype SupportedProtocolVersion,\n\ttype Tool,\n} from \"./protocol/types.ts\";\nimport type { McpTransport } from \"./transports/transport.ts\";\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst MAX_LIST_PAGES = 1_000;\n\ntype ClientState = \"idle\" | \"connecting\" | \"connected\" | \"closed\";\ntype NotificationListener = (params: unknown) => void;\ntype ErrorListener = (error: Error) => void;\ntype CloseListener = () => void;\ntype RequestHandler = (params: unknown, context: { signal: AbortSignal }) => unknown | Promise<unknown>;\n\nexport interface McpClientOptions extends Implementation {\n\tcapabilities?: ClientCapabilities;\n\tprotocolVersion?: SupportedProtocolVersion;\n\trequestTimeoutMs?: number;\n\troots?: readonly Root[] | (() => readonly Root[] | Promise<readonly Root[]>);\n}\n\nexport interface McpRequestOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n\tonProgress?: (progress: ProgressNotification) => void;\n}\n\ninterface PendingRequest {\n\tresolve: (value: unknown) => void;\n\treject: (reason: unknown) => void;\n\ttimeoutMs: number;\n\ttimer: ReturnType<typeof setTimeout> | undefined;\n\tsignal: AbortSignal | undefined;\n\tonAbort: () => void;\n\tcancellable: boolean;\n\tonProgress: ((progress: ProgressNotification) => void) | undefined;\n\tprogressToken: JsonRpcId | undefined;\n}\n\nfunction validateInitializeResult(value: unknown): InitializeResult {\n\tif (\n\t\t!isObject(value) ||\n\t\ttypeof value.protocolVersion !== \"string\" ||\n\t\t!isObject(value.capabilities) ||\n\t\t!isObject(value.serverInfo) ||\n\t\ttypeof value.serverInfo.name !== \"string\" ||\n\t\ttypeof value.serverInfo.version !== \"string\" ||\n\t\t(value.instructions !== undefined && typeof value.instructions !== \"string\")\n\t) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP initialize result\");\n\t}\n\treturn value as unknown as InitializeResult;\n}\n\nfunction invalid(message: string): McpError {\n\treturn new McpError(JSON_RPC_ERROR_CODES.invalidRequest, message);\n}\n\n/** One page of a paginated list: the items under `key`, each checked by `isItem`. */\nfunction validateListPage(\n\tmethod: string,\n\tkey: string,\n\tvalue: unknown,\n\tisItem: (item: Record<string, unknown>) => boolean,\n): { items: Record<string, unknown>[]; nextCursor?: string } {\n\tconst items = isObject(value) ? value[key] : undefined;\n\tif (!isObject(value) || !Array.isArray(items)) throw invalid(`Invalid MCP ${method} result`);\n\tfor (const item of items) {\n\t\tif (!isObject(item) || !isItem(item)) throw invalid(`Invalid entry in MCP ${method} result`);\n\t}\n\tif (value.nextCursor !== undefined && typeof value.nextCursor !== \"string\") {\n\t\tthrow invalid(`Invalid MCP ${method} cursor`);\n\t}\n\treturn { items, ...(value.nextCursor === undefined ? {} : { nextCursor: value.nextCursor }) };\n}\n\nconst isTool = (tool: Record<string, unknown>) => typeof tool.name === \"string\" && isObject(tool.inputSchema);\n// `name` is required by the spec, but some servers omit it; the URI stands in.\nconst isResource = (resource: Record<string, unknown>) =>\n\ttypeof resource.uri === \"string\" && (resource.name === undefined || typeof resource.name === \"string\");\nconst isResourceTemplate = (template: Record<string, unknown>) =>\n\ttypeof template.uriTemplate === \"string\" && (template.name === undefined || typeof template.name === \"string\");\n\nfunction toResource(item: Record<string, unknown>): Resource {\n\treturn { ...item, name: item.name ?? item.uri } as Resource;\n}\n\nfunction toResourceTemplate(item: Record<string, unknown>): ResourceTemplate {\n\treturn { ...item, name: item.name ?? item.uriTemplate } as ResourceTemplate;\n}\n\nfunction pageCursor(page: { nextCursor?: string }): { nextCursor?: string } {\n\treturn page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor };\n}\n\nfunction validateReadResourceResult(value: unknown): ReadResourceResult {\n\tif (!isObject(value) || !Array.isArray(value.contents)) throw invalid(\"Invalid MCP resources/read result\");\n\tfor (const contents of value.contents) {\n\t\tif (\n\t\t\t!isObject(contents) ||\n\t\t\ttypeof contents.uri !== \"string\" ||\n\t\t\t(typeof contents.text !== \"string\" && typeof contents.blob !== \"string\")\n\t\t) {\n\t\t\tthrow invalid(\"Invalid contents in MCP resources/read result\");\n\t\t}\n\t}\n\treturn value as unknown as ReadResourceResult;\n}\n\n/** `content` is required by the spec, but servers that only return `structuredContent` omit it (the SDK defaults it too). */\nfunction validateCallToolResult(value: unknown): CallToolResult {\n\tif (!isObject(value) || (value.content !== undefined && !Array.isArray(value.content))) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP tools/call result\");\n\t}\n\tif (value.structuredContent !== undefined && !isObject(value.structuredContent)) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP tools/call structured content\");\n\t}\n\treturn (value.content === undefined ? { ...value, content: [] } : value) as unknown as CallToolResult;\n}\n\nexport class McpClient {\n\treadonly options: Readonly<McpClientOptions>;\n\tprivate state: ClientState = \"idle\";\n\tprivate transport: McpTransport | undefined;\n\tprivate nextRequestId = 1;\n\tprivate serverInfoValue: Implementation | undefined;\n\tprivate serverCapabilitiesValue: ServerCapabilities | undefined;\n\tprivate instructionsValue: string | undefined;\n\tprivate protocolVersionValue: string | undefined;\n\tprivate pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate progressRequests = new Map<JsonRpcId, JsonRpcId>();\n\tprivate incoming = new Map<JsonRpcId, AbortController>();\n\tprivate requestHandlers = new Map<string, RequestHandler>();\n\tprivate notificationListeners = new Map<string, Set<NotificationListener>>();\n\tprivate errorListeners = new Set<ErrorListener>();\n\tprivate closeListeners = new Set<CloseListener>();\n\tprivate disposers: (() => void)[] = [];\n\n\tconstructor(options: McpClientOptions) {\n\t\tthis.options = Object.freeze({ ...options });\n\t\tthis.requestHandlers.set(\"ping\", () => ({}));\n\t\tconst roots = options.roots;\n\t\tif (roots) {\n\t\t\tthis.requestHandlers.set(\"roots/list\", async () => ({\n\t\t\t\troots: [...(typeof roots === \"function\" ? await roots() : roots)],\n\t\t\t}));\n\t\t}\n\t}\n\n\tget connectionState(): ClientState {\n\t\treturn this.state;\n\t}\n\n\tget serverInfo(): Implementation | undefined {\n\t\treturn this.serverInfoValue;\n\t}\n\n\tget serverCapabilities(): ServerCapabilities | undefined {\n\t\treturn this.serverCapabilitiesValue;\n\t}\n\n\tget instructions(): string | undefined {\n\t\treturn this.instructionsValue;\n\t}\n\n\tget protocolVersion(): string | undefined {\n\t\treturn this.protocolVersionValue;\n\t}\n\n\tasync connect(transport: McpTransport): Promise<InitializeResult> {\n\t\tif (this.state !== \"idle\") throw new Error(`Cannot connect MCP client in ${this.state} state`);\n\t\tthis.state = \"connecting\";\n\t\tthis.transport = transport;\n\t\tthis.disposers = [\n\t\t\ttransport.onMessage((message) => this.handleMessage(message)),\n\t\t\t// Transport errors are reported only. Pending requests fail when the transport closes.\n\t\t\ttransport.onError((error) => this.emitError(error)),\n\t\t\ttransport.onClose(() => this.handleTransportClose()),\n\t\t];\n\n\t\ttry {\n\t\t\tawait transport.start();\n\t\t\tconst capabilities: ClientCapabilities = { ...this.options.capabilities };\n\t\t\tif (this.options.roots && capabilities.roots === undefined) capabilities.roots = {};\n\t\t\tconst result = validateInitializeResult(\n\t\t\t\tawait this.requestInternal(\n\t\t\t\t\t\"initialize\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocolVersion: this.options.protocolVersion ?? LATEST_PROTOCOL_VERSION,\n\t\t\t\t\t\tcapabilities,\n\t\t\t\t\t\tclientInfo: {\n\t\t\t\t\t\t\tname: this.options.name,\n\t\t\t\t\t\t\tversion: this.options.version,\n\t\t\t\t\t\t\t...(this.options.title === undefined ? {} : { title: this.options.title }),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{},\n\t\t\t\t\ttrue,\n\t\t\t\t),\n\t\t\t);\n\t\t\tif (!(SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(result.protocolVersion)) {\n\t\t\t\tthrow new Error(`MCP server selected unsupported protocol version ${result.protocolVersion}`);\n\t\t\t}\n\t\t\tthis.protocolVersionValue = result.protocolVersion;\n\t\t\tthis.serverInfoValue = result.serverInfo;\n\t\t\tthis.serverCapabilitiesValue = result.capabilities;\n\t\t\tthis.instructionsValue = result.instructions;\n\t\t\ttransport.setProtocolVersion?.(result.protocolVersion);\n\t\t\tawait this.notifyInternal(\"notifications/initialized\", undefined, true);\n\t\t\tthis.state = \"connected\";\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tawait this.close().catch(() => {});\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\trequest<Result = unknown>(\n\t\tmethod: string,\n\t\tparams?: Record<string, unknown>,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<Result> {\n\t\treturn this.requestInternal(method, params, options, false) as Promise<Result>;\n\t}\n\n\tnotify(method: string, params?: Record<string, unknown>): Promise<void> {\n\t\treturn this.notifyInternal(method, params, false);\n\t}\n\n\tsetRequestHandler(method: string, handler: RequestHandler): () => void {\n\t\tthis.requestHandlers.set(method, handler);\n\t\treturn () => {\n\t\t\tif (this.requestHandlers.get(method) === handler) this.requestHandlers.delete(method);\n\t\t};\n\t}\n\n\tonNotification(method: string, listener: NotificationListener): () => void {\n\t\tconst listeners = this.notificationListeners.get(method) ?? new Set<NotificationListener>();\n\t\tthis.notificationListeners.set(method, listeners);\n\t\tlisteners.add(listener);\n\t\treturn () => {\n\t\t\tlisteners.delete(listener);\n\t\t\tif (listeners.size === 0) this.notificationListeners.delete(method);\n\t\t};\n\t}\n\n\tonError(listener: ErrorListener): () => void {\n\t\tthis.errorListeners.add(listener);\n\t\treturn () => this.errorListeners.delete(listener);\n\t}\n\n\t/** Called once when the connection closes, whether the transport dropped or `close()` was called. */\n\tonClose(listener: CloseListener): () => void {\n\t\tthis.closeListeners.add(listener);\n\t\treturn () => this.closeListeners.delete(listener);\n\t}\n\n\tasync ping(options: McpRequestOptions = {}): Promise<void> {\n\t\tawait this.request(\"ping\", undefined, options);\n\t}\n\n\tasync listTools(options: McpRequestOptions = {}): Promise<Tool[]> {\n\t\treturn (await this.listAll(\"tools/list\", \"tools\", isTool, options)) as unknown as Tool[];\n\t}\n\n\t/** Every resource, following `nextCursor` through all pages. */\n\tasync listResources(options: McpRequestOptions = {}): Promise<Resource[]> {\n\t\treturn (await this.listAll(\"resources/list\", \"resources\", isResource, options)).map(toResource);\n\t}\n\n\t/** One page of resources, starting at `cursor`. */\n\tasync listResourcesPage(cursor?: string, options: McpRequestOptions = {}): Promise<ListResourcesResult> {\n\t\tconst page = await this.listPage(\"resources/list\", \"resources\", isResource, cursor, options);\n\t\treturn { resources: page.items.map(toResource), ...pageCursor(page) };\n\t}\n\n\t/** Every resource template, following `nextCursor` through all pages. */\n\tasync listResourceTemplates(options: McpRequestOptions = {}): Promise<ResourceTemplate[]> {\n\t\tconst templates = await this.listAll(\n\t\t\t\"resources/templates/list\",\n\t\t\t\"resourceTemplates\",\n\t\t\tisResourceTemplate,\n\t\t\toptions,\n\t\t);\n\t\treturn templates.map(toResourceTemplate);\n\t}\n\n\t/** One page of resource templates, starting at `cursor`. */\n\tasync listResourceTemplatesPage(\n\t\tcursor?: string,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<ListResourceTemplatesResult> {\n\t\tconst page = await this.listPage(\n\t\t\t\"resources/templates/list\",\n\t\t\t\"resourceTemplates\",\n\t\t\tisResourceTemplate,\n\t\t\tcursor,\n\t\t\toptions,\n\t\t);\n\t\treturn { resourceTemplates: page.items.map(toResourceTemplate), ...pageCursor(page) };\n\t}\n\n\tasync readResource(uri: string, options: McpRequestOptions = {}): Promise<ReadResourceResult> {\n\t\treturn validateReadResourceResult(await this.request(\"resources/read\", { uri }, options));\n\t}\n\n\tprivate async listPage(\n\t\tmethod: string,\n\t\tkey: string,\n\t\tisItem: (item: Record<string, unknown>) => boolean,\n\t\tcursor: string | undefined,\n\t\toptions: McpRequestOptions,\n\t): Promise<{ items: Record<string, unknown>[]; nextCursor?: string }> {\n\t\treturn validateListPage(\n\t\t\tmethod,\n\t\t\tkey,\n\t\t\tawait this.request(method, cursor === undefined ? undefined : { cursor }, options),\n\t\t\tisItem,\n\t\t);\n\t}\n\n\t/** Every item of a paginated list method. */\n\tprivate async listAll(\n\t\tmethod: string,\n\t\tkey: string,\n\t\tisItem: (item: Record<string, unknown>) => boolean,\n\t\toptions: McpRequestOptions,\n\t): Promise<Record<string, unknown>[]> {\n\t\tconst items: Record<string, unknown>[] = [];\n\t\tconst cursors = new Set<string>();\n\t\tlet cursor: string | undefined;\n\t\tfor (let pageNumber = 0; pageNumber < MAX_LIST_PAGES; pageNumber++) {\n\t\t\tconst page = await this.listPage(method, key, isItem, cursor, options);\n\t\t\titems.push(...page.items);\n\t\t\tif (page.nextCursor === undefined) return items;\n\t\t\tif (cursors.has(page.nextCursor))\n\t\t\t\tthrow new Error(`MCP ${method} returned duplicate cursor: ${page.nextCursor}`);\n\t\t\tcursors.add(page.nextCursor);\n\t\t\tcursor = page.nextCursor;\n\t\t}\n\t\tthrow new Error(`MCP ${method} exceeded ${MAX_LIST_PAGES} pages`);\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs?: Record<string, unknown>,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<CallToolResult> {\n\t\treturn validateCallToolResult(\n\t\t\tawait this.request(\"tools/call\", { name, ...(args === undefined ? {} : { arguments: args }) }, options),\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tconst transport = this.transport;\n\t\tthis.transport = undefined;\n\t\tthis.disposeTransportListeners();\n\t\tthis.markClosed(new McpConnectionClosedError());\n\t\tawait transport?.close();\n\t}\n\n\tprivate async requestInternal(\n\t\tmethod: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\toptions: McpRequestOptions,\n\t\tallowConnecting: boolean,\n\t): Promise<unknown> {\n\t\tconst transport = this.requireTransport(allowConnecting);\n\t\tif (options.signal?.aborted) throw new McpAbortError();\n\t\tconst id = this.nextRequestId++;\n\t\tconst progressToken = options.onProgress ? id : undefined;\n\t\tconst requestParams =\n\t\t\tprogressToken === undefined\n\t\t\t\t? params\n\t\t\t\t: { ...params, _meta: { ...(isObject(params?._meta) ? params._meta : {}), progressToken } };\n\t\tconst message: JsonRpcRequest = {\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid,\n\t\t\tmethod,\n\t\t\t...(requestParams === undefined ? {} : { params: requestParams }),\n\t\t};\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\tconst entry: PendingRequest = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t\ttimeoutMs: options.timeoutMs ?? this.options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n\t\t\t\ttimer: undefined,\n\t\t\t\tsignal: options.signal,\n\t\t\t\t// The spec forbids cancelling `initialize`.\n\t\t\t\tonAbort: () =>\n\t\t\t\t\tthis.cancelPending(\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tnew McpAbortError(),\n\t\t\t\t\t\tmethod !== \"initialize\",\n\t\t\t\t\t\tString(options.signal?.reason ?? \"Aborted\"),\n\t\t\t\t\t),\n\t\t\t\tcancellable: method !== \"initialize\",\n\t\t\t\tonProgress: options.onProgress,\n\t\t\t\tprogressToken,\n\t\t\t};\n\t\t\tthis.pending.set(id, entry);\n\t\t\tif (progressToken !== undefined) this.progressRequests.set(progressToken, id);\n\t\t\toptions.signal?.addEventListener(\"abort\", entry.onAbort, { once: true });\n\t\t\tthis.armTimeout(id, entry);\n\t\t\ttransport.send(message).catch((error) => this.cancelPending(id, error, false));\n\t\t});\n\t}\n\n\tprivate async notifyInternal(\n\t\tmethod: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\tallowConnecting: boolean,\n\t): Promise<void> {\n\t\tawait this.requireTransport(allowConnecting).send({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tmethod,\n\t\t\t...(params === undefined ? {} : { params }),\n\t\t});\n\t}\n\n\tprivate requireTransport(allowConnecting: boolean): McpTransport {\n\t\tif (this.transport && (this.state === \"connected\" || (allowConnecting && this.state === \"connecting\"))) {\n\t\t\treturn this.transport;\n\t\t}\n\t\tthrow new McpConnectionClosedError(`MCP client is ${this.state}`);\n\t}\n\n\tprivate handleMessage(message: JsonRpcMessage): void {\n\t\tif (isJsonRpcResponse(message)) {\n\t\t\tthis.handleResponse(message);\n\t\t\treturn;\n\t\t}\n\t\tif (isJsonRpcRequest(message)) {\n\t\t\tvoid this.handleRequest(message);\n\t\t\treturn;\n\t\t}\n\t\tif (isJsonRpcNotification(message)) {\n\t\t\tthis.handleNotification(message.method, message.params);\n\t\t\treturn;\n\t\t}\n\t\tthis.emitError(new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Received invalid JSON-RPC message\"));\n\t}\n\n\tprivate handleResponse(message: JsonRpcResponse): void {\n\t\tconst entry = this.pending.get(message.id);\n\t\tif (!entry) {\n\t\t\tthis.emitError(new Error(`Received response for unknown MCP request ${String(message.id)}`));\n\t\t\treturn;\n\t\t}\n\t\tthis.removePending(message.id, entry);\n\t\tif (\"error\" in message) entry.reject(new McpError(message.error.code, message.error.message, message.error.data));\n\t\telse entry.resolve(message.result);\n\t}\n\n\tprivate async handleRequest(message: JsonRpcRequest): Promise<void> {\n\t\tconst transport = this.transport;\n\t\tif (!transport) return;\n\t\tconst handler = this.requestHandlers.get(message.method);\n\t\tif (!handler) {\n\t\t\tawait transport\n\t\t\t\t.send({\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\tid: message.id,\n\t\t\t\t\terror: { code: JSON_RPC_ERROR_CODES.methodNotFound, message: `Method not found: ${message.method}` },\n\t\t\t\t})\n\t\t\t\t.catch((error) => this.emitError(error));\n\t\t\treturn;\n\t\t}\n\t\tconst controller = new AbortController();\n\t\tthis.incoming.set(message.id, controller);\n\t\ttry {\n\t\t\tconst result = await handler(message.params, { signal: controller.signal });\n\t\t\tawait transport.send({ jsonrpc: \"2.0\", id: message.id, result: result ?? {} });\n\t\t} catch (error) {\n\t\t\tconst responseError =\n\t\t\t\terror instanceof McpError\n\t\t\t\t\t? { code: error.code, message: error.message, data: error.data }\n\t\t\t\t\t: { code: JSON_RPC_ERROR_CODES.internalError, message: toError(error).message };\n\t\t\tawait transport\n\t\t\t\t.send({ jsonrpc: \"2.0\", id: message.id, error: responseError })\n\t\t\t\t.catch((sendError) => this.emitError(sendError));\n\t\t} finally {\n\t\t\tthis.incoming.delete(message.id);\n\t\t}\n\t}\n\n\tprivate handleNotification(method: string, params: unknown): void {\n\t\tif (method === \"notifications/progress\") this.handleProgress(params);\n\t\telse if (method === \"notifications/cancelled\") this.handleCancelled(params);\n\t\tfor (const listener of this.notificationListeners.get(method) ?? []) {\n\t\t\ttry {\n\t\t\t\tlistener(params);\n\t\t\t} catch (error) {\n\t\t\t\tthis.emitError(error);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleProgress(params: unknown): void {\n\t\tif (!isObject(params) || !isJsonRpcId(params.progressToken) || typeof params.progress !== \"number\") return;\n\t\tconst requestId = this.progressRequests.get(params.progressToken);\n\t\tconst entry = requestId === undefined ? undefined : this.pending.get(requestId);\n\t\tif (requestId === undefined || !entry) return;\n\t\tthis.armTimeout(requestId, entry);\n\t\ttry {\n\t\t\tentry.onProgress?.(params as unknown as ProgressNotification);\n\t\t} catch (error) {\n\t\t\tthis.emitError(error);\n\t\t}\n\t}\n\n\tprivate handleCancelled(params: unknown): void {\n\t\tif (isObject(params) && isJsonRpcId(params.requestId)) this.incoming.get(params.requestId)?.abort(params.reason);\n\t}\n\n\tprivate armTimeout(id: JsonRpcId, entry: PendingRequest): void {\n\t\tif (entry.timer) clearTimeout(entry.timer);\n\t\tif (!Number.isFinite(entry.timeoutMs) || entry.timeoutMs <= 0) return;\n\t\tentry.timer = setTimeout(() => {\n\t\t\tthis.cancelPending(id, new McpTimeoutError(entry.timeoutMs), entry.cancellable, \"Request timed out\");\n\t\t}, entry.timeoutMs);\n\t}\n\n\tprivate cancelPending(id: JsonRpcId, error: unknown, notifyServer: boolean, reason?: string): void {\n\t\tconst entry = this.pending.get(id);\n\t\tif (!entry) return;\n\t\tthis.removePending(id, entry);\n\t\tentry.reject(error);\n\t\tif (notifyServer && this.transport) {\n\t\t\tvoid this.transport\n\t\t\t\t.send({\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\tmethod: \"notifications/cancelled\",\n\t\t\t\t\tparams: { requestId: id, ...(reason ? { reason } : {}) },\n\t\t\t\t})\n\t\t\t\t.catch((sendError) => this.emitError(sendError));\n\t\t}\n\t}\n\n\tprivate removePending(id: JsonRpcId, entry: PendingRequest): void {\n\t\tthis.pending.delete(id);\n\t\tif (entry.timer) clearTimeout(entry.timer);\n\t\tif (entry.progressToken !== undefined) this.progressRequests.delete(entry.progressToken);\n\t\tentry.signal?.removeEventListener(\"abort\", entry.onAbort);\n\t}\n\n\tprivate rejectPending(error: unknown): void {\n\t\tfor (const [id, entry] of this.pending) {\n\t\t\tthis.removePending(id, entry);\n\t\t\tentry.reject(error);\n\t\t}\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tthis.markClosed(new McpConnectionClosedError());\n\t}\n\n\t/** Idempotent: rejects in-flight requests, aborts server requests we are serving, and flips the state. */\n\tprivate markClosed(error: Error): void {\n\t\tconst wasClosed = this.state === \"closed\";\n\t\tthis.state = \"closed\";\n\t\tthis.rejectPending(error);\n\t\tfor (const controller of this.incoming.values()) controller.abort(error);\n\t\tthis.incoming.clear();\n\t\tif (wasClosed) return;\n\t\tfor (const listener of [...this.closeListeners]) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch (listenerError) {\n\t\t\t\tthis.emitError(listenerError);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate emitError(error: unknown): void {\n\t\tconst normalized = toError(error);\n\t\tfor (const listener of this.errorListeners) listener(normalized);\n\t}\n\n\tprivate disposeTransportListeners(): void {\n\t\tfor (const dispose of this.disposers.splice(0)) dispose();\n\t}\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CallToolResult } from \"./protocol/content.ts\";\nimport {\n\tisJsonRpcId,\n\tisJsonRpcNotification,\n\tisJsonRpcRequest,\n\tisJsonRpcResponse,\n\tisObject,\n\tJSON_RPC_ERROR_CODES,\n\ttype JsonRpcId,\n\ttype JsonRpcMessage,\n\ttype JsonRpcRequest,\n\ttype JsonRpcResponse,\n\tMcpAbortError,\n\tMcpConnectionClosedError,\n\tMcpError,\n\tMcpTimeoutError,\n\ttoError,\n} from \"./protocol/jsonrpc.ts\";\nimport {\n\ttype ClientCapabilities,\n\ttype Implementation,\n\ttype InitializeResult,\n\tLATEST_PROTOCOL_VERSION,\n\ttype ListResourcesResult,\n\ttype ListResourceTemplatesResult,\n\ttype ProgressNotification,\n\ttype ReadResourceResult,\n\ttype Resource,\n\ttype ResourceTemplate,\n\ttype Root,\n\ttype ServerCapabilities,\n\tSUPPORTED_PROTOCOL_VERSIONS,\n\ttype SupportedProtocolVersion,\n\ttype Tool,\n} from \"./protocol/types.ts\";\nimport type { McpTransport } from \"./transports/transport.ts\";\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst MAX_LIST_PAGES = 1_000;\n\ntype ClientState = \"idle\" | \"connecting\" | \"connected\" | \"closed\";\ntype NotificationListener = (params: unknown) => void;\ntype ErrorListener = (error: Error) => void;\ntype CloseListener = () => void;\ntype RequestHandler = (params: unknown, context: { signal: AbortSignal }) => unknown | Promise<unknown>;\n\nexport interface McpClientOptions extends Implementation {\n\tcapabilities?: ClientCapabilities;\n\tprotocolVersion?: SupportedProtocolVersion;\n\trequestTimeoutMs?: number;\n\troots?: readonly Root[] | (() => readonly Root[] | Promise<readonly Root[]>);\n}\n\nexport interface McpRequestOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n\tonProgress?: (progress: ProgressNotification) => void;\n}\n\ninterface PendingRequest {\n\tresolve: (value: unknown) => void;\n\treject: (reason: unknown) => void;\n\ttimeoutMs: number;\n\ttimer: ReturnType<typeof setTimeout> | undefined;\n\tsignal: AbortSignal | undefined;\n\tonAbort: () => void;\n\tcancellable: boolean;\n\tonProgress: ((progress: ProgressNotification) => void) | undefined;\n\tprogressToken: JsonRpcId | undefined;\n}\n\nfunction validateInitializeResult(value: unknown): InitializeResult {\n\tif (\n\t\t!isObject(value) ||\n\t\ttypeof value.protocolVersion !== \"string\" ||\n\t\t!isObject(value.capabilities) ||\n\t\t!isObject(value.serverInfo) ||\n\t\ttypeof value.serverInfo.name !== \"string\" ||\n\t\ttypeof value.serverInfo.version !== \"string\" ||\n\t\t(value.instructions !== undefined && typeof value.instructions !== \"string\")\n\t) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP initialize result\");\n\t}\n\treturn value as unknown as InitializeResult;\n}\n\nfunction invalid(message: string): McpError {\n\treturn new McpError(JSON_RPC_ERROR_CODES.invalidRequest, message);\n}\n\n/** One page of a paginated list: the items under `key`, each checked by `isItem`. */\nfunction validateListPage(\n\tmethod: string,\n\tkey: string,\n\tvalue: unknown,\n\tisItem: (item: Record<string, unknown>) => boolean,\n): { items: Record<string, unknown>[]; nextCursor?: string } {\n\tconst items = isObject(value) ? value[key] : undefined;\n\tif (!isObject(value) || !Array.isArray(items)) throw invalid(`Invalid MCP ${method} result`);\n\tfor (const item of items) {\n\t\tif (!isObject(item) || !isItem(item)) throw invalid(`Invalid entry in MCP ${method} result`);\n\t}\n\t// Some servers end pagination with `null` or `\"\"` instead of omitting the cursor.\n\tconst nextCursor = value.nextCursor === null || value.nextCursor === \"\" ? undefined : value.nextCursor;\n\tif (nextCursor !== undefined && typeof nextCursor !== \"string\") throw invalid(`Invalid MCP ${method} cursor`);\n\treturn { items, ...(nextCursor === undefined ? {} : { nextCursor }) };\n}\n\nconst isTool = (tool: Record<string, unknown>) => typeof tool.name === \"string\" && isObject(tool.inputSchema);\n// `name` is required by the spec, but some servers omit it; the URI stands in.\nconst isResource = (resource: Record<string, unknown>) =>\n\ttypeof resource.uri === \"string\" && (resource.name === undefined || typeof resource.name === \"string\");\nconst isResourceTemplate = (template: Record<string, unknown>) =>\n\ttypeof template.uriTemplate === \"string\" && (template.name === undefined || typeof template.name === \"string\");\n\nfunction toResource(item: Record<string, unknown>): Resource {\n\treturn { ...item, name: item.name ?? item.uri } as Resource;\n}\n\nfunction toResourceTemplate(item: Record<string, unknown>): ResourceTemplate {\n\treturn { ...item, name: item.name ?? item.uriTemplate } as ResourceTemplate;\n}\n\nfunction pageCursor(page: { nextCursor?: string }): { nextCursor?: string } {\n\treturn page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor };\n}\n\nfunction validateReadResourceResult(value: unknown): ReadResourceResult {\n\tif (!isObject(value) || !Array.isArray(value.contents)) throw invalid(\"Invalid MCP resources/read result\");\n\tfor (const contents of value.contents) {\n\t\tif (\n\t\t\t!isObject(contents) ||\n\t\t\ttypeof contents.uri !== \"string\" ||\n\t\t\t(typeof contents.text !== \"string\" && typeof contents.blob !== \"string\")\n\t\t) {\n\t\t\tthrow invalid(\"Invalid contents in MCP resources/read result\");\n\t\t}\n\t}\n\treturn value as unknown as ReadResourceResult;\n}\n\n/** `content` is required by the spec, but servers that only return `structuredContent` omit it (the SDK defaults it too). */\nfunction validateCallToolResult(value: unknown): CallToolResult {\n\tif (!isObject(value) || (value.content !== undefined && !Array.isArray(value.content))) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP tools/call result\");\n\t}\n\tif (value.structuredContent !== undefined && !isObject(value.structuredContent)) {\n\t\tthrow new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Invalid MCP tools/call structured content\");\n\t}\n\treturn (value.content === undefined ? { ...value, content: [] } : value) as unknown as CallToolResult;\n}\n\nexport class McpClient {\n\treadonly options: Readonly<McpClientOptions>;\n\tprivate state: ClientState = \"idle\";\n\tprivate transport: McpTransport | undefined;\n\tprivate nextRequestId = 1;\n\tprivate serverInfoValue: Implementation | undefined;\n\tprivate serverCapabilitiesValue: ServerCapabilities | undefined;\n\tprivate instructionsValue: string | undefined;\n\tprivate protocolVersionValue: string | undefined;\n\tprivate pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate progressRequests = new Map<JsonRpcId, JsonRpcId>();\n\tprivate incoming = new Map<JsonRpcId, AbortController>();\n\tprivate requestHandlers = new Map<string, RequestHandler>();\n\tprivate notificationListeners = new Map<string, Set<NotificationListener>>();\n\tprivate errorListeners = new Set<ErrorListener>();\n\tprivate closeListeners = new Set<CloseListener>();\n\tprivate disposers: (() => void)[] = [];\n\n\tconstructor(options: McpClientOptions) {\n\t\tthis.options = Object.freeze({ ...options });\n\t\tthis.requestHandlers.set(\"ping\", () => ({}));\n\t\tconst roots = options.roots;\n\t\tif (roots) {\n\t\t\tthis.requestHandlers.set(\"roots/list\", async () => ({\n\t\t\t\troots: [...(typeof roots === \"function\" ? await roots() : roots)],\n\t\t\t}));\n\t\t}\n\t}\n\n\tget connectionState(): ClientState {\n\t\treturn this.state;\n\t}\n\n\tget serverInfo(): Implementation | undefined {\n\t\treturn this.serverInfoValue;\n\t}\n\n\tget serverCapabilities(): ServerCapabilities | undefined {\n\t\treturn this.serverCapabilitiesValue;\n\t}\n\n\tget instructions(): string | undefined {\n\t\treturn this.instructionsValue;\n\t}\n\n\tget protocolVersion(): string | undefined {\n\t\treturn this.protocolVersionValue;\n\t}\n\n\tasync connect(transport: McpTransport): Promise<InitializeResult> {\n\t\tif (this.state !== \"idle\") throw new Error(`Cannot connect MCP client in ${this.state} state`);\n\t\tthis.state = \"connecting\";\n\t\tthis.transport = transport;\n\t\tthis.disposers = [\n\t\t\ttransport.onMessage((message) => this.handleMessage(message)),\n\t\t\t// Transport errors are reported only. Pending requests fail when the transport closes.\n\t\t\ttransport.onError((error) => this.emitError(error)),\n\t\t\ttransport.onClose(() => this.handleTransportClose()),\n\t\t];\n\n\t\ttry {\n\t\t\tawait transport.start();\n\t\t\tconst capabilities: ClientCapabilities = { ...this.options.capabilities };\n\t\t\tif (this.options.roots && capabilities.roots === undefined) capabilities.roots = {};\n\t\t\tconst result = validateInitializeResult(\n\t\t\t\tawait this.requestInternal(\n\t\t\t\t\t\"initialize\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocolVersion: this.options.protocolVersion ?? LATEST_PROTOCOL_VERSION,\n\t\t\t\t\t\tcapabilities,\n\t\t\t\t\t\tclientInfo: {\n\t\t\t\t\t\t\tname: this.options.name,\n\t\t\t\t\t\t\tversion: this.options.version,\n\t\t\t\t\t\t\t...(this.options.title === undefined ? {} : { title: this.options.title }),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{},\n\t\t\t\t\ttrue,\n\t\t\t\t),\n\t\t\t);\n\t\t\tif (!(SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(result.protocolVersion)) {\n\t\t\t\tthrow new Error(`MCP server selected unsupported protocol version ${result.protocolVersion}`);\n\t\t\t}\n\t\t\tthis.protocolVersionValue = result.protocolVersion;\n\t\t\tthis.serverInfoValue = result.serverInfo;\n\t\t\tthis.serverCapabilitiesValue = result.capabilities;\n\t\t\tthis.instructionsValue = result.instructions;\n\t\t\ttransport.setProtocolVersion?.(result.protocolVersion);\n\t\t\tawait this.notifyInternal(\"notifications/initialized\", undefined, true);\n\t\t\tthis.state = \"connected\";\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tawait this.close().catch(() => {});\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\trequest<Result = unknown>(\n\t\tmethod: string,\n\t\tparams?: Record<string, unknown>,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<Result> {\n\t\treturn this.requestInternal(method, params, options, false) as Promise<Result>;\n\t}\n\n\tnotify(method: string, params?: Record<string, unknown>): Promise<void> {\n\t\treturn this.notifyInternal(method, params, false);\n\t}\n\n\tsetRequestHandler(method: string, handler: RequestHandler): () => void {\n\t\tthis.requestHandlers.set(method, handler);\n\t\treturn () => {\n\t\t\tif (this.requestHandlers.get(method) === handler) this.requestHandlers.delete(method);\n\t\t};\n\t}\n\n\tonNotification(method: string, listener: NotificationListener): () => void {\n\t\tconst listeners = this.notificationListeners.get(method) ?? new Set<NotificationListener>();\n\t\tthis.notificationListeners.set(method, listeners);\n\t\tlisteners.add(listener);\n\t\treturn () => {\n\t\t\tlisteners.delete(listener);\n\t\t\tif (listeners.size === 0) this.notificationListeners.delete(method);\n\t\t};\n\t}\n\n\tonError(listener: ErrorListener): () => void {\n\t\tthis.errorListeners.add(listener);\n\t\treturn () => this.errorListeners.delete(listener);\n\t}\n\n\t/** Called once when the connection closes, whether the transport dropped or `close()` was called. */\n\tonClose(listener: CloseListener): () => void {\n\t\tthis.closeListeners.add(listener);\n\t\treturn () => this.closeListeners.delete(listener);\n\t}\n\n\tasync ping(options: McpRequestOptions = {}): Promise<void> {\n\t\tawait this.request(\"ping\", undefined, options);\n\t}\n\n\tasync listTools(options: McpRequestOptions = {}): Promise<Tool[]> {\n\t\treturn (await this.listAll(\"tools/list\", \"tools\", isTool, options)) as unknown as Tool[];\n\t}\n\n\t/** Every resource, following `nextCursor` through all pages. */\n\tasync listResources(options: McpRequestOptions = {}): Promise<Resource[]> {\n\t\treturn (await this.listAll(\"resources/list\", \"resources\", isResource, options)).map(toResource);\n\t}\n\n\t/** One page of resources, starting at `cursor`. */\n\tasync listResourcesPage(cursor?: string, options: McpRequestOptions = {}): Promise<ListResourcesResult> {\n\t\tconst page = await this.listPage(\"resources/list\", \"resources\", isResource, cursor, options);\n\t\treturn { resources: page.items.map(toResource), ...pageCursor(page) };\n\t}\n\n\t/** Every resource template, following `nextCursor` through all pages. */\n\tasync listResourceTemplates(options: McpRequestOptions = {}): Promise<ResourceTemplate[]> {\n\t\tconst templates = await this.listAll(\n\t\t\t\"resources/templates/list\",\n\t\t\t\"resourceTemplates\",\n\t\t\tisResourceTemplate,\n\t\t\toptions,\n\t\t);\n\t\treturn templates.map(toResourceTemplate);\n\t}\n\n\t/** One page of resource templates, starting at `cursor`. */\n\tasync listResourceTemplatesPage(\n\t\tcursor?: string,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<ListResourceTemplatesResult> {\n\t\tconst page = await this.listPage(\n\t\t\t\"resources/templates/list\",\n\t\t\t\"resourceTemplates\",\n\t\t\tisResourceTemplate,\n\t\t\tcursor,\n\t\t\toptions,\n\t\t);\n\t\treturn { resourceTemplates: page.items.map(toResourceTemplate), ...pageCursor(page) };\n\t}\n\n\tasync readResource(uri: string, options: McpRequestOptions = {}): Promise<ReadResourceResult> {\n\t\treturn validateReadResourceResult(await this.request(\"resources/read\", { uri }, options));\n\t}\n\n\tprivate async listPage(\n\t\tmethod: string,\n\t\tkey: string,\n\t\tisItem: (item: Record<string, unknown>) => boolean,\n\t\tcursor: string | undefined,\n\t\toptions: McpRequestOptions,\n\t): Promise<{ items: Record<string, unknown>[]; nextCursor?: string }> {\n\t\treturn validateListPage(\n\t\t\tmethod,\n\t\t\tkey,\n\t\t\tawait this.request(method, cursor === undefined ? undefined : { cursor }, options),\n\t\t\tisItem,\n\t\t);\n\t}\n\n\t/** Every item of a paginated list method. */\n\tprivate async listAll(\n\t\tmethod: string,\n\t\tkey: string,\n\t\tisItem: (item: Record<string, unknown>) => boolean,\n\t\toptions: McpRequestOptions,\n\t): Promise<Record<string, unknown>[]> {\n\t\tconst items: Record<string, unknown>[] = [];\n\t\tconst cursors = new Set<string>();\n\t\tlet cursor: string | undefined;\n\t\tfor (let pageNumber = 0; pageNumber < MAX_LIST_PAGES; pageNumber++) {\n\t\t\tconst page = await this.listPage(method, key, isItem, cursor, options);\n\t\t\titems.push(...page.items);\n\t\t\tif (page.nextCursor === undefined) return items;\n\t\t\tif (cursors.has(page.nextCursor))\n\t\t\t\tthrow new Error(`MCP ${method} returned duplicate cursor: ${page.nextCursor}`);\n\t\t\tcursors.add(page.nextCursor);\n\t\t\tcursor = page.nextCursor;\n\t\t}\n\t\tthrow new Error(`MCP ${method} exceeded ${MAX_LIST_PAGES} pages`);\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs?: Record<string, unknown>,\n\t\toptions: McpRequestOptions = {},\n\t): Promise<CallToolResult> {\n\t\treturn validateCallToolResult(\n\t\t\tawait this.request(\"tools/call\", { name, ...(args === undefined ? {} : { arguments: args }) }, options),\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tconst transport = this.transport;\n\t\tthis.transport = undefined;\n\t\tthis.disposeTransportListeners();\n\t\tthis.markClosed(new McpConnectionClosedError());\n\t\tawait transport?.close();\n\t}\n\n\tprivate async requestInternal(\n\t\tmethod: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\toptions: McpRequestOptions,\n\t\tallowConnecting: boolean,\n\t): Promise<unknown> {\n\t\tconst transport = this.requireTransport(allowConnecting);\n\t\tif (options.signal?.aborted) throw new McpAbortError();\n\t\tconst id = this.nextRequestId++;\n\t\tconst progressToken = options.onProgress ? id : undefined;\n\t\tconst requestParams =\n\t\t\tprogressToken === undefined\n\t\t\t\t? params\n\t\t\t\t: { ...params, _meta: { ...(isObject(params?._meta) ? params._meta : {}), progressToken } };\n\t\tconst message: JsonRpcRequest = {\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid,\n\t\t\tmethod,\n\t\t\t...(requestParams === undefined ? {} : { params: requestParams }),\n\t\t};\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\tconst entry: PendingRequest = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t\ttimeoutMs: options.timeoutMs ?? this.options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n\t\t\t\ttimer: undefined,\n\t\t\t\tsignal: options.signal,\n\t\t\t\t// The spec forbids cancelling `initialize`.\n\t\t\t\tonAbort: () =>\n\t\t\t\t\tthis.cancelPending(\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tnew McpAbortError(),\n\t\t\t\t\t\tmethod !== \"initialize\",\n\t\t\t\t\t\tString(options.signal?.reason ?? \"Aborted\"),\n\t\t\t\t\t),\n\t\t\t\tcancellable: method !== \"initialize\",\n\t\t\t\tonProgress: options.onProgress,\n\t\t\t\tprogressToken,\n\t\t\t};\n\t\t\tthis.pending.set(id, entry);\n\t\t\tif (progressToken !== undefined) this.progressRequests.set(progressToken, id);\n\t\t\toptions.signal?.addEventListener(\"abort\", entry.onAbort, { once: true });\n\t\t\tthis.armTimeout(id, entry);\n\t\t\ttransport.send(message).catch((error) => this.cancelPending(id, error, false));\n\t\t});\n\t}\n\n\tprivate async notifyInternal(\n\t\tmethod: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\tallowConnecting: boolean,\n\t): Promise<void> {\n\t\tawait this.requireTransport(allowConnecting).send({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tmethod,\n\t\t\t...(params === undefined ? {} : { params }),\n\t\t});\n\t}\n\n\tprivate requireTransport(allowConnecting: boolean): McpTransport {\n\t\tif (this.transport && (this.state === \"connected\" || (allowConnecting && this.state === \"connecting\"))) {\n\t\t\treturn this.transport;\n\t\t}\n\t\tthrow new McpConnectionClosedError(`MCP client is ${this.state}`);\n\t}\n\n\tprivate handleMessage(message: JsonRpcMessage): void {\n\t\tif (isJsonRpcResponse(message)) {\n\t\t\tthis.handleResponse(message);\n\t\t\treturn;\n\t\t}\n\t\tif (isJsonRpcRequest(message)) {\n\t\t\tvoid this.handleRequest(message);\n\t\t\treturn;\n\t\t}\n\t\tif (isJsonRpcNotification(message)) {\n\t\t\tthis.handleNotification(message.method, message.params);\n\t\t\treturn;\n\t\t}\n\t\tthis.emitError(new McpError(JSON_RPC_ERROR_CODES.invalidRequest, \"Received invalid JSON-RPC message\"));\n\t}\n\n\tprivate handleResponse(message: JsonRpcResponse): void {\n\t\tconst entry = this.pending.get(message.id);\n\t\tif (!entry) {\n\t\t\tthis.emitError(new Error(`Received response for unknown MCP request ${String(message.id)}`));\n\t\t\treturn;\n\t\t}\n\t\tthis.removePending(message.id, entry);\n\t\tif (\"error\" in message) entry.reject(new McpError(message.error.code, message.error.message, message.error.data));\n\t\telse entry.resolve(message.result);\n\t}\n\n\tprivate async handleRequest(message: JsonRpcRequest): Promise<void> {\n\t\tconst transport = this.transport;\n\t\tif (!transport) return;\n\t\tconst handler = this.requestHandlers.get(message.method);\n\t\tif (!handler) {\n\t\t\tawait transport\n\t\t\t\t.send({\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\tid: message.id,\n\t\t\t\t\terror: { code: JSON_RPC_ERROR_CODES.methodNotFound, message: `Method not found: ${message.method}` },\n\t\t\t\t})\n\t\t\t\t.catch((error) => this.emitError(error));\n\t\t\treturn;\n\t\t}\n\t\tconst controller = new AbortController();\n\t\tthis.incoming.set(message.id, controller);\n\t\ttry {\n\t\t\tconst result = await handler(message.params, { signal: controller.signal });\n\t\t\tawait transport.send({ jsonrpc: \"2.0\", id: message.id, result: result ?? {} });\n\t\t} catch (error) {\n\t\t\tconst responseError =\n\t\t\t\terror instanceof McpError\n\t\t\t\t\t? { code: error.code, message: error.message, data: error.data }\n\t\t\t\t\t: { code: JSON_RPC_ERROR_CODES.internalError, message: toError(error).message };\n\t\t\tawait transport\n\t\t\t\t.send({ jsonrpc: \"2.0\", id: message.id, error: responseError })\n\t\t\t\t.catch((sendError) => this.emitError(sendError));\n\t\t} finally {\n\t\t\tthis.incoming.delete(message.id);\n\t\t}\n\t}\n\n\tprivate handleNotification(method: string, params: unknown): void {\n\t\tif (method === \"notifications/progress\") this.handleProgress(params);\n\t\telse if (method === \"notifications/cancelled\") this.handleCancelled(params);\n\t\tfor (const listener of this.notificationListeners.get(method) ?? []) {\n\t\t\ttry {\n\t\t\t\tlistener(params);\n\t\t\t} catch (error) {\n\t\t\t\tthis.emitError(error);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleProgress(params: unknown): void {\n\t\tif (!isObject(params) || !isJsonRpcId(params.progressToken) || typeof params.progress !== \"number\") return;\n\t\tconst requestId = this.progressRequests.get(params.progressToken);\n\t\tconst entry = requestId === undefined ? undefined : this.pending.get(requestId);\n\t\tif (requestId === undefined || !entry) return;\n\t\tthis.armTimeout(requestId, entry);\n\t\ttry {\n\t\t\tentry.onProgress?.(params as unknown as ProgressNotification);\n\t\t} catch (error) {\n\t\t\tthis.emitError(error);\n\t\t}\n\t}\n\n\tprivate handleCancelled(params: unknown): void {\n\t\tif (isObject(params) && isJsonRpcId(params.requestId)) this.incoming.get(params.requestId)?.abort(params.reason);\n\t}\n\n\tprivate armTimeout(id: JsonRpcId, entry: PendingRequest): void {\n\t\tif (entry.timer) clearTimeout(entry.timer);\n\t\tif (!Number.isFinite(entry.timeoutMs) || entry.timeoutMs <= 0) return;\n\t\tentry.timer = setTimeout(() => {\n\t\t\tthis.cancelPending(id, new McpTimeoutError(entry.timeoutMs), entry.cancellable, \"Request timed out\");\n\t\t}, entry.timeoutMs);\n\t}\n\n\tprivate cancelPending(id: JsonRpcId, error: unknown, notifyServer: boolean, reason?: string): void {\n\t\tconst entry = this.pending.get(id);\n\t\tif (!entry) return;\n\t\tthis.removePending(id, entry);\n\t\tentry.reject(error);\n\t\tif (notifyServer && this.transport) {\n\t\t\tvoid this.transport\n\t\t\t\t.send({\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\tmethod: \"notifications/cancelled\",\n\t\t\t\t\tparams: { requestId: id, ...(reason ? { reason } : {}) },\n\t\t\t\t})\n\t\t\t\t.catch((sendError) => this.emitError(sendError));\n\t\t}\n\t}\n\n\tprivate removePending(id: JsonRpcId, entry: PendingRequest): void {\n\t\tthis.pending.delete(id);\n\t\tif (entry.timer) clearTimeout(entry.timer);\n\t\tif (entry.progressToken !== undefined) this.progressRequests.delete(entry.progressToken);\n\t\tentry.signal?.removeEventListener(\"abort\", entry.onAbort);\n\t}\n\n\tprivate rejectPending(error: unknown): void {\n\t\tfor (const [id, entry] of this.pending) {\n\t\t\tthis.removePending(id, entry);\n\t\t\tentry.reject(error);\n\t\t}\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tthis.markClosed(new McpConnectionClosedError());\n\t}\n\n\t/** Idempotent: rejects in-flight requests, aborts server requests we are serving, and flips the state. */\n\tprivate markClosed(error: Error): void {\n\t\tconst wasClosed = this.state === \"closed\";\n\t\tthis.state = \"closed\";\n\t\tthis.rejectPending(error);\n\t\tfor (const controller of this.incoming.values()) controller.abort(error);\n\t\tthis.incoming.clear();\n\t\tif (wasClosed) return;\n\t\tfor (const listener of [...this.closeListeners]) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch (listenerError) {\n\t\t\t\tthis.emitError(listenerError);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate emitError(error: unknown): void {\n\t\tconst normalized = toError(error);\n\t\tfor (const listener of this.errorListeners) listener(normalized);\n\t}\n\n\tprivate disposeTransportListeners(): void {\n\t\tfor (const dispose of this.disposers.splice(0)) dispose();\n\t}\n}\n"]}
@@ -21,6 +21,8 @@ export interface OAuthCallbackServerOptions {
21
21
  redirectHost?: string;
22
22
  port?: number;
23
23
  path?: string;
24
+ /** More paths that receive the callback, for example a server-specific path of a redirect URI. */
25
+ extraPaths?: string[];
24
26
  timeoutMs?: number;
25
27
  /** Render the browser page as HTML. Default: a plain-text message. */
26
28
  renderPage?: (page: OAuthCallbackPage) => string;
@@ -28,13 +30,17 @@ export interface OAuthCallbackServerOptions {
28
30
  export declare class OAuthCallbackServer {
29
31
  readonly redirectUrl: string;
30
32
  private server;
31
- private path;
33
+ private paths;
32
34
  private timeoutMs;
33
35
  private renderPage;
34
36
  private pending;
35
37
  private constructor();
36
38
  static listen(options?: OAuthCallbackServerOptions): Promise<OAuthCallbackServer>;
37
- waitForCallback(state: string): Promise<OAuthCallback>;
39
+ /**
40
+ * Wait for the authorization response with `state`. With `path`, a response on another path fails, so
41
+ * a server-specific redirect URI can tell authorization servers apart (RFC 9700 section 4.4.2.2).
42
+ */
43
+ waitForCallback(state: string, path?: string): Promise<OAuthCallback>;
38
44
  close(): Promise<void>;
39
45
  private reply;
40
46
  private handle;
@@ -1 +1 @@
1
- {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,MAAM,WAAW,0BAA0B;IAC1C,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,MAAM,CAAC;CACjD;AAOD,qBAAa,mBAAmB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAoD;IACtE,OAAO,CAAC,OAAO,CAOX;IAEJ,OAAO,eAYN;IAED,OAAa,MAAM,CAAC,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuB1F;IAED,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CASrD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAS3B;IAED,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,MAAM;CAmCd"}
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,MAAM,WAAW,0BAA0B;IAC1C,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,MAAM,CAAC;CACjD;AAOD,qBAAa,mBAAmB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAoD;IACtE,OAAO,CAAC,OAAO,CAQX;IAEJ,OAAO,eAYN;IAED,OAAa,MAAM,CAAC,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuB1F;IAED;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CASpE;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAS3B;IAED,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,MAAM;CAwCd"}
@@ -7,14 +7,14 @@ function plainText(page) {
7
7
  export class OAuthCallbackServer {
8
8
  redirectUrl;
9
9
  server;
10
- path;
10
+ paths;
11
11
  timeoutMs;
12
12
  renderPage;
13
13
  pending = new Map();
14
- constructor(server, redirectUrl, path, timeoutMs, renderPage) {
14
+ constructor(server, redirectUrl, paths, timeoutMs, renderPage) {
15
15
  this.server = server;
16
16
  this.redirectUrl = redirectUrl;
17
- this.path = path;
17
+ this.paths = paths;
18
18
  this.timeoutMs = timeoutMs;
19
19
  this.renderPage = renderPage;
20
20
  }
@@ -34,10 +34,14 @@ export class OAuthCallbackServer {
34
34
  const address = server.address();
35
35
  if (!address || typeof address === "string")
36
36
  throw new Error("OAuth callback server did not bind to TCP");
37
- instance = new OAuthCallbackServer(server, `http://${redirectHost.includes(":") ? `[${redirectHost}]` : redirectHost}:${address.port}${path}`, path, options.timeoutMs ?? 5 * 60_000, options.renderPage);
37
+ instance = new OAuthCallbackServer(server, `http://${redirectHost.includes(":") ? `[${redirectHost}]` : redirectHost}:${address.port}${path}`, [path, ...(options.extraPaths ?? [])], options.timeoutMs ?? 5 * 60_000, options.renderPage);
38
38
  return instance;
39
39
  }
40
- waitForCallback(state) {
40
+ /**
41
+ * Wait for the authorization response with `state`. With `path`, a response on another path fails, so
42
+ * a server-specific redirect URI can tell authorization servers apart (RFC 9700 section 4.4.2.2).
43
+ */
44
+ waitForCallback(state, path) {
41
45
  if (this.pending.has(state))
42
46
  throw new Error("OAuth state is already pending");
43
47
  return new Promise((resolve, reject) => {
@@ -45,7 +49,7 @@ export class OAuthCallbackServer {
45
49
  this.pending.delete(state);
46
50
  reject(new Error("OAuth callback timed out"));
47
51
  }, this.timeoutMs);
48
- this.pending.set(state, { resolve, reject, timer });
52
+ this.pending.set(state, { resolve, reject, timer, path });
49
53
  });
50
54
  }
51
55
  async close() {
@@ -69,7 +73,7 @@ export class OAuthCallbackServer {
69
73
  }
70
74
  handle(rawUrl, response) {
71
75
  const url = new URL(rawUrl, this.redirectUrl);
72
- if (url.pathname !== this.path) {
76
+ if (!this.paths.includes(url.pathname)) {
73
77
  this.reply(response, 404, { ok: false, message: "Not found" });
74
78
  return;
75
79
  }
@@ -81,6 +85,11 @@ export class OAuthCallbackServer {
81
85
  }
82
86
  clearTimeout(pending.timer);
83
87
  this.pending.delete(state);
88
+ if (pending.path !== undefined && url.pathname !== pending.path) {
89
+ pending.reject(new Error("The authorization response arrived on another redirect URI"));
90
+ this.reply(response, 400, { ok: false, message: "Unexpected redirect URI" });
91
+ return;
92
+ }
84
93
  const error = url.searchParams.get("error");
85
94
  if (error) {
86
95
  const description = url.searchParams.get("error_description") ?? error;
@@ -1 +1 @@
1
- {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server, type ServerResponse } from \"node:http\";\n\nexport interface OAuthCallback {\n\tcode: string;\n\tstate: string;\n\tiss?: string;\n}\n\n/** Outcome shown on the browser page after the redirect. */\nexport type OAuthCallbackPage = { ok: true } | { ok: false; message: string; details?: string };\n\nexport interface OAuthCallbackServerOptions {\n\t/** Address to listen on. Default: `127.0.0.1`. */\n\thost?: string;\n\t/**\n\t * Host name in `redirectUrl`, for example `localhost` for a client registered with it while\n\t * listening on `127.0.0.1`. Default: `host`.\n\t */\n\tredirectHost?: string;\n\tport?: number;\n\tpath?: string;\n\ttimeoutMs?: number;\n\t/** Render the browser page as HTML. Default: a plain-text message. */\n\trenderPage?: (page: OAuthCallbackPage) => string;\n}\n\nfunction plainText(page: OAuthCallbackPage): string {\n\tif (page.ok) return \"Authorization complete. You may close this window.\";\n\treturn page.details ? `${page.message}\\n\\n${page.details}` : page.message;\n}\n\nexport class OAuthCallbackServer {\n\treadonly redirectUrl: string;\n\tprivate server: Server;\n\tprivate path: string;\n\tprivate timeoutMs: number;\n\tprivate renderPage: ((page: OAuthCallbackPage) => string) | undefined;\n\tprivate pending = new Map<\n\t\tstring,\n\t\t{\n\t\t\tresolve: (callback: OAuthCallback) => void;\n\t\t\treject: (error: Error) => void;\n\t\t\ttimer: ReturnType<typeof setTimeout>;\n\t\t}\n\t>();\n\n\tprivate constructor(\n\t\tserver: Server,\n\t\tredirectUrl: string,\n\t\tpath: string,\n\t\ttimeoutMs: number,\n\t\trenderPage: ((page: OAuthCallbackPage) => string) | undefined,\n\t) {\n\t\tthis.server = server;\n\t\tthis.redirectUrl = redirectUrl;\n\t\tthis.path = path;\n\t\tthis.timeoutMs = timeoutMs;\n\t\tthis.renderPage = renderPage;\n\t}\n\n\tstatic async listen(options: OAuthCallbackServerOptions = {}): Promise<OAuthCallbackServer> {\n\t\tconst host = options.host ?? \"127.0.0.1\";\n\t\tconst redirectHost = options.redirectHost ?? host;\n\t\tconst path = options.path ?? \"/callback\";\n\t\tlet instance: OAuthCallbackServer | undefined;\n\t\tconst server = createServer((request, response) => instance?.handle(request.url ?? \"/\", response));\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tserver.once(\"error\", reject);\n\t\t\tserver.listen(options.port ?? 0, host, () => {\n\t\t\t\tserver.off(\"error\", reject);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t\tconst address = server.address();\n\t\tif (!address || typeof address === \"string\") throw new Error(\"OAuth callback server did not bind to TCP\");\n\t\tinstance = new OAuthCallbackServer(\n\t\t\tserver,\n\t\t\t`http://${redirectHost.includes(\":\") ? `[${redirectHost}]` : redirectHost}:${address.port}${path}`,\n\t\t\tpath,\n\t\t\toptions.timeoutMs ?? 5 * 60_000,\n\t\t\toptions.renderPage,\n\t\t);\n\t\treturn instance;\n\t}\n\n\twaitForCallback(state: string): Promise<OAuthCallback> {\n\t\tif (this.pending.has(state)) throw new Error(\"OAuth state is already pending\");\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.pending.delete(state);\n\t\t\t\treject(new Error(\"OAuth callback timed out\"));\n\t\t\t}, this.timeoutMs);\n\t\t\tthis.pending.set(state, { resolve, reject, timer });\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tfor (const pending of this.pending.values()) {\n\t\t\tclearTimeout(pending.timer);\n\t\t\tpending.reject(new Error(\"OAuth callback server closed\"));\n\t\t}\n\t\tthis.pending.clear();\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.server.close((error) => (error ? reject(error) : resolve()));\n\t\t});\n\t}\n\n\tprivate reply(response: ServerResponse, status: number, page: OAuthCallbackPage): void {\n\t\tif (this.renderPage) {\n\t\t\tresponse.writeHead(status, { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\" });\n\t\t\tresponse.end(this.renderPage(page));\n\t\t} else {\n\t\t\tresponse.writeHead(status, { \"content-type\": \"text/plain; charset=utf-8\" }).end(plainText(page));\n\t\t}\n\t}\n\n\tprivate handle(rawUrl: string, response: ServerResponse): void {\n\t\tconst url = new URL(rawUrl, this.redirectUrl);\n\t\tif (url.pathname !== this.path) {\n\t\t\tthis.reply(response, 404, { ok: false, message: \"Not found\" });\n\t\t\treturn;\n\t\t}\n\t\tconst state = url.searchParams.get(\"state\");\n\t\tconst pending = state ? this.pending.get(state) : undefined;\n\t\tif (!state || !pending) {\n\t\t\tthis.reply(response, 400, { ok: false, message: \"Invalid or expired OAuth state\" });\n\t\t\treturn;\n\t\t}\n\t\tclearTimeout(pending.timer);\n\t\tthis.pending.delete(state);\n\t\tconst error = url.searchParams.get(\"error\");\n\t\tif (error) {\n\t\t\tconst description = url.searchParams.get(\"error_description\") ?? error;\n\t\t\tpending.reject(new Error(description));\n\t\t\tthis.reply(response, 200, {\n\t\t\t\tok: false,\n\t\t\t\tmessage: \"Authorization failed. You may close this window.\",\n\t\t\t\tdetails: description,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst code = url.searchParams.get(\"code\");\n\t\tif (!code) {\n\t\t\tpending.reject(new Error(\"OAuth callback did not include an authorization code\"));\n\t\t\tthis.reply(response, 400, { ok: false, message: \"Missing authorization code\" });\n\t\t\treturn;\n\t\t}\n\t\tconst iss = url.searchParams.get(\"iss\");\n\t\tpending.resolve({ code, state, ...(iss ? { iss } : {}) });\n\t\tthis.reply(response, 200, { ok: true });\n\t}\n}\n"]}
1
+ {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server, type ServerResponse } from \"node:http\";\n\nexport interface OAuthCallback {\n\tcode: string;\n\tstate: string;\n\tiss?: string;\n}\n\n/** Outcome shown on the browser page after the redirect. */\nexport type OAuthCallbackPage = { ok: true } | { ok: false; message: string; details?: string };\n\nexport interface OAuthCallbackServerOptions {\n\t/** Address to listen on. Default: `127.0.0.1`. */\n\thost?: string;\n\t/**\n\t * Host name in `redirectUrl`, for example `localhost` for a client registered with it while\n\t * listening on `127.0.0.1`. Default: `host`.\n\t */\n\tredirectHost?: string;\n\tport?: number;\n\tpath?: string;\n\t/** More paths that receive the callback, for example a server-specific path of a redirect URI. */\n\textraPaths?: string[];\n\ttimeoutMs?: number;\n\t/** Render the browser page as HTML. Default: a plain-text message. */\n\trenderPage?: (page: OAuthCallbackPage) => string;\n}\n\nfunction plainText(page: OAuthCallbackPage): string {\n\tif (page.ok) return \"Authorization complete. You may close this window.\";\n\treturn page.details ? `${page.message}\\n\\n${page.details}` : page.message;\n}\n\nexport class OAuthCallbackServer {\n\treadonly redirectUrl: string;\n\tprivate server: Server;\n\tprivate paths: string[];\n\tprivate timeoutMs: number;\n\tprivate renderPage: ((page: OAuthCallbackPage) => string) | undefined;\n\tprivate pending = new Map<\n\t\tstring,\n\t\t{\n\t\t\tresolve: (callback: OAuthCallback) => void;\n\t\t\treject: (error: Error) => void;\n\t\t\ttimer: ReturnType<typeof setTimeout>;\n\t\t\tpath: string | undefined;\n\t\t}\n\t>();\n\n\tprivate constructor(\n\t\tserver: Server,\n\t\tredirectUrl: string,\n\t\tpaths: string[],\n\t\ttimeoutMs: number,\n\t\trenderPage: ((page: OAuthCallbackPage) => string) | undefined,\n\t) {\n\t\tthis.server = server;\n\t\tthis.redirectUrl = redirectUrl;\n\t\tthis.paths = paths;\n\t\tthis.timeoutMs = timeoutMs;\n\t\tthis.renderPage = renderPage;\n\t}\n\n\tstatic async listen(options: OAuthCallbackServerOptions = {}): Promise<OAuthCallbackServer> {\n\t\tconst host = options.host ?? \"127.0.0.1\";\n\t\tconst redirectHost = options.redirectHost ?? host;\n\t\tconst path = options.path ?? \"/callback\";\n\t\tlet instance: OAuthCallbackServer | undefined;\n\t\tconst server = createServer((request, response) => instance?.handle(request.url ?? \"/\", response));\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tserver.once(\"error\", reject);\n\t\t\tserver.listen(options.port ?? 0, host, () => {\n\t\t\t\tserver.off(\"error\", reject);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t\tconst address = server.address();\n\t\tif (!address || typeof address === \"string\") throw new Error(\"OAuth callback server did not bind to TCP\");\n\t\tinstance = new OAuthCallbackServer(\n\t\t\tserver,\n\t\t\t`http://${redirectHost.includes(\":\") ? `[${redirectHost}]` : redirectHost}:${address.port}${path}`,\n\t\t\t[path, ...(options.extraPaths ?? [])],\n\t\t\toptions.timeoutMs ?? 5 * 60_000,\n\t\t\toptions.renderPage,\n\t\t);\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Wait for the authorization response with `state`. With `path`, a response on another path fails, so\n\t * a server-specific redirect URI can tell authorization servers apart (RFC 9700 section 4.4.2.2).\n\t */\n\twaitForCallback(state: string, path?: string): Promise<OAuthCallback> {\n\t\tif (this.pending.has(state)) throw new Error(\"OAuth state is already pending\");\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.pending.delete(state);\n\t\t\t\treject(new Error(\"OAuth callback timed out\"));\n\t\t\t}, this.timeoutMs);\n\t\t\tthis.pending.set(state, { resolve, reject, timer, path });\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tfor (const pending of this.pending.values()) {\n\t\t\tclearTimeout(pending.timer);\n\t\t\tpending.reject(new Error(\"OAuth callback server closed\"));\n\t\t}\n\t\tthis.pending.clear();\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.server.close((error) => (error ? reject(error) : resolve()));\n\t\t});\n\t}\n\n\tprivate reply(response: ServerResponse, status: number, page: OAuthCallbackPage): void {\n\t\tif (this.renderPage) {\n\t\t\tresponse.writeHead(status, { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\" });\n\t\t\tresponse.end(this.renderPage(page));\n\t\t} else {\n\t\t\tresponse.writeHead(status, { \"content-type\": \"text/plain; charset=utf-8\" }).end(plainText(page));\n\t\t}\n\t}\n\n\tprivate handle(rawUrl: string, response: ServerResponse): void {\n\t\tconst url = new URL(rawUrl, this.redirectUrl);\n\t\tif (!this.paths.includes(url.pathname)) {\n\t\t\tthis.reply(response, 404, { ok: false, message: \"Not found\" });\n\t\t\treturn;\n\t\t}\n\t\tconst state = url.searchParams.get(\"state\");\n\t\tconst pending = state ? this.pending.get(state) : undefined;\n\t\tif (!state || !pending) {\n\t\t\tthis.reply(response, 400, { ok: false, message: \"Invalid or expired OAuth state\" });\n\t\t\treturn;\n\t\t}\n\t\tclearTimeout(pending.timer);\n\t\tthis.pending.delete(state);\n\t\tif (pending.path !== undefined && url.pathname !== pending.path) {\n\t\t\tpending.reject(new Error(\"The authorization response arrived on another redirect URI\"));\n\t\t\tthis.reply(response, 400, { ok: false, message: \"Unexpected redirect URI\" });\n\t\t\treturn;\n\t\t}\n\t\tconst error = url.searchParams.get(\"error\");\n\t\tif (error) {\n\t\t\tconst description = url.searchParams.get(\"error_description\") ?? error;\n\t\t\tpending.reject(new Error(description));\n\t\t\tthis.reply(response, 200, {\n\t\t\t\tok: false,\n\t\t\t\tmessage: \"Authorization failed. You may close this window.\",\n\t\t\t\tdetails: description,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst code = url.searchParams.get(\"code\");\n\t\tif (!code) {\n\t\t\tpending.reject(new Error(\"OAuth callback did not include an authorization code\"));\n\t\t\tthis.reply(response, 400, { ok: false, message: \"Missing authorization code\" });\n\t\t\treturn;\n\t\t}\n\t\tconst iss = url.searchParams.get(\"iss\");\n\t\tpending.resolve({ code, state, ...(iss ? { iss } : {}) });\n\t\tthis.reply(response, 200, { ok: true });\n\t}\n}\n"]}
@@ -17,6 +17,8 @@ export declare function discoverAuthorizationServerMetadata(authorizationServerU
17
17
  }): Promise<AuthorizationServerMetadata | undefined>;
18
18
  export declare function discoverOAuthServerInfo(serverUrl: string | URL, options?: {
19
19
  resourceMetadataUrl?: URL;
20
+ /** Metadata document to use instead of discovery. It is trusted as configured, so its issuer is not checked. */
21
+ authorizationServerMetadataUrl?: URL;
20
22
  fetch?: McpFetch;
21
23
  skipIssuerValidation?: boolean;
22
24
  }): Promise<OAuthServerInfo>;
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EACN,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,8BAA8B,EACnC,KAAK,eAAe,EAGpB,MAAM,YAAY,CAAC;AAqBpB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAiB1E;AAQD,wBAAsB,iCAAiC,CACtD,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAO,GAC9F,OAAO,CAAC,8BAA8B,CAAC,CAoBzC;AAED,wBAAgB,qCAAqC,CACpD,sBAAsB,EAAE,MAAM,GAAG,GAAG,GAClC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,EAAE,CASxC;AAED,wBAAsB,mCAAmC,CACxD,sBAAsB,EAAE,MAAM,GAAG,GAAG,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1F,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAmBlD;AAED,wBAAsB,uBAAuB,CAC5C,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IACR,mBAAmB,CAAC,EAAE,GAAG,CAAC;IAC1B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC1B,GACJ,OAAO,CAAC,eAAe,CAAC,CAmB1B;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAIjE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,8BAA8B,GAAG,MAAM,GAAG,SAAS,CAarH"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EACN,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,8BAA8B,EACnC,KAAK,eAAe,EAGpB,MAAM,YAAY,CAAC;AAsBpB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAiB1E;AAQD,wBAAsB,iCAAiC,CACtD,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAO,GAC9F,OAAO,CAAC,8BAA8B,CAAC,CAoBzC;AAED,wBAAgB,qCAAqC,CACpD,sBAAsB,EAAE,MAAM,GAAG,GAAG,GAClC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,EAAE,CASxC;AAED,wBAAsB,mCAAmC,CACxD,sBAAsB,EAAE,MAAM,GAAG,GAAG,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1F,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAmBlD;AAED,wBAAsB,uBAAuB,CAC5C,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IACR,mBAAmB,CAAC,EAAE,GAAG,CAAC;IAC1B,gHAAgH;IAChH,8BAA8B,CAAC,EAAE,GAAG,CAAC;IACrC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC1B,GACJ,OAAO,CAAC,eAAe,CAAC,CA6B1B;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAIjE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,8BAA8B,GAAG,MAAM,GAAG,SAAS,CAarH"}
@@ -19,7 +19,8 @@ function pathSuffix(pathname) {
19
19
  }
20
20
  function field(header, name) {
21
21
  const match = header.match(new RegExp(String.raw `(?:^|[,\s])${name}=(?:"([^"]*)"|([^\s,]+))`, "i"));
22
- return match?.[1] ?? match?.[2];
22
+ // An empty value (`scope=""`) carries no information, so it counts as absent.
23
+ return match?.[1] || match?.[2] || undefined;
23
24
  }
24
25
  export function parseWwwAuthenticate(header) {
25
26
  if (!header)
@@ -109,6 +110,16 @@ export async function discoverOAuthServerInfo(serverUrl, options = {}) {
109
110
  if (error instanceof TypeError)
110
111
  throw error;
111
112
  }
113
+ if (options.authorizationServerMetadataUrl) {
114
+ const url = options.authorizationServerMetadataUrl;
115
+ const response = await fetchMetadata(url, options.fetch ?? globalThis.fetch, LATEST_PROTOCOL_VERSION);
116
+ if (!response.ok) {
117
+ discard(response);
118
+ throw new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);
119
+ }
120
+ const metadata = parseAuthorizationServerMetadata(await response.json());
121
+ return { authorizationServerUrl: metadata.issuer, authorizationServerMetadata: metadata, resourceMetadata };
122
+ }
112
123
  const authorizationServerUrl = resourceMetadata?.authorization_servers?.[0] ?? String(new URL("/", serverUrl));
113
124
  return {
114
125
  authorizationServerUrl,
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove Zod/CORS shims and enforce authorization-server issuer validation.\n */\n\nimport type { McpFetch } from \"../auth-provider.ts\";\nimport { LATEST_PROTOCOL_VERSION } from \"../protocol/types.ts\";\nimport { OAuthIssuerMismatchError } from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthChallenge,\n\ttype OAuthProtectedResourceMetadata,\n\ttype OAuthServerInfo,\n\tparseAuthorizationServerMetadata,\n\tparseProtectedResourceMetadata,\n} from \"./types.ts\";\n\nfunction discard(response: Response | undefined): void {\n\tvoid response?.body?.cancel().catch(() => {});\n}\n\n/** 4xx and 502 mean \"not here\", so discovery tries the next candidate URL. */\nfunction isDiscoveryMiss(status: number): boolean {\n\treturn (status >= 400 && status < 500) || status === 502;\n}\n\n/** Path suffix for `/.well-known/<kind><path>`; empty for the root path. */\nfunction pathSuffix(pathname: string): string {\n\treturn pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\nfunction field(header: string, name: string): string | undefined {\n\tconst match = header.match(new RegExp(String.raw`(?:^|[,\\s])${name}=(?:\"([^\"]*)\"|([^\\s,]+))`, \"i\"));\n\treturn match?.[1] ?? match?.[2];\n}\n\nexport function parseWwwAuthenticate(header: string | null): OAuthChallenge {\n\tif (!header) return {};\n\tconst scheme = header.trimStart().split(/\\s+/, 1)[0]?.toLowerCase();\n\tif (scheme !== \"bearer\" && scheme !== \"dpop\") return {};\n\tconst resourceMetadata = field(header, \"resource_metadata\");\n\tlet resourceMetadataUrl: URL | undefined;\n\tif (resourceMetadata) {\n\t\ttry {\n\t\t\tresourceMetadataUrl = new URL(resourceMetadata);\n\t\t} catch {}\n\t}\n\treturn {\n\t\tresourceMetadataUrl,\n\t\tscope: field(header, \"scope\"),\n\t\terror: field(header, \"error\"),\n\t\terrorDescription: field(header, \"error_description\"),\n\t};\n}\n\nasync function fetchMetadata(url: URL, fetch: McpFetch, protocolVersion: string): Promise<Response> {\n\treturn fetch(url, {\n\t\theaders: { Accept: \"application/json\", \"MCP-Protocol-Version\": protocolVersion },\n\t});\n}\n\nexport async function discoverProtectedResourceMetadata(\n\tserverUrl: string | URL,\n\toptions: { resourceMetadataUrl?: string | URL; protocolVersion?: string; fetch?: McpFetch } = {},\n): Promise<OAuthProtectedResourceMetadata> {\n\tconst server = new URL(serverUrl);\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tconst version = options.protocolVersion ?? LATEST_PROTOCOL_VERSION;\n\tlet response = await fetchMetadata(\n\t\toptions.resourceMetadataUrl\n\t\t\t? new URL(options.resourceMetadataUrl)\n\t\t\t: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin),\n\t\tfetch,\n\t\tversion,\n\t);\n\tif (!options.resourceMetadataUrl && server.pathname !== \"/\" && isDiscoveryMiss(response.status)) {\n\t\tdiscard(response);\n\t\tresponse = await fetchMetadata(new URL(\"/.well-known/oauth-protected-resource\", server.origin), fetch, version);\n\t}\n\tif (!response.ok) {\n\t\tdiscard(response);\n\t\tthrow new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);\n\t}\n\treturn parseProtectedResourceMetadata(await response.json());\n}\n\nexport function buildAuthorizationServerDiscoveryUrls(\n\tauthorizationServerUrl: string | URL,\n): { url: URL; type: \"oauth\" | \"oidc\" }[] {\n\tconst issuer = new URL(authorizationServerUrl);\n\tconst path = pathSuffix(issuer.pathname);\n\tconst urls: { url: URL; type: \"oauth\" | \"oidc\" }[] = [\n\t\t{ url: new URL(`/.well-known/oauth-authorization-server${path}`, issuer.origin), type: \"oauth\" },\n\t\t{ url: new URL(`/.well-known/openid-configuration${path}`, issuer.origin), type: \"oidc\" },\n\t];\n\tif (path) urls.push({ url: new URL(`${path}/.well-known/openid-configuration`, issuer.origin), type: \"oidc\" });\n\treturn urls;\n}\n\nexport async function discoverAuthorizationServerMetadata(\n\tauthorizationServerUrl: string | URL,\n\toptions: { fetch?: McpFetch; protocolVersion?: string; skipIssuerValidation?: boolean } = {},\n): Promise<AuthorizationServerMetadata | undefined> {\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tfor (const { url } of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)) {\n\t\tconst response = await fetchMetadata(url, fetch, options.protocolVersion ?? LATEST_PROTOCOL_VERSION);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tif (isDiscoveryMiss(response.status)) continue;\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\tif (!options.skipIssuerValidation) {\n\t\t\tconst expected = String(authorizationServerUrl);\n\t\t\t// URL parsing adds a trailing slash to bare origins, so compare without one on either side.\n\t\t\tconst trim = (value: string) => (value.endsWith(\"/\") ? value.slice(0, -1) : value);\n\t\t\tif (trim(metadata.issuer) !== trim(expected)) throw new OAuthIssuerMismatchError(expected, metadata.issuer);\n\t\t}\n\t\treturn metadata;\n\t}\n\treturn undefined;\n}\n\nexport async function discoverOAuthServerInfo(\n\tserverUrl: string | URL,\n\toptions: {\n\t\tresourceMetadataUrl?: URL;\n\t\tfetch?: McpFetch;\n\t\tskipIssuerValidation?: boolean;\n\t} = {},\n): Promise<OAuthServerInfo> {\n\tlet resourceMetadata: OAuthProtectedResourceMetadata | undefined;\n\ttry {\n\t\tresourceMetadata = await discoverProtectedResourceMetadata(serverUrl, {\n\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\tfetch: options.fetch,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof TypeError) throw error;\n\t}\n\tconst authorizationServerUrl = resourceMetadata?.authorization_servers?.[0] ?? String(new URL(\"/\", serverUrl));\n\treturn {\n\t\tauthorizationServerUrl,\n\t\tauthorizationServerMetadata: await discoverAuthorizationServerMetadata(authorizationServerUrl, {\n\t\t\tfetch: options.fetch,\n\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t}),\n\t\tresourceMetadata,\n\t};\n}\n\nexport function resourceUrlFromServerUrl(value: string | URL): URL {\n\tconst url = new URL(value);\n\turl.hash = \"\";\n\treturn url;\n}\n\nexport function selectResource(serverUrl: string | URL, metadata?: OAuthProtectedResourceMetadata): string | undefined {\n\tif (!metadata) return undefined;\n\tconst requested = resourceUrlFromServerUrl(serverUrl);\n\tconst configured = new URL(metadata.resource);\n\tif (requested.origin !== configured.origin) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\tconst requestedPath = requested.pathname.endsWith(\"/\") ? requested.pathname : `${requested.pathname}/`;\n\tconst configuredPath = configured.pathname.endsWith(\"/\") ? configured.pathname : `${configured.pathname}/`;\n\tif (!requestedPath.startsWith(configuredPath)) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\treturn metadata.resource;\n}\n"]}
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove Zod/CORS shims and enforce authorization-server issuer validation.\n */\n\nimport type { McpFetch } from \"../auth-provider.ts\";\nimport { LATEST_PROTOCOL_VERSION } from \"../protocol/types.ts\";\nimport { OAuthIssuerMismatchError } from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthChallenge,\n\ttype OAuthProtectedResourceMetadata,\n\ttype OAuthServerInfo,\n\tparseAuthorizationServerMetadata,\n\tparseProtectedResourceMetadata,\n} from \"./types.ts\";\n\nfunction discard(response: Response | undefined): void {\n\tvoid response?.body?.cancel().catch(() => {});\n}\n\n/** 4xx and 502 mean \"not here\", so discovery tries the next candidate URL. */\nfunction isDiscoveryMiss(status: number): boolean {\n\treturn (status >= 400 && status < 500) || status === 502;\n}\n\n/** Path suffix for `/.well-known/<kind><path>`; empty for the root path. */\nfunction pathSuffix(pathname: string): string {\n\treturn pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\nfunction field(header: string, name: string): string | undefined {\n\tconst match = header.match(new RegExp(String.raw`(?:^|[,\\s])${name}=(?:\"([^\"]*)\"|([^\\s,]+))`, \"i\"));\n\t// An empty value (`scope=\"\"`) carries no information, so it counts as absent.\n\treturn match?.[1] || match?.[2] || undefined;\n}\n\nexport function parseWwwAuthenticate(header: string | null): OAuthChallenge {\n\tif (!header) return {};\n\tconst scheme = header.trimStart().split(/\\s+/, 1)[0]?.toLowerCase();\n\tif (scheme !== \"bearer\" && scheme !== \"dpop\") return {};\n\tconst resourceMetadata = field(header, \"resource_metadata\");\n\tlet resourceMetadataUrl: URL | undefined;\n\tif (resourceMetadata) {\n\t\ttry {\n\t\t\tresourceMetadataUrl = new URL(resourceMetadata);\n\t\t} catch {}\n\t}\n\treturn {\n\t\tresourceMetadataUrl,\n\t\tscope: field(header, \"scope\"),\n\t\terror: field(header, \"error\"),\n\t\terrorDescription: field(header, \"error_description\"),\n\t};\n}\n\nasync function fetchMetadata(url: URL, fetch: McpFetch, protocolVersion: string): Promise<Response> {\n\treturn fetch(url, {\n\t\theaders: { Accept: \"application/json\", \"MCP-Protocol-Version\": protocolVersion },\n\t});\n}\n\nexport async function discoverProtectedResourceMetadata(\n\tserverUrl: string | URL,\n\toptions: { resourceMetadataUrl?: string | URL; protocolVersion?: string; fetch?: McpFetch } = {},\n): Promise<OAuthProtectedResourceMetadata> {\n\tconst server = new URL(serverUrl);\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tconst version = options.protocolVersion ?? LATEST_PROTOCOL_VERSION;\n\tlet response = await fetchMetadata(\n\t\toptions.resourceMetadataUrl\n\t\t\t? new URL(options.resourceMetadataUrl)\n\t\t\t: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin),\n\t\tfetch,\n\t\tversion,\n\t);\n\tif (!options.resourceMetadataUrl && server.pathname !== \"/\" && isDiscoveryMiss(response.status)) {\n\t\tdiscard(response);\n\t\tresponse = await fetchMetadata(new URL(\"/.well-known/oauth-protected-resource\", server.origin), fetch, version);\n\t}\n\tif (!response.ok) {\n\t\tdiscard(response);\n\t\tthrow new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);\n\t}\n\treturn parseProtectedResourceMetadata(await response.json());\n}\n\nexport function buildAuthorizationServerDiscoveryUrls(\n\tauthorizationServerUrl: string | URL,\n): { url: URL; type: \"oauth\" | \"oidc\" }[] {\n\tconst issuer = new URL(authorizationServerUrl);\n\tconst path = pathSuffix(issuer.pathname);\n\tconst urls: { url: URL; type: \"oauth\" | \"oidc\" }[] = [\n\t\t{ url: new URL(`/.well-known/oauth-authorization-server${path}`, issuer.origin), type: \"oauth\" },\n\t\t{ url: new URL(`/.well-known/openid-configuration${path}`, issuer.origin), type: \"oidc\" },\n\t];\n\tif (path) urls.push({ url: new URL(`${path}/.well-known/openid-configuration`, issuer.origin), type: \"oidc\" });\n\treturn urls;\n}\n\nexport async function discoverAuthorizationServerMetadata(\n\tauthorizationServerUrl: string | URL,\n\toptions: { fetch?: McpFetch; protocolVersion?: string; skipIssuerValidation?: boolean } = {},\n): Promise<AuthorizationServerMetadata | undefined> {\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tfor (const { url } of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)) {\n\t\tconst response = await fetchMetadata(url, fetch, options.protocolVersion ?? LATEST_PROTOCOL_VERSION);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tif (isDiscoveryMiss(response.status)) continue;\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\tif (!options.skipIssuerValidation) {\n\t\t\tconst expected = String(authorizationServerUrl);\n\t\t\t// URL parsing adds a trailing slash to bare origins, so compare without one on either side.\n\t\t\tconst trim = (value: string) => (value.endsWith(\"/\") ? value.slice(0, -1) : value);\n\t\t\tif (trim(metadata.issuer) !== trim(expected)) throw new OAuthIssuerMismatchError(expected, metadata.issuer);\n\t\t}\n\t\treturn metadata;\n\t}\n\treturn undefined;\n}\n\nexport async function discoverOAuthServerInfo(\n\tserverUrl: string | URL,\n\toptions: {\n\t\tresourceMetadataUrl?: URL;\n\t\t/** Metadata document to use instead of discovery. It is trusted as configured, so its issuer is not checked. */\n\t\tauthorizationServerMetadataUrl?: URL;\n\t\tfetch?: McpFetch;\n\t\tskipIssuerValidation?: boolean;\n\t} = {},\n): Promise<OAuthServerInfo> {\n\tlet resourceMetadata: OAuthProtectedResourceMetadata | undefined;\n\ttry {\n\t\tresourceMetadata = await discoverProtectedResourceMetadata(serverUrl, {\n\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\tfetch: options.fetch,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof TypeError) throw error;\n\t}\n\tif (options.authorizationServerMetadataUrl) {\n\t\tconst url = options.authorizationServerMetadataUrl;\n\t\tconst response = await fetchMetadata(url, options.fetch ?? globalThis.fetch, LATEST_PROTOCOL_VERSION);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\treturn { authorizationServerUrl: metadata.issuer, authorizationServerMetadata: metadata, resourceMetadata };\n\t}\n\tconst authorizationServerUrl = resourceMetadata?.authorization_servers?.[0] ?? String(new URL(\"/\", serverUrl));\n\treturn {\n\t\tauthorizationServerUrl,\n\t\tauthorizationServerMetadata: await discoverAuthorizationServerMetadata(authorizationServerUrl, {\n\t\t\tfetch: options.fetch,\n\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t}),\n\t\tresourceMetadata,\n\t};\n}\n\nexport function resourceUrlFromServerUrl(value: string | URL): URL {\n\tconst url = new URL(value);\n\turl.hash = \"\";\n\treturn url;\n}\n\nexport function selectResource(serverUrl: string | URL, metadata?: OAuthProtectedResourceMetadata): string | undefined {\n\tif (!metadata) return undefined;\n\tconst requested = resourceUrlFromServerUrl(serverUrl);\n\tconst configured = new URL(metadata.resource);\n\tif (requested.origin !== configured.origin) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\tconst requestedPath = requested.pathname.endsWith(\"/\") ? requested.pathname : `${requested.pathname}/`;\n\tconst configuredPath = configured.pathname.endsWith(\"/\") ? configured.pathname : `${configured.pathname}/`;\n\tif (!requestedPath.startsWith(configuredPath)) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\treturn metadata.resource;\n}\n"]}
@@ -5,8 +5,9 @@ export declare class OAuthError extends Error {
5
5
  }
6
6
  export declare class OAuthIssuerMismatchError extends Error {
7
7
  readonly expected: string;
8
- readonly received: string;
9
- constructor(expected: string, received: string);
8
+ /** `undefined` when an authorization response lacks the `iss` parameter its server promised (RFC 9207). */
9
+ readonly received: string | undefined;
10
+ constructor(expected: string, received: string | undefined);
10
11
  }
11
12
  export declare class OAuthInsecureEndpointError extends Error {
12
13
  readonly endpoint: string;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/oauth/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAK3D;CACD;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAK7C;CACD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAI3B;CACD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAKvC;CACD;AAED,qBAAa,kCAAmC,SAAQ,KAAK;IAC5D,cAGC;CACD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/oauth/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAK3D;CACD;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2GAA2G;IAC3G,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,YAAY,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAOzD;CACD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YAAY,QAAQ,EAAE,MAAM,EAI3B;CACD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAKvC;CACD;AAED,qBAAa,kCAAmC,SAAQ,KAAK;IAC5D,cAGC;CACD"}
@@ -10,9 +10,10 @@ export class OAuthError extends Error {
10
10
  }
11
11
  export class OAuthIssuerMismatchError extends Error {
12
12
  expected;
13
+ /** `undefined` when an authorization response lacks the `iss` parameter its server promised (RFC 9207). */
13
14
  received;
14
15
  constructor(expected, received) {
15
- super(`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${JSON.stringify(received)}`);
16
+ super(`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${received === undefined ? "none" : JSON.stringify(received)}`);
16
17
  this.name = "OAuthIssuerMismatchError";
17
18
  this.expected = expected;
18
19
  this.received = received;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/oauth/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC3B,IAAI,CAAS;IACb,QAAQ,CAAqB;IAEtC,YAAY,IAAY,EAAE,OAAe,EAAE,QAAiB;QAC3D,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACzC,QAAQ,CAAS;IACjB,QAAQ,CAAS;IAE1B,YAAY,QAAgB,EAAE,QAAgB;QAC7C,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3G,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC3C,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC3B,KAAK,CAAC,4DAA4D,QAAQ,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACvC,MAAM,CAAS;IACf,IAAI,CAAS;IAEtB,YAAY,MAAc,EAAE,IAAY;QACvC,KAAK,CAAC,wDAAwD,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;CACD;AAED,MAAM,OAAO,kCAAmC,SAAQ,KAAK;IAC5D;QACC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,oCAAoC,CAAC;IAClD,CAAC;CACD","sourcesContent":["export class OAuthError extends Error {\n\treadonly code: string;\n\treadonly errorUri: string | undefined;\n\n\tconstructor(code: string, message: string, errorUri?: string) {\n\t\tsuper(message || code);\n\t\tthis.name = \"OAuthError\";\n\t\tthis.code = code;\n\t\tthis.errorUri = errorUri;\n\t}\n}\n\nexport class OAuthIssuerMismatchError extends Error {\n\treadonly expected: string;\n\treadonly received: string;\n\n\tconstructor(expected: string, received: string) {\n\t\tsuper(`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${JSON.stringify(received)}`);\n\t\tthis.name = \"OAuthIssuerMismatchError\";\n\t\tthis.expected = expected;\n\t\tthis.received = received;\n\t}\n}\n\nexport class OAuthInsecureEndpointError extends Error {\n\treadonly endpoint: string;\n\n\tconstructor(endpoint: string) {\n\t\tsuper(`Refusing to send OAuth credentials to non-HTTPS endpoint ${endpoint}`);\n\t\tthis.name = \"OAuthInsecureEndpointError\";\n\t\tthis.endpoint = endpoint;\n\t}\n}\n\nexport class OAuthRegistrationError extends Error {\n\treadonly status: number;\n\treadonly body: string;\n\n\tconstructor(status: number, body: string) {\n\t\tsuper(`OAuth dynamic client registration failed with status ${status}: ${body}`);\n\t\tthis.name = \"OAuthRegistrationError\";\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport class McpOAuthAuthorizationRequiredError extends Error {\n\tconstructor() {\n\t\tsuper(\"MCP OAuth authorization requires user interaction\");\n\t\tthis.name = \"McpOAuthAuthorizationRequiredError\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/oauth/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC3B,IAAI,CAAS;IACb,QAAQ,CAAqB;IAEtC,YAAY,IAAY,EAAE,OAAe,EAAE,QAAiB;QAC3D,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACzC,QAAQ,CAAS;IAC1B,2GAA2G;IAClG,QAAQ,CAAqB;IAEtC,YAAY,QAAgB,EAAE,QAA4B;QACzD,KAAK,CACJ,mCAAmC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CACrI,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC3C,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC3B,KAAK,CAAC,4DAA4D,QAAQ,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACvC,MAAM,CAAS;IACf,IAAI,CAAS;IAEtB,YAAY,MAAc,EAAE,IAAY;QACvC,KAAK,CAAC,wDAAwD,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;CACD;AAED,MAAM,OAAO,kCAAmC,SAAQ,KAAK;IAC5D;QACC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,oCAAoC,CAAC;IAClD,CAAC;CACD","sourcesContent":["export class OAuthError extends Error {\n\treadonly code: string;\n\treadonly errorUri: string | undefined;\n\n\tconstructor(code: string, message: string, errorUri?: string) {\n\t\tsuper(message || code);\n\t\tthis.name = \"OAuthError\";\n\t\tthis.code = code;\n\t\tthis.errorUri = errorUri;\n\t}\n}\n\nexport class OAuthIssuerMismatchError extends Error {\n\treadonly expected: string;\n\t/** `undefined` when an authorization response lacks the `iss` parameter its server promised (RFC 9207). */\n\treadonly received: string | undefined;\n\n\tconstructor(expected: string, received: string | undefined) {\n\t\tsuper(\n\t\t\t`OAuth issuer mismatch: expected ${JSON.stringify(expected)}, received ${received === undefined ? \"none\" : JSON.stringify(received)}`,\n\t\t);\n\t\tthis.name = \"OAuthIssuerMismatchError\";\n\t\tthis.expected = expected;\n\t\tthis.received = received;\n\t}\n}\n\nexport class OAuthInsecureEndpointError extends Error {\n\treadonly endpoint: string;\n\n\tconstructor(endpoint: string) {\n\t\tsuper(`Refusing to send OAuth credentials to non-HTTPS endpoint ${endpoint}`);\n\t\tthis.name = \"OAuthInsecureEndpointError\";\n\t\tthis.endpoint = endpoint;\n\t}\n}\n\nexport class OAuthRegistrationError extends Error {\n\treadonly status: number;\n\treadonly body: string;\n\n\tconstructor(status: number, body: string) {\n\t\tsuper(`OAuth dynamic client registration failed with status ${status}: ${body}`);\n\t\tthis.name = \"OAuthRegistrationError\";\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport class McpOAuthAuthorizationRequiredError extends Error {\n\tconstructor() {\n\t\tsuper(\"MCP OAuth authorization requires user interaction\");\n\t\tthis.name = \"McpOAuthAuthorizationRequiredError\";\n\t}\n}\n"]}