agents 0.19.0 → 0.20.0

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.
Files changed (49) hide show
  1. package/README.md +24 -19
  2. package/dist/{agent-tool-types-BNUGGBzQ.d.ts → agent-tool-types-Btk9ETS-.d.ts} +997 -356
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-BFbzVLFc.d.ts → agent-tools-UuScsJg3.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/browser/ai.js +1 -1
  7. package/dist/browser/index.js +1 -1
  8. package/dist/chat/index.d.ts +2 -2
  9. package/dist/chat-sdk/index.d.ts +1 -1
  10. package/dist/client-invoker-BNSZxAkv.d.ts +20 -0
  11. package/dist/client-invoker-VNZ7X0nn.js +57 -0
  12. package/dist/client-invoker-VNZ7X0nn.js.map +1 -0
  13. package/dist/{client-CcjiFpTf.js → client-zqKcsyFa.js} +434 -168
  14. package/dist/client-zqKcsyFa.js.map +1 -0
  15. package/dist/client.d.ts +1 -1
  16. package/dist/{connector-CdldGF3h.js → connector-KEJnl6e5.js} +2 -2
  17. package/dist/connector-KEJnl6e5.js.map +1 -0
  18. package/dist/{do-oauth-client-provider-D4ZwyBDu.d.ts → do-oauth-client-provider-VTZj2VtM.d.ts} +23 -11
  19. package/dist/experimental/webmcp.js +1 -1
  20. package/dist/handler-stateless-8hQN_kC3.js +367 -0
  21. package/dist/handler-stateless-8hQN_kC3.js.map +1 -0
  22. package/dist/handler-stateless-C_bo-Ytq.d.ts +107 -0
  23. package/dist/index.d.ts +12 -12
  24. package/dist/index.js +3 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp/client.d.ts +22 -18
  27. package/dist/mcp/client.js +1 -1
  28. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  29. package/dist/mcp/do-oauth-client-provider.js +25 -12
  30. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  31. package/dist/mcp/index.d.ts +48 -34
  32. package/dist/mcp/index.js +84 -79
  33. package/dist/mcp/index.js.map +1 -1
  34. package/dist/mcp/server.d.ts +17 -0
  35. package/dist/mcp/server.js +2 -0
  36. package/dist/mcp/x402.d.ts +21 -9
  37. package/dist/mcp/x402.js +8 -7
  38. package/dist/mcp/x402.js.map +1 -1
  39. package/dist/react.d.ts +1 -1
  40. package/dist/serializable.d.ts +1 -1
  41. package/dist/sub-routing.d.ts +6 -6
  42. package/dist/workflows.d.ts +1 -1
  43. package/docs/human-in-the-loop.md +63 -82
  44. package/docs/mcp-client.md +31 -7
  45. package/docs/mcp-servers.md +125 -88
  46. package/docs/securing-mcp-servers.md +9 -6
  47. package/package.json +28 -7
  48. package/dist/client-CcjiFpTf.js.map +0 -1
  49. package/dist/connector-CdldGF3h.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-zqKcsyFa.js","names":[],"sources":["../src/core/events.ts","../src/mcp/abort.ts","../src/mcp/client-catalog.ts","../src/mcp/client-runtime.ts","../src/mcp/errors.ts","../src/mcp/rpc.ts","../src/mcp/client-connection.ts","../src/mcp/client-storage.ts","../src/mcp/client.ts"],"sourcesContent":["export interface Disposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): Disposable {\n return { dispose: fn };\n}\n\nexport class DisposableStore implements Disposable {\n private readonly _items: Disposable[] = [];\n\n add<T extends Disposable>(d: T): T {\n this._items.push(d);\n return d;\n }\n\n dispose(): void {\n while (this._items.length) {\n try {\n this._items.pop()!.dispose();\n } catch {\n // best-effort cleanup\n }\n }\n }\n}\n\nexport type Event<T> = (listener: (e: T) => void) => Disposable;\n\nexport class Emitter<T> implements Disposable {\n private _listeners: Set<(e: T) => void> = new Set();\n\n readonly event: Event<T> = (listener) => {\n this._listeners.add(listener);\n return toDisposable(() => this._listeners.delete(listener));\n };\n\n fire(data: T): void {\n for (const listener of [...this._listeners]) {\n try {\n listener(data);\n } catch (err) {\n // do not let one bad listener break others\n console.error(\"Emitter listener error:\", err);\n }\n }\n }\n\n dispose(): void {\n this._listeners.clear();\n }\n}\n","export function abortError(signal: AbortSignal): Error {\n return signal.reason instanceof Error\n ? signal.reason\n : new Error(String(signal.reason ?? \"Aborted\"));\n}\n\n/**\n * Stop awaiting an operation when its owner aborts. The underlying operation\n * remains responsible for observing the same signal and cancelling its work.\n */\nexport async function raceWithSignal<T>(\n promise: Promise<T>,\n signal?: AbortSignal\n): Promise<T> {\n if (!signal) return promise;\n if (signal.aborted) throw abortError(signal);\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(abortError(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n promise.then(resolve, reject).finally(() => {\n signal.removeEventListener(\"abort\", onAbort);\n });\n });\n}\n","import type {\n Client,\n ListPromptsResult,\n ListResourceTemplatesResult,\n ListResourcesResult,\n ListToolsResult,\n Prompt,\n Resource,\n ResourceTemplateType as ResourceTemplate,\n Tool\n} from \"@modelcontextprotocol/client\";\n\ntype CapabilityErrorHandler = <T>(\n empty: T,\n method: string\n) => (error: { code: number }) => T;\n\ntype CatalogFetchOptions = {\n probing: boolean;\n onCapabilityError: CapabilityErrorHandler;\n};\n\nexport async function fetchMcpTools(\n client: Client,\n options: CatalogFetchOptions\n): Promise<Tool[]> {\n let aggregate: Tool[] = [];\n let page: ListToolsResult = { tools: [] };\n do {\n const params = { cursor: page.nextCursor };\n page = await (\n options.probing\n ? client.request({ method: \"tools/list\", params })\n : client.listTools(params)\n ).catch(options.onCapabilityError({ tools: [] }, \"tools/list\"));\n aggregate = aggregate.concat(page.tools);\n } while (page.nextCursor);\n return aggregate;\n}\n\nexport async function fetchMcpResources(\n client: Client,\n options: CatalogFetchOptions\n): Promise<Resource[]> {\n let aggregate: Resource[] = [];\n let page: ListResourcesResult = { resources: [] };\n do {\n const params = { cursor: page.nextCursor };\n page = await (\n options.probing\n ? client.request({ method: \"resources/list\", params })\n : client.listResources(params)\n ).catch(options.onCapabilityError({ resources: [] }, \"resources/list\"));\n aggregate = aggregate.concat(page.resources);\n } while (page.nextCursor);\n return aggregate;\n}\n\nexport async function fetchMcpPrompts(\n client: Client,\n options: CatalogFetchOptions\n): Promise<Prompt[]> {\n let aggregate: Prompt[] = [];\n let page: ListPromptsResult = { prompts: [] };\n do {\n const params = { cursor: page.nextCursor };\n page = await (\n options.probing\n ? client.request({ method: \"prompts/list\", params })\n : client.listPrompts(params)\n ).catch(options.onCapabilityError({ prompts: [] }, \"prompts/list\"));\n aggregate = aggregate.concat(page.prompts);\n } while (page.nextCursor);\n return aggregate;\n}\n\nexport async function fetchMcpResourceTemplates(\n client: Client,\n options: CatalogFetchOptions\n): Promise<ResourceTemplate[]> {\n let aggregate: ResourceTemplate[] = [];\n let page: ListResourceTemplatesResult = { resourceTemplates: [] };\n do {\n const params = { cursor: page.nextCursor };\n page = await (\n options.probing\n ? client.request({ method: \"resources/templates/list\", params })\n : client.listResourceTemplates(params)\n ).catch(\n options.onCapabilityError(\n { resourceTemplates: [] },\n \"resources/templates/list\"\n )\n );\n aggregate = aggregate.concat(page.resourceTemplates);\n } while (page.nextCursor);\n return aggregate;\n}\n","import {\n Client,\n type ClientCapabilities,\n type JsonSchemaType,\n type jsonSchemaValidator,\n type ListChangedHandlers,\n type Prompt,\n type Resource,\n type Tool\n} from \"@modelcontextprotocol/client\";\nimport { CfWorkerJsonSchemaValidator } from \"@modelcontextprotocol/client/validators/cf-worker\";\nimport type { McpClientOptions } from \"./types\";\n\nclass CompatibleWorkerJsonSchemaValidator\n extends CfWorkerJsonSchemaValidator\n implements jsonSchemaValidator\n{\n private readonly legacy = new CfWorkerJsonSchemaValidator({ draft: \"7\" });\n\n override getValidator<T>(schema: JsonSchemaType) {\n const dialect = schema.$schema;\n return typeof dialect === \"string\" && /draft-0?7/i.test(dialect)\n ? this.legacy.getValidator<T>(schema)\n : super.getValidator<T>(schema);\n }\n}\n\nconst DEFAULT_CLIENT_OPTIONS: NonNullable<McpClientOptions> = {\n jsonSchemaValidator: new CompatibleWorkerJsonSchemaValidator(),\n versionNegotiation: { mode: \"auto\" },\n inputRequired: { autoFulfill: true }\n};\n\nexport function normalizeMcpClientOptions(\n options?: McpClientOptions\n): NonNullable<McpClientOptions> {\n return {\n ...DEFAULT_CLIENT_OPTIONS,\n ...options,\n versionNegotiation: {\n ...DEFAULT_CLIENT_OPTIONS.versionNegotiation,\n ...options?.versionNegotiation\n },\n inputRequired: {\n ...DEFAULT_CLIENT_OPTIONS.inputRequired,\n ...options?.inputRequired\n }\n };\n}\n\nexport function elicitationCapabilitiesFromHandlers(handlers?: {\n form?: unknown;\n url?: unknown;\n}): ClientCapabilities[\"elicitation\"] | undefined {\n if (!handlers) return undefined;\n const elicitation: NonNullable<ClientCapabilities[\"elicitation\"]> = {};\n if (handlers.form) elicitation.form = {};\n if (handlers.url) elicitation.url = {};\n return elicitation.form || elicitation.url ? elicitation : undefined;\n}\n\ntype CatalogCallbacks = {\n tools(error: Error | null, tools: Tool[] | null): void;\n prompts(error: Error | null, prompts: Prompt[] | null): void;\n resources(error: Error | null, resources: Resource[] | null): void;\n};\n\nfunction listChangedHandlers(\n configured: ListChangedHandlers | undefined,\n callbacks: CatalogCallbacks\n): ListChangedHandlers {\n return {\n tools: {\n ...configured?.tools,\n onChanged: (error, tools) => {\n callbacks.tools(error, tools);\n configured?.tools?.onChanged(error, tools);\n }\n },\n prompts: {\n ...configured?.prompts,\n onChanged: (error, prompts) => {\n callbacks.prompts(error, prompts);\n configured?.prompts?.onChanged(error, prompts);\n }\n },\n resources: {\n ...configured?.resources,\n onChanged: (error, resources) => {\n callbacks.resources(error, resources);\n configured?.resources?.onChanged(error, resources);\n }\n }\n };\n}\n\nexport function createMcpSdkClient(\n info: ConstructorParameters<typeof Client>[0],\n options: NonNullable<McpClientOptions>,\n capabilitySeed: ClientCapabilities | undefined,\n handlerModes: { form?: unknown; url?: unknown } | undefined,\n callbacks: CatalogCallbacks\n): { client: Client; elicitationEnabled: boolean } {\n const elicitation =\n options.capabilities?.elicitation ??\n elicitationCapabilitiesFromHandlers(handlerModes) ??\n capabilitySeed?.elicitation;\n const client = new Client(info, {\n ...options,\n capabilities: {\n ...capabilitySeed,\n ...options.capabilities,\n ...(elicitation ? { elicitation } : {})\n },\n listChanged: listChangedHandlers(options.listChanged, callbacks)\n });\n return { client, elicitationEnabled: elicitation !== undefined };\n}\n","export function toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction getErrorStatus(error: unknown): number | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n const record = error as {\n code?: unknown;\n status?: unknown;\n data?: { status?: unknown; cause?: unknown };\n };\n if (typeof record.code === \"number\") return record.code;\n if (typeof record.status === \"number\") return record.status;\n if (typeof record.data?.status === \"number\") return record.data.status;\n return undefined;\n}\n\nfunction getErrorCause(error: unknown): unknown {\n if (!error || typeof error !== \"object\") return undefined;\n return (\n (error as { cause?: unknown; data?: { cause?: unknown } }).cause ??\n (error as { data?: { cause?: unknown } }).data?.cause\n );\n}\n\nexport function isUnauthorized(error: unknown): boolean {\n const status = getErrorStatus(error);\n if (status === 401) return true;\n const cause = getErrorCause(error);\n if (cause && cause !== error && isUnauthorized(cause)) return true;\n\n const msg = toErrorMessage(error);\n return msg.includes(\"Unauthorized\") || msg.includes(\"401\");\n}\n\n// MCP SDK change (v1.24.0, commit 6b90e1a):\n// - Old: Error POSTing to endpoint (HTTP 404): Not Found\n// - New: StreamableHTTPError with code: 404 and message Error POSTing to endpoint: Not Found\nexport function isTransportNotImplemented(error: unknown): boolean {\n const status = getErrorStatus(error);\n if (status === 404 || status === 405) return true;\n const cause = getErrorCause(error);\n if (cause && cause !== error && isTransportNotImplemented(cause)) return true;\n\n const msg = toErrorMessage(error);\n return (\n msg.includes(\"404\") ||\n msg.includes(\"405\") ||\n msg.includes(\"Error POSTing to endpoint: Not Found\") ||\n msg.includes(\"Not Implemented\") ||\n msg.includes(\"not implemented\")\n );\n}\n","import type {\n JSONRPCMessage as V2JSONRPCMessage,\n MessageExtraInfo as V2MessageExtraInfo,\n Transport as V2Transport,\n TransportSendOptions as V2TransportSendOptions\n} from \"@modelcontextprotocol/client\";\nimport type {\n Transport as V1Transport,\n TransportSendOptions as V1TransportSendOptions\n} from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n JSONRPCMessage as V1JSONRPCMessage,\n MessageExtraInfo as V1MessageExtraInfo\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n isJSONRPCErrorResponse,\n isJSONRPCResultResponse,\n JSONRPCMessageSchema\n} from \"@modelcontextprotocol/sdk/types.js\";\n\ntype JSONRPCMessage = V1JSONRPCMessage;\ntype MessageExtraInfo = V1MessageExtraInfo;\nimport { getServerByName } from \"partyserver\";\nimport type { McpAgent } from \".\";\nimport { raceWithSignal } from \"./abort\";\n\nexport const RPC_DO_PREFIX = \"rpc:\";\n\nfunction makeInvalidRequestError(id: unknown): JSONRPCMessage {\n return {\n jsonrpc: \"2.0\",\n id: id ?? null,\n error: {\n code: -32600,\n message: \"Invalid Request\"\n }\n } as JSONRPCMessage;\n}\n\nfunction validateBatch(batch: JSONRPCMessage[]): void {\n if (batch.length === 0) {\n throw new Error(\"Invalid JSON-RPC batch: array must not be empty\");\n }\n}\n\nexport interface RPCClientTransportOptions<T extends McpAgent = McpAgent> {\n namespace: DurableObjectNamespace<T>;\n name: string;\n props?: Record<string, unknown>;\n}\n\nexport class RPCClientTransport implements V2Transport {\n private _namespace: DurableObjectNamespace<McpAgent>;\n private _name: string;\n private _props?: Record<string, unknown>;\n private _stub?: DurableObjectStub<McpAgent>;\n private _started = false;\n private _protocolVersion?: string;\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: V2JSONRPCMessage, extra?: V2MessageExtraInfo) => void;\n\n constructor(options: RPCClientTransportOptions<McpAgent>) {\n this._namespace = options.namespace;\n this._name = options.name;\n this._props = options.props;\n }\n\n setProtocolVersion(version: string): void {\n this._protocolVersion = version;\n }\n\n getProtocolVersion(): string | undefined {\n return this._protocolVersion;\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n\n const doName = `${RPC_DO_PREFIX}${this._name}`;\n this._stub = await getServerByName<Cloudflare.Env, McpAgent>(\n this._namespace,\n doName,\n { props: this._props }\n );\n\n this._started = true;\n }\n\n async close(): Promise<void> {\n this._started = false;\n this._stub = undefined;\n this.onclose?.();\n }\n\n async send(\n message: V2JSONRPCMessage | V2JSONRPCMessage[],\n options?: V2TransportSendOptions\n ): Promise<void> {\n if (!this._started || !this._stub) {\n throw new Error(\"Transport not started\");\n }\n\n try {\n const pending = this._stub.handleMcpMessage(\n message as JSONRPCMessage | JSONRPCMessage[]\n ) as Promise<V2JSONRPCMessage | V2JSONRPCMessage[] | undefined>;\n const result = await raceWithSignal(pending, options?.requestSignal);\n\n if (!result || options?.requestSignal?.aborted) {\n return;\n }\n\n // The v2 client transport contract no longer uses the v1 requestInfo\n // placeholder. Correlation is carried by JSON-RPC ids in this adapter.\n const extra: V2MessageExtraInfo | undefined = undefined;\n\n const messages = Array.isArray(result) ? result : [result];\n for (const msg of messages) {\n this.onmessage?.(msg, extra);\n }\n } catch (error) {\n this.onerror?.(error as Error);\n throw error;\n }\n }\n}\n\nexport interface RPCServerTransportOptions {\n timeout?: number;\n}\n\ntype PendingRPCResponse = {\n messages: JSONRPCMessage[];\n resolve: (response: JSONRPCMessage | JSONRPCMessage[] | undefined) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\nexport class RPCServerTransport implements V1Transport {\n private _started = false;\n private _protocolVersion?: string;\n private _timeout: number;\n private _pendingRequests = new Map<string, PendingRPCResponse>();\n private _pendingContinuations: PendingRPCResponse[] = [];\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n constructor(options?: RPCServerTransportOptions) {\n this._timeout = options?.timeout ?? 60000;\n }\n\n setProtocolVersion(version: string): void {\n this._protocolVersion = version;\n }\n\n getProtocolVersion(): string | undefined {\n return this._protocolVersion;\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error(\"Transport already started\");\n }\n this._started = true;\n }\n\n async close(): Promise<void> {\n this._started = false;\n this.onclose?.();\n\n const error = new Error(\"Transport closed\");\n for (const pending of this._pendingRequests.values()) {\n clearTimeout(pending.timeoutId);\n pending.reject(error);\n }\n this._pendingRequests.clear();\n\n for (const pending of this._pendingContinuations) {\n clearTimeout(pending.timeoutId);\n pending.reject(error);\n }\n this._pendingContinuations = [];\n }\n\n private _makeTimeout(onTimeout: () => void): ReturnType<typeof setTimeout> {\n return setTimeout(onTimeout, this._timeout);\n }\n\n private _appendPending(\n pending: PendingRPCResponse,\n message: JSONRPCMessage\n ): void {\n pending.messages.push(message);\n }\n\n private _completePending(\n pending: PendingRPCResponse,\n message: JSONRPCMessage\n ): void {\n pending.messages.push(message);\n clearTimeout(pending.timeoutId);\n\n const messages = pending.messages;\n queueMicrotask(() => {\n pending.resolve(messages.length === 1 ? messages[0] : messages);\n });\n }\n\n private _completeRequest(key: string, message: JSONRPCMessage): boolean {\n const pending = this._pendingRequests.get(key);\n if (!pending) return false;\n\n this._pendingRequests.delete(key);\n this._completePending(pending, message);\n return true;\n }\n\n private _appendRequest(key: string, message: JSONRPCMessage): boolean {\n const pending = this._pendingRequests.get(key);\n if (!pending) return false;\n\n this._appendPending(pending, message);\n return true;\n }\n\n private _completeContinuation(message: JSONRPCMessage): boolean {\n const pending = this._pendingContinuations.shift();\n if (!pending) return false;\n\n this._completePending(pending, message);\n return true;\n }\n\n private _appendContinuation(message: JSONRPCMessage): boolean {\n const pending = this._pendingContinuations[0];\n if (!pending) return false;\n\n this._appendPending(pending, message);\n return true;\n }\n\n async send(\n message: JSONRPCMessage,\n options?: V1TransportSendOptions\n ): Promise<void> {\n if (!this._started) {\n throw new Error(\"Transport not started\");\n }\n\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n const id = message.id;\n if (id === undefined) {\n this.onerror?.(\n new Error(`RPC response missing id: ${JSON.stringify(message)}`)\n );\n return;\n }\n\n if (this._completeRequest(id.toString(), message)) {\n return;\n }\n\n if (this._completeContinuation(message)) {\n return;\n }\n\n this.onerror?.(\n new Error(\n `No pending RPC request found for response: ${JSON.stringify(\n message\n )}`\n )\n );\n return;\n }\n\n const relatedRequestId = options?.relatedRequestId?.toString();\n const expectsResponse = \"id\" in message;\n\n if (relatedRequestId) {\n if (expectsResponse) {\n if (this._completeRequest(relatedRequestId, message)) return;\n } else if (this._appendRequest(relatedRequestId, message)) {\n return;\n }\n }\n\n if (expectsResponse) {\n if (this._completeContinuation(message)) return;\n } else if (this._appendContinuation(message)) {\n return;\n }\n\n this.onerror?.(\n new Error(\n `No pending RPC request found for message: ${JSON.stringify(message)}`\n )\n );\n }\n\n /**\n * @internal Called by McpAgent.handleMcpMessage() — not for external use.\n *\n * Wait for the next unmatched send() call that expects a client response or\n * completes a resumed tool call.\n *\n * Used after resolving an elicitation response: the original tool call has\n * already returned the elicitation request to the RPC client, and the resumed\n * tool handler will eventually send the final tool result. That final response\n * has the original tool request id, so there is no active handle() waiter left\n * for id-based routing; this continuation waiter receives it instead.\n */\n async _awaitPendingResponse(): Promise<\n JSONRPCMessage | JSONRPCMessage[] | undefined\n > {\n if (!this._started) {\n throw new Error(\"Transport not started\");\n }\n\n return await new Promise<JSONRPCMessage | JSONRPCMessage[] | undefined>(\n (resolve, reject) => {\n const pending: PendingRPCResponse = {\n messages: [],\n resolve,\n reject,\n timeoutId: this._makeTimeout(() => {\n const index = this._pendingContinuations.indexOf(pending);\n if (index !== -1) {\n this._pendingContinuations.splice(index, 1);\n }\n reject(\n new Error(\n `Request timeout: No response received within ${this._timeout}ms`\n )\n );\n })\n };\n this._pendingContinuations.push(pending);\n }\n );\n }\n\n async handle(\n message: JSONRPCMessage | JSONRPCMessage[]\n ): Promise<JSONRPCMessage | JSONRPCMessage[] | undefined> {\n if (!this._started) {\n throw new Error(\"Transport not started\");\n }\n\n if (Array.isArray(message)) {\n validateBatch(message);\n\n const responses = await Promise.all(\n message.map((msg) => this.handle(msg))\n );\n const flattened = responses.flatMap((response) => {\n if (response === undefined) return [];\n return Array.isArray(response) ? response : [response];\n });\n\n return flattened.length === 0 ? undefined : flattened;\n }\n\n try {\n JSONRPCMessageSchema.parse(message);\n } catch {\n const id =\n typeof message === \"object\" && message !== null && \"id\" in message\n ? (message as { id: unknown }).id\n : null;\n return makeInvalidRequestError(id);\n }\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n this.onmessage?.(message);\n return undefined;\n }\n\n const id = message.id?.toString();\n if (!id) {\n return makeInvalidRequestError(message.id);\n }\n\n if (this._pendingRequests.has(id)) {\n throw new Error(`Duplicate pending RPC request id: ${id}`);\n }\n\n const responsePromise = new Promise<\n JSONRPCMessage | JSONRPCMessage[] | undefined\n >((resolve, reject) => {\n const pending: PendingRPCResponse = {\n messages: [],\n resolve,\n reject,\n timeoutId: this._makeTimeout(() => {\n this._pendingRequests.delete(id);\n reject(\n new Error(\n `Request timeout: No response received within ${this._timeout}ms`\n )\n );\n })\n };\n\n this._pendingRequests.set(id, pending);\n });\n\n this.onmessage?.(message);\n\n return await responsePromise;\n }\n}\n","import {\n Client,\n SSEClientTransport,\n StreamableHTTPClientTransport,\n SdkHttpError,\n type ClientCapabilities,\n type ClientContext,\n type DiscoverResult,\n type ElicitRequest,\n type ElicitResult,\n type McpSubscription,\n type Prompt,\n type Resource,\n type ResourceTemplateType as ResourceTemplate,\n type ServerCapabilities,\n type SSEClientTransportOptions,\n type StreamableHTTPClientTransportOptions,\n type Tool\n} from \"@modelcontextprotocol/client\";\nimport { Emitter, type Event } from \"../core/events\";\nimport type { MCPObservabilityEvent } from \"../observability/mcp\";\nimport { raceWithSignal } from \"./abort\";\nimport {\n fetchMcpPrompts,\n fetchMcpResources,\n fetchMcpResourceTemplates,\n fetchMcpTools\n} from \"./client-catalog\";\nimport type { AgentMcpOAuthProvider } from \"./do-oauth-client-provider\";\nimport {\n createMcpSdkClient,\n normalizeMcpClientOptions\n} from \"./client-runtime\";\nexport { elicitationCapabilitiesFromHandlers } from \"./client-runtime\";\nimport {\n isTransportNotImplemented,\n isUnauthorized,\n toErrorMessage\n} from \"./errors\";\nimport { RPCClientTransport, type RPCClientTransportOptions } from \"./rpc\";\nimport type {\n BaseTransportType,\n HttpTransportType,\n TransportType,\n McpClientOptions\n} from \"./types\";\n\n/**\n * Connection state machine for MCP client connections.\n *\n * State transitions:\n * - Non-OAuth: init() → CONNECTING → DISCOVERING → READY\n * - OAuth: init() → AUTHENTICATING → (callback) → CONNECTING → DISCOVERING → READY\n * - Any state can transition to FAILED on error\n */\nexport const MCPConnectionState = {\n /** Waiting for OAuth authorization to complete */\n AUTHENTICATING: \"authenticating\",\n /** Establishing transport connection to MCP server */\n CONNECTING: \"connecting\",\n /** Transport connection established */\n CONNECTED: \"connected\",\n /** Discovering server capabilities (tools, resources, prompts) */\n DISCOVERING: \"discovering\",\n /** Fully connected and ready to use */\n READY: \"ready\",\n /** Connection failed at some point */\n FAILED: \"failed\"\n} as const;\n\n/**\n * Connection state type for MCP client connections.\n */\nexport type MCPConnectionState =\n (typeof MCPConnectionState)[keyof typeof MCPConnectionState];\n\n/**\n * Transport options for MCP client connections.\n * Combines transport-specific options with auth provider and type selection.\n */\nexport type MCPTransportOptions = (\n | SSEClientTransportOptions\n | StreamableHTTPClientTransportOptions\n | RPCClientTransportOptions\n) & {\n authProvider?: AgentMcpOAuthProvider;\n type?: TransportType;\n};\n\nexport type MCPClientConnectionResult = {\n state: MCPConnectionState;\n error?: Error;\n transport?: BaseTransportType;\n};\n\n/** Result of discovering server capabilities. */\nexport type MCPDiscoveryResult =\n | { success: true }\n | { success: false; reason: \"error\" | \"stale-session\"; error: string };\n\n/**\n * Handler for server-initiated `elicitation/create` requests.\n * Held in memory only — never persisted — so it must be re-supplied when a\n * connection is recreated (e.g. after Durable Object hibernation).\n */\nexport type MCPElicitationHandler = (\n request: ElicitRequest,\n /** Aborts when the originating MCP call is cancelled or exhausts its total-time budget. */\n signal?: AbortSignal\n) => Promise<ElicitResult>;\n\nexport type MCPElicitationHandlers = {\n form?: MCPElicitationHandler;\n url?: MCPElicitationHandler;\n};\n\nexport class MCPClientConnection {\n client: Client;\n connectionState: MCPConnectionState = MCPConnectionState.CONNECTING;\n connectionError: string | null = null;\n lastConnectedTransport: BaseTransportType | undefined;\n instructions?: string;\n tools: Tool[] = [];\n private _transport?:\n | StreamableHTTPClientTransport\n | SSEClientTransport\n | RPCClientTransport;\n\n /**\n * Transport that received the 401 during the initial connect attempt.\n * Kept so finishAuth() runs on the transport that captured the resource\n * metadata URL from the WWW-Authenticate header — a fresh transport would\n * rediscover from defaults and exchange the code at the wrong token\n * endpoint when the authorization server is not at the default location.\n */\n private _pendingAuthTransport?:\n | StreamableHTTPClientTransport\n | SSEClientTransport\n | RPCClientTransport;\n private _restoredListSubscription?: McpSubscription;\n prompts: Prompt[] = [];\n resources: Resource[] = [];\n resourceTemplates: ResourceTemplate[] = [];\n serverCapabilities: ServerCapabilities | undefined;\n\n /** True when resuming a streamable-http session without cached capabilities */\n private _probingCapabilities = false;\n\n /** Tracks in-flight discovery to allow cancellation */\n private _discoveryAbortController: AbortController | undefined;\n\n private readonly _onObservabilityEvent = new Emitter<MCPObservabilityEvent>();\n public readonly onObservabilityEvent: Event<MCPObservabilityEvent> =\n this._onObservabilityEvent.event;\n\n private readonly _onListChanged = new Emitter<void>();\n public readonly onListChanged: Event<void> = this._onListChanged.event;\n\n /**\n * Whether the connection advertised the elicitation capability. The SDK\n * client refuses to register an `elicitation/create` request handler when\n * the capability was not declared, so handler registration is gated on\n * this.\n */\n private _elicitationEnabled = false;\n\n constructor(\n public url: URL,\n private readonly _info: ConstructorParameters<typeof Client>[0],\n public options: {\n transport: MCPTransportOptions;\n client: NonNullable<McpClientOptions>;\n elicitationHandlers?: MCPElicitationHandlers;\n /**\n * Client capabilities persisted from a previous session, advertised\n * until handlers are reconfigured after a hibernation restore. Cleared\n * by {@link configureElicitationHandlers} — reconfigured handlers are\n * the source of truth. Explicit `client.capabilities` win per key.\n */\n capabilitySeed?: ClientCapabilities;\n /** SDK discovery result paired with a resumed Stateless HTTP session. */\n discoverResult?: DiscoverResult;\n } = { client: {}, transport: {} }\n ) {\n this.options = {\n ...options,\n client: normalizeMcpClientOptions(options.client)\n };\n\n this.client = this.createClient();\n }\n\n private createClient(): Client {\n const created = createMcpSdkClient(\n this._info,\n this.options.client,\n this.options.capabilitySeed,\n this.options.elicitationHandlers,\n {\n tools: (error, tools) => {\n if (!error && tools) this.tools = tools;\n this._onListChanged.fire();\n },\n prompts: (error, prompts) => {\n if (!error && prompts) this.prompts = prompts;\n this._onListChanged.fire();\n },\n resources: (error, resources) => {\n if (!error && resources) this.resources = resources;\n this._onListChanged.fire();\n }\n }\n );\n this._elicitationEnabled = created.elicitationEnabled;\n return created.client;\n }\n\n /**\n * Configure the handler used for server-initiated elicitation requests.\n *\n * If the connection has not been initialized yet, rebuild the SDK client so\n * handler-driven elicitation capabilities are reflected in the initial\n * handshake. A rebuild (rather than `Client.registerCapabilities`) is\n * required because SDK capability registration is merge-only — it cannot\n * un-advertise a mode when handlers are cleared before connecting. Active\n * connections keep their negotiated capabilities until they reconnect.\n */\n configureElicitationHandlers(handlers?: MCPElicitationHandlers): void {\n this.options.elicitationHandlers = handlers;\n // Handlers are now the source of truth — drop the restore seed so\n // clearing the handlers un-advertises the capability on rebuild.\n this.options.capabilitySeed = undefined;\n\n if (!this._transport) {\n this.client = this.createClient();\n }\n }\n\n /**\n * Initialize a client connection, if authentication is required, the connection will be in the AUTHENTICATING state\n * Sets connection state based on the result and emits observability events\n *\n * @returns Error message if connection failed, undefined otherwise\n */\n async init(): Promise<string | undefined> {\n const transportType = this.options.transport.type;\n if (!transportType) {\n throw new Error(\"Transport type must be specified\");\n }\n\n // init() can be re-entered after a mid-session 401 → OAuth → reconnect\n // cycle (e.g. scope step-up, token revocation). The SDK client refuses\n // to connect while a previous transport is still attached, so detach it\n // first. Rebuild the client so the new handshake advertises the current\n // handler-derived capabilities — reconnects are documented as the point\n // where handler changes on a live connection take effect.\n if (this._transport) {\n this._transport = undefined;\n try {\n await this.client.close();\n } catch {\n // Closing a transport that just failed auth is best-effort.\n }\n this.client = this.createClient();\n }\n\n const res = await this.tryConnect(transportType);\n\n // Set the connection state\n this.connectionState = res.state;\n\n // Handle the result and emit appropriate events\n if (res.state === MCPConnectionState.CONNECTED && res.transport) {\n // Set up the elicitation request handler after a successful\n // connection. Only when the capability was advertised — the SDK\n // client throws on registering a handler for an undeclared capability.\n if (this._elicitationEnabled) {\n this.client.setRequestHandler(\n \"elicitation/create\",\n async (request: ElicitRequest, context: ClientContext) =>\n await this.handleElicitationRequest(request, context.mcpReq.signal)\n );\n }\n\n this.lastConnectedTransport = res.transport;\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: this.url.toString(),\n transport: res.transport,\n state: this.connectionState\n },\n timestamp: Date.now()\n });\n return undefined;\n } else if (res.state === MCPConnectionState.FAILED && res.error) {\n const errorMessage = toErrorMessage(res.error);\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: this.url.toString(),\n transport: transportType,\n state: this.connectionState,\n error: errorMessage\n },\n timestamp: Date.now()\n });\n return errorMessage;\n }\n return undefined;\n }\n\n /**\n * Finish OAuth by probing transports based on configured type.\n * - Explicit: finish on that transport\n * - Auto: try streamable-http, then sse on 404/405/Not Implemented\n */\n private async finishAuthProbe(\n callbackParams: URLSearchParams\n ): Promise<void> {\n if (!this.options.transport.authProvider) {\n throw new Error(\"No auth provider configured\");\n }\n\n const configuredType = this.options.transport.type;\n if (!configuredType) {\n throw new Error(\"Transport type must be specified\");\n }\n\n const finishAuth = async (base: HttpTransportType) => {\n const transport = this.getTransport(base);\n let completed = false;\n try {\n if (\n \"finishAuth\" in transport &&\n typeof transport.finishAuth === \"function\"\n ) {\n await transport.finishAuth(callbackParams);\n completed = true;\n }\n } finally {\n if (typeof transport.close === \"function\") {\n await transport.close().catch(() => {});\n }\n }\n if (completed) this.client = this.createClient();\n };\n\n if (configuredType === \"rpc\") {\n throw new Error(\"RPC transport does not support authentication\");\n }\n\n // Prefer the transport that triggered authentication (initial-connect\n // 401, or the active transport for a mid-session 401 such as a scope\n // step-up): it holds the resource metadata URL from the WWW-Authenticate\n // header that finishAuth() needs to locate the authorization server.\n const authTransport = this._pendingAuthTransport ?? this._transport;\n this._pendingAuthTransport = undefined;\n if (\n authTransport &&\n \"finishAuth\" in authTransport &&\n typeof authTransport.finishAuth === \"function\"\n ) {\n let completed = false;\n try {\n await authTransport.finishAuth(callbackParams);\n completed = true;\n } finally {\n if (typeof authTransport.close === \"function\") {\n await authTransport.close().catch(() => {});\n }\n if (this._transport === authTransport) this._transport = undefined;\n }\n if (completed) this.client = this.createClient();\n return;\n }\n\n if (configuredType === \"sse\" || configuredType === \"streamable-http\") {\n await finishAuth(configuredType);\n return;\n }\n\n // For \"auto\" mode, try streamable-http first, then fall back to SSE\n try {\n await finishAuth(\"streamable-http\");\n } catch (e) {\n if (isTransportNotImplemented(e)) {\n await finishAuth(\"sse\");\n return;\n }\n throw e;\n }\n }\n\n /**\n * Complete OAuth authorization\n */\n async completeAuthorization(\n callback: string | URLSearchParams,\n options: { alreadyAccepted?: boolean } = {}\n ): Promise<void> {\n const expectedState = options.alreadyAccepted\n ? MCPConnectionState.CONNECTING\n : MCPConnectionState.AUTHENTICATING;\n if (this.connectionState !== expectedState) {\n throw new Error(\n `Connection must be in ${expectedState} state to complete authorization`\n );\n }\n\n if (!options.alreadyAccepted) {\n this.connectionState = MCPConnectionState.CONNECTING;\n }\n\n try {\n // Finish OAuth by probing transports per configuration\n const callbackParams =\n typeof callback === \"string\"\n ? new URLSearchParams({ code: callback })\n : callback;\n await this.finishAuthProbe(callbackParams);\n } catch (error) {\n this.connectionState = MCPConnectionState.FAILED;\n throw error;\n }\n }\n\n /**\n * Discover server capabilities and register tools, resources, prompts, and templates.\n * This method does the work but does not manage connection state - that's handled by discover().\n */\n async discoverAndRegister(): Promise<void> {\n const discoveredCapabilities = this.client.getServerCapabilities();\n const shouldProbeCapabilities =\n !discoveredCapabilities && this.isResumedStreamableHttpSession();\n\n this.serverCapabilities = discoveredCapabilities;\n this._probingCapabilities = shouldProbeCapabilities;\n\n if (!discoveredCapabilities && !shouldProbeCapabilities) {\n throw new Error(\"The MCP Server failed to return server capabilities\");\n }\n\n // Build list of operations to perform based on server capabilities.\n // For resumed streamable-http sessions, the MCP SDK skips initialize()\n // when a sessionId already exists, so a fresh Client instance may not have\n // cached server capabilities yet. In that case, probe the list endpoints\n // directly and treat -32601 as capability absence.\n type DiscoveryResult =\n | string\n | undefined\n | Tool[]\n | Resource[]\n | Prompt[]\n | ResourceTemplate[];\n const operations: Promise<DiscoveryResult>[] = [];\n const operationNames: string[] = [];\n\n // Instructions (always try to fetch if available)\n operations.push(Promise.resolve(this.client.getInstructions()));\n operationNames.push(\"instructions\");\n\n if (discoveredCapabilities?.tools || shouldProbeCapabilities) {\n operations.push(this.registerTools());\n operationNames.push(\"tools\");\n }\n\n if (discoveredCapabilities?.resources || shouldProbeCapabilities) {\n operations.push(this.registerResources());\n operationNames.push(\"resources\");\n }\n\n if (discoveredCapabilities?.prompts || shouldProbeCapabilities) {\n operations.push(this.registerPrompts());\n operationNames.push(\"prompts\");\n }\n\n if (discoveredCapabilities?.resources || shouldProbeCapabilities) {\n operations.push(this.registerResourceTemplates());\n operationNames.push(\"resource templates\");\n }\n\n try {\n const results = await Promise.all(operations);\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n const name = operationNames[i];\n\n switch (name) {\n case \"instructions\":\n this.instructions = result as string | undefined;\n break;\n case \"tools\":\n this.tools = result as Tool[];\n break;\n case \"resources\":\n this.resources = result as Resource[];\n break;\n case \"prompts\":\n this.prompts = result as Prompt[];\n break;\n case \"resource templates\":\n this.resourceTemplates = result as ResourceTemplate[];\n break;\n }\n }\n } catch (error) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {\n url: this.url.toString(),\n error: toErrorMessage(error)\n },\n timestamp: Date.now()\n });\n\n throw error;\n }\n }\n\n /**\n * Discover server capabilities with timeout and cancellation support.\n * If called while a previous discovery is in-flight, the previous discovery will be aborted.\n *\n * @param options Optional configuration\n * @param options.timeoutMs Timeout in milliseconds (default: 15000)\n * @returns Result indicating success/failure with optional error message\n */\n async discover(\n options: { timeoutMs?: number } = {}\n ): Promise<MCPDiscoveryResult> {\n const { timeoutMs = 15000 } = options;\n\n // Check if state allows discovery\n if (\n this.connectionState !== MCPConnectionState.CONNECTED &&\n this.connectionState !== MCPConnectionState.READY\n ) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {\n url: this.url.toString(),\n state: this.connectionState\n },\n timestamp: Date.now()\n });\n return {\n success: false,\n reason: \"error\",\n error: `Discovery skipped - connection in ${this.connectionState} state`\n };\n }\n\n // Cancel any previous in-flight discovery\n if (this._discoveryAbortController) {\n this._discoveryAbortController.abort();\n this._discoveryAbortController = undefined;\n }\n\n // Create a new AbortController for this discovery\n const abortController = new AbortController();\n this._discoveryAbortController = abortController;\n\n this.connectionState = MCPConnectionState.DISCOVERING;\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(\n () => reject(new Error(`Discovery timed out after ${timeoutMs}ms`)),\n timeoutMs\n );\n });\n\n // Check if aborted before starting\n if (abortController.signal.aborted) {\n throw new Error(\"Discovery was cancelled\");\n }\n\n // Create an abort promise that rejects when signal fires\n const abortPromise = new Promise<never>((_, reject) => {\n abortController.signal.addEventListener(\"abort\", () => {\n reject(new Error(\"Discovery was cancelled\"));\n });\n });\n\n await Promise.race([\n this.discoverAndRegister(),\n timeoutPromise,\n abortPromise\n ]);\n\n // Clear timeout on success\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n\n // Discovery succeeded - transition to ready\n this.connectionState = MCPConnectionState.READY;\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {\n url: this.url.toString()\n },\n timestamp: Date.now()\n });\n\n return { success: true };\n } catch (e) {\n // Always clear the timeout\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n\n // Ordinary discovery failures return to CONNECTED so callers can retry.\n // A 401 is different: the live transport has already produced an OAuth\n // authorization URL, so preserve AUTHENTICATING for the manager to\n // persist and expose that continuation.\n this.connectionState = isUnauthorized(e)\n ? MCPConnectionState.AUTHENTICATING\n : MCPConnectionState.CONNECTED;\n\n const error = e instanceof Error ? e.message : String(e);\n // A restored streamable HTTP session rejected with 404 must be\n // initialized again without its persisted session id.\n const staleSession =\n this._probingCapabilities &&\n e instanceof SdkHttpError &&\n e.status === 404;\n return {\n success: false,\n reason: staleSession ? \"stale-session\" : \"error\",\n error\n };\n } finally {\n // Clean up the abort controller\n this._discoveryAbortController = undefined;\n }\n }\n\n /**\n * Cancel any in-flight discovery operation.\n * Called when closing the connection.\n */\n cancelDiscovery(): void {\n if (this._discoveryAbortController) {\n this._discoveryAbortController.abort();\n this._discoveryAbortController = undefined;\n }\n }\n\n /**\n * Notification handler registration for tools\n * Should only be called if serverCapabilities.tools exists\n */\n async registerTools(): Promise<Tool[]> {\n if (this._probingCapabilities) {\n this.client.setNotificationHandler(\n \"notifications/tools/list_changed\",\n async () => {\n this.tools = await this.fetchTools();\n this._onListChanged.fire();\n }\n );\n }\n return this.fetchTools();\n }\n\n /**\n * Notification handler registration for resources\n * Should only be called if serverCapabilities.resources exists\n */\n async registerResources(): Promise<Resource[]> {\n if (this._probingCapabilities) {\n this.client.setNotificationHandler(\n \"notifications/resources/list_changed\",\n async () => {\n this.resources = await this.fetchResources();\n this._onListChanged.fire();\n }\n );\n }\n return this.fetchResources();\n }\n\n /**\n * Notification handler registration for prompts\n * Should only be called if serverCapabilities.prompts exists\n */\n async registerPrompts(): Promise<Prompt[]> {\n if (this._probingCapabilities) {\n this.client.setNotificationHandler(\n \"notifications/prompts/list_changed\",\n async () => {\n this.prompts = await this.fetchPrompts();\n this._onListChanged.fire();\n }\n );\n }\n return this.fetchPrompts();\n }\n\n async registerResourceTemplates(): Promise<ResourceTemplate[]> {\n return this.fetchResourceTemplates();\n }\n\n private catalogFetchOptions() {\n return {\n probing: this._probingCapabilities,\n onCapabilityError: this._capabilityErrorHandler.bind(this)\n };\n }\n\n async fetchTools() {\n return fetchMcpTools(this.client, this.catalogFetchOptions());\n }\n\n async fetchResources() {\n return fetchMcpResources(this.client, this.catalogFetchOptions());\n }\n\n async fetchPrompts() {\n return fetchMcpPrompts(this.client, this.catalogFetchOptions());\n }\n\n async fetchResourceTemplates() {\n return fetchMcpResourceTemplates(this.client, this.catalogFetchOptions());\n }\n\n /**\n * Handle elicitation request from server.\n *\n * Delegates to the `elicitationHandlers` connection option when provided.\n *\n * @deprecated Overriding or instance-patching this method directly is\n * deprecated — pass the `elicitationHandlers` connection option instead.\n */\n async handleElicitationRequest(\n request: ElicitRequest,\n signal?: AbortSignal\n ): Promise<ElicitResult> {\n const mode = request.params.mode === \"url\" ? \"url\" : \"form\";\n const handler = this.options.elicitationHandlers?.[mode];\n if (handler) {\n const pending = signal ? handler(request, signal) : handler(request);\n return raceWithSignal(pending, signal);\n }\n if (this.options.elicitationHandlers) {\n throw new Error(\n `No MCP ${mode}-mode elicitation handler configured for this connection.`\n );\n }\n throw new Error(\n \"Elicitation handler must be implemented for your platform. Provide the MCPClientConnection elicitationHandlers option, or register handlers through the MCP client manager before connecting.\"\n );\n }\n\n private isResumedStreamableHttpSession(): boolean {\n return (\n this._transport instanceof StreamableHTTPClientTransport &&\n typeof this._transport.sessionId === \"string\"\n );\n }\n\n get sessionId(): string | undefined {\n if (this._transport instanceof StreamableHTTPClientTransport) {\n return this._transport.sessionId;\n }\n\n return undefined;\n }\n\n /** @internal Clear a restored session before reconnecting. */\n clearResumedSession(): void {\n if (\"sessionId\" in this.options.transport) {\n delete this.options.transport.sessionId;\n }\n }\n\n get protocolVersion(): string | undefined {\n if (this._transport instanceof StreamableHTTPClientTransport) {\n return this._transport.protocolVersion;\n }\n\n return undefined;\n }\n\n get discoverResult(): DiscoverResult | undefined {\n return this.client.getDiscoverResult();\n }\n\n private async openRestoredListSubscription(): Promise<void> {\n const capabilities = this.client.getServerCapabilities();\n const filter = {\n ...(capabilities?.tools?.listChanged && { toolsListChanged: true }),\n ...(capabilities?.prompts?.listChanged && { promptsListChanged: true }),\n ...(capabilities?.resources?.listChanged && {\n resourcesListChanged: true\n })\n };\n if (Object.keys(filter).length === 0) return;\n\n try {\n this._restoredListSubscription = await this.client.listen(filter);\n } catch (error) {\n // A restored session is still usable when its optional listen stream\n // cannot be reopened. Surface the error without failing the connection.\n this.client.onerror?.(\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n private getTransportName(\n transport?:\n | StreamableHTTPClientTransport\n | SSEClientTransport\n | RPCClientTransport\n ): string | undefined {\n if (transport instanceof StreamableHTTPClientTransport) {\n return \"streamable-http\";\n }\n\n if (transport instanceof SSEClientTransport) {\n return \"sse\";\n }\n\n if (transport instanceof RPCClientTransport) {\n return \"rpc\";\n }\n\n return this.lastConnectedTransport;\n }\n\n async close(): Promise<void> {\n const transport = this._transport;\n this._transport = undefined;\n await this._restoredListSubscription?.close().catch(() => {});\n this._restoredListSubscription = undefined;\n const url = this.url.toString();\n const transportName = this.getTransportName(transport);\n\n if (\n transport instanceof StreamableHTTPClientTransport &&\n transport.sessionId\n ) {\n try {\n await transport.terminateSession();\n } catch (error) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:close\",\n payload: {\n url,\n transport: transportName,\n state: \"error\",\n error: toErrorMessage(error),\n phase: \"terminate-session\"\n },\n timestamp: Date.now()\n });\n }\n }\n\n try {\n await this.client.close();\n } catch (error) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:close\",\n payload: {\n url,\n transport: transportName,\n state: \"error\",\n error: toErrorMessage(error),\n phase: \"client-close\"\n },\n timestamp: Date.now()\n });\n throw error;\n }\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:close\",\n payload: {\n url,\n transport: transportName,\n state: \"closed\"\n },\n timestamp: Date.now()\n });\n }\n\n /**\n * Get the transport for the client\n * @param transportType - The transport type to get\n * @returns The transport for the client\n */\n getTransport(transportType: BaseTransportType) {\n switch (transportType) {\n case \"streamable-http\":\n return new StreamableHTTPClientTransport(\n this.url,\n this.options.transport as StreamableHTTPClientTransportOptions\n );\n case \"sse\":\n return new SSEClientTransport(\n this.url,\n this.options.transport as SSEClientTransportOptions\n );\n case \"rpc\":\n return new RPCClientTransport(\n this.options.transport as RPCClientTransportOptions\n );\n default:\n throw new Error(`Unsupported transport type: ${transportType}`);\n }\n }\n\n private async tryConnect(\n transportType: TransportType\n ): Promise<MCPClientConnectionResult> {\n const transports: BaseTransportType[] =\n transportType === \"auto\" ? [\"streamable-http\", \"sse\"] : [transportType];\n\n for (const currentTransportType of transports) {\n const isLastTransport =\n currentTransportType === transports[transports.length - 1];\n const hasFallback =\n transportType === \"auto\" &&\n currentTransportType === \"streamable-http\" &&\n !isLastTransport;\n\n const transport = this.getTransport(currentTransportType);\n\n try {\n const prior =\n transport instanceof StreamableHTTPClientTransport &&\n transport.sessionId &&\n this.options.discoverResult\n ? { kind: \"modern\" as const, discover: this.options.discoverResult }\n : undefined;\n await this.client.connect(transport, prior ? { prior } : undefined);\n this._transport = transport;\n this._pendingAuthTransport = undefined;\n if (prior) await this.openRestoredListSubscription();\n\n return {\n state: MCPConnectionState.CONNECTED,\n transport: currentTransportType\n };\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e));\n\n if (isUnauthorized(error)) {\n this._pendingAuthTransport = transport;\n return {\n state: MCPConnectionState.AUTHENTICATING\n };\n }\n\n if (isTransportNotImplemented(error) && hasFallback) {\n // Try the next transport\n continue;\n }\n\n return {\n state: MCPConnectionState.FAILED,\n error\n };\n }\n }\n\n // Should never reach here\n return {\n state: MCPConnectionState.FAILED,\n error: new Error(\"No transports available\")\n };\n }\n\n private _capabilityErrorHandler<T>(empty: T, method: string) {\n return (e: { code: number }) => {\n // server is badly behaved and returning invalid capabilities. This commonly occurs for resource templates\n if (e.code === -32601) {\n const url = this.url.toString();\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {\n url,\n capability: method.split(\"/\")[0],\n error: toErrorMessage(e)\n },\n timestamp: Date.now()\n });\n return empty;\n }\n throw e;\n };\n }\n}\n","import type {\n ClientCapabilities,\n DiscoverResult,\n StreamableHTTPReconnectionOptions\n} from \"@modelcontextprotocol/client\";\nimport type { RetryOptions } from \"../retries\";\nimport type { McpClientOptions, TransportType } from \"./types\";\n\n/**\n * Represents a row in the cf_agents_mcp_servers table.\n */\nexport type MCPServerRow = {\n id: string;\n name: string;\n server_url: string;\n client_id: string | null;\n auth_url: string | null;\n callback_url: string;\n server_options: string | null;\n};\n\n/** Explicitly supported durable subset of MCP SDK client options. */\nexport type PersistedMcpClientOptions = Pick<\n McpClientOptions,\n | \"capabilities\"\n | \"supportedProtocolVersions\"\n | \"enforceStrictCapabilities\"\n | \"debouncedNotificationMethods\"\n | \"versionNegotiation\"\n | \"inputRequired\"\n | \"listMaxPages\"\n | \"cachePartition\"\n | \"defaultCacheTtlMs\"\n>;\n\nexport type PersistedMcpTransportOptions = {\n type?: TransportType;\n headers?: HeadersInit;\n requestInit?: RequestInit;\n reconnectionOptions?: StreamableHTTPReconnectionOptions;\n skipIssuerMetadataValidation?: boolean;\n onInsufficientScope?: \"reauthorize\" | \"throw\";\n maxStepUpRetries?: number;\n sessionId?: string;\n protocolVersion?: string;\n};\n\nexport type PersistedMcpServerOptions = {\n client?: PersistedMcpClientOptions;\n transport?: PersistedMcpTransportOptions;\n discoverResult?: DiscoverResult;\n retry?: RetryOptions;\n /** Durable Object binding used to restore an RPC MCP connection. */\n bindingName?: string;\n /** Application props passed back to a restored RPC MCP connection. */\n props?: Record<string, unknown>;\n /** One-wake capability seed; handler functions remain memory-only. */\n capabilities?: ClientCapabilities;\n};\n\ntype PersistableTransportOptions = PersistedMcpTransportOptions & {\n authProvider?: unknown;\n fetch?: unknown;\n reconnectionScheduler?: unknown;\n eventSourceInit?: unknown;\n};\n\ntype PersistableRegistration = {\n client?: McpClientOptions;\n transport?: PersistableTransportOptions;\n discoverResult?: DiscoverResult;\n retry?: RetryOptions;\n bindingName?: string;\n props?: Record<string, unknown>;\n capabilities?: ClientCapabilities;\n};\n\nfunction persistClientOptions(\n client?: McpClientOptions\n): PersistedMcpClientOptions | undefined {\n if (!client) return undefined;\n return {\n capabilities: client.capabilities,\n supportedProtocolVersions: client.supportedProtocolVersions,\n enforceStrictCapabilities: client.enforceStrictCapabilities,\n debouncedNotificationMethods: client.debouncedNotificationMethods,\n versionNegotiation: client.versionNegotiation,\n inputRequired: client.inputRequired,\n listMaxPages: client.listMaxPages,\n cachePartition: client.cachePartition,\n defaultCacheTtlMs: client.defaultCacheTtlMs\n };\n}\n\nfunction persistTransportOptions(\n value?: PersistableTransportOptions\n): PersistedMcpTransportOptions | undefined {\n if (!value) return undefined;\n return {\n type: value.type,\n headers: value.headers,\n requestInit: value.requestInit,\n reconnectionOptions: value.reconnectionOptions,\n skipIssuerMetadataValidation: value.skipIssuerMetadataValidation,\n onInsufficientScope: value.onInsufficientScope,\n maxStepUpRetries: value.maxStepUpRetries,\n sessionId: value.sessionId,\n protocolVersion: value.protocolVersion\n };\n}\n\nexport function encodeMcpServerOptions(\n options: PersistableRegistration\n): string {\n return JSON.stringify({\n client: persistClientOptions(options.client),\n transport: persistTransportOptions(options.transport),\n discoverResult: options.discoverResult,\n retry: options.retry,\n bindingName: options.bindingName,\n props: options.props,\n capabilities: options.capabilities\n } satisfies PersistedMcpServerOptions);\n}\n\nexport function decodeMcpServerOptions(\n value: string | null\n): PersistedMcpServerOptions {\n if (!value) return {};\n const parsed = JSON.parse(value) as PersistedMcpServerOptions;\n const transport = persistTransportOptions(parsed.transport);\n const statelessWithoutPrior =\n transport?.protocolVersion === \"2026-07-28\" && !parsed.discoverResult;\n if (\n transport?.sessionId &&\n (!transport.protocolVersion || statelessWithoutPrior)\n ) {\n delete transport.sessionId;\n delete transport.protocolVersion;\n delete parsed.discoverResult;\n }\n return {\n client: persistClientOptions(parsed.client),\n transport,\n discoverResult: parsed.discoverResult,\n retry: parsed.retry,\n ...(parsed.bindingName !== undefined && {\n bindingName: parsed.bindingName\n }),\n ...(parsed.props !== undefined && { props: parsed.props }),\n capabilities: parsed.capabilities\n };\n}\n\nexport function withMcpSession(\n options: PersistedMcpServerOptions,\n session?: {\n id: string;\n protocolVersion: string;\n discoverResult?: DiscoverResult;\n }\n): PersistedMcpServerOptions {\n const transport = { ...(options.transport ?? {}) };\n if (!session) {\n delete transport.sessionId;\n delete transport.protocolVersion;\n const next = { ...options, transport };\n delete next.discoverResult;\n return next;\n }\n transport.sessionId = session.id;\n transport.protocolVersion = session.protocolVersion;\n return {\n ...options,\n transport,\n ...(session.discoverResult\n ? { discoverResult: session.discoverResult }\n : { discoverResult: undefined })\n };\n}\n","import type {\n CallToolRequest,\n CallToolRequestOptions,\n CacheableRequestOptions,\n Client,\n ClientCapabilities,\n DiscoverResult,\n ElicitRequest,\n ElicitResult,\n GetPromptRequest,\n Prompt,\n ReadResourceRequest,\n RequestOptions,\n Resource,\n ResourceTemplateType as ResourceTemplate,\n Tool\n} from \"@modelcontextprotocol/client\";\nexport type { ElicitRequest, ElicitResult } from \"@modelcontextprotocol/client\";\nimport { type RetryOptions, tryN } from \"../retries\";\nimport { z } from \"zod\";\nimport { nanoid } from \"nanoid\";\nimport { Emitter, type Event, DisposableStore } from \"../core/events\";\nimport type { MCPObservabilityEvent } from \"../observability/mcp\";\nimport {\n elicitationCapabilitiesFromHandlers,\n MCPClientConnection,\n MCPConnectionState,\n type MCPDiscoveryResult,\n type MCPElicitationHandlers,\n type MCPTransportOptions\n} from \"./client-connection\";\nimport {\n callV2Tool,\n type CallToolSchemaOrOptions,\n type LegacyCallToolResultSchema\n} from \"./client-invoker\";\nimport { toErrorMessage } from \"./errors\";\nimport { RPC_DO_PREFIX } from \"./rpc\";\nimport type { McpClientOptions, TransportType } from \"./types\";\nimport {\n decodeMcpServerOptions,\n encodeMcpServerOptions,\n withMcpSession,\n type MCPServerRow,\n type PersistedMcpServerOptions\n} from \"./client-storage\";\nimport type { AgentMcpOAuthProvider } from \"./do-oauth-client-provider\";\nimport { DurableObjectOAuthClientProvider } from \"./do-oauth-client-provider\";\n\nexport type MCPAITool = {\n description?: string;\n title?: string;\n execute: (\n args: Record<string, unknown>,\n options?: unknown\n ) => Promise<unknown>;\n inputSchema: z.ZodType;\n outputSchema?: z.ZodType;\n};\n\n/**\n * Structural tool set returned by {@link MCPClientManager.getAITools}.\n * Compatible with the AI SDK without importing its types into the core\n * `agents` declaration graph.\n */\nexport type MCPAIToolSet = Record<string, MCPAITool>;\n\ntype MCPAIConvertedSchemas = {\n inputSchema: z.ZodType;\n outputSchema?: z.ZodType;\n};\n\ntype MCPAISchemaSource = {\n tool: Tool;\n inputSchema: Tool[\"inputSchema\"] | undefined;\n outputSchema: Tool[\"outputSchema\"] | undefined;\n};\n\ntype MCPAISchemaCacheSlot = MCPAISchemaSource &\n (\n | { status: \"converted\"; converted: MCPAIConvertedSchemas }\n | { status: \"failed\"; error: string }\n );\n\ntype MCPAISchemaCacheEntry = {\n catalog: Tool[];\n converted: Array<MCPAISchemaCacheSlot | undefined>;\n};\n\n/** Maximum length of a normalized MCP server id. */\nexport const MCP_SERVER_ID_MAX_LENGTH = 64;\n\n/**\n * Normalize a caller-supplied MCP server id into a stable, storage- and\n * tool-name-safe form.\n *\n * The id is surfaced in several places where the character set matters:\n * - as the primary key in the `cf_agents_mcp_servers` SQLite table\n * - embedded in AI SDK tool names as `` `tool_${id.replace(/-/g, \"\")}_${tool}` ``\n * (tool names must match `/^[A-Za-z0-9_]+$/`)\n * - as a key on the `mcpConnections` map and OAuth provider storage\n *\n * Rules:\n * 1. Lowercase.\n * 2. Replace any run of disallowed characters with a single `-`.\n * 3. Collapse repeated `-` and trim leading/trailing `-`/`_`.\n * 4. Prefix with `id-` if the result is empty or doesn't start with a letter.\n * 5. Truncate to {@link MCP_SERVER_ID_MAX_LENGTH} characters.\n *\n * @example\n * normalizeServerId(\"my-supplied-id\"); // \"my-supplied-id\"\n * normalizeServerId(\"GitHub MCP!\"); // \"github-mcp\"\n * normalizeServerId(\"42-things\"); // \"id-42-things\"\n */\nexport function normalizeServerId(input: string): string {\n if (typeof input !== \"string\") {\n throw new TypeError(\n `normalizeServerId: expected string, got ${typeof input}`\n );\n }\n\n let id = input\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^[-_]+|[-_]+$/g, \"\");\n\n if (id.length === 0 || !/^[a-z]/.test(id)) {\n id = `id-${id}`.replace(/-+$/g, \"\");\n }\n\n if (id.length > MCP_SERVER_ID_MAX_LENGTH) {\n id = id.slice(0, MCP_SERVER_ID_MAX_LENGTH).replace(/-+$/g, \"\");\n }\n\n return id;\n}\n\n/**\n * Blocked hostname patterns for SSRF protection.\n * Prevents MCP client from connecting to internal/private network addresses\n * while allowing loopback hosts for local development.\n */\nconst BLOCKED_HOSTNAMES = new Set([\n \"0.0.0.0\",\n \"[::]\",\n \"metadata.google.internal\"\n]);\n\n/**\n * Check whether four IPv4 octets belong to a private/reserved range.\n * Blocks RFC 1918, link-local, cloud metadata, and unspecified addresses.\n */\nfunction isPrivateIPv4(octets: number[]): boolean {\n const [a, b] = octets;\n // 10.0.0.0/8\n if (a === 10) return true;\n // 172.16.0.0/12\n if (a === 172 && b >= 16 && b <= 31) return true;\n // 192.168.0.0/16\n if (a === 192 && b === 168) return true;\n // 169.254.0.0/16 (link-local / cloud metadata)\n if (a === 169 && b === 254) return true;\n // 0.0.0.0/8\n if (a === 0) return true;\n return false;\n}\n\n/**\n * fe80::/10 — IPv6 link-local (RFC 4291 §2.5.6).\n *\n * The /10 boundary fixes the first 10 bits (1111111010), which means valid\n * first hextets range from fe80 through febf. Only hex digits 8, 9, a, b\n * have high two bits \"10\" — anything else (e.g. fe7f, fec0) is out of range.\n * The fourth hex digit is unconstrained by the /10 boundary.\n *\n * Historical bug: `startsWith(\"fe80\")` only matched the narrower fe80::/16\n * prefix and let fe81::/feab::/febf:: slip through. See issue #1325.\n */\nconst IPV6_LINK_LOCAL = /^fe[89ab][0-9a-f]/;\n\n/**\n * Check whether a bracket-stripped, lowercased IPv6 address belongs to a\n * private/reserved range. Also unwraps IPv4-mapped IPv6 (::ffff:...) and\n * delegates to isPrivateIPv4 for those.\n *\n * Loopback (::1) and unspecified (::) are NOT blocked here:\n * - ::1 is intentionally allowed (parallel to 127.x.x.x for local dev)\n * - :: (== [::]) is blocked via BLOCKED_HOSTNAMES at the hostname level\n */\nfunction isPrivateIPv6(addr: string): boolean {\n // fc00::/7 — unique local addresses (fc00:: through fdff::).\n // /7 fixes first 7 bits \"1111110\", so the 8-bit prefix is either\n // fc (11111100) or fd (11111101). No other first hextets qualify.\n if (addr.startsWith(\"fc\") || addr.startsWith(\"fd\")) return true;\n\n // fe80::/10 — link-local addresses (fe80:: through febf:...).\n if (IPV6_LINK_LOCAL.test(addr)) return true;\n\n // IPv4-mapped IPv6 (::ffff:x.x.x.x or ::ffff:XXYY:ZZWW).\n // The WHATWG URL parser does NOT canonicalize hex-form tails to dotted\n // form — [::ffff:a00:1] stays as \"::ffff:a00:1\" and will only be caught\n // by the hex branch. Both forms must therefore be handled here.\n if (addr.startsWith(\"::ffff:\")) {\n const mapped = addr.slice(7);\n const dotParts = mapped.split(\".\");\n if (dotParts.length === 4 && dotParts.every((p) => /^\\d{1,3}$/.test(p))) {\n if (isPrivateIPv4(dotParts.map(Number))) return true;\n } else {\n const hexParts = mapped.split(\":\");\n if (hexParts.length === 2) {\n const hi = parseInt(hexParts[0], 16);\n const lo = parseInt(hexParts[1], 16);\n if (\n isPrivateIPv4([\n (hi >> 8) & 0xff,\n hi & 0xff,\n (lo >> 8) & 0xff,\n lo & 0xff\n ])\n )\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check whether a hostname looks like a private/internal IP address.\n * Blocks RFC 1918, link-local, unique-local, unspecified,\n * and cloud metadata endpoints. Also detects IPv4-mapped IPv6 addresses.\n */\nfunction isBlockedUrl(url: string): boolean {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return true; // Malformed URLs are blocked\n }\n\n const hostname = parsed.hostname;\n\n if (BLOCKED_HOSTNAMES.has(hostname)) return true;\n\n // IPv4 checks\n const ipv4Parts = hostname.split(\".\");\n if (ipv4Parts.length === 4 && ipv4Parts.every((p) => /^\\d{1,3}$/.test(p))) {\n if (isPrivateIPv4(ipv4Parts.map(Number))) return true;\n }\n\n // IPv6 private range checks.\n // URL parser keeps brackets: hostname for [fc00::1] is \"[fc00::1]\".\n // The parser also lowercases/canonicalizes the address, but we\n // lowercase again defensively in case this helper is ever called with\n // a non-parser-produced hostname.\n if (hostname.startsWith(\"[\") && hostname.endsWith(\"]\")) {\n if (isPrivateIPv6(hostname.slice(1, -1).toLowerCase())) return true;\n }\n\n return false;\n}\n\nexport type MCPServerOptions = PersistedMcpServerOptions;\n\n/**\n * Result of an OAuth callback request\n */\nexport type MCPOAuthCallbackResult =\n | { serverId: string; authSuccess: true; authError?: undefined }\n | { serverId?: string; authSuccess: false; authError: string };\n\n/**\n * Options for registering an MCP server\n */\nexport type RegisterServerOptions = {\n url: string;\n name: string;\n callbackUrl?: string;\n client?: McpClientOptions;\n transport?: MCPTransportOptions;\n authUrl?: string;\n clientId?: string;\n /** Retry options for connection and reconnection attempts */\n retry?: RetryOptions;\n};\n\n/**\n * Result of attempting to connect to an MCP server.\n * Discriminated union ensures error is present only on failure.\n */\nexport type MCPConnectionResult =\n | {\n state: typeof MCPConnectionState.FAILED;\n error: string;\n }\n | {\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n clientId?: string;\n }\n | {\n state: typeof MCPConnectionState.CONNECTED;\n };\n\n/** Converts a resolved connection failure into a retry signal. */\nclass ConnectRetryError extends Error {\n constructor(readonly result: MCPConnectionResult) {\n super(\"MCP connection attempt failed\");\n }\n}\n\n/**\n * Result of discovering server capabilities.\n * success indicates whether discovery completed successfully.\n * state is the current connection state at time of return.\n * error is present when success is false.\n */\nexport type MCPDiscoverResult = {\n success: boolean;\n state: MCPConnectionState;\n error?: string;\n};\n\nexport type MCPClientOAuthCallbackConfig = {\n successRedirect?: string;\n errorRedirect?: string;\n customHandler?: (result: MCPClientOAuthResult) => Response;\n};\n\nexport type MCPClientOAuthResult =\n | { serverId: string; authSuccess: true; authError?: undefined }\n | {\n serverId?: string;\n authSuccess: false;\n /** May contain untrusted content from external OAuth providers. Escape appropriately for your output context. */\n authError: string;\n };\n\nexport type MCPClientElicitationHandler = (\n request: ElicitRequest,\n serverId: string,\n /** Aborts when the originating MCP operation is cancelled. */\n signal?: AbortSignal\n) => Promise<ElicitResult>;\n\nexport type MCPClientElicitationHandlers = {\n form?: MCPClientElicitationHandler;\n url?: MCPClientElicitationHandler;\n};\n\nexport type MCPClientManagerOptions = {\n storage: DurableObjectStorage;\n createAuthProvider?: (callbackUrl: string) => AgentMcpOAuthProvider;\n};\n\n/**\n * Filter options for scoping tools, prompts, resources, and resource templates\n * to a subset of connected MCP servers. All specified criteria are AND'd together.\n */\nexport type MCPServerFilter = {\n /** Include only connections matching this server ID (or IDs). */\n serverId?: string | string[];\n /** Include only connections whose stored name matches (or is in) this value. */\n serverName?: string | string[];\n /** Include only connections currently in this state (or states). */\n state?: MCPConnectionState | MCPConnectionState[];\n};\n\n/**\n * Utility class that aggregates multiple MCP clients into one\n */\nexport class MCPClientManager {\n public mcpConnections: Record<string, MCPClientConnection> = {};\n /** Cache only the current catalog so old schema graphs are not retained. */\n private readonly _aiToolSchemas = new WeakMap<\n MCPClientConnection,\n MCPAISchemaCacheEntry\n >();\n private _didWarnAboutUnstableGetAITools = false;\n private _oauthCallbackConfig?: MCPClientOAuthCallbackConfig;\n private _connectionDisposables = new Map<string, DisposableStore>();\n private _storage: DurableObjectStorage;\n private _createAuthProviderFn?: (\n callbackUrl: string\n ) => AgentMcpOAuthProvider;\n private _isRestored = false;\n private _pendingConnections = new Map<string, Promise<void>>();\n private _elicitationHandlers?: MCPClientElicitationHandlers;\n\n /** @internal Protected for testing purposes. */\n protected readonly _onObservabilityEvent =\n new Emitter<MCPObservabilityEvent>();\n public readonly onObservabilityEvent: Event<MCPObservabilityEvent> =\n this._onObservabilityEvent.event;\n\n private readonly _onServerStateChanged = new Emitter<void>();\n /**\n * Event that fires whenever any MCP server state changes (registered, connected, removed, etc.)\n * This is useful for broadcasting server state to clients.\n */\n public readonly onServerStateChanged: Event<void> =\n this._onServerStateChanged.event;\n\n /**\n * @param _name Name of the MCP client\n * @param _version Version of the MCP Client\n * @param options Storage adapter for persisting MCP server state\n */\n constructor(\n private _name: string,\n private _version: string,\n options: MCPClientManagerOptions\n ) {\n if (!options.storage) {\n throw new Error(\n \"MCPClientManager requires a valid DurableObjectStorage instance\"\n );\n }\n this._storage = options.storage;\n this._createAuthProviderFn = options.createAuthProvider;\n }\n\n /**\n * Scope the manager-level elicitation handler to a single connection.\n * Returns undefined when no handler is configured so the connection keeps\n * its default throwing behavior.\n */\n private scopedElicitationHandlers(\n serverId: string\n ): MCPElicitationHandlers | undefined {\n const handlers = this._elicitationHandlers;\n if (!handlers) return undefined;\n\n const form = handlers.form;\n const url = handlers.url;\n return {\n form: form\n ? (request, signal) =>\n signal ? form(request, serverId, signal) : form(request, serverId)\n : undefined,\n url: url\n ? (request, signal) =>\n signal ? url(request, serverId, signal) : url(request, serverId)\n : undefined\n };\n }\n\n // SQL helper - runs a query and returns results as array\n private sql<T extends Record<string, SqlStorageValue>>(\n query: string,\n ...bindings: SqlStorageValue[]\n ): T[] {\n return [...this._storage.sql.exec<T>(query, ...bindings)];\n }\n\n // Storage operations\n private saveServerToStorage(server: MCPServerRow): void {\n this.sql(\n `INSERT OR REPLACE INTO cf_agents_mcp_servers (\n id, name, server_url, client_id, auth_url, callback_url, server_options\n ) VALUES (?, ?, ?, ?, ?, ?, ?)`,\n server.id,\n server.name,\n server.server_url,\n server.client_id ?? null,\n server.auth_url ?? null,\n server.callback_url,\n server.server_options ?? null\n );\n }\n\n private removeServerFromStorage(serverId: string): void {\n this.sql(\"DELETE FROM cf_agents_mcp_servers WHERE id = ?\", serverId);\n }\n\n /**\n * Rename a server's id, in-place, across every place the id is used as a\n * key. Used to JIT-migrate servers that were originally registered under an\n * auto-generated nanoid to a caller-supplied stable id (see\n * `Agent.addMcpServer`'s `{ id }` option).\n *\n * Migrates:\n * - the `cf_agents_mcp_servers` row (primary key)\n * - the in-memory `mcpConnections` map key\n * - the connection disposables map key\n * - the attached `authProvider.serverId`, if any\n * - OAuth-related storage keys under `/{clientName}/{oldId}/...`\n *\n * Safe to call when no OAuth keys exist (RPC / bearer-token HTTP servers).\n * If `oldId === newId` this is a no-op. If a row already exists under\n * `newId`, throws — the caller is expected to have verified uniqueness.\n *\n * @internal Exposed for `Agent.addMcpServer` JIT-migration.\n */\n async migrateServerId(\n oldId: string,\n newId: string,\n clientName: string\n ): Promise<void> {\n if (oldId === newId) return;\n\n // Restore work closes over oldId. Drain it before renaming, including\n // replacement work registered while an earlier task settles.\n while (true) {\n const pending = this._pendingConnections.get(oldId);\n if (!pending) break;\n await pending.catch(() => {});\n }\n\n const existing = this.sql<MCPServerRow>(\n \"SELECT id FROM cf_agents_mcp_servers WHERE id = ?\",\n oldId\n );\n if (existing.length === 0) {\n // Nothing in storage to rename; just rename the in-memory connection if any.\n this._renameInMemoryConnection(oldId, newId);\n return;\n }\n\n const collision = this.sql<MCPServerRow>(\n \"SELECT id FROM cf_agents_mcp_servers WHERE id = ?\",\n newId\n );\n if (collision.length > 0) {\n throw new Error(\n `Cannot migrate MCP server id \"${oldId}\" → \"${newId}\": new id is already in use.`\n );\n }\n\n // 1. Storage: rename the SQL row.\n this.sql(\n \"UPDATE cf_agents_mcp_servers SET id = ? WHERE id = ?\",\n newId,\n oldId\n );\n\n // 2. OAuth-related storage keys. The DurableObjectOAuthClientProvider\n // keys everything under `/{clientName}/{serverId}/...`. Other servers\n // won't have any keys with this prefix, so the list will be empty and\n // this is a no-op for them.\n const oldPrefix = `/${clientName}/${oldId}/`;\n const newPrefix = `/${clientName}/${newId}/`;\n try {\n const keys = await this._storage.list({ prefix: oldPrefix });\n if (keys.size > 0) {\n const writes: Record<string, unknown> = {};\n const deletes: string[] = [];\n for (const [oldKey, value] of keys) {\n const newKey = newPrefix + oldKey.slice(oldPrefix.length);\n writes[newKey] = value;\n deletes.push(oldKey);\n }\n await this._storage.put(writes);\n await this._storage.delete(deletes);\n }\n } catch (error) {\n // Best-effort: storage rename failures shouldn't break the SQL-level\n // rename that already succeeded. Log and continue.\n console.warn(\n `[MCPClientManager] OAuth key migration ${oldPrefix} → ${newPrefix} failed:`,\n error\n );\n }\n\n // 3. In-memory connection + disposables + authProvider.\n this._renameInMemoryConnection(oldId, newId);\n\n this._onServerStateChanged.fire();\n }\n\n private _renameInMemoryConnection(oldId: string, newId: string): void {\n if (oldId === newId) return;\n\n const conn = this.mcpConnections[oldId];\n if (conn) {\n this.mcpConnections[newId] = conn;\n delete this.mcpConnections[oldId];\n const authProvider = conn.options.transport.authProvider;\n if (authProvider) {\n authProvider.serverId = newId;\n }\n // The elicitation handler closes over the server id it was created\n // with — rescope it so elicitation requests report the new id. With no\n // handlers there is nothing to rescope, and configuring would wipe the\n // connection's restored capability seed.\n const scoped = this.scopedElicitationHandlers(newId);\n if (scoped) {\n conn.configureElicitationHandlers(scoped);\n }\n }\n\n const disposables = this._connectionDisposables.get(oldId);\n if (disposables) {\n this._connectionDisposables.set(newId, disposables);\n this._connectionDisposables.delete(oldId);\n }\n }\n\n private getServersFromStorage(): MCPServerRow[] {\n return this.sql<MCPServerRow>(\n \"SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers\"\n );\n }\n\n private filterConnections(\n filter?: MCPServerFilter\n ): Record<string, MCPClientConnection> {\n if (!filter) return this.mcpConnections;\n\n const serverIds = filter.serverId\n ? Array.isArray(filter.serverId)\n ? filter.serverId\n : [filter.serverId]\n : undefined;\n\n const serverNames = filter.serverName\n ? Array.isArray(filter.serverName)\n ? filter.serverName\n : [filter.serverName]\n : undefined;\n\n const states = filter.state\n ? Array.isArray(filter.state)\n ? filter.state\n : [filter.state]\n : undefined;\n\n let nameMatchedIds: Set<string> | undefined;\n if (serverNames) {\n const servers = this.getServersFromStorage();\n nameMatchedIds = new Set(\n servers.filter((s) => serverNames.includes(s.name)).map((s) => s.id)\n );\n }\n\n return Object.fromEntries(\n Object.entries(this.mcpConnections).filter(([id, conn]) => {\n if (serverIds && !serverIds.includes(id)) return false;\n if (nameMatchedIds && !nameMatchedIds.has(id)) return false;\n if (states && !states.includes(conn.connectionState)) return false;\n return true;\n })\n );\n }\n\n /**\n * Get the parsed server_options for a stored server, if any.\n */\n private getStoredServerOptions(\n serverId: string\n ): MCPServerOptions | undefined {\n const rows = this.sql<MCPServerRow>(\n \"SELECT server_options FROM cf_agents_mcp_servers WHERE id = ?\",\n serverId\n );\n if (!rows.length || !rows[0].server_options) return undefined;\n return decodeMcpServerOptions(rows[0].server_options);\n }\n\n /**\n * Clear the capabilities persisted on a stored server row. Called once a\n * seeded connection's handshake completes (see `createConnection`): the\n * stamp is valid for one successful restore — sessions that configure\n * handlers re-stamp every row, so a deploy that stops configuring them\n * stops advertising stale modes after its first connected wake instead of\n * forever, while wakes that never handshake don't burn the stamp.\n */\n private clearStoredCapabilities(serverId: string): void {\n const rows = this.sql<MCPServerRow>(\n \"SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers WHERE id = ?\",\n serverId\n );\n const row = rows[0];\n if (!row?.server_options) return;\n const options = decodeMcpServerOptions(row.server_options);\n if (!options.capabilities) return;\n options.capabilities = undefined;\n this.saveServerToStorage({\n ...row,\n server_options: encodeMcpServerOptions(options)\n });\n }\n\n /**\n * Get the retry options for a server from stored server_options\n */\n private getServerRetryOptions(serverId: string): RetryOptions | undefined {\n return this.getStoredServerOptions(serverId)?.retry;\n }\n\n private clearServerAuthUrl(serverId: string): void {\n this.sql(\n \"UPDATE cf_agents_mcp_servers SET auth_url = NULL WHERE id = ?\",\n serverId\n );\n }\n\n private updateStoredSession(\n id: string,\n sessionId?: string,\n protocolVersion?: string,\n discoverResult?: DiscoverResult\n ): void {\n const servers = this.getServersFromStorage();\n const serverRow = servers.find((server) => server.id === id);\n if (!serverRow) {\n return;\n }\n\n const options = decodeMcpServerOptions(serverRow.server_options);\n const next =\n sessionId && protocolVersion\n ? withMcpSession(options, {\n id: sessionId,\n protocolVersion,\n discoverResult\n })\n : withMcpSession(options);\n this.saveServerToStorage({\n ...serverRow,\n server_options: encodeMcpServerOptions(next)\n });\n }\n\n private failConnection(\n serverId: string,\n error: string\n ): MCPOAuthCallbackResult {\n this.clearServerAuthUrl(serverId);\n if (this.mcpConnections[serverId]) {\n this.mcpConnections[serverId].connectionState = MCPConnectionState.FAILED;\n this.mcpConnections[serverId].connectionError = error;\n }\n this._onServerStateChanged.fire();\n return { serverId, authSuccess: false, authError: error };\n }\n\n private isAuthAcceptedConnection(conn: MCPClientConnection): boolean {\n return (\n conn.connectionState === MCPConnectionState.READY ||\n conn.connectionState === MCPConnectionState.CONNECTED ||\n conn.connectionState === MCPConnectionState.CONNECTING ||\n conn.connectionState === MCPConnectionState.DISCOVERING\n );\n }\n\n private oauthCallbackSuccess(\n serverId: string,\n conn: MCPClientConnection\n ): MCPOAuthCallbackResult {\n this.clearServerAuthUrl(serverId);\n conn.connectionError = null;\n return { serverId, authSuccess: true };\n }\n\n private async runWithCodeVerifierState<T>(\n authProvider: AgentMcpOAuthProvider,\n state: string,\n callback: () => Promise<T>\n ): Promise<T> {\n if (authProvider.runWithCodeVerifierState) {\n return authProvider.runWithCodeVerifierState(state, callback);\n }\n return callback();\n }\n\n private async hasRedeemableOAuthState(\n serverId: string,\n authProvider: AgentMcpOAuthProvider,\n state: string\n ): Promise<boolean> {\n authProvider.serverId = serverId;\n try {\n return (await authProvider.checkState(state)).valid;\n } catch {\n return false;\n }\n }\n\n private ignoreUnverifiedCallback(\n serverId: string,\n error: string\n ): MCPOAuthCallbackResult {\n console.warn(\n `[MCPClientManager] Ignoring OAuth callback with unverified state for server \"${serverId}\": ${error}`\n );\n return { serverId, authSuccess: false, authError: error };\n }\n\n private async consumeStaleOAuthState(\n serverId: string,\n authProvider: AgentMcpOAuthProvider,\n state: string\n ): Promise<void> {\n try {\n const stateValidation = await authProvider.checkState(state);\n if (!stateValidation.valid) {\n console.warn(\n `[MCPClientManager] Ignoring stale OAuth callback with invalid state for server \"${serverId}\": ${\n stateValidation.error ?? \"Invalid state\"\n }`\n );\n return;\n }\n await authProvider.consumeState(state);\n } catch (cleanupError) {\n console.warn(\n `[MCPClientManager] Failed to clean up stale OAuth callback state for server \"${serverId}\":`,\n cleanupError\n );\n }\n }\n\n private async completeAuthorizationAndCleanupVerifier(\n serverId: string,\n conn: MCPClientConnection,\n authProvider: AgentMcpOAuthProvider,\n state: string,\n callbackParams: URLSearchParams\n ): Promise<void> {\n await this.runWithCodeVerifierState(authProvider, state, async () => {\n let completeError: unknown;\n let cleanupError: unknown;\n\n try {\n await conn.completeAuthorization(callbackParams, {\n alreadyAccepted: true\n });\n } catch (error) {\n completeError = error;\n }\n\n try {\n await authProvider.deleteCodeVerifier();\n } catch (deleteError) {\n cleanupError = deleteError;\n }\n\n if (completeError) {\n if (cleanupError) {\n console.warn(\n `[MCPClientManager] Failed to clean up OAuth code verifier for server \"${serverId}\":`,\n cleanupError\n );\n }\n throw completeError;\n }\n\n if (cleanupError) {\n throw cleanupError;\n }\n });\n }\n\n /**\n * Create an auth provider for a server\n * @internal\n */\n private createAuthProvider(\n serverId: string,\n callbackUrl: string,\n clientName: string,\n clientId?: string\n ): AgentMcpOAuthProvider {\n if (!this._storage) {\n throw new Error(\n \"Cannot create auth provider: storage is not initialized\"\n );\n }\n const authProvider = new DurableObjectOAuthClientProvider(\n this._storage,\n clientName,\n callbackUrl\n );\n authProvider.serverId = serverId;\n if (clientId) {\n authProvider.clientId = clientId;\n }\n return authProvider;\n }\n\n /**\n * Get saved RPC servers from storage (servers with rpc:// URLs).\n * These are restored separately by the Agent class since they need env bindings.\n */\n getRpcServersFromStorage(): MCPServerRow[] {\n return this.getServersFromStorage().filter((s) =>\n s.server_url.startsWith(RPC_DO_PREFIX)\n );\n }\n\n /**\n * Save an RPC server to storage for hibernation recovery.\n * The bindingName is stored in server_options so the Agent can look up\n * the namespace from env during restore.\n */\n saveRpcServerToStorage(\n id: string,\n name: string,\n normalizedName: string,\n bindingName: string,\n props?: Record<string, unknown>\n ): void {\n this.saveServerToStorage({\n id,\n name,\n server_url: `${RPC_DO_PREFIX}${normalizedName}`,\n client_id: null,\n auth_url: null,\n callback_url: \"\",\n server_options: encodeMcpServerOptions({\n bindingName,\n props,\n capabilities: this.advertisedHandlerCapabilities()\n })\n });\n }\n\n /**\n * Restore MCP server connections from storage\n * This method is called on Agent initialization to restore previously connected servers.\n * RPC servers (rpc:// URLs) are skipped here -- they are restored by the Agent class\n * which has access to env bindings.\n *\n * @param clientName Name to use for OAuth client (typically the agent instance name)\n */\n async restoreConnectionsFromStorage(clientName: string): Promise<void> {\n if (this._isRestored) {\n return;\n }\n\n const servers = this.getServersFromStorage();\n\n if (!servers || servers.length === 0) {\n this._isRestored = true;\n return;\n }\n\n for (const server of servers) {\n if (server.server_url.startsWith(RPC_DO_PREFIX)) {\n continue;\n }\n\n const existingConn = this.mcpConnections[server.id];\n\n // Skip if connection already exists and is in a good state\n if (existingConn) {\n if (existingConn.connectionState === MCPConnectionState.READY) {\n console.warn(\n `[MCPClientManager] Server ${server.id} already has a ready connection. Skipping recreation.`\n );\n continue;\n }\n\n // Don't interrupt in-flight OAuth or connections\n if (\n existingConn.connectionState === MCPConnectionState.AUTHENTICATING ||\n existingConn.connectionState === MCPConnectionState.CONNECTING ||\n existingConn.connectionState === MCPConnectionState.DISCOVERING\n ) {\n // Let the existing flow complete\n continue;\n }\n\n // If failed, clean up the old connection before recreating\n if (existingConn.connectionState === MCPConnectionState.FAILED) {\n try {\n await existingConn.close();\n } catch (error) {\n console.warn(\n `[MCPClientManager] Error closing failed connection ${server.id}:`,\n error\n );\n } finally {\n this.cleanupClosedConnection(server.id);\n }\n }\n }\n\n const parsedOptions = decodeMcpServerOptions(server.server_options);\n\n let authProvider: AgentMcpOAuthProvider | undefined;\n if (server.callback_url) {\n authProvider = this._createAuthProviderFn\n ? this._createAuthProviderFn(server.callback_url)\n : this.createAuthProvider(\n server.id,\n server.callback_url,\n clientName,\n server.client_id ?? undefined\n );\n authProvider.serverId = server.id;\n if (server.client_id) {\n authProvider.clientId = server.client_id;\n }\n }\n\n // Create the in-memory connection object (no need to save to storage - we just read from it!)\n const conn = this.createConnection(server.id, server.server_url, {\n client: parsedOptions?.client ?? {},\n transport: {\n ...(parsedOptions?.transport ?? {}),\n type: parsedOptions?.transport?.type ?? (\"auto\" as TransportType),\n authProvider\n },\n discoverResult: parsedOptions?.discoverResult\n });\n\n // If auth_url exists, OAuth flow is in progress - set state and wait for callback\n if (server.auth_url) {\n conn.connectionState = MCPConnectionState.AUTHENTICATING;\n continue;\n }\n\n // Start connection in background (don't await) to avoid blocking the DO\n this._trackConnection(\n server.id,\n this._restoreServer(server.id, parsedOptions?.retry)\n );\n }\n\n this._isRestored = true;\n }\n\n /**\n * Track a pending connection promise for a server.\n * The promise is removed from the map when it settles.\n */\n private _trackConnection(serverId: string, promise: Promise<void>): void {\n const tracked = promise.finally(() => {\n // Only delete if it's still the same promise (not replaced by a newer one)\n if (this._pendingConnections.get(serverId) === tracked) {\n this._pendingConnections.delete(serverId);\n }\n });\n this._pendingConnections.set(serverId, tracked);\n }\n\n /**\n * Wait for all in-flight connection and discovery operations to settle.\n * This is useful when you need MCP tools to be available before proceeding,\n * e.g. before calling getAITools() after the agent wakes from hibernation.\n *\n * Returns once every pending connection has either connected and discovered,\n * failed, or timed out. Never rejects.\n *\n * @param options.timeout - Maximum time in milliseconds to wait.\n * `0` returns immediately without waiting.\n * `undefined` (default) waits indefinitely.\n */\n async waitForConnections(options?: { timeout?: number }): Promise<void> {\n if (this._pendingConnections.size === 0) {\n return;\n }\n if (options?.timeout != null && options.timeout <= 0) {\n return;\n }\n const settled = Promise.allSettled(this._pendingConnections.values());\n if (options?.timeout != null && options.timeout > 0) {\n let timerId: ReturnType<typeof setTimeout>;\n const timer = new Promise<void>((resolve) => {\n timerId = setTimeout(resolve, options.timeout);\n });\n await Promise.race([settled, timer]);\n clearTimeout(timerId!);\n } else {\n await settled;\n }\n }\n\n private async _connectWithRetry(\n serverId: string,\n retry?: RetryOptions\n ): Promise<MCPConnectionResult> {\n const maxAttempts = retry?.maxAttempts ?? 3;\n const baseDelayMs = retry?.baseDelayMs ?? 500;\n const maxDelayMs = retry?.maxDelayMs ?? 5000;\n\n try {\n return await tryN(\n maxAttempts,\n async () => {\n const result = await this.connectToServer(serverId);\n if (result.state === MCPConnectionState.FAILED) {\n throw new ConnectRetryError(result);\n }\n return result;\n },\n { baseDelayMs, maxDelayMs }\n );\n } catch (error) {\n if (error instanceof ConnectRetryError) {\n return error.result;\n }\n throw error;\n }\n }\n\n /**\n * Internal method to restore a single server connection and discovery\n */\n private async _restoreServer(\n serverId: string,\n retry?: RetryOptions\n ): Promise<void> {\n // Always try to connect - the connection logic will determine if OAuth is needed\n // If stored OAuth tokens are valid, connection will succeed automatically\n // If tokens are missing/invalid, connection will fail with Unauthorized\n // and state will be set to \"authenticating\"\n const connectResult = await this._connectWithRetry(serverId, retry).catch(\n (error) => {\n console.error(`Error connecting to ${serverId}:`, error);\n return null;\n }\n );\n\n if (connectResult?.state === MCPConnectionState.CONNECTED) {\n const discoverResult = await this.discoverIfConnected(serverId);\n if (discoverResult && !discoverResult.success) {\n console.error(`Error discovering ${serverId}:`, discoverResult.error);\n }\n }\n }\n\n /**\n * Connect to and register an MCP server\n *\n * @deprecated This method is maintained for backward compatibility.\n * For new code, use registerServer() and connectToServer() separately.\n *\n * @param url Server URL\n * @param options Connection options\n * @returns Object with server ID, auth URL (if OAuth), and client ID (if OAuth)\n */\n async connect(\n url: string,\n options: {\n // Allows you to reconnect to a server (in the case of an auth reconnect)\n reconnect?: {\n // server id\n id: string;\n oauthClientId?: string;\n oauthCode?: string;\n };\n // we're overriding authProvider here because we want to be able to access the auth URL\n transport?: MCPTransportOptions;\n client?: McpClientOptions;\n } = {}\n ): Promise<{\n id: string;\n authUrl?: string;\n clientId?: string;\n }> {\n const id = options.reconnect?.id ?? nanoid(8);\n\n if (options.transport?.authProvider) {\n options.transport.authProvider.serverId = id;\n // reconnect with auth\n if (options.reconnect?.oauthClientId) {\n options.transport.authProvider.clientId =\n options.reconnect?.oauthClientId;\n }\n }\n\n if (isBlockedUrl(url)) {\n throw new Error(\n `Blocked URL: ${url} — MCP client connections to private/internal addresses are not allowed`\n );\n }\n\n // During OAuth reconnect, reuse existing connection to preserve state;\n // otherwise drop any existing connection and rebuild it.\n if (!options.reconnect?.oauthCode || !this.mcpConnections[id]) {\n const replaced = this.mcpConnections[id];\n if (replaced) {\n delete this.mcpConnections[id];\n // Once removed from the map, nothing else can close this transport.\n await replaced.close().catch(() => {});\n this.updateStoredSession(id, undefined);\n }\n this.createConnection(id, url, {\n client: options.client,\n transport: options.transport ?? {}\n });\n }\n\n // Initialize connection first. this will try connect\n await this.mcpConnections[id].init();\n\n // Handle OAuth completion if we have a reconnect code\n if (options.reconnect?.oauthCode) {\n try {\n const authProvider =\n this.mcpConnections[id].options.transport.authProvider;\n let completeError: unknown;\n try {\n await this.mcpConnections[id].completeAuthorization(\n options.reconnect.oauthCode\n );\n } catch (error) {\n completeError = error;\n }\n\n try {\n await authProvider?.deleteCodeVerifier();\n } catch (cleanupError) {\n console.warn(\n `[MCPClientManager] Failed to clean up OAuth code verifier for server \"${id}\":`,\n cleanupError\n );\n }\n\n if (completeError) {\n throw completeError;\n }\n\n // Reinitialize connection\n await this.mcpConnections[id].init();\n } catch (error) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: url,\n transport: options.transport?.type ?? \"auto\",\n state: this.mcpConnections[id].connectionState,\n error: toErrorMessage(error)\n },\n timestamp: Date.now()\n });\n // Re-throw to signal failure to the caller\n throw error;\n }\n }\n\n // If connection is in authenticating state, return auth URL for OAuth flow\n const authUrl = options.transport?.authProvider?.authUrl;\n if (\n this.mcpConnections[id].connectionState ===\n MCPConnectionState.AUTHENTICATING &&\n authUrl &&\n options.transport?.authProvider?.redirectUrl\n ) {\n return {\n authUrl,\n clientId: options.transport?.authProvider?.clientId,\n id\n };\n }\n\n // If connection is connected, discover capabilities\n const discoverResult = await this.discoverIfConnected(id);\n if (discoverResult && !discoverResult.success) {\n throw new Error(\n `Failed to discover server capabilities: ${discoverResult.error}`\n );\n }\n\n return {\n id\n };\n }\n\n /**\n * Create an in-memory connection object and set up observability\n * Does NOT save to storage - use registerServer() for that\n * @returns The connection object (existing or newly created)\n */\n private createConnection(\n id: string,\n url: string,\n options: {\n client?: McpClientOptions;\n transport: MCPTransportOptions;\n discoverResult?: DiscoverResult;\n }\n ): MCPClientConnection {\n // Return existing connection if already exists\n if (this.mcpConnections[id]) {\n return this.mcpConnections[id];\n }\n\n const normalizedTransport = {\n ...options.transport,\n type: options.transport?.type ?? (\"auto\" as TransportType)\n };\n\n // Stored servers re-advertise the capabilities persisted on their row\n // (see MCPServerOptions.capabilities); fresh registrations have no row\n // yet and rely on the handlers below. The stamp is read without\n // clearing so a wake that never handshakes (OAuth still pending, isolate\n // death before connect) doesn't burn it — it is consumed at first use,\n // once a seeded handshake completes.\n const capabilitySeed = this.getStoredServerOptions(id)?.capabilities;\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this._name,\n version: this._version\n },\n {\n client: options.client ?? {},\n transport: normalizedTransport,\n elicitationHandlers: this.scopedElicitationHandlers(id),\n capabilitySeed,\n discoverResult: options.discoverResult\n }\n );\n\n // Pipe connection-level observability events to the manager-level emitter\n const store = new DisposableStore();\n const existing = this._connectionDisposables.get(id);\n if (existing) existing.dispose();\n this._connectionDisposables.set(id, store);\n store.add(\n this.mcpConnections[id].onObservabilityEvent((event) => {\n this._onObservabilityEvent.fire(event);\n })\n );\n store.add(\n this.mcpConnections[id].onListChanged(() => {\n this._onServerStateChanged.fire();\n })\n );\n\n if (capabilitySeed) {\n const conn = this.mcpConnections[id];\n // Every handshake reports its success through this event, so it marks\n // the seed's first use. The burn only targets deploys that stopped\n // configuring handlers: a session with handlers configured owns the\n // row stamps (each configure call re-stamps them, and re-registering\n // a server writes a fresh one), and configureElicitationHandlers\n // drops the in-memory seed on live connections — either way a fresh\n // stamp meant for the next wake is never wiped here.\n const seedClear = conn.onObservabilityEvent((event) => {\n if (\n event.type !== \"mcp:client:connect\" ||\n event.payload.state !== MCPConnectionState.CONNECTED\n ) {\n return;\n }\n seedClear.dispose();\n if (this._elicitationHandlers || !conn.options.capabilitySeed) return;\n // migrateServerId may have renamed the row while the handshake was\n // in flight — clear under the connection's current id.\n const currentId = Object.keys(this.mcpConnections).find(\n (key) => this.mcpConnections[key] === conn\n );\n if (currentId) {\n this.clearStoredCapabilities(currentId);\n }\n });\n store.add(seedClear);\n }\n\n return this.mcpConnections[id];\n }\n\n /**\n * Register an MCP server connection without connecting\n * Creates the connection object, sets up observability, and saves to storage\n *\n * @param id Server ID\n * @param options Registration options including URL, name, callback URL, and connection config\n * @returns Server ID\n */\n async registerServer(\n id: string,\n options: RegisterServerOptions\n ): Promise<string> {\n if (isBlockedUrl(options.url)) {\n throw new Error(\n `Blocked URL: ${options.url} — MCP client connections to private/internal addresses are not allowed`\n );\n }\n\n // Create the in-memory connection\n this.createConnection(id, options.url, {\n client: options.client,\n transport: {\n ...options.transport,\n type: options.transport?.type ?? (\"auto\" as TransportType)\n }\n });\n\n this.saveServerToStorage({\n id,\n name: options.name,\n server_url: options.url,\n callback_url: options.callbackUrl ?? \"\",\n client_id: options.clientId ?? null,\n auth_url: options.authUrl ?? null,\n server_options: encodeMcpServerOptions({\n client: options.client,\n transport: options.transport,\n retry: options.retry,\n capabilities: this.advertisedHandlerCapabilities()\n })\n });\n\n this._onServerStateChanged.fire();\n\n return id;\n }\n\n /** Persist and emit an OAuth continuation produced by connect or discovery. */\n private persistAuthContinuation(\n id: string,\n conn: MCPClientConnection\n ): { authUrl: string; clientId?: string } | undefined {\n const authProvider = conn.options.transport.authProvider;\n const authUrl = authProvider?.authUrl;\n if (!authUrl || !authProvider.redirectUrl) return undefined;\n\n const clientId = authProvider.clientId;\n const serverRow = this.getServersFromStorage().find((s) => s.id === id);\n if (serverRow) {\n this.saveServerToStorage({\n ...serverRow,\n auth_url: authUrl,\n client_id: clientId ?? null\n });\n }\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:authorize\",\n payload: { serverId: id, authUrl, clientId },\n timestamp: Date.now()\n });\n return { authUrl, clientId };\n }\n\n /**\n * Connect to an already registered MCP server and initialize the connection.\n *\n * For OAuth servers, returns `{ state: \"authenticating\", authUrl, clientId? }`.\n * The user must complete the OAuth flow via the authUrl, which triggers a\n * callback handled by `handleCallbackRequest()`.\n *\n * For non-OAuth servers, establishes the transport connection and returns\n * `{ state: \"connected\" }`. Call `discoverIfConnected()` afterwards to\n * discover capabilities and transition to \"ready\" state.\n *\n * @param id Server ID (must be registered first via registerServer())\n * @returns Connection result with current state and OAuth info (if applicable)\n */\n async connectToServer(id: string): Promise<MCPConnectionResult> {\n const conn = this.mcpConnections[id];\n if (!conn) {\n throw new Error(\n `Server ${id} is not registered. Call registerServer() first.`\n );\n }\n\n const error = await conn.init();\n this.updateStoredSession(\n id,\n conn.sessionId,\n conn.protocolVersion,\n conn.discoverResult\n );\n this._onServerStateChanged.fire();\n\n switch (conn.connectionState) {\n case MCPConnectionState.FAILED:\n return {\n state: conn.connectionState,\n error: error ?? \"Unknown connection error\"\n };\n\n case MCPConnectionState.AUTHENTICATING: {\n const auth = this.persistAuthContinuation(id, conn);\n if (!auth) {\n const provider = conn.options.transport.authProvider;\n return {\n state: MCPConnectionState.FAILED,\n error: `OAuth configuration incomplete: missing ${\n !provider?.authUrl ? \"authUrl\" : \"redirectUrl\"\n }`\n };\n }\n\n // Broadcast again after auth_url is durable so clients can serve it.\n this._onServerStateChanged.fire();\n return { state: conn.connectionState, ...auth };\n }\n\n case MCPConnectionState.CONNECTED:\n return { state: conn.connectionState };\n\n default:\n return {\n state: MCPConnectionState.FAILED,\n error: `Unexpected connection state after init: ${conn.connectionState}`\n };\n }\n }\n\n private extractServerIdFromState(state: string | null): string | null {\n if (!state) return null;\n const parts = state.split(\".\");\n return parts.length === 2 ? parts[1] : null;\n }\n\n isCallbackRequest(req: Request): boolean {\n if (req.method !== \"GET\") {\n return false;\n }\n\n const url = new URL(req.url);\n const state = url.searchParams.get(\"state\");\n const serverId = this.extractServerIdFromState(state);\n if (!serverId) {\n return false;\n }\n\n // Match by server ID AND verify the request origin + pathname matches the registered callback URL.\n // This prevents unrelated GET requests with a `state` param from being intercepted.\n const servers = this.getServersFromStorage();\n return servers.some((server) => {\n if (server.id !== serverId) return false;\n try {\n const storedUrl = new URL(server.callback_url);\n return (\n storedUrl.origin === url.origin && storedUrl.pathname === url.pathname\n );\n } catch {\n return false;\n }\n });\n }\n\n private validateCallbackRequest(req: Request):\n | {\n valid: true;\n serverId: string;\n state: string;\n callbackParams: URLSearchParams;\n }\n | { valid: false; serverId?: string; state?: string; error: string } {\n const url = new URL(req.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n\n // Early validation - return errors because we can't identify the connection\n if (!state) {\n return {\n valid: false,\n error: \"Unauthorized: no state provided\"\n };\n }\n\n const serverId = this.extractServerIdFromState(state);\n if (!serverId) {\n return {\n valid: false,\n error:\n \"No serverId found in state parameter. Expected format: {nonce}.{serverId}\"\n };\n }\n\n if (!code && !error) {\n return {\n serverId,\n state,\n valid: false,\n error: \"Unauthorized: no code provided\"\n };\n }\n\n const servers = this.getServersFromStorage();\n const serverExists = servers.some((server) => server.id === serverId);\n if (!serverExists) {\n return {\n serverId: serverId,\n valid: false,\n error: `No server found with id \"${serverId}\". Was the request matched with \\`isCallbackRequest()\\`?`\n };\n }\n\n if (this.mcpConnections[serverId] === undefined) {\n return {\n serverId: serverId,\n valid: false,\n error: `No connection found for serverId \"${serverId}\".`\n };\n }\n\n return {\n valid: true,\n serverId,\n state,\n callbackParams: url.searchParams\n };\n }\n\n async handleCallbackRequest(req: Request): Promise<MCPOAuthCallbackResult> {\n const validation = this.validateCallbackRequest(req);\n\n if (!validation.valid) {\n const conn = validation.serverId\n ? this.mcpConnections[validation.serverId]\n : undefined;\n if (validation.serverId && conn) {\n if (this.isAuthAcceptedConnection(conn)) {\n const authProvider = conn.options.transport.authProvider;\n if (validation.state && authProvider) {\n authProvider.serverId = validation.serverId;\n await this.consumeStaleOAuthState(\n validation.serverId,\n authProvider,\n validation.state\n );\n }\n return this.oauthCallbackSuccess(validation.serverId, conn);\n }\n // Only a callback carrying a genuine state nonce may fail the\n // connection; a stray or invalid callback must not alter the\n // connection state machine.\n const authProvider = conn.options.transport.authProvider;\n if (\n validation.state &&\n authProvider &&\n !(await this.hasRedeemableOAuthState(\n validation.serverId,\n authProvider,\n validation.state\n ))\n ) {\n return this.ignoreUnverifiedCallback(\n validation.serverId,\n validation.error\n );\n }\n return this.failConnection(validation.serverId, validation.error);\n }\n\n return {\n serverId: validation.serverId,\n authSuccess: false,\n authError: validation.error\n };\n }\n\n const { serverId, state, callbackParams } = validation;\n const conn = this.mcpConnections[serverId]; // We have a valid connection - all errors from here should fail the connection\n\n try {\n if (!conn.options.transport.authProvider) {\n throw new Error(\n \"Trying to finalize authentication for a server connection without an authProvider\"\n );\n }\n\n const authProvider = conn.options.transport.authProvider;\n authProvider.serverId = serverId;\n\n // Two-phase state validation: check first (non-destructive), consume later\n // This prevents DoS attacks where attacker consumes valid state before legitimate callback\n const stateValidation = await authProvider.checkState(state);\n if (!stateValidation.valid) {\n if (this.isAuthAcceptedConnection(conn)) {\n await this.consumeStaleOAuthState(serverId, authProvider, state);\n return this.oauthCallbackSuccess(serverId, conn);\n }\n // Same rule as the invalid branch above: a callback whose nonce\n // cannot be verified must not alter the connection state machine.\n return this.ignoreUnverifiedCallback(\n serverId,\n callbackParams.get(\"error_description\") ??\n callbackParams.get(\"error\") ??\n stateValidation.error ??\n \"Invalid state\"\n );\n }\n\n // A stale popup can complete after another callback already exchanged tokens.\n // Treat it as success, but consume its state so it cannot be replayed.\n if (this.isAuthAcceptedConnection(conn)) {\n await this.consumeStaleOAuthState(serverId, authProvider, state);\n return this.oauthCallbackSuccess(serverId, conn);\n }\n\n if (\n conn.connectionState !== MCPConnectionState.AUTHENTICATING &&\n conn.connectionState !== MCPConnectionState.FAILED\n ) {\n throw new Error(\n `Failed to authenticate from \"${conn.connectionState}\" state`\n );\n }\n\n // A genuine callback can recover a flow that previously entered FAILED.\n conn.connectionState = MCPConnectionState.CONNECTING;\n await authProvider.consumeState(state);\n await this.completeAuthorizationAndCleanupVerifier(\n serverId,\n conn,\n authProvider,\n state,\n callbackParams\n );\n this.updateStoredSession(\n serverId,\n conn.sessionId,\n conn.protocolVersion,\n conn.discoverResult\n );\n const result = this.oauthCallbackSuccess(serverId, conn);\n this._onServerStateChanged.fire();\n\n return result;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return this.failConnection(serverId, message);\n }\n }\n\n /**\n * Discover server capabilities if connection is in CONNECTED or READY state.\n * Transitions to DISCOVERING then READY (or CONNECTED on error).\n * Can be called to refresh server capabilities (e.g., from a UI refresh button).\n *\n * If called while a previous discovery is in-flight for the same server,\n * the previous discovery will be aborted.\n *\n * @param serverId The server ID to discover\n * @param options Optional configuration\n * @param options.timeoutMs Timeout in milliseconds (default: 30000)\n * @returns Result with current state and optional error, or undefined if connection not found\n */\n async discoverIfConnected(\n serverId: string,\n options: { timeoutMs?: number } = {}\n ): Promise<MCPDiscoverResult | undefined> {\n const conn = this.mcpConnections[serverId];\n if (!conn) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {},\n timestamp: Date.now()\n });\n return undefined;\n }\n\n // Delegate to connection's discover method which handles cancellation and timeout\n const result = await conn.discover(options);\n if (!result.success && result.reason === \"stale-session\") {\n return this._recoverStaleSession(conn, serverId, options);\n }\n if (conn.connectionState === MCPConnectionState.AUTHENTICATING) {\n this.persistAuthContinuation(serverId, conn);\n }\n this._onServerStateChanged.fire();\n\n return this._toDiscoverResult(conn, result);\n }\n\n private _toDiscoverResult(\n conn: MCPClientConnection,\n result: MCPDiscoveryResult\n ): MCPDiscoverResult {\n return result.success\n ? { success: true, state: conn.connectionState }\n : { success: false, error: result.error, state: conn.connectionState };\n }\n\n private async _recoverStaleSession(\n conn: MCPClientConnection,\n serverId: string,\n options: { timeoutMs?: number }\n ): Promise<MCPDiscoverResult> {\n conn.clearResumedSession();\n this.updateStoredSession(serverId, undefined);\n\n let connectResult: MCPConnectionResult;\n try {\n connectResult = await this.connectToServer(serverId);\n } catch (error) {\n return {\n success: false,\n error: toErrorMessage(error),\n state: conn.connectionState\n };\n }\n\n if (connectResult.state !== MCPConnectionState.CONNECTED) {\n return {\n success: false,\n error:\n connectResult.state === MCPConnectionState.FAILED\n ? connectResult.error\n : `Connection in ${connectResult.state} state after session re-initialization`,\n state: conn.connectionState\n };\n }\n\n const result = await conn.discover(options);\n this._onServerStateChanged.fire();\n\n return this._toDiscoverResult(conn, result);\n }\n\n /**\n * Establish connection in the background after OAuth completion.\n * This method connects to the server and discovers its capabilities.\n * The connection is automatically tracked so that `waitForConnections()`\n * will include it.\n * @param serverId The server ID to establish connection for\n */\n async establishConnection(serverId: string): Promise<void> {\n const promise = this._doEstablishConnection(serverId);\n this._trackConnection(serverId, promise);\n return promise;\n }\n\n private async _doEstablishConnection(serverId: string): Promise<void> {\n const conn = this.mcpConnections[serverId];\n if (!conn) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:preconnect\",\n payload: { serverId },\n timestamp: Date.now()\n });\n return;\n }\n\n // Skip if already discovering or ready - prevents duplicate work\n if (\n conn.connectionState === MCPConnectionState.DISCOVERING ||\n conn.connectionState === MCPConnectionState.READY\n ) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: conn.url.toString(),\n transport: conn.options.transport.type || \"unknown\",\n state: conn.connectionState\n },\n timestamp: Date.now()\n });\n return;\n }\n\n const retry = this.getServerRetryOptions(serverId);\n const connectResult = await this._connectWithRetry(serverId, retry);\n this._onServerStateChanged.fire();\n\n if (connectResult.state === MCPConnectionState.CONNECTED) {\n await this.discoverIfConnected(serverId);\n }\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: conn.url.toString(),\n transport: conn.options.transport.type || \"unknown\",\n state: conn.connectionState\n },\n timestamp: Date.now()\n });\n }\n\n /**\n * Configure OAuth callback handling\n * @param config OAuth callback configuration\n */\n configureOAuthCallback(config: MCPClientOAuthCallbackConfig): void {\n this._oauthCallbackConfig = config;\n }\n\n /**\n * Configure handling for server-initiated `elicitation/create` requests.\n *\n * The handler is held in memory only and applied to every MCP connection\n * created or restored by this manager. Call this before registering\n * connections when you want the initial MCP handshake to advertise\n * handler-driven form- and url-mode elicitation. Existing active connections\n * keep their negotiated capabilities until they reconnect.\n *\n * The advertised modes are persisted with each stored server, so\n * connections restored after hibernation re-advertise them at the handshake\n * even when this is called later in the wake-up (e.g. from onStart) — the\n * handlers attach to the live connections as soon as this runs.\n *\n * Pass undefined to clear the handler.\n *\n * @param handlers Elicitation handlers keyed by mode, each scoped with the server id that sent the request\n */\n configureElicitationHandlers(handlers?: MCPClientElicitationHandlers): void {\n this._elicitationHandlers =\n handlers && (handlers.form || handlers.url) ? handlers : undefined;\n this.persistAdvertisedCapabilities();\n for (const [id, connection] of Object.entries(this.mcpConnections)) {\n connection.configureElicitationHandlers(\n this.scopedElicitationHandlers(id)\n );\n }\n }\n\n /** Client capabilities advertised from the currently configured handlers. */\n private advertisedHandlerCapabilities(): ClientCapabilities | undefined {\n const elicitation = elicitationCapabilitiesFromHandlers(\n this._elicitationHandlers\n );\n return elicitation ? { elicitation } : undefined;\n }\n\n /**\n * Record the handler-derived capabilities on every stored server row so a\n * restore after hibernation re-advertises them before the handlers\n * themselves are reconfigured.\n */\n private persistAdvertisedCapabilities(): void {\n const capabilities = this.advertisedHandlerCapabilities();\n for (const server of this.getServersFromStorage()) {\n const options = decodeMcpServerOptions(server.server_options);\n if (\n JSON.stringify(options.capabilities) === JSON.stringify(capabilities)\n ) {\n continue;\n }\n options.capabilities = capabilities;\n this.saveServerToStorage({\n ...server,\n server_options: encodeMcpServerOptions(options)\n });\n }\n }\n\n /**\n * Get the current OAuth callback configuration\n * @returns The current OAuth callback configuration\n */\n getOAuthCallbackConfig(): MCPClientOAuthCallbackConfig | undefined {\n return this._oauthCallbackConfig;\n }\n\n /**\n * @param filter - Optional filter to scope results to specific servers\n * @returns namespaced list of tools\n */\n listTools(filter?: MCPServerFilter): NamespacedData[\"tools\"] {\n return getNamespacedData(this.filterConnections(filter), \"tools\");\n }\n\n /**\n * Convert connected MCP tools for the AI SDK. Converted schemas are reused\n * while a live connection retains the same catalog array and schema-source\n * identities; tool records and execute closures are rebuilt on every call.\n *\n * @param filter - Optional filter to scope results to specific servers\n * @returns a set of tools that you can use with the AI SDK\n */\n getAITools(filter?: MCPServerFilter): MCPAIToolSet {\n const connections = this.filterConnections(filter);\n const entries: [string, MCPAITool][] = [];\n\n for (const [serverId, conn] of Object.entries(connections)) {\n if (\n conn.connectionState !== MCPConnectionState.READY &&\n conn.connectionState !== MCPConnectionState.AUTHENTICATING\n ) {\n console.warn(\n `[getAITools] WARNING: Reading tools from connection ${serverId} in state \"${conn.connectionState}\". Tools may not be loaded yet.`\n );\n }\n\n const catalog = conn.tools;\n let cache = this._aiToolSchemas.get(conn);\n if (!cache || cache.catalog !== catalog) {\n cache = { catalog, converted: [] };\n this._aiToolSchemas.set(conn, cache);\n }\n\n for (const [index, tool] of catalog.entries()) {\n const toolName = tool.name;\n try {\n const sourceInputSchema = tool.inputSchema;\n const sourceOutputSchema = tool.outputSchema;\n let slot = cache.converted[index];\n if (\n !slot ||\n slot.tool !== tool ||\n slot.inputSchema !== sourceInputSchema ||\n slot.outputSchema !== sourceOutputSchema\n ) {\n try {\n slot = {\n status: \"converted\",\n tool,\n inputSchema: sourceInputSchema,\n outputSchema: sourceOutputSchema,\n converted: {\n inputSchema: sourceInputSchema\n ? z.fromJSONSchema(\n sourceInputSchema as Parameters<\n typeof z.fromJSONSchema\n >[0]\n )\n : z.fromJSONSchema({ type: \"object\" }),\n outputSchema: sourceOutputSchema\n ? z.fromJSONSchema(\n sourceOutputSchema as Parameters<\n typeof z.fromJSONSchema\n >[0]\n )\n : undefined\n }\n };\n } catch (error) {\n const errorText = String(error);\n cache.converted[index] = {\n status: \"failed\",\n tool,\n inputSchema: sourceInputSchema,\n outputSchema: sourceOutputSchema,\n error: errorText\n };\n console.warn(\n `[getAITools] Skipping tool \"${toolName}\" from \"${serverId}\": ${errorText}`\n );\n continue;\n }\n cache.converted[index] = slot;\n }\n\n if (slot.status === \"failed\") continue;\n\n const toolKey = `tool_${serverId.replace(/-/g, \"\")}_${toolName}`;\n const title = tool.title ?? tool.annotations?.title;\n const description = tool.description;\n entries.push([\n toolKey,\n {\n description,\n title,\n execute: async (args) => {\n const result = await this.callTool({\n arguments: args,\n name: toolName,\n serverId\n });\n if (result.isError) {\n const content = result.content as\n | Array<{ type: string; text?: string }>\n | undefined;\n const textContent = content?.[0];\n const message =\n textContent?.type === \"text\" && textContent.text\n ? textContent.text\n : \"Tool call failed\";\n throw new Error(message);\n }\n return result;\n },\n inputSchema: slot.converted.inputSchema,\n outputSchema: slot.converted.outputSchema\n }\n ]);\n } catch (error) {\n console.warn(\n `[getAITools] Skipping tool \"${toolName}\" from \"${serverId}\": ${error}`\n );\n }\n }\n\n // Release removed slots when a public catalog array is spliced in place.\n cache.converted.length = catalog.length;\n }\n\n return Object.fromEntries(entries);\n }\n\n /**\n * @deprecated this has been renamed to getAITools(), and unstable_getAITools will be removed in the next major version\n * @param filter - Optional filter to scope results to specific servers\n * @returns a set of tools that you can use with the AI SDK\n */\n unstable_getAITools(filter?: MCPServerFilter): MCPAIToolSet {\n if (!this._didWarnAboutUnstableGetAITools) {\n this._didWarnAboutUnstableGetAITools = true;\n console.warn(\n \"unstable_getAITools is deprecated, use getAITools instead. unstable_getAITools will be removed in the next major version.\"\n );\n }\n return this.getAITools(filter);\n }\n\n /**\n * Closes all active in-memory connections to MCP servers.\n *\n * Note: This only closes the transport connections - it does NOT remove\n * servers from storage. Servers will still be listed and their callback\n * URLs will still match incoming OAuth requests.\n *\n * Use removeServer() instead if you want to fully clean up a server\n * (closes connection AND removes from storage).\n */\n private cleanupClosedConnection(id: string): void {\n this.updateStoredSession(id, undefined);\n\n const store = this._connectionDisposables.get(id);\n if (store) store.dispose();\n this._connectionDisposables.delete(id);\n\n delete this.mcpConnections[id];\n }\n\n async closeAllConnections() {\n const ids = Object.keys(this.mcpConnections);\n\n // Clear all pending connection tracking\n this._pendingConnections.clear();\n\n // Cancel all in-flight discoveries\n for (const id of ids) {\n this.mcpConnections[id].cancelDiscovery();\n }\n\n const results = await Promise.allSettled(\n ids.map(async (id) => {\n try {\n await this.mcpConnections[id].close();\n } finally {\n this.cleanupClosedConnection(id);\n }\n })\n );\n\n const errors = results.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : []\n );\n\n if (errors.length === 1) {\n throw errors[0];\n }\n\n if (errors.length > 1) {\n throw new AggregateError(\n errors,\n \"Failed to close one or more MCP connections\"\n );\n }\n }\n\n /**\n * Closes a connection to an MCP server\n * @param id The id of the connection to close\n */\n async closeConnection(id: string) {\n const connection = this.mcpConnections[id];\n if (!connection) {\n throw new Error(`Connection with id \"${id}\" does not exist.`);\n }\n\n // Cancel any in-flight discovery\n connection.cancelDiscovery();\n\n // Remove from pending so waitForConnections() doesn't block on a closed server\n this._pendingConnections.delete(id);\n\n try {\n await connection.close();\n } finally {\n this.cleanupClosedConnection(id);\n }\n }\n\n /**\n * Remove an MCP server - closes connection if active and removes from storage.\n */\n async removeServer(serverId: string): Promise<void> {\n if (this.mcpConnections[serverId]) {\n try {\n await this.closeConnection(serverId);\n } catch (_e) {\n // Ignore errors when closing\n }\n }\n this.removeServerFromStorage(serverId);\n this._onServerStateChanged.fire();\n }\n\n /**\n * List all MCP servers from storage\n */\n listServers(): MCPServerRow[] {\n return this.getServersFromStorage();\n }\n\n /**\n * Dispose the manager and all resources.\n */\n async dispose(): Promise<void> {\n try {\n await this.closeAllConnections();\n } finally {\n // Dispose manager-level emitters\n this._onServerStateChanged.dispose();\n this._onObservabilityEvent.dispose();\n }\n }\n\n /**\n * @param filter - Optional filter to scope results to specific servers\n * @returns namespaced list of prompts\n */\n listPrompts(filter?: MCPServerFilter): NamespacedData[\"prompts\"] {\n return getNamespacedData(this.filterConnections(filter), \"prompts\");\n }\n\n /**\n * @param filter - Optional filter to scope results to specific servers\n * @returns namespaced list of resources\n */\n listResources(filter?: MCPServerFilter): NamespacedData[\"resources\"] {\n return getNamespacedData(this.filterConnections(filter), \"resources\");\n }\n\n /**\n * @param filter - Optional filter to scope results to specific servers\n * @returns namespaced list of resource templates\n */\n listResourceTemplates(\n filter?: MCPServerFilter\n ): NamespacedData[\"resourceTemplates\"] {\n return getNamespacedData(\n this.filterConnections(filter),\n \"resourceTemplates\"\n );\n }\n\n /**\n * Namespaced version of callTool\n */\n async callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n options?: CallToolRequestOptions\n ): ReturnType<Client[\"callTool\"]>;\n /**\n * @deprecated Prefer the v2 request-options overload. Explicit legacy result\n * schemas remain honored through the v2 SDK request funnel.\n */\n async callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n resultSchema: LegacyCallToolResultSchema,\n options?: CallToolRequestOptions\n ): ReturnType<Client[\"callTool\"]>;\n async callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n schemaOrOptions?: CallToolSchemaOrOptions,\n options?: CallToolRequestOptions\n ): ReturnType<Client[\"callTool\"]> {\n const { serverId, ...mcpParams } = params;\n const unqualifiedName = mcpParams.name.replace(`${serverId}.`, \"\");\n return callV2Tool(\n this.mcpConnections[serverId].client,\n { ...mcpParams, name: unqualifiedName },\n schemaOrOptions,\n options\n );\n }\n\n /**\n * Namespaced version of readResource\n */\n readResource(\n params: ReadResourceRequest[\"params\"] & { serverId: string },\n options?: CacheableRequestOptions\n ) {\n const { serverId, ...mcpParams } = params;\n return this.mcpConnections[serverId].client.readResource(\n mcpParams,\n options\n );\n }\n\n /**\n * Namespaced version of getPrompt\n */\n getPrompt(\n params: GetPromptRequest[\"params\"] & { serverId: string },\n options?: RequestOptions\n ) {\n const { serverId, ...mcpParams } = params;\n return this.mcpConnections[serverId].client.getPrompt(mcpParams, options);\n }\n}\n\ntype NamespacedData = {\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n resourceTemplates: (ResourceTemplate & { serverId: string })[];\n};\n\nexport function getNamespacedData<T extends keyof NamespacedData>(\n mcpClients: Record<string, MCPClientConnection>,\n type: T\n): NamespacedData[T] {\n const sets = Object.entries(mcpClients).map(([name, conn]) => {\n return { data: conn[type], name };\n });\n\n const namespacedData = sets.flatMap(({ name: serverId, data }) => {\n return data.map((item) => {\n return {\n ...item,\n // we add a serverId so we can easily pull it out and send the tool call to the right server\n serverId\n };\n });\n });\n\n return namespacedData as NamespacedData[T]; // Type assertion needed due to TS limitations with conditional return types\n}\n"],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as Agent } from "./agent-tool-types-BNUGGBzQ.js";
1
+ import { O as Agent } from "./agent-tool-types-Btk9ETS-.js";
2
2
  import {
3
3
  ClientParameters,
4
4
  Method,
@@ -516,7 +516,7 @@ const EXEC_TOUCH_INTERVAL_MS = 60 * 1e3;
516
516
  */
517
517
  const LIVE_VIEW_URL_TTL_MS = 300 * 1e3;
518
518
  function isMissingBrowserSession(error) {
519
- return error instanceof BrowserRenderingError && error.status === 404;
519
+ return error instanceof BrowserRenderingError && (error.status === 404 || error.status === 410);
520
520
  }
521
521
  /**
522
522
  * Rewrite the hosted Live View UI's `mode` query param (`tab` | `devtools`).
@@ -1288,4 +1288,4 @@ async function _closeStoredSession(key) {
1288
1288
  //#endregion
1289
1289
  export { connectUrl as C, CdpSession as S, connectBrowserSession as _, loadCdpSpec as a, getBrowserRecording as b, browserLinks as c, browserScrape as d, browserScreenshot as f, connectBrowser as g, BrowserRenderingError as h, DurableBrowserSessionStore as i, browserMarkdown as l, runQuickAction as m, DEFAULT_EXEC_SWEEP_IDLE_MS as n, browserContent as o, browserSnapshot as p, DEFAULT_SWEEP_IDLE_MS as r, browserExtract as s, BrowserConnector as t, browserPdf as u, createBrowserSession as v, listBrowserTargets as x, deleteBrowserSession as y };
1290
1290
 
1291
- //# sourceMappingURL=connector-CdldGF3h.js.map
1291
+ //# sourceMappingURL=connector-KEJnl6e5.js.map