@adcp/sdk 12.0.4 → 12.0.6

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 (39) hide show
  1. package/dist/lib/protocols/a2a.mjs +5 -0
  2. package/dist/lib/protocols/a2a.mjs.map +1 -1
  3. package/dist/lib/protocols/abort.mjs +5 -0
  4. package/dist/lib/protocols/abort.mjs.map +1 -1
  5. package/dist/lib/protocols/index.mjs +5 -0
  6. package/dist/lib/protocols/index.mjs.map +1 -1
  7. package/dist/lib/protocols/mcp-modern.mjs +5 -0
  8. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  9. package/dist/lib/protocols/mcp-tasks.mjs +5 -0
  10. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  11. package/dist/lib/protocols/mcp.mjs +5 -0
  12. package/dist/lib/protocols/mcp.mjs.map +1 -1
  13. package/dist/lib/protocols/rawResponseCapture.mjs +5 -0
  14. package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
  15. package/dist/lib/protocols/responseSizeLimit.mjs +5 -0
  16. package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
  17. package/dist/lib/protocols/transportDiagnostics.mjs +5 -0
  18. package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
  19. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  20. package/dist/lib/server/decisioning/index.d.mts +1 -1
  21. package/dist/lib/server/decisioning/index.d.ts +1 -1
  22. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  23. package/dist/lib/server/decisioning/index.js.map +1 -1
  24. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  25. package/dist/lib/server/decisioning/runtime/from-platform.js +21 -13
  26. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  27. package/dist/lib/server/decisioning/runtime/from-platform.mjs +21 -13
  28. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  29. package/dist/lib/server/decisioning/specialisms/sales.d.mts +8 -2
  30. package/dist/lib/server/decisioning/specialisms/sales.d.ts +8 -2
  31. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
  32. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
  33. package/dist/lib/version.d.mts +3 -3
  34. package/dist/lib/version.d.ts +3 -3
  35. package/dist/lib/version.js +3 -3
  36. package/dist/lib/version.js.map +1 -1
  37. package/dist/lib/version.mjs +3 -3
  38. package/dist/lib/version.mjs.map +1 -1
  39. package/package.json +2 -2
@@ -1,3 +1,8 @@
1
+ import { fileURLToPath as __adcpFileURLToPath } from "node:url";
2
+ import { dirname as __adcpDirname } from "node:path";
3
+ import { createRequire as __adcpCreateRequire } from "node:module";
4
+ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
5
+ const require2 = __adcpCreateRequire(import.meta.url);
1
6
  import { A2AClient as A2AClientImpl } from "@a2a-js/sdk/client";
2
7
  import { AsyncLocalStorage } from "node:async_hooks";
3
8
  import { createHmac, randomUUID } from "node:crypto";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/protocols/a2a.ts"],"sourcesContent":["// Official A2A client implementation - NO FALLBACKS\nimport { A2AClient as A2AClientImpl } from '@a2a-js/sdk/client';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHmac, randomUUID } from 'node:crypto';\nimport type { PushNotificationConfig } from '../types/tools.generated';\nimport type { DebugLogEntry } from '../types/adcp';\nimport { AuthenticationRequiredError, is401Error } from '../errors';\nimport { discoverOAuthMetadata } from '../auth/oauth/discovery';\nimport { probeAuthChallenge } from '../auth/oauth/authorization-required';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { isAgentCardPath, buildCardUrls } from '../utils/a2a-discovery';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport { toSignerKey, isInlineSigningConfig, isProviderSigningConfig } from '../signing/agent-fetch';\nimport { createSigningFetch, type FetchLike } from '../signing/fetch';\nimport { createSigningFetchAsync } from '../signing/fetch-async';\nimport type { AgentConfig } from '../types/adcp';\nimport { redactIdempotencyKeyInArgs } from '../utils/idempotency';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\nimport { DEFAULT_REQUEST_TIMEOUT_MS, resolveRequestTimeoutMs, withAbortSignal } from './abort';\nimport { getLatestA2ADataPartFromResponse } from '../utils/a2a-artifacts';\n\n// The A2A SDK client is used untyped: request/response shapes are validated at\n// runtime against the AdCP wire contract, not against the SDK's exported\n// types. Preserves the prior behaviour of the CommonJS `require` form.\nconst A2AClient: any = A2AClientImpl;\n\nif (!A2AClient) {\n throw new Error('A2A SDK client is required. Please install @a2a-js/sdk');\n}\n\n/**\n * Per-call state flowed through AsyncLocalStorage so concurrent callers\n * that share a cached A2AClient don't clobber each other's debugLogs,\n * customHeaders, or 401 flag.\n */\ninterface A2ACallContext {\n customHeaders?: Record<string, string>;\n debugLogs: DebugLogEntry[];\n got401Ref: { value: boolean };\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n}\n\nconst callContextStorage = new AsyncLocalStorage<A2ACallContext>();\n\n/**\n * Cached A2AClient keyed by (agentUrl, authToken hash). Avoids re-fetching\n * /.well-known/agent.json on every tool call. The cached client's fetchImpl\n * reads per-call state from callContextStorage, so concurrent calls to the\n * same cache entry are safe.\n *\n * Process-global singleton — not suitable for multi-tenant servers that\n * want per-tenant isolation (use separate processes or explicit cache keys).\n */\nconst a2aClientCache = new Map<string, InstanceType<typeof A2AClient>>();\nconst pendingA2AClients = new Map<string, Promise<InstanceType<typeof A2AClient>>>();\n\n/**\n * Build the A2A connection-cache key. Mirrors the rationale in\n * `src/lib/protocols/mcp.ts:connectionCacheKey`: when the caller is using a\n * non-bearer scheme (RFC 7617 Basic from the CLI's `--auth-scheme basic`\n * shape, or any future caller-injected `Authorization` header), `authToken`\n * is undefined and the credential rides on the customHeaders bag. Hashing\n * only `authToken` would let two callers with different `user:pass`\n * credentials share a single cached A2AClient — single-CLI-process safe,\n * multi-tenant SDK consumer not safe.\n *\n * `customHeaders` also feed the key so tenant/routing headers cannot reuse\n * a card/client discovered for another caller.\n */\nfunction a2aCacheKey(\n agentUrl: string,\n authToken?: string,\n signingCacheKey?: string,\n customHeaders?: Record<string, string>\n): string {\n // 64-bit Map-key disambiguator — NOT a password hash. The cached client\n // closes over the full credential, so a hypothetical hash collision still\n // sends the original credential on the wire, just possibly cache-miss\n // and reconnect. Routed via `cacheDisambiguator` (HMAC-SHA256 with empty\n // key) instead of bare `createHash` so CodeQL's\n // `js/insufficient-password-hash` heuristic doesn't misclassify the\n // dataflow — see the helper docstring for the full rationale.\n const fingerprint = authToken ?? extractA2AAuthHeader(customHeaders);\n const tokenSuffix = fingerprint ? `::${cacheDisambiguator(fingerprint)}` : '';\n const headersKey = headersCacheDisambiguator(customHeaders);\n const headersSuffix = headersKey ? `::headers:${headersKey}` : '';\n const signingSuffix = signingCacheKey ? `::${signingCacheKey}` : '';\n return `${agentUrl}${tokenSuffix}${headersSuffix}${signingSuffix}`;\n}\n\n/**\n * Produce a stable 64-bit Map-key disambiguator from credential material.\n * Mirrors the helper in `src/lib/protocols/mcp.ts` — the two protocol\n * modules intentionally don't share runtime imports, so each carries its\n * own copy. See the MCP-side docstring for the full rationale.\n */\nfunction cacheDisambiguator(value: string): string {\n return createHmac('sha256', '').update(value).digest('hex').slice(0, 16);\n}\n\n/**\n * Case-insensitive lookup of `Authorization` on a header bag. Mirrors the\n * MCP-side helper; A2A keeps its own copy because the two protocol modules\n * intentionally don't share runtime imports.\n */\nfunction extractA2AAuthHeader(headers: Record<string, string> | undefined): string | undefined {\n if (!headers) return undefined;\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === 'authorization' && value) return value;\n }\n return undefined;\n}\n\nfunction headersCacheDisambiguator(headers?: Record<string, string>): string | undefined {\n const entries = Object.entries(headers ?? {})\n .filter(([key]) => {\n const lower = key.toLowerCase();\n return lower !== 'traceparent' && lower !== 'tracestate' && lower !== 'baggage';\n })\n .map(([key, value]) => [key.toLowerCase(), value] as const)\n .sort(([a], [b]) => a.localeCompare(b));\n return entries.length > 0 ? cacheDisambiguator(JSON.stringify(entries)) : undefined;\n}\n\nfunction redactHeadersForDebug(headers: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.keys(headers).map(key => [key, '***']));\n}\n\nfunction redactPushNotificationConfigForDebug(\n config: PushNotificationConfig | undefined\n): PushNotificationConfig | undefined {\n if (!config) return undefined;\n return {\n ...config,\n ...(config.token && { token: '***' }),\n ...(config.authentication && {\n authentication: {\n ...config.authentication,\n ...(config.authentication.credentials && { credentials: '***' }),\n },\n }),\n };\n}\n\n/**\n * Clear all cached A2A clients. Called by closeConnections('a2a').\n * A2A clients hold no persistent network resources (unlike MCP), so this\n * is just cache eviction.\n */\nexport function closeA2AConnections(): void {\n a2aClientCache.clear();\n pendingA2AClients.clear();\n}\n\n/**\n * Wall-clock cap on a fire-and-forget cancel. A2A sellers that accept the\n * TCP connect but never respond would otherwise pin the event loop past the\n * buyer's abort, which defeats the whole point of fire-and-forget.\n */\nconst CANCEL_TIMEOUT_MS = 5000;\n\n/**\n * Fire-and-forget A2A tasks/cancel for an in-flight task (A2A 0.3.0 §7.4).\n *\n * Sends a raw JSON-RPC 2.0 POST directly to the agent endpoint with the same\n * auth header shape as `callA2AToolImpl` (Bearer + x-adcp-auth). Does NOT\n * enter `callContextStorage` — debug-log capture and 401-cache-eviction are\n * intentionally skipped for best-effort cancellation.\n *\n * **Auth-code OAuth gap:** `authToken` is resolved by `getAuthToken(agent)`,\n * which returns `undefined` for authorization-code-flow sellers (those tokens\n * are managed by the OAuth provider path in `ProtocolClient.callTool`, not\n * accessible here). Cancel calls to those sellers go out unauthenticated and\n * will likely 401 non-fatally.\n *\n * **Phase 2 (adcp-client#1617 follow-up):** when `agent.request_signing` is\n * configured, the cancel POST is signed with the agent's signer key. The\n * `signingContextStorage` ALS scope around `callA2AToolImpl` does NOT extend\n * into `pollTaskCompletion` (sibling promise trees), so we can't replay the\n * captured ALS context — instead we rebuild a one-shot signer fetch from\n * `agent.request_signing` directly and use it for this single POST. Inline\n * keys go through `createSigningFetch` (sync); provider-backed configs use\n * `createSigningFetchAsync`. A `signed-requests` seller that requires\n * signing on `tasks/cancel` (or applies a uniform \"all mutating POSTs must\n * be signed\" policy) now accepts the cancel; one without signing config on\n * the agent gets the Phase 1 unsigned path.\n *\n * The caller is responsible for swallowing errors: cancel failure\n * (TaskNotCancelable, network error, auth rejection, network timeout) is\n * non-fatal because the buyer is already abandoning the task.\n *\n * @param agent The agent config (used for URL, auth token, signing).\n * @param taskId The server-assigned A2A Task.id to cancel.\n */\nexport async function cancelA2ATask(agent: AgentConfig, taskId: string): Promise<void> {\n // Defense-in-depth (ad-tech-protocol-expert review of #1640): the cancel\n // POST is JSON-RPC at the bare A2A endpoint. Calling this on an MCP agent\n // would POST `tasks/cancel` JSON-RPC at an MCP endpoint and 404. The\n // single call site (`pollTaskCompletion`) already gates on\n // `agent.protocol === 'a2a'`; this assertion catches future call sites\n // that forget the gate.\n if (agent.protocol !== 'a2a') {\n return;\n }\n const agentUrl = agent.agent_uri;\n const authToken = agent.auth_token;\n\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/json',\n };\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n headers['x-adcp-auth'] = authToken;\n }\n // JSON-RPC 2.0 §4.1.3: `id: null` flags the request as a *notification*,\n // and the server MUST NOT respond. A2A 0.3.0 §7.4 defines `tasks/cancel`\n // as a request/response method (returns the canceled `Task` or\n // `TaskNotCancelableError`), so a strict A2A server can legitimately\n // reject `id: null` as a protocol violation. Use a real id and just drop\n // the response on the floor — fire-and-forget is the caller's discipline,\n // not a wire-protocol claim.\n const body = JSON.stringify({\n jsonrpc: '2.0',\n id: randomUUID(),\n method: 'tasks/cancel',\n params: { id: taskId },\n });\n // Bound the cancel: a hung fetch would orphan-pin the event loop past the\n // buyer's abort, defeating fire-and-forget. AbortSignal.timeout() is the\n // standard primitive; the caller's `.catch()` swallows the AbortError.\n const init: RequestInit = {\n method: 'POST',\n headers,\n body,\n signal: AbortSignal.timeout(CANCEL_TIMEOUT_MS),\n };\n\n // adcp-client#1617 Phase 2: sign the cancel POST when the agent has a\n // signer configured. We bypass the `buildAgentSigningFetch` capability-\n // gate path because `tasks/cancel` is an A2A protocol method, not an\n // AdCP tool — the seller's `request_signing.supported_for` typically\n // lists AdCP tool names, not protocol-level methods. The right model\n // here: if the agent claims signing AT ALL, sign every mutating POST\n // we send to it on the cancel path. Sellers with uniform \"must be\n // signed\" policies accept this; sellers that only check signing on\n // specific AdCP tools simply ignore the extra signature.\n //\n // TODO(adcp#4318, adcp-client#1617): when the AdCP spec adds explicit\n // verifier coverage for A2A protocol methods (likely in 3.1 as a new\n // `protocol_methods_supported_for` / `protocol_methods_required_for`\n // field on `request_signing`), narrow this default by reading the\n // seller's advertised coverage from `getCapability()` and gating on\n // the `tasks/cancel` membership. The over-sign default stays as the\n // fallback for spec-silent sellers (3.0.x and earlier).\n if (agent.request_signing) {\n const upstream: FetchLike = (input, ini) => fetch(input as RequestInfo, ini);\n if (isInlineSigningConfig(agent.request_signing)) {\n const signed = createSigningFetch(upstream, toSignerKey(agent.request_signing));\n await signed(agentUrl, init);\n return;\n }\n if (isProviderSigningConfig(agent.request_signing)) {\n const signed = createSigningFetchAsync(upstream, agent.request_signing.provider);\n await signed(agentUrl, init);\n return;\n }\n }\n\n await fetch(agentUrl, init);\n}\n\nasync function getOrCreateA2AClient(\n agentUrl: string,\n authToken: string | undefined,\n customHeaders?: Record<string, string>,\n bypassCache = false\n): Promise<InstanceType<typeof A2AClient>> {\n const signingContext = signingContextStorage.getStore();\n const cacheKey = a2aCacheKey(agentUrl, authToken, signingContext?.cacheKey, customHeaders);\n if (bypassCache) {\n return createA2AClient(agentUrl, authToken);\n }\n const cached = a2aClientCache.get(cacheKey);\n if (cached) return cached;\n\n const pending = pendingA2AClients.get(cacheKey);\n if (pending) return pending;\n\n const promise = createA2AClient(agentUrl, authToken)\n .then(client => {\n a2aClientCache.set(cacheKey, client);\n return client;\n })\n .finally(() => {\n pendingA2AClients.delete(cacheKey);\n });\n\n pendingA2AClients.set(cacheKey, promise);\n return promise;\n}\n\nasync function createA2AClient(\n agentUrl: string,\n authToken: string | undefined\n): Promise<InstanceType<typeof A2AClient>> {\n const fetchImpl = buildFetchImpl(authToken);\n const cardUrls = buildCardUrls(agentUrl);\n\n const context = callContextStorage.getStore();\n context?.debugLogs.push({\n type: 'info',\n message: `A2A: Discovering agent card at ${cardUrls.join(', ')}`,\n timestamp: new Date().toISOString(),\n });\n\n let client: InstanceType<typeof A2AClient> | undefined;\n let lastError: Error = new Error(`A2A agent card not found at ${cardUrls.join(', ')}`);\n for (const cardUrl of cardUrls) {\n try {\n client = await A2AClient.fromCardUrl(cardUrl, { fetchImpl });\n break;\n } catch (err: unknown) {\n lastError = err as Error;\n if (context?.got401Ref.value) break;\n }\n }\n if (!client) throw lastError;\n\n return client;\n}\n\nfunction buildFetchImpl(authToken: string | undefined) {\n // The A2A client is cached per (url, authToken, signingCacheKey). We capture\n // the signing context at client-creation time so all subsequent calls that\n // share this cached client use the same signing identity — changing identity\n // requires a different cache entry, built on a separate call that enters ALS\n // with a different context.\n const signingContext = signingContextStorage.getStore();\n\n // Innermost wrapper: enforce response body size cap from the active\n // `responseSizeLimitStorage` slot. Pass-through when no slot is set.\n const networkFetch = wrapFetchWithTransportDiagnostics(\n wrapFetchWithSizeLimit((input, init) => fetch(input as any, init))\n );\n\n // Inner fetch handles auth/header injection and 401 detection. If the\n // agent has request-signing configured, we wrap it with the AdCP signing\n // fetch so the signature covers the exact bytes we're about to send (auth\n // headers included, since the signer re-reads the final header record).\n const baseFetch = async (url: string | URL | Request, options?: RequestInit): Promise<Response> => {\n const context = callContextStorage.getStore();\n\n const existingHeaders: Record<string, string> = {};\n if (options?.headers) {\n if (options.headers instanceof Headers) {\n options.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n } else if (Array.isArray(options.headers)) {\n for (const [key, value] of options.headers) {\n existingHeaders[key] = value;\n }\n } else {\n Object.assign(existingHeaders, options.headers);\n }\n }\n\n // Only inject trace context headers for actual tool requests, not discovery.\n // The agent card endpoint is external/untrusted — don't leak trace IDs to it.\n const urlString = typeof url === 'string' ? url : url.toString();\n const isDiscoveryRequest = isAgentCardPath(urlString);\n const traceHeaders = isDiscoveryRequest ? {} : injectTraceHeaders();\n const requestTimeoutMs = isDiscoveryRequest\n ? resolveRequestTimeoutMs(context?.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS)\n : resolveRequestTimeoutMs(context?.requestTimeoutMs);\n\n // Merge: existing < trace < custom < auth (auth always wins)\n const headers: Record<string, string> = {\n ...existingHeaders,\n ...traceHeaders,\n ...context?.customHeaders,\n ...(authToken && {\n Authorization: `Bearer ${authToken}`,\n 'x-adcp-auth': authToken,\n }),\n };\n\n context?.debugLogs.push({\n type: 'info',\n message: `A2A: Fetch to ${urlString}`,\n timestamp: new Date().toISOString(),\n hasAuth: !!authToken,\n headers: redactHeadersForDebug(headers),\n });\n\n const response = await withAbortSignal<Response>([context?.signal, options?.signal], requestTimeoutMs, signal =>\n networkFetch(url as any, { ...options, headers, signal })\n );\n\n if (response.status === 401 && context) {\n context.got401Ref.value = true;\n }\n\n return response;\n };\n\n if (!signingContext) return wrapFetchWithCapture(baseFetch);\n\n // The signing wrapper assembles headers into the signature base. We invoke\n // it first so the signer sees the caller-supplied headers; baseFetch then\n // overlays auth/trace headers afterwards — A2A's auth scheme (bearer) is\n // not among the MANDATORY_COMPONENTS and is injected by the counterparty's\n // transport layer, not signed.\n const signingFetch = buildAgentSigningFetch({\n upstream: (input, init) => baseFetch(input as any, init),\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n });\n return wrapFetchWithCapture(signingFetch as typeof fetch);\n}\n\n/**\n * Terminal A2A task states per A2A 0.3.0 §3.4. Only these can carry the\n * AdCP-mandated artifact + DataPart envelope (per transport-errors §A2A\n * Binding); intermediate states (`working`, `submitted`, `input-required`,\n * `auth-required`) carry no completion artifact.\n */\nconst TERMINAL_A2A_STATES = new Set(['completed', 'failed', 'rejected', 'canceled']);\n\n/**\n * Detect whether a JSON-RPC response carries a spec-compliant terminal-state\n * Task with at least one artifact containing a structured DataPart payload.\n * Per AdCP transport-errors §A2A Binding, the artifact's DataPart is the\n * canonical envelope for both the success arm (`completed`) and the error\n * arms (`failed` / `rejected` / `canceled`). The criterion intentionally\n * matches the unwrapper's terminal-state extraction in\n * `unwrapA2AResponse` — keeping protocol layer and unwrapper in lockstep\n * across all terminal states, not just the error arms.\n *\n * Used to short-circuit the generic \"A2A agent returned error\" throw when\n * a non-conformant seller surfaces both a transport-level `result.error`\n * hint and the canonical artifact envelope side-by-side. The DataPart is\n * authoritative; the throw would otherwise swallow it.\n */\nfunction hasTerminalTaskWithDataArtifact(response: unknown): boolean {\n if (!response || typeof response !== 'object') return false;\n const result = (response as { result?: unknown }).result;\n if (!result || typeof result !== 'object') return false;\n const r = result as { kind?: unknown; status?: unknown; artifacts?: unknown };\n if (r.kind !== 'task') return false;\n const status = r.status as { state?: unknown } | undefined;\n if (typeof status?.state !== 'string' || !TERMINAL_A2A_STATES.has(status.state)) return false;\n return getLatestA2ADataPartFromResponse(response) !== undefined;\n}\n\n/**\n * Protocol-level session identifiers that ride on the A2A Message envelope\n * (not in the skill parameters). `contextId` binds sends to a server-side\n * conversation; `taskId` resumes an existing non-terminal task.\n *\n * Callers (buyers) typically retain these across calls on a per-conversation\n * AgentClient; see AgentClient.getContextId() / getPendingTaskId().\n */\nexport interface A2ASessionIds {\n contextId?: string;\n taskId?: string;\n}\n\nexport async function callA2ATool(\n agentUrl: string,\n toolName: string,\n parameters: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n pushNotificationConfig?: PushNotificationConfig,\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n session?: A2ASessionIds,\n signal?: AbortSignal,\n requestTimeoutMs?: number\n): Promise<unknown> {\n return withSpan(\n 'adcp.a2a.call_tool',\n {\n 'adcp.tool': toolName,\n 'http.url': agentUrl,\n },\n async () => {\n const context: A2ACallContext = {\n customHeaders,\n debugLogs,\n got401Ref: { value: false },\n signal,\n requestTimeoutMs,\n };\n return signingContextStorage.run(signingContext, () =>\n callContextStorage.run(context, () =>\n callA2AToolImpl(\n agentUrl,\n toolName,\n parameters,\n authToken,\n debugLogs,\n pushNotificationConfig,\n context,\n session\n )\n )\n );\n }\n );\n}\n\nasync function callA2AToolImpl(\n agentUrl: string,\n toolName: string,\n parameters: Record<string, unknown>,\n authToken: string | undefined,\n debugLogs: DebugLogEntry[],\n pushNotificationConfig: PushNotificationConfig | undefined,\n context: A2ACallContext,\n session: A2ASessionIds | undefined\n): Promise<unknown> {\n try {\n const client = await getOrCreateA2AClient(\n agentUrl,\n authToken,\n context.customHeaders,\n !!context.signal || context.requestTimeoutMs !== undefined\n );\n\n const requestPayload: {\n message: {\n messageId: string;\n role: string;\n kind: string;\n parts: Array<{ kind: string; data: { skill: string; parameters: Record<string, unknown> } }>;\n contextId?: string;\n taskId?: string;\n };\n configuration?: { pushNotificationConfig: PushNotificationConfig };\n } = {\n message: {\n messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n role: 'user',\n kind: 'message',\n parts: [\n {\n kind: 'data',\n data: {\n skill: toolName,\n parameters: parameters,\n },\n },\n ],\n ...(session?.contextId && { contextId: session.contextId }),\n ...(session?.taskId && { taskId: session.taskId }),\n },\n };\n\n if (pushNotificationConfig) {\n requestPayload.configuration = {\n pushNotificationConfig: pushNotificationConfig,\n };\n }\n\n const payloadSize = JSON.stringify(requestPayload).length;\n const redactedParameters = redactIdempotencyKeyInArgs(parameters);\n const redactedPayload = {\n ...requestPayload,\n message: {\n ...requestPayload.message,\n parts: [\n {\n kind: 'data',\n data: { skill: toolName, parameters: redactedParameters },\n },\n ],\n },\n ...(requestPayload.configuration && {\n configuration: {\n pushNotificationConfig: redactPushNotificationConfigForDebug(\n requestPayload.configuration.pushNotificationConfig\n )!,\n },\n }),\n };\n debugLogs.push({\n type: 'info',\n message: `A2A: Calling skill ${toolName} with parameters: ${JSON.stringify(\n redactedParameters\n )}. Payload size: ${payloadSize} bytes`,\n timestamp: new Date().toISOString(),\n payloadSize,\n actualPayload: redactedPayload,\n });\n\n debugLogs.push({\n type: 'info',\n message: `A2A: Sending message via sendMessage()`,\n timestamp: new Date().toISOString(),\n skill: toolName,\n });\n\n const messageResponse = await client.sendMessage(requestPayload);\n\n debugLogs.push({\n type: messageResponse?.error ? 'error' : 'success',\n message: `A2A: Response received (${messageResponse?.error ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: messageResponse,\n skill: toolName,\n });\n\n if (messageResponse?.error || messageResponse?.result?.error) {\n // adcp-client#1575: when the seller emits a spec-compliant terminal-state\n // Task carrying an `adcp_error` DataPart (per AdCP transport-errors §A2A\n // Binding), the structured artifact is canonical — even if the seller\n // also surfaced a transport-level error string. Pass the response\n // through so the upstream unwrapper extracts `adcp_error.code` instead\n // of throwing a generic message that loses the AdCP error envelope.\n if (!hasTerminalTaskWithDataArtifact(messageResponse)) {\n const errorObj = messageResponse.error || messageResponse.result?.error;\n const errorMessage = errorObj.message || JSON.stringify(errorObj);\n throw new Error(`A2A agent returned error: ${errorMessage}`);\n }\n }\n\n return messageResponse;\n } catch (error: unknown) {\n if (is401Error(error, context.got401Ref.value)) {\n // Evict this cache entry — credential may have expired or been\n // revoked. Same disambiguator as the original `getOrCreateA2AClient`\n // call: when the credential rode on customHeaders.Authorization (Basic\n // case) rather than authToken, the cache key must reflect that or we\n // evict the wrong entry.\n const signingContext = signingContextStorage.getStore();\n a2aClientCache.delete(a2aCacheKey(agentUrl, authToken, signingContext?.cacheKey, context.customHeaders));\n\n debugLogs.push({\n type: 'error',\n message: `A2A: Authentication required for ${agentUrl}`,\n timestamp: new Date().toISOString(),\n });\n\n // Re-probe to surface the WWW-Authenticate scheme on the error envelope.\n // Basic-fronted agents (Apigee/Kong/AWS API GW with a BasicAuthentication\n // policy) would otherwise leave consumers chasing OAuth metadata that\n // doesn't exist. Matches the MCP discovery throw site in\n // `SingleAgentClient.discoverMCPEndpoint`.\n const challenge = await probeAuthChallenge(agentUrl);\n const oauthMetadata = await discoverOAuthMetadata(agentUrl);\n throw new AuthenticationRequiredError(agentUrl, oauthMetadata || undefined, undefined, challenge ?? undefined);\n }\n\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/protocols/a2a.ts"],"sourcesContent":["import { fileURLToPath as __adcpFileURLToPath } from 'node:url';\nimport { dirname as __adcpDirname } from 'node:path';\nimport { createRequire as __adcpCreateRequire } from 'node:module';\nconst __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));\nconst require = __adcpCreateRequire(import.meta.url);\n// Official A2A client implementation - NO FALLBACKS\nimport { A2AClient as A2AClientImpl } from '@a2a-js/sdk/client';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { createHmac, randomUUID } from 'node:crypto';\nimport type { PushNotificationConfig } from '../types/tools.generated';\nimport type { DebugLogEntry } from '../types/adcp';\nimport { AuthenticationRequiredError, is401Error } from '../errors';\nimport { discoverOAuthMetadata } from '../auth/oauth/discovery';\nimport { probeAuthChallenge } from '../auth/oauth/authorization-required';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { isAgentCardPath, buildCardUrls } from '../utils/a2a-discovery';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport { toSignerKey, isInlineSigningConfig, isProviderSigningConfig } from '../signing/agent-fetch';\nimport { createSigningFetch, type FetchLike } from '../signing/fetch';\nimport { createSigningFetchAsync } from '../signing/fetch-async';\nimport type { AgentConfig } from '../types/adcp';\nimport { redactIdempotencyKeyInArgs } from '../utils/idempotency';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\nimport { DEFAULT_REQUEST_TIMEOUT_MS, resolveRequestTimeoutMs, withAbortSignal } from './abort';\nimport { getLatestA2ADataPartFromResponse } from '../utils/a2a-artifacts';\n\n// The A2A SDK client is used untyped: request/response shapes are validated at\n// runtime against the AdCP wire contract, not against the SDK's exported\n// types. Preserves the prior behaviour of the CommonJS `require` form.\nconst A2AClient: any = A2AClientImpl;\n\nif (!A2AClient) {\n throw new Error('A2A SDK client is required. Please install @a2a-js/sdk');\n}\n\n/**\n * Per-call state flowed through AsyncLocalStorage so concurrent callers\n * that share a cached A2AClient don't clobber each other's debugLogs,\n * customHeaders, or 401 flag.\n */\ninterface A2ACallContext {\n customHeaders?: Record<string, string>;\n debugLogs: DebugLogEntry[];\n got401Ref: { value: boolean };\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n}\n\nconst callContextStorage = new AsyncLocalStorage<A2ACallContext>();\n\n/**\n * Cached A2AClient keyed by (agentUrl, authToken hash). Avoids re-fetching\n * /.well-known/agent.json on every tool call. The cached client's fetchImpl\n * reads per-call state from callContextStorage, so concurrent calls to the\n * same cache entry are safe.\n *\n * Process-global singleton — not suitable for multi-tenant servers that\n * want per-tenant isolation (use separate processes or explicit cache keys).\n */\nconst a2aClientCache = new Map<string, InstanceType<typeof A2AClient>>();\nconst pendingA2AClients = new Map<string, Promise<InstanceType<typeof A2AClient>>>();\n\n/**\n * Build the A2A connection-cache key. Mirrors the rationale in\n * `src/lib/protocols/mcp.ts:connectionCacheKey`: when the caller is using a\n * non-bearer scheme (RFC 7617 Basic from the CLI's `--auth-scheme basic`\n * shape, or any future caller-injected `Authorization` header), `authToken`\n * is undefined and the credential rides on the customHeaders bag. Hashing\n * only `authToken` would let two callers with different `user:pass`\n * credentials share a single cached A2AClient — single-CLI-process safe,\n * multi-tenant SDK consumer not safe.\n *\n * `customHeaders` also feed the key so tenant/routing headers cannot reuse\n * a card/client discovered for another caller.\n */\nfunction a2aCacheKey(\n agentUrl: string,\n authToken?: string,\n signingCacheKey?: string,\n customHeaders?: Record<string, string>\n): string {\n // 64-bit Map-key disambiguator — NOT a password hash. The cached client\n // closes over the full credential, so a hypothetical hash collision still\n // sends the original credential on the wire, just possibly cache-miss\n // and reconnect. Routed via `cacheDisambiguator` (HMAC-SHA256 with empty\n // key) instead of bare `createHash` so CodeQL's\n // `js/insufficient-password-hash` heuristic doesn't misclassify the\n // dataflow — see the helper docstring for the full rationale.\n const fingerprint = authToken ?? extractA2AAuthHeader(customHeaders);\n const tokenSuffix = fingerprint ? `::${cacheDisambiguator(fingerprint)}` : '';\n const headersKey = headersCacheDisambiguator(customHeaders);\n const headersSuffix = headersKey ? `::headers:${headersKey}` : '';\n const signingSuffix = signingCacheKey ? `::${signingCacheKey}` : '';\n return `${agentUrl}${tokenSuffix}${headersSuffix}${signingSuffix}`;\n}\n\n/**\n * Produce a stable 64-bit Map-key disambiguator from credential material.\n * Mirrors the helper in `src/lib/protocols/mcp.ts` — the two protocol\n * modules intentionally don't share runtime imports, so each carries its\n * own copy. See the MCP-side docstring for the full rationale.\n */\nfunction cacheDisambiguator(value: string): string {\n return createHmac('sha256', '').update(value).digest('hex').slice(0, 16);\n}\n\n/**\n * Case-insensitive lookup of `Authorization` on a header bag. Mirrors the\n * MCP-side helper; A2A keeps its own copy because the two protocol modules\n * intentionally don't share runtime imports.\n */\nfunction extractA2AAuthHeader(headers: Record<string, string> | undefined): string | undefined {\n if (!headers) return undefined;\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === 'authorization' && value) return value;\n }\n return undefined;\n}\n\nfunction headersCacheDisambiguator(headers?: Record<string, string>): string | undefined {\n const entries = Object.entries(headers ?? {})\n .filter(([key]) => {\n const lower = key.toLowerCase();\n return lower !== 'traceparent' && lower !== 'tracestate' && lower !== 'baggage';\n })\n .map(([key, value]) => [key.toLowerCase(), value] as const)\n .sort(([a], [b]) => a.localeCompare(b));\n return entries.length > 0 ? cacheDisambiguator(JSON.stringify(entries)) : undefined;\n}\n\nfunction redactHeadersForDebug(headers: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.keys(headers).map(key => [key, '***']));\n}\n\nfunction redactPushNotificationConfigForDebug(\n config: PushNotificationConfig | undefined\n): PushNotificationConfig | undefined {\n if (!config) return undefined;\n return {\n ...config,\n ...(config.token && { token: '***' }),\n ...(config.authentication && {\n authentication: {\n ...config.authentication,\n ...(config.authentication.credentials && { credentials: '***' }),\n },\n }),\n };\n}\n\n/**\n * Clear all cached A2A clients. Called by closeConnections('a2a').\n * A2A clients hold no persistent network resources (unlike MCP), so this\n * is just cache eviction.\n */\nexport function closeA2AConnections(): void {\n a2aClientCache.clear();\n pendingA2AClients.clear();\n}\n\n/**\n * Wall-clock cap on a fire-and-forget cancel. A2A sellers that accept the\n * TCP connect but never respond would otherwise pin the event loop past the\n * buyer's abort, which defeats the whole point of fire-and-forget.\n */\nconst CANCEL_TIMEOUT_MS = 5000;\n\n/**\n * Fire-and-forget A2A tasks/cancel for an in-flight task (A2A 0.3.0 §7.4).\n *\n * Sends a raw JSON-RPC 2.0 POST directly to the agent endpoint with the same\n * auth header shape as `callA2AToolImpl` (Bearer + x-adcp-auth). Does NOT\n * enter `callContextStorage` — debug-log capture and 401-cache-eviction are\n * intentionally skipped for best-effort cancellation.\n *\n * **Auth-code OAuth gap:** `authToken` is resolved by `getAuthToken(agent)`,\n * which returns `undefined` for authorization-code-flow sellers (those tokens\n * are managed by the OAuth provider path in `ProtocolClient.callTool`, not\n * accessible here). Cancel calls to those sellers go out unauthenticated and\n * will likely 401 non-fatally.\n *\n * **Phase 2 (adcp-client#1617 follow-up):** when `agent.request_signing` is\n * configured, the cancel POST is signed with the agent's signer key. The\n * `signingContextStorage` ALS scope around `callA2AToolImpl` does NOT extend\n * into `pollTaskCompletion` (sibling promise trees), so we can't replay the\n * captured ALS context — instead we rebuild a one-shot signer fetch from\n * `agent.request_signing` directly and use it for this single POST. Inline\n * keys go through `createSigningFetch` (sync); provider-backed configs use\n * `createSigningFetchAsync`. A `signed-requests` seller that requires\n * signing on `tasks/cancel` (or applies a uniform \"all mutating POSTs must\n * be signed\" policy) now accepts the cancel; one without signing config on\n * the agent gets the Phase 1 unsigned path.\n *\n * The caller is responsible for swallowing errors: cancel failure\n * (TaskNotCancelable, network error, auth rejection, network timeout) is\n * non-fatal because the buyer is already abandoning the task.\n *\n * @param agent The agent config (used for URL, auth token, signing).\n * @param taskId The server-assigned A2A Task.id to cancel.\n */\nexport async function cancelA2ATask(agent: AgentConfig, taskId: string): Promise<void> {\n // Defense-in-depth (ad-tech-protocol-expert review of #1640): the cancel\n // POST is JSON-RPC at the bare A2A endpoint. Calling this on an MCP agent\n // would POST `tasks/cancel` JSON-RPC at an MCP endpoint and 404. The\n // single call site (`pollTaskCompletion`) already gates on\n // `agent.protocol === 'a2a'`; this assertion catches future call sites\n // that forget the gate.\n if (agent.protocol !== 'a2a') {\n return;\n }\n const agentUrl = agent.agent_uri;\n const authToken = agent.auth_token;\n\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/json',\n };\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n headers['x-adcp-auth'] = authToken;\n }\n // JSON-RPC 2.0 §4.1.3: `id: null` flags the request as a *notification*,\n // and the server MUST NOT respond. A2A 0.3.0 §7.4 defines `tasks/cancel`\n // as a request/response method (returns the canceled `Task` or\n // `TaskNotCancelableError`), so a strict A2A server can legitimately\n // reject `id: null` as a protocol violation. Use a real id and just drop\n // the response on the floor — fire-and-forget is the caller's discipline,\n // not a wire-protocol claim.\n const body = JSON.stringify({\n jsonrpc: '2.0',\n id: randomUUID(),\n method: 'tasks/cancel',\n params: { id: taskId },\n });\n // Bound the cancel: a hung fetch would orphan-pin the event loop past the\n // buyer's abort, defeating fire-and-forget. AbortSignal.timeout() is the\n // standard primitive; the caller's `.catch()` swallows the AbortError.\n const init: RequestInit = {\n method: 'POST',\n headers,\n body,\n signal: AbortSignal.timeout(CANCEL_TIMEOUT_MS),\n };\n\n // adcp-client#1617 Phase 2: sign the cancel POST when the agent has a\n // signer configured. We bypass the `buildAgentSigningFetch` capability-\n // gate path because `tasks/cancel` is an A2A protocol method, not an\n // AdCP tool — the seller's `request_signing.supported_for` typically\n // lists AdCP tool names, not protocol-level methods. The right model\n // here: if the agent claims signing AT ALL, sign every mutating POST\n // we send to it on the cancel path. Sellers with uniform \"must be\n // signed\" policies accept this; sellers that only check signing on\n // specific AdCP tools simply ignore the extra signature.\n //\n // TODO(adcp#4318, adcp-client#1617): when the AdCP spec adds explicit\n // verifier coverage for A2A protocol methods (likely in 3.1 as a new\n // `protocol_methods_supported_for` / `protocol_methods_required_for`\n // field on `request_signing`), narrow this default by reading the\n // seller's advertised coverage from `getCapability()` and gating on\n // the `tasks/cancel` membership. The over-sign default stays as the\n // fallback for spec-silent sellers (3.0.x and earlier).\n if (agent.request_signing) {\n const upstream: FetchLike = (input, ini) => fetch(input as RequestInfo, ini);\n if (isInlineSigningConfig(agent.request_signing)) {\n const signed = createSigningFetch(upstream, toSignerKey(agent.request_signing));\n await signed(agentUrl, init);\n return;\n }\n if (isProviderSigningConfig(agent.request_signing)) {\n const signed = createSigningFetchAsync(upstream, agent.request_signing.provider);\n await signed(agentUrl, init);\n return;\n }\n }\n\n await fetch(agentUrl, init);\n}\n\nasync function getOrCreateA2AClient(\n agentUrl: string,\n authToken: string | undefined,\n customHeaders?: Record<string, string>,\n bypassCache = false\n): Promise<InstanceType<typeof A2AClient>> {\n const signingContext = signingContextStorage.getStore();\n const cacheKey = a2aCacheKey(agentUrl, authToken, signingContext?.cacheKey, customHeaders);\n if (bypassCache) {\n return createA2AClient(agentUrl, authToken);\n }\n const cached = a2aClientCache.get(cacheKey);\n if (cached) return cached;\n\n const pending = pendingA2AClients.get(cacheKey);\n if (pending) return pending;\n\n const promise = createA2AClient(agentUrl, authToken)\n .then(client => {\n a2aClientCache.set(cacheKey, client);\n return client;\n })\n .finally(() => {\n pendingA2AClients.delete(cacheKey);\n });\n\n pendingA2AClients.set(cacheKey, promise);\n return promise;\n}\n\nasync function createA2AClient(\n agentUrl: string,\n authToken: string | undefined\n): Promise<InstanceType<typeof A2AClient>> {\n const fetchImpl = buildFetchImpl(authToken);\n const cardUrls = buildCardUrls(agentUrl);\n\n const context = callContextStorage.getStore();\n context?.debugLogs.push({\n type: 'info',\n message: `A2A: Discovering agent card at ${cardUrls.join(', ')}`,\n timestamp: new Date().toISOString(),\n });\n\n let client: InstanceType<typeof A2AClient> | undefined;\n let lastError: Error = new Error(`A2A agent card not found at ${cardUrls.join(', ')}`);\n for (const cardUrl of cardUrls) {\n try {\n client = await A2AClient.fromCardUrl(cardUrl, { fetchImpl });\n break;\n } catch (err: unknown) {\n lastError = err as Error;\n if (context?.got401Ref.value) break;\n }\n }\n if (!client) throw lastError;\n\n return client;\n}\n\nfunction buildFetchImpl(authToken: string | undefined) {\n // The A2A client is cached per (url, authToken, signingCacheKey). We capture\n // the signing context at client-creation time so all subsequent calls that\n // share this cached client use the same signing identity — changing identity\n // requires a different cache entry, built on a separate call that enters ALS\n // with a different context.\n const signingContext = signingContextStorage.getStore();\n\n // Innermost wrapper: enforce response body size cap from the active\n // `responseSizeLimitStorage` slot. Pass-through when no slot is set.\n const networkFetch = wrapFetchWithTransportDiagnostics(\n wrapFetchWithSizeLimit((input, init) => fetch(input as any, init))\n );\n\n // Inner fetch handles auth/header injection and 401 detection. If the\n // agent has request-signing configured, we wrap it with the AdCP signing\n // fetch so the signature covers the exact bytes we're about to send (auth\n // headers included, since the signer re-reads the final header record).\n const baseFetch = async (url: string | URL | Request, options?: RequestInit): Promise<Response> => {\n const context = callContextStorage.getStore();\n\n const existingHeaders: Record<string, string> = {};\n if (options?.headers) {\n if (options.headers instanceof Headers) {\n options.headers.forEach((value, key) => {\n existingHeaders[key] = value;\n });\n } else if (Array.isArray(options.headers)) {\n for (const [key, value] of options.headers) {\n existingHeaders[key] = value;\n }\n } else {\n Object.assign(existingHeaders, options.headers);\n }\n }\n\n // Only inject trace context headers for actual tool requests, not discovery.\n // The agent card endpoint is external/untrusted — don't leak trace IDs to it.\n const urlString = typeof url === 'string' ? url : url.toString();\n const isDiscoveryRequest = isAgentCardPath(urlString);\n const traceHeaders = isDiscoveryRequest ? {} : injectTraceHeaders();\n const requestTimeoutMs = isDiscoveryRequest\n ? resolveRequestTimeoutMs(context?.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS)\n : resolveRequestTimeoutMs(context?.requestTimeoutMs);\n\n // Merge: existing < trace < custom < auth (auth always wins)\n const headers: Record<string, string> = {\n ...existingHeaders,\n ...traceHeaders,\n ...context?.customHeaders,\n ...(authToken && {\n Authorization: `Bearer ${authToken}`,\n 'x-adcp-auth': authToken,\n }),\n };\n\n context?.debugLogs.push({\n type: 'info',\n message: `A2A: Fetch to ${urlString}`,\n timestamp: new Date().toISOString(),\n hasAuth: !!authToken,\n headers: redactHeadersForDebug(headers),\n });\n\n const response = await withAbortSignal<Response>([context?.signal, options?.signal], requestTimeoutMs, signal =>\n networkFetch(url as any, { ...options, headers, signal })\n );\n\n if (response.status === 401 && context) {\n context.got401Ref.value = true;\n }\n\n return response;\n };\n\n if (!signingContext) return wrapFetchWithCapture(baseFetch);\n\n // The signing wrapper assembles headers into the signature base. We invoke\n // it first so the signer sees the caller-supplied headers; baseFetch then\n // overlays auth/trace headers afterwards — A2A's auth scheme (bearer) is\n // not among the MANDATORY_COMPONENTS and is injected by the counterparty's\n // transport layer, not signed.\n const signingFetch = buildAgentSigningFetch({\n upstream: (input, init) => baseFetch(input as any, init),\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n });\n return wrapFetchWithCapture(signingFetch as typeof fetch);\n}\n\n/**\n * Terminal A2A task states per A2A 0.3.0 §3.4. Only these can carry the\n * AdCP-mandated artifact + DataPart envelope (per transport-errors §A2A\n * Binding); intermediate states (`working`, `submitted`, `input-required`,\n * `auth-required`) carry no completion artifact.\n */\nconst TERMINAL_A2A_STATES = new Set(['completed', 'failed', 'rejected', 'canceled']);\n\n/**\n * Detect whether a JSON-RPC response carries a spec-compliant terminal-state\n * Task with at least one artifact containing a structured DataPart payload.\n * Per AdCP transport-errors §A2A Binding, the artifact's DataPart is the\n * canonical envelope for both the success arm (`completed`) and the error\n * arms (`failed` / `rejected` / `canceled`). The criterion intentionally\n * matches the unwrapper's terminal-state extraction in\n * `unwrapA2AResponse` — keeping protocol layer and unwrapper in lockstep\n * across all terminal states, not just the error arms.\n *\n * Used to short-circuit the generic \"A2A agent returned error\" throw when\n * a non-conformant seller surfaces both a transport-level `result.error`\n * hint and the canonical artifact envelope side-by-side. The DataPart is\n * authoritative; the throw would otherwise swallow it.\n */\nfunction hasTerminalTaskWithDataArtifact(response: unknown): boolean {\n if (!response || typeof response !== 'object') return false;\n const result = (response as { result?: unknown }).result;\n if (!result || typeof result !== 'object') return false;\n const r = result as { kind?: unknown; status?: unknown; artifacts?: unknown };\n if (r.kind !== 'task') return false;\n const status = r.status as { state?: unknown } | undefined;\n if (typeof status?.state !== 'string' || !TERMINAL_A2A_STATES.has(status.state)) return false;\n return getLatestA2ADataPartFromResponse(response) !== undefined;\n}\n\n/**\n * Protocol-level session identifiers that ride on the A2A Message envelope\n * (not in the skill parameters). `contextId` binds sends to a server-side\n * conversation; `taskId` resumes an existing non-terminal task.\n *\n * Callers (buyers) typically retain these across calls on a per-conversation\n * AgentClient; see AgentClient.getContextId() / getPendingTaskId().\n */\nexport interface A2ASessionIds {\n contextId?: string;\n taskId?: string;\n}\n\nexport async function callA2ATool(\n agentUrl: string,\n toolName: string,\n parameters: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n pushNotificationConfig?: PushNotificationConfig,\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n session?: A2ASessionIds,\n signal?: AbortSignal,\n requestTimeoutMs?: number\n): Promise<unknown> {\n return withSpan(\n 'adcp.a2a.call_tool',\n {\n 'adcp.tool': toolName,\n 'http.url': agentUrl,\n },\n async () => {\n const context: A2ACallContext = {\n customHeaders,\n debugLogs,\n got401Ref: { value: false },\n signal,\n requestTimeoutMs,\n };\n return signingContextStorage.run(signingContext, () =>\n callContextStorage.run(context, () =>\n callA2AToolImpl(\n agentUrl,\n toolName,\n parameters,\n authToken,\n debugLogs,\n pushNotificationConfig,\n context,\n session\n )\n )\n );\n }\n );\n}\n\nasync function callA2AToolImpl(\n agentUrl: string,\n toolName: string,\n parameters: Record<string, unknown>,\n authToken: string | undefined,\n debugLogs: DebugLogEntry[],\n pushNotificationConfig: PushNotificationConfig | undefined,\n context: A2ACallContext,\n session: A2ASessionIds | undefined\n): Promise<unknown> {\n try {\n const client = await getOrCreateA2AClient(\n agentUrl,\n authToken,\n context.customHeaders,\n !!context.signal || context.requestTimeoutMs !== undefined\n );\n\n const requestPayload: {\n message: {\n messageId: string;\n role: string;\n kind: string;\n parts: Array<{ kind: string; data: { skill: string; parameters: Record<string, unknown> } }>;\n contextId?: string;\n taskId?: string;\n };\n configuration?: { pushNotificationConfig: PushNotificationConfig };\n } = {\n message: {\n messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n role: 'user',\n kind: 'message',\n parts: [\n {\n kind: 'data',\n data: {\n skill: toolName,\n parameters: parameters,\n },\n },\n ],\n ...(session?.contextId && { contextId: session.contextId }),\n ...(session?.taskId && { taskId: session.taskId }),\n },\n };\n\n if (pushNotificationConfig) {\n requestPayload.configuration = {\n pushNotificationConfig: pushNotificationConfig,\n };\n }\n\n const payloadSize = JSON.stringify(requestPayload).length;\n const redactedParameters = redactIdempotencyKeyInArgs(parameters);\n const redactedPayload = {\n ...requestPayload,\n message: {\n ...requestPayload.message,\n parts: [\n {\n kind: 'data',\n data: { skill: toolName, parameters: redactedParameters },\n },\n ],\n },\n ...(requestPayload.configuration && {\n configuration: {\n pushNotificationConfig: redactPushNotificationConfigForDebug(\n requestPayload.configuration.pushNotificationConfig\n )!,\n },\n }),\n };\n debugLogs.push({\n type: 'info',\n message: `A2A: Calling skill ${toolName} with parameters: ${JSON.stringify(\n redactedParameters\n )}. Payload size: ${payloadSize} bytes`,\n timestamp: new Date().toISOString(),\n payloadSize,\n actualPayload: redactedPayload,\n });\n\n debugLogs.push({\n type: 'info',\n message: `A2A: Sending message via sendMessage()`,\n timestamp: new Date().toISOString(),\n skill: toolName,\n });\n\n const messageResponse = await client.sendMessage(requestPayload);\n\n debugLogs.push({\n type: messageResponse?.error ? 'error' : 'success',\n message: `A2A: Response received (${messageResponse?.error ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: messageResponse,\n skill: toolName,\n });\n\n if (messageResponse?.error || messageResponse?.result?.error) {\n // adcp-client#1575: when the seller emits a spec-compliant terminal-state\n // Task carrying an `adcp_error` DataPart (per AdCP transport-errors §A2A\n // Binding), the structured artifact is canonical — even if the seller\n // also surfaced a transport-level error string. Pass the response\n // through so the upstream unwrapper extracts `adcp_error.code` instead\n // of throwing a generic message that loses the AdCP error envelope.\n if (!hasTerminalTaskWithDataArtifact(messageResponse)) {\n const errorObj = messageResponse.error || messageResponse.result?.error;\n const errorMessage = errorObj.message || JSON.stringify(errorObj);\n throw new Error(`A2A agent returned error: ${errorMessage}`);\n }\n }\n\n return messageResponse;\n } catch (error: unknown) {\n if (is401Error(error, context.got401Ref.value)) {\n // Evict this cache entry — credential may have expired or been\n // revoked. Same disambiguator as the original `getOrCreateA2AClient`\n // call: when the credential rode on customHeaders.Authorization (Basic\n // case) rather than authToken, the cache key must reflect that or we\n // evict the wrong entry.\n const signingContext = signingContextStorage.getStore();\n a2aClientCache.delete(a2aCacheKey(agentUrl, authToken, signingContext?.cacheKey, context.customHeaders));\n\n debugLogs.push({\n type: 'error',\n message: `A2A: Authentication required for ${agentUrl}`,\n timestamp: new Date().toISOString(),\n });\n\n // Re-probe to surface the WWW-Authenticate scheme on the error envelope.\n // Basic-fronted agents (Apigee/Kong/AWS API GW with a BasicAuthentication\n // policy) would otherwise leave consumers chasing OAuth metadata that\n // doesn't exist. Matches the MCP discovery throw site in\n // `SingleAgentClient.discoverMCPEndpoint`.\n const challenge = await probeAuthChallenge(agentUrl);\n const oauthMetadata = await discoverOAuthMetadata(agentUrl);\n throw new AuthenticationRequiredError(agentUrl, oauthMetadata || undefined, undefined, challenge ?? undefined);\n }\n\n throw error;\n }\n}\n"],"mappings":"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","names":["require"]}
@@ -1,3 +1,8 @@
1
+ import { fileURLToPath as __adcpFileURLToPath } from "node:url";
2
+ import { dirname as __adcpDirname } from "node:path";
3
+ import { createRequire as __adcpCreateRequire } from "node:module";
4
+ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
5
+ const require2 = __adcpCreateRequire(import.meta.url);
1
6
  const DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
2
7
  const MAX_TIMER_DELAY_MS = 2147483647;
3
8
  function resolveRequestTimeoutMs(timeoutMs, defaultTimeoutMs) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/protocols/abort.ts"],"sourcesContent":["export const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nexport function resolveRequestTimeoutMs(timeoutMs: number | undefined, defaultTimeoutMs?: number): number | undefined {\n const resolved = timeoutMs ?? defaultTimeoutMs;\n if (resolved == null) return undefined;\n if (resolved === 0) return undefined;\n if (!Number.isFinite(resolved) || resolved < 0 || resolved > MAX_TIMER_DELAY_MS) {\n throw new RangeError(`requestTimeoutMs must be a finite non-negative number <= ${MAX_TIMER_DELAY_MS}`);\n }\n return resolved;\n}\n\nexport function resolveClientRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n if (timeoutMs === 0) return MAX_TIMER_DELAY_MS;\n return resolveRequestTimeoutMs(timeoutMs);\n}\n\nexport function createAbortError(reason?: unknown): Error {\n if (reason instanceof Error && (reason.name === 'AbortError' || reason.name === 'TimeoutError')) return reason;\n const error = new Error(reason == null ? 'The operation was aborted' : String(reason));\n error.name = 'AbortError';\n if (reason instanceof Error) {\n (error as Error & { cause?: unknown }).cause = reason;\n error.message = reason.message;\n }\n return error;\n}\n\nexport function createTimeoutError(timeoutMs: number): Error {\n const error = new Error(`Request timed out after ${timeoutMs} ms`);\n error.name = 'TimeoutError';\n return error;\n}\n\nexport function isAbortOrTimeoutError(error: unknown): boolean {\n if (error == null || typeof error !== 'object') return false;\n const value = error as { name?: unknown; code?: unknown };\n if (value.name === 'AbortError' || value.name === 'TimeoutError') return true;\n // MCP SDK v1 raises JSON-RPC RequestTimeout (-32001); the v2 packages use\n // the typed SDK error code REQUEST_TIMEOUT. Both represent the same\n // timeout/cancellation boundary and must bypass endpoint fallback.\n return value.code === -32001 || value.code === 'REQUEST_TIMEOUT';\n}\n\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) {\n throw createAbortError(signal.reason);\n }\n}\n\nexport async function withAbortSignal<T>(\n signals: Array<AbortSignal | null | undefined>,\n timeoutMs: number | undefined,\n fn: (signal?: AbortSignal) => Promise<T>\n): Promise<T> {\n const activeSignals = signals.filter((signal): signal is AbortSignal => signal != null);\n for (const signal of activeSignals) {\n throwIfAborted(signal);\n }\n\n if (timeoutMs == null && activeSignals.length === 0) {\n return fn(undefined);\n }\n\n if (timeoutMs == null && activeSignals.length === 1) {\n const signal = activeSignals[0]!;\n try {\n return await fn(signal);\n } catch (error) {\n if (signal.aborted) {\n throw createAbortError(signal.reason);\n }\n throw error;\n }\n }\n\n const controller = new AbortController();\n const abort = (reason?: unknown) => {\n if (!controller.signal.aborted) {\n controller.abort(reason);\n }\n };\n\n const listeners = activeSignals.map(signal => {\n const listener = () => abort(createAbortError(signal.reason));\n signal.addEventListener('abort', listener, { once: true });\n return { signal, listener };\n });\n const timer =\n timeoutMs == null\n ? undefined\n : setTimeout(() => {\n abort(createTimeoutError(timeoutMs));\n }, timeoutMs);\n\n try {\n return await fn(controller.signal);\n } finally {\n if (timer) clearTimeout(timer);\n for (const { signal, listener } of listeners) {\n signal.removeEventListener('abort', listener);\n }\n }\n}\n"],"mappings":"AAAO,MAAM,6BAA6B;AACnC,MAAM,qBAAqB;AAE3B,SAAS,wBAAwB,WAA+B,kBAA+C;AACpH,QAAM,WAAW,aAAa;AAC9B,MAAI,YAAY,KAAM,QAAO;AAC7B,MAAI,aAAa,EAAG,QAAO;AAC3B,MAAI,CAAC,OAAO,SAAS,QAAQ,KAAK,WAAW,KAAK,WAAW,oBAAoB;AAC/E,UAAM,IAAI,WAAW,4DAA4D,kBAAkB,EAAE;AAAA,EACvG;AACA,SAAO;AACT;AAEO,SAAS,8BAA8B,WAAmD;AAC/F,MAAI,cAAc,EAAG,QAAO;AAC5B,SAAO,wBAAwB,SAAS;AAC1C;AAEO,SAAS,iBAAiB,QAAyB;AACxD,MAAI,kBAAkB,UAAU,OAAO,SAAS,gBAAgB,OAAO,SAAS,gBAAiB,QAAO;AACxG,QAAM,QAAQ,IAAI,MAAM,UAAU,OAAO,8BAA8B,OAAO,MAAM,CAAC;AACrF,QAAM,OAAO;AACb,MAAI,kBAAkB,OAAO;AAC3B,IAAC,MAAsC,QAAQ;AAC/C,UAAM,UAAU,OAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,WAA0B;AAC3D,QAAM,QAAQ,IAAI,MAAM,2BAA2B,SAAS,KAAK;AACjE,QAAM,OAAO;AACb,SAAO;AACT;AAEO,SAAS,sBAAsB,OAAyB;AAC7D,MAAI,SAAS,QAAQ,OAAO,UAAU,SAAU,QAAO;AACvD,QAAM,QAAQ;AACd,MAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,eAAgB,QAAO;AAIzE,SAAO,MAAM,SAAS,UAAU,MAAM,SAAS;AACjD;AAEO,SAAS,eAAe,QAA4B;AACzD,MAAI,QAAQ,SAAS;AACnB,UAAM,iBAAiB,OAAO,MAAM;AAAA,EACtC;AACF;AAEA,eAAsB,gBACpB,SACA,WACA,IACY;AACZ,QAAM,gBAAgB,QAAQ,OAAO,CAAC,WAAkC,UAAU,IAAI;AACtF,aAAW,UAAU,eAAe;AAClC,mBAAe,MAAM;AAAA,EACvB;AAEA,MAAI,aAAa,QAAQ,cAAc,WAAW,GAAG;AACnD,WAAO,GAAG,MAAS;AAAA,EACrB;AAEA,MAAI,aAAa,QAAQ,cAAc,WAAW,GAAG;AACnD,UAAM,SAAS,cAAc,CAAC;AAC9B,QAAI;AACF,aAAO,MAAM,GAAG,MAAM;AAAA,IACxB,SAAS,OAAO;AACd,UAAI,OAAO,SAAS;AAClB,cAAM,iBAAiB,OAAO,MAAM;AAAA,MACtC;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,CAAC,WAAqB;AAClC,QAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,iBAAW,MAAM,MAAM;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,YAAY,cAAc,IAAI,YAAU;AAC5C,UAAM,WAAW,MAAM,MAAM,iBAAiB,OAAO,MAAM,CAAC;AAC5D,WAAO,iBAAiB,SAAS,UAAU,EAAE,MAAM,KAAK,CAAC;AACzD,WAAO,EAAE,QAAQ,SAAS;AAAA,EAC5B,CAAC;AACD,QAAM,QACJ,aAAa,OACT,SACA,WAAW,MAAM;AACf,UAAM,mBAAmB,SAAS,CAAC;AAAA,EACrC,GAAG,SAAS;AAElB,MAAI;AACF,WAAO,MAAM,GAAG,WAAW,MAAM;AAAA,EACnC,UAAE;AACA,QAAI,MAAO,cAAa,KAAK;AAC7B,eAAW,EAAE,QAAQ,SAAS,KAAK,WAAW;AAC5C,aAAO,oBAAoB,SAAS,QAAQ;AAAA,IAC9C;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/protocols/abort.ts"],"sourcesContent":["import { fileURLToPath as __adcpFileURLToPath } from 'node:url';\nimport { dirname as __adcpDirname } from 'node:path';\nimport { createRequire as __adcpCreateRequire } from 'node:module';\nconst __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));\nconst require = __adcpCreateRequire(import.meta.url);\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nexport function resolveRequestTimeoutMs(timeoutMs: number | undefined, defaultTimeoutMs?: number): number | undefined {\n const resolved = timeoutMs ?? defaultTimeoutMs;\n if (resolved == null) return undefined;\n if (resolved === 0) return undefined;\n if (!Number.isFinite(resolved) || resolved < 0 || resolved > MAX_TIMER_DELAY_MS) {\n throw new RangeError(`requestTimeoutMs must be a finite non-negative number <= ${MAX_TIMER_DELAY_MS}`);\n }\n return resolved;\n}\n\nexport function resolveClientRequestTimeoutMs(timeoutMs: number | undefined): number | undefined {\n if (timeoutMs === 0) return MAX_TIMER_DELAY_MS;\n return resolveRequestTimeoutMs(timeoutMs);\n}\n\nexport function createAbortError(reason?: unknown): Error {\n if (reason instanceof Error && (reason.name === 'AbortError' || reason.name === 'TimeoutError')) return reason;\n const error = new Error(reason == null ? 'The operation was aborted' : String(reason));\n error.name = 'AbortError';\n if (reason instanceof Error) {\n (error as Error & { cause?: unknown }).cause = reason;\n error.message = reason.message;\n }\n return error;\n}\n\nexport function createTimeoutError(timeoutMs: number): Error {\n const error = new Error(`Request timed out after ${timeoutMs} ms`);\n error.name = 'TimeoutError';\n return error;\n}\n\nexport function isAbortOrTimeoutError(error: unknown): boolean {\n if (error == null || typeof error !== 'object') return false;\n const value = error as { name?: unknown; code?: unknown };\n if (value.name === 'AbortError' || value.name === 'TimeoutError') return true;\n // MCP SDK v1 raises JSON-RPC RequestTimeout (-32001); the v2 packages use\n // the typed SDK error code REQUEST_TIMEOUT. Both represent the same\n // timeout/cancellation boundary and must bypass endpoint fallback.\n return value.code === -32001 || value.code === 'REQUEST_TIMEOUT';\n}\n\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) {\n throw createAbortError(signal.reason);\n }\n}\n\nexport async function withAbortSignal<T>(\n signals: Array<AbortSignal | null | undefined>,\n timeoutMs: number | undefined,\n fn: (signal?: AbortSignal) => Promise<T>\n): Promise<T> {\n const activeSignals = signals.filter((signal): signal is AbortSignal => signal != null);\n for (const signal of activeSignals) {\n throwIfAborted(signal);\n }\n\n if (timeoutMs == null && activeSignals.length === 0) {\n return fn(undefined);\n }\n\n if (timeoutMs == null && activeSignals.length === 1) {\n const signal = activeSignals[0]!;\n try {\n return await fn(signal);\n } catch (error) {\n if (signal.aborted) {\n throw createAbortError(signal.reason);\n }\n throw error;\n }\n }\n\n const controller = new AbortController();\n const abort = (reason?: unknown) => {\n if (!controller.signal.aborted) {\n controller.abort(reason);\n }\n };\n\n const listeners = activeSignals.map(signal => {\n const listener = () => abort(createAbortError(signal.reason));\n signal.addEventListener('abort', listener, { once: true });\n return { signal, listener };\n });\n const timer =\n timeoutMs == null\n ? undefined\n : setTimeout(() => {\n abort(createTimeoutError(timeoutMs));\n }, timeoutMs);\n\n try {\n return await fn(controller.signal);\n } finally {\n if (timer) clearTimeout(timer);\n for (const { signal, listener } of listeners) {\n signal.removeEventListener('abort', listener);\n }\n }\n}\n"],"mappings":"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","names":["require"]}
@@ -1,3 +1,8 @@
1
+ import { fileURLToPath as __adcpFileURLToPath } from "node:url";
2
+ import { dirname as __adcpDirname } from "node:path";
3
+ import { createRequire as __adcpCreateRequire } from "node:module";
4
+ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
5
+ const require2 = __adcpCreateRequire(import.meta.url);
1
6
  import {
2
7
  callMCPTool,
3
8
  callMCPToolWithOAuth,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/protocols/index.ts"],"sourcesContent":["// Unified Protocol Interface for AdCP\nexport {\n callMCPTool,\n callMCPToolWithOAuth,\n connectMCP,\n closeMCPConnections,\n closeOAuthConnections,\n UnauthorizedError,\n} from './mcp';\n\nimport { closeMCPConnections } from './mcp';\nimport { closeA2AConnections } from './a2a';\n\n/**\n * Close protocol connections for the given protocol.\n * MCP closes persistent HTTP transports; A2A clears the agent-card client cache.\n */\nexport async function closeConnections(protocol: 'mcp' | 'a2a' = 'mcp'): Promise<void> {\n if (protocol === 'mcp') {\n await closeMCPConnections();\n } else {\n closeA2AConnections();\n }\n}\nexport type { MCPCallOptions, MCPConnectionResult } from './mcp';\nexport { callA2ATool } from './a2a';\nexport { DEFAULT_REQUEST_TIMEOUT_MS } from './abort';\nexport {\n callMCPToolWithTasks,\n getMCPTaskStatus,\n getMCPTaskResult,\n listMCPTasks,\n cancelMCPTask,\n mapMCPTaskStatus,\n serverSupportsTasks,\n} from './mcp-tasks';\n\nimport { callMCPToolWithTasks, callMCPToolWithClient } from './mcp-tasks';\nimport { callMCPToolWithOAuth } from './mcp';\nimport { callA2ATool } from './a2a';\nimport type { AgentConfig, DebugLogEntry } from '../types';\nimport type { PushNotificationConfig } from '../types/tools.generated';\nimport { getAuthToken } from '../auth';\nimport {\n createNonInteractiveOAuthProvider,\n discoverAuthorizationRequirements,\n NeedsAuthorizationError,\n getAgentStorage,\n ensureClientCredentialsTokens,\n} from '../auth/oauth';\nimport { is401Error } from '../errors';\nimport { isLikelyPrivateUrl } from '../net';\nimport { validateAgentUrl } from '../validation';\nimport { withSpan } from '../observability/tracing';\nimport { ADCP_MAJOR_VERSION, ADCP_VERSION, parseAdcpMajorVersion } from '../version';\nimport { ConfigurationError } from '../errors';\nimport { resolveBundleKey, toReleasePrecisionWire, validateAdcpVersionWire } from '../validation/schema-loader';\nimport { buildAgentSigningContext, CAPABILITY_OP, ensureCapabilityLoaded } from '../signing/client';\nimport { withResponseSizeLimit } from './responseSizeLimit';\nimport {\n withTransportDiagnostics,\n type TransportActivityHandler as TransportActivityHandlerFn,\n} from './transportDiagnostics';\n\nexport {\n sanitizeTransportHeaders,\n sanitizeTransportUrl,\n withTransportDiagnostics,\n wrapFetchWithTransportDiagnostics,\n} from './transportDiagnostics';\nexport type { TransportActivity, TransportActivityContext, TransportActivityHandler } from './transportDiagnostics';\n\nexport type VersionEnvelopeMode = 'auto' | 'none' | 'major-only';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<\n AgentConfig,\n ReturnType<typeof createNonInteractiveOAuthProvider>\n>();\n\nfunction getNonInteractiveOAuthProvider(agent: AgentConfig): ReturnType<typeof createNonInteractiveOAuthProvider> {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n const storage = getAgentStorage(agent);\n provider = createNonInteractiveOAuthProvider(agent, {\n agentHint: agent.id,\n storage,\n });\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/**\n * Derive the wire-level `adcp_major_version` integer from a caller-supplied\n * pin. Returns the SDK default when no pin is provided; throws on a pin\n * that doesn't parse so misuse surfaces at the factory boundary instead\n * of silently emitting the SDK's major.\n *\n * Throws `ConfigurationError` (not a plain `Error`) so a typo'd pin\n * surfaces with the same error class as the construction-time gate in\n * `resolveAdcpVersion` — one shape for all pin-misuse paths.\n */\nfunction resolveWireMajor(adcpVersion: string | undefined): number {\n if (adcpVersion === undefined) return ADCP_MAJOR_VERSION;\n const parsed = parseAdcpMajorVersion(adcpVersion);\n if (!Number.isFinite(parsed)) {\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} is not a valid AdCP version. ` +\n `Expected a semver string (e.g. '3.0.1', '3.1.0-beta.1') or a legacy alias (e.g. 'v3').`,\n 'adcpVersion'\n );\n }\n return parsed;\n}\n\n/**\n * Returns true when the AdCP release that `bundleKey` identifies declares the\n * top-level `adcp_version` envelope field. The field landed in AdCP 3.1 per\n * spec PR `adcontextprotocol/adcp#3493` — 3.0 (any patch / prerelease) does\n * not carry it; 3.1+ does. Used to gate dual-emit on the wire so a 3.0-pinned\n * client doesn't emit a field its target schema doesn't define.\n */\nexport function bundleSupportsAdcpVersionField(bundleKey: string): boolean {\n const major = parseAdcpMajorVersion(bundleKey);\n if (!Number.isFinite(major)) return false;\n if (major < 3) return false;\n if (major > 3) return true;\n // Major 3 — only 3.1+ has the field. Bundle key shape is normalized by\n // `resolveBundleKey`: `'3.0'` / `'3.1'` for stable; `'3.0.0-beta.1'` /\n // `'3.1.0-beta.1'` for prereleases. Match the minor.\n const minorMatch = bundleKey.match(/^\\d+\\.(\\d+)/);\n if (!minorMatch) return false;\n return parseInt(minorMatch[1]!, 10) >= 1;\n}\n\n/**\n * Build the wire-level version envelope to merge into outgoing request args.\n *\n * Per AdCP 3.1 (spec PR `adcontextprotocol/adcp#3493`), 3.1+ requests carry\n * BOTH the integer `adcp_major_version` (deprecated through 3.x, removed in\n * 4.0) AND the release-precision string `adcp_version`. 3.0 schemas don't\n * define the string field, so a 3.0-pinned client emits the integer only —\n * matches the 3.0 spec exactly.\n *\n * Wire string is release-precision (MAJOR.MINOR with optional prerelease tag),\n * per `core/version-envelope.json`'s pattern `^\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$`.\n * Full-semver bundle keys (`'3.1.0-beta.1'`) are collapsed via\n * `toReleasePrecisionWire` to `'3.1-beta.1'` before emit — meta-field shapes\n * are explicitly NOT valid wire values per the envelope schema's own\n * normalization rule.\n *\n * Returns `{}` for v2 callers (predates the major-version field entirely).\n */\nfunction buildVersionEnvelope(\n adcpVersion: string | undefined,\n serverVersion: 'v2' | 'v3' | undefined\n): Record<string, unknown> {\n if (serverVersion === 'v2') return {};\n const wireMajor = resolveWireMajor(adcpVersion);\n const bundleKey = resolveBundleKey(adcpVersion ?? ADCP_VERSION);\n if (!bundleSupportsAdcpVersionField(bundleKey)) {\n return { adcp_major_version: wireMajor };\n }\n const wireValue = toReleasePrecisionWire(bundleKey);\n // Defensive postcondition — should never throw in well-formed code, but\n // if a future refactor breaks the normalization the error message tells\n // the developer to call `toReleasePrecisionWire` instead of silently\n // emitting a non-spec wire string.\n validateAdcpVersionWire(wireValue);\n return { adcp_major_version: wireMajor, adcp_version: wireValue };\n}\n\nfunction buildVersionEnvelopeForMode(\n mode: VersionEnvelopeMode,\n adcpVersion: string | undefined,\n serverVersion: 'v2' | 'v3' | undefined\n): Record<string, unknown> {\n if (mode === 'none' || serverVersion === 'v2') return {};\n if (mode === 'major-only') return { adcp_major_version: resolveWireMajor(adcpVersion) };\n return buildVersionEnvelope(adcpVersion, serverVersion);\n}\n\n/**\n * Merge the wire-level version envelope into a caller-supplied args object.\n * Caller args win: an explicit `adcp_major_version` / `adcp_version` in\n * `args` (e.g. a conformance harness probing `VERSION_UNSUPPORTED`) passes\n * through unchanged. The envelope only fills fields the caller didn't set.\n *\n * Single chokepoint for all four wire-injection sites so a future refactor\n * can't silently flip the spread order on one branch and leave the others\n * intact. Stale dual-field drift is caught at the server boundary by\n * `createAdcpServer`'s field-disagreement check (spec PR\n * `adcontextprotocol/adcp#3493`).\n *\n * @internal\n */\nexport function applyVersionEnvelope(\n args: Record<string, unknown>,\n envelope: Record<string, unknown>\n): Record<string, unknown> {\n return { ...envelope, ...args };\n}\n\n/**\n * Transport-level safeguards applied to a call.\n *\n * Wired into the SDK's internal fetch chain via AsyncLocalStorage, so the\n * cap takes effect even when the underlying transport's connection cache\n * reuses a fetch that was created on an earlier call with different limits.\n */\nexport interface TransportOptions {\n /**\n * Maximum response body size (in octets) the SDK will read before aborting\n * with `ResponseTooLargeError`. When unset, the SDK does not impose a cap —\n * matches the underlying MCP / A2A transport defaults.\n *\n * Set this when crawling **untrusted** agents (registries, federated\n * discovery layers, monitoring tools) to prevent a hostile vendor from\n * buffering a large reply before any application-layer schema validation\n * runs. Counted across response chunks; pre-cancels when `Content-Length`\n * exceeds the cap. Applies to A2A agent-card discovery\n * (`/.well-known/agent.json`) on the same call as well.\n *\n * Per-call override (`TaskOptions.transport.maxResponseBytes`) beats the\n * value set on the client constructor (`SingleAgentClientConfig.transport`).\n *\n * @remarks\n * **Safe to set on all calls.** SSE responses (`text/event-stream`) are\n * passed through unchanged — a single tool call legitimately emits N status\n * frames + a final result, bounded by protocol-level framing rather than\n * cumulative byte counts. The cap applies to one-shot JSON responses\n * (`get_adcp_capabilities`, agent-card lookup, tool result payloads on\n * non-streaming transports) where the body is bounded by definition.\n *\n * @remarks\n * **Hostile-peer note:** A peer can opt itself out of this cap by responding\n * with `Content-Type: text/event-stream`. SSE is bypassed because cumulative\n * event-frame bytes are unbounded by spec — MCP and A2A both stream tool\n * responses this way. The MCP/A2A SDKs consume SSE incrementally and frame\n * termination bounds memory in practice, so this is not a memory-bomb risk\n * for well-formed transports. Adopters relying on `maxResponseBytes` as a\n * hostile-server defense should treat it as best-effort for non-SSE\n * responses only.\n *\n * @remarks\n * Future hardening knobs (DNS-rebind defense, scheme allow-list, request\n * timeout overrides) will land here as additional fields rather than\n * forcing callers to compose their own `fetch` — wrap order with the SDK's\n * existing signing / capture wrappers is non-obvious and a footgun.\n */\n maxResponseBytes?: number;\n /**\n * Timeout in milliseconds for bounded one-shot transport requests such as\n * A2A agent-card discovery and MCP read-path probes. Defaults to 60 seconds\n * for A2A discovery so an unresponsive card endpoint cannot hang forever.\n * Set to `0` to disable the SDK-imposed discovery timeout.\n */\n requestTimeoutMs?: number;\n}\n\n/**\n * Options for {@link ProtocolClient.callTool}. All fields are optional.\n *\n * `webhookUrl` / `webhookSecret` / `webhookToken` are for ASYNC TASK STATUS\n * notifications (push_notification_config). For reporting webhooks\n * (reporting_webhook), include them directly in `args` — they stay in skill\n * parameters and are sent verbatim to the agent.\n */\nexport interface CallToolOptions {\n /** Debug log array. Mutated in place by the protocol layer. */\n debugLogs?: DebugLogEntry[];\n /** URL for async task status notifications. */\n webhookUrl?: string;\n /** HMAC-SHA256 secret for push_notification_config authentication. */\n webhookSecret?: string;\n /** Bearer token for push_notification_config validation. */\n webhookToken?: string;\n /** Pinned protocol generation when the agent advertises both v2 and v3. */\n serverVersion?: 'v2' | 'v3';\n /** A2A session continuity (contextId carries conversation, taskId resumes a task). */\n session?: { contextId?: string; taskId?: string };\n /**\n * AdCP version pin from the calling client/server instance. Sets the\n * wire-level `adcp_major_version` field per-call instead of from the\n * SDK-pinned `ADCP_MAJOR_VERSION` constant. Default falls back to the\n * constant so call sites that don't plumb a per-instance version keep\n * their existing behavior. An explicit `adcp_major_version` /\n * `adcp_version` in `args` overrides this — conformance harnesses use\n * that path to probe seller version negotiation.\n */\n adcpVersion?: string;\n /**\n * Optional wire-only version override. Schema selection and client\n * construction can remain pinned to `adcpVersion`; the request envelope is\n * emitted for this release-precision line.\n */\n wireAdcpVersion?: string;\n /**\n * Controls whether the SDK injects AdCP version envelope fields into the\n * outgoing request. Defaults to `auto`. 3.0 pins emit only the legacy\n * `adcp_major_version`; 3.1+ pins emit both the legacy major and exact\n * `adcp_version` marker. `major-only` forces the legacy integer marker\n * without the 3.1 string marker for strict pre-3.1 peers discovered at\n * runtime.\n */\n versionEnvelope?: VersionEnvelopeMode;\n /**\n * Transport-level safeguards (size caps, etc.). Per-call override of any\n * matching field on the client constructor's `transport` option.\n */\n transport?: TransportOptions;\n /** Caller-owned cancellation signal for the in-flight protocol call. */\n signal?: AbortSignal;\n /** Transport-level diagnostics callback for outbound HTTP requests. */\n onTransportActivity?: TransportActivityHandlerFn;\n /**\n * Correlation metadata attached to transport diagnostics events emitted\n * while this protocol call is active.\n */\n transportActivityContext?: {\n operationId?: string;\n taskId?: string;\n contextId?: string;\n idempotencyKey?: string;\n };\n}\n\n/**\n * Universal protocol client - automatically routes to the correct protocol implementation\n */\nexport class ProtocolClient {\n /**\n * Call a tool on an agent using the appropriate protocol.\n *\n * @param agent - Agent configuration\n * @param toolName - Name of the tool/skill to call\n * @param args - Tool arguments (includes reporting_webhook if needed - NOT removed)\n * @param options - Optional call-level configuration. See {@link CallToolOptions}.\n */\n static async callTool(\n agent: AgentConfig,\n toolName: string,\n args: Record<string, unknown>,\n options: CallToolOptions = {}\n ): Promise<unknown> {\n const {\n debugLogs = [],\n webhookUrl,\n webhookSecret,\n webhookToken,\n serverVersion,\n session,\n adcpVersion,\n wireAdcpVersion,\n versionEnvelope: versionEnvelopeMode = 'auto',\n transport,\n signal,\n onTransportActivity,\n transportActivityContext,\n } = options;\n // Per-instance version envelope. Throws on unparseable pins via\n // `resolveWireMajor`; construction-time `resolveAdcpVersion` is the\n // primary gate but this is the failsafe for callers reaching\n // `ProtocolClient.callTool` directly (test harnesses, the in-process\n // MCP path). Returns `{ adcp_major_version }` for 3.0 pins and\n // `{ adcp_major_version, adcp_version }` for 3.1+ pins.\n const versionEnvelope = buildVersionEnvelopeForMode(\n versionEnvelopeMode,\n wireAdcpVersion ?? adcpVersion,\n serverVersion\n );\n // Enter the response-size-limit ALS slot once for this call. The slot is\n // read by `wrapFetchWithSizeLimit` in both protocol transports, so the\n // cap applies regardless of which path (MCP / A2A / OAuth refresh) the\n // call ends up taking. No-op when the cap is unset or non-positive.\n return withResponseSizeLimit(transport?.maxResponseBytes, () =>\n withTransportDiagnostics(\n {\n agentId: agent.id,\n protocol: agent.protocol,\n tool: toolName,\n taskType: toolName,\n ...transportActivityContext,\n onTransportActivity,\n },\n () =>\n withSpan(\n `adcp.${agent.protocol}.call_tool`,\n {\n 'adcp.agent_id': agent.id,\n 'adcp.protocol': agent.protocol,\n 'adcp.tool': toolName,\n 'http.url': agent.agent_uri,\n },\n async () => {\n // In-process MCP path: pre-connected client, no HTTP transport.\n // Idempotency injection, schema validation, and governance middleware all\n // still apply (they run in SingleAgentClient above this call). We skip\n // URL validation, OAuth refresh, and signing — none apply in-process.\n if (agent.protocol === 'mcp' && agent._inProcessMcpClient) {\n const inProcArgs = applyVersionEnvelope(args, versionEnvelope);\n return callMCPToolWithClient(agent._inProcessMcpClient, toolName, inProcArgs, debugLogs, {\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n });\n }\n\n validateAgentUrl(agent.agent_uri);\n\n // OAuth 2.0 client credentials (RFC 6749 §4.4): re-exchange the\n // secret for a fresh access token whenever the cached one is within\n // its expiration skew. Runs before every call so mid-session expiry\n // can't leave the caller with a stale bearer. No-op if the agent\n // doesn't declare client credentials. Cheap on warm cache (single\n // `Date.now()` compare); a single POST to the token endpoint on miss.\n //\n // `allowPrivateIp` inherits the trust the caller already placed in\n // `agent.agent_uri` — if they're making a call to a private-IP agent,\n // they've authorized this process to talk to private-IP hosts, so\n // the token endpoint on the same network is reachable too. Public\n // agent URLs with private-IP token endpoints still require an\n // explicit opt-in via the library API.\n if (agent.oauth_client_credentials) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, allowPrivateIp });\n }\n\n const authToken = getAuthToken(agent);\n\n // RFC 9421 signing context. Built once per call and passed through\n // to each protocol-layer entry (`callMCPToolWithTasks`, `callA2ATool`,\n // `callMCPToolWithOAuth`) — those entries seed `signingContextStorage`\n // (AsyncLocalStorage) so the internal transport helpers read it\n // without an explicit parameter. Keep the explicit arg here: it's the\n // ALS seed, not incidental plumbing. `get_adcp_capabilities` is\n // exempt from signing (it's the discovery call itself) and also\n // triggers cache priming for any other op on agents with\n // `request_signing` configured.\n const signingContext = buildAgentSigningContext(agent);\n if (signingContext && toolName !== CAPABILITY_OP) {\n await ensureCapabilityLoaded(agent, signingContext, primeArgs =>\n ProtocolClient.callTool(agent, CAPABILITY_OP, primeArgs, {\n debugLogs,\n serverVersion,\n adcpVersion,\n ...(versionEnvelopeMode !== 'auto' && { versionEnvelope: versionEnvelopeMode }),\n transport,\n signal,\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n onTransportActivity,\n transportActivityContext,\n })\n );\n }\n\n // Inject the version envelope on every request so sellers can validate\n // compatibility. Skip for v2 servers — they don't recognise the\n // version fields and strict-schema agents reject them. The envelope\n // shape is per-pin: 3.0 pins get the integer `adcp_major_version`\n // alone; 3.1+ pins get both that and the release-precision string\n // `adcp_version` (`'3.1'` / `'3.1.0-beta.1'`) per spec PR\n // `adcontextprotocol/adcp#3493`.\n const argsWithVersion = applyVersionEnvelope(args, versionEnvelope);\n\n // Build push_notification_config for ASYNC TASK STATUS notifications\n // (NOT for reporting_webhook - that stays in args)\n // Schema: https://adcontextprotocol.org/schemas/v1/core/push-notification-config.json\n const pushNotificationConfig: PushNotificationConfig | undefined = webhookUrl\n ? {\n url: webhookUrl,\n ...(webhookToken && { token: webhookToken }),\n authentication: {\n schemes: ['HMAC-SHA256'],\n credentials: webhookSecret || 'placeholder_secret_min_32_characters_required',\n },\n }\n : undefined;\n\n if (agent.protocol === 'mcp') {\n // For MCP, include push_notification_config in tool arguments (MCP spec)\n const argsWithWebhook = pushNotificationConfig\n ? { ...argsWithVersion, push_notification_config: pushNotificationConfig }\n : argsWithVersion;\n\n // If the agent config carries authorization-code OAuth tokens,\n // route through the OAuth provider path so the MCP SDK can refresh\n // on 401 instead of hard-failing. Excludes client-credentials\n // agents: they have a cached access token but no refresh_token,\n // and their refresh path is a secret re-exchange (handled above),\n // not the SDK's refresh_token grant.\n if (agent.oauth_tokens && !agent.oauth_client_credentials) {\n const authProvider = getNonInteractiveOAuthProvider(agent);\n try {\n return await callMCPToolWithOAuth({\n agentUrl: agent.agent_uri,\n toolName,\n args: argsWithWebhook,\n authProvider,\n debugLogs,\n customHeaders: agent.headers,\n signingContext,\n signal,\n requestTimeoutMs: transport?.requestTimeoutMs,\n });\n } catch (err) {\n // Refresh failed or server rejected the refreshed token — walk the\n // discovery chain so the caller can distinguish \"re-auth needed\"\n // from other failure modes.\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n }\n\n // Use callMCPToolWithTasks which auto-detects server tasks capability\n // and falls back to standard callTool when tasks are not supported\n try {\n return await callMCPToolWithTasks(\n agent.agent_uri,\n toolName,\n argsWithWebhook,\n authToken,\n debugLogs,\n agent.headers,\n {\n ...(signingContext && { signingContext }),\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: transport.requestTimeoutMs,\n }),\n }\n );\n } catch (err) {\n // Client-credentials agents: on 401, the AS may have rotated\n // something out-of-band. Force a fresh exchange and retry once\n // before surfacing the error. Bounded (single retry) so we don't\n // loop if the credentials are genuinely wrong.\n if (agent.oauth_client_credentials && is401Error(err)) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, force: true, allowPrivateIp });\n const retryAuthToken = agent.oauth_tokens?.access_token ?? authToken;\n try {\n return await callMCPToolWithTasks(\n agent.agent_uri,\n toolName,\n argsWithWebhook,\n retryAuthToken,\n debugLogs,\n agent.headers,\n {\n ...(signingContext && { signingContext }),\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: transport.requestTimeoutMs,\n }),\n }\n );\n } catch (retryErr) {\n await rethrowAsNeedsAuthorization(retryErr, agent.agent_uri);\n throw retryErr;\n }\n }\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n } else if (agent.protocol === 'a2a') {\n // For A2A, pass pushNotificationConfig separately (not in skill parameters)\n try {\n return await callA2ATool(\n agent.agent_uri,\n toolName,\n argsWithVersion,\n authToken,\n debugLogs,\n pushNotificationConfig,\n agent.headers,\n signingContext,\n session,\n signal,\n transport?.requestTimeoutMs\n );\n } catch (err) {\n // Same single-retry-on-401 for client-credentials agents as the\n // MCP path above. Kept symmetric so A2A CC agents aren't a\n // second-class experience — including the NeedsAuthorizationError\n // rewrap on a retry that still 401s.\n if (agent.oauth_client_credentials && is401Error(err)) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, force: true, allowPrivateIp });\n const retryAuthToken = agent.oauth_tokens?.access_token ?? authToken;\n try {\n return await callA2ATool(\n agent.agent_uri,\n toolName,\n argsWithVersion,\n retryAuthToken,\n debugLogs,\n pushNotificationConfig,\n agent.headers,\n signingContext,\n session,\n signal,\n transport?.requestTimeoutMs\n );\n } catch (retryErr) {\n await rethrowAsNeedsAuthorization(retryErr, agent.agent_uri);\n throw retryErr;\n }\n }\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n } else {\n throw new Error(`Unsupported protocol: ${agent.protocol}`);\n }\n }\n )\n )\n );\n }\n}\n\n/**\n * If `err` looks like a 401 from the MCP transport, probe the agent for a\n * Bearer challenge and throw a {@link NeedsAuthorizationError} carrying\n * walked discovery metadata. If the error isn't a 401 or we can't build a\n * requirements record, return silently so the caller re-throws the original.\n *\n * Keeping this off the hot path: we only probe on error, and the probe is\n * a single unauthenticated `tools/list` POST — no retries, no DNS rebind.\n */\nasync function rethrowAsNeedsAuthorization(err: unknown, agentUrl: string): Promise<void> {\n if (err instanceof NeedsAuthorizationError) throw err;\n if (!is401Error(err)) return;\n\n // If the caller has already connected to the agent URL, they've implicitly\n // trusted it — inherit that trust for the discovery probe so loopback /\n // private-IP development agents work the same way as public ones.\n const allowPrivateIp = isLikelyPrivateUrl(agentUrl);\n\n // discoverAuthorizationRequirements internally catches network failures and\n // returns null rather than throwing — anything that escapes is a genuine\n // bug we want to surface rather than mask the 401 with.\n const requirements = await discoverAuthorizationRequirements(agentUrl, { allowPrivateIp });\n if (requirements) {\n throw new NeedsAuthorizationError(requirements);\n }\n // No requirements walked; let the caller re-throw the original error.\n}\n\n/**\n * Simple factory functions for protocol-specific clients.\n *\n * Both factories accept a `transport` argument that flows through to the\n * size-cap surface so callers reaching the factory exports honor the same\n * `maxResponseBytes` contract as `ProtocolClient.callTool`. Without it,\n * the factories would silently bypass the cap, which the public API\n * (`TransportOptions`) implies they honor.\n */\nexport const createMCPClient = (\n agentUrl: string,\n authToken?: string,\n headers?: Record<string, string>,\n serverVersion?: 'v2' | 'v3',\n adcpVersion?: string,\n transport?: TransportOptions,\n versionEnvelopeMode: VersionEnvelopeMode = 'auto'\n) => {\n // Validate the pin at factory time so a typo surfaces here rather than at\n // first call. `buildVersionEnvelope` throws via `resolveWireMajor` on bad\n // input — call it once to surface, then close over the envelope.\n const versionEnvelope = buildVersionEnvelopeForMode(versionEnvelopeMode, adcpVersion, serverVersion);\n return {\n callTool: (toolName: string, args: Record<string, unknown>, debugLogs?: DebugLogEntry[]) =>\n withResponseSizeLimit(transport?.maxResponseBytes, () =>\n callMCPToolWithTasks(\n agentUrl,\n toolName,\n applyVersionEnvelope(args, versionEnvelope),\n authToken,\n debugLogs,\n headers,\n {\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n }\n )\n ),\n };\n};\n\nexport const createA2AClient = (\n agentUrl: string,\n authToken?: string,\n headers?: Record<string, string>,\n serverVersion?: 'v2' | 'v3',\n adcpVersion?: string,\n transport?: TransportOptions,\n versionEnvelopeMode: VersionEnvelopeMode = 'auto'\n) => {\n const versionEnvelope = buildVersionEnvelopeForMode(versionEnvelopeMode, adcpVersion, serverVersion);\n return {\n callTool: (toolName: string, parameters: Record<string, unknown>, debugLogs?: DebugLogEntry[]) =>\n withResponseSizeLimit(transport?.maxResponseBytes, () =>\n callA2ATool(\n agentUrl,\n toolName,\n applyVersionEnvelope(parameters, versionEnvelope),\n authToken,\n debugLogs,\n undefined,\n headers,\n undefined,\n undefined,\n undefined,\n transport?.requestTimeoutMs\n )\n ),\n };\n};\n"],"mappings":"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","names":["closeMCPConnections","callMCPToolWithTasks","callMCPToolWithOAuth","callA2ATool","withTransportDiagnostics"]}
1
+ {"version":3,"sources":["../../../src/lib/protocols/index.ts"],"sourcesContent":["import { fileURLToPath as __adcpFileURLToPath } from 'node:url';\nimport { dirname as __adcpDirname } from 'node:path';\nimport { createRequire as __adcpCreateRequire } from 'node:module';\nconst __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));\nconst require = __adcpCreateRequire(import.meta.url);\n// Unified Protocol Interface for AdCP\nexport {\n callMCPTool,\n callMCPToolWithOAuth,\n connectMCP,\n closeMCPConnections,\n closeOAuthConnections,\n UnauthorizedError,\n} from './mcp';\n\nimport { closeMCPConnections } from './mcp';\nimport { closeA2AConnections } from './a2a';\n\n/**\n * Close protocol connections for the given protocol.\n * MCP closes persistent HTTP transports; A2A clears the agent-card client cache.\n */\nexport async function closeConnections(protocol: 'mcp' | 'a2a' = 'mcp'): Promise<void> {\n if (protocol === 'mcp') {\n await closeMCPConnections();\n } else {\n closeA2AConnections();\n }\n}\nexport type { MCPCallOptions, MCPConnectionResult } from './mcp';\nexport { callA2ATool } from './a2a';\nexport { DEFAULT_REQUEST_TIMEOUT_MS } from './abort';\nexport {\n callMCPToolWithTasks,\n getMCPTaskStatus,\n getMCPTaskResult,\n listMCPTasks,\n cancelMCPTask,\n mapMCPTaskStatus,\n serverSupportsTasks,\n} from './mcp-tasks';\n\nimport { callMCPToolWithTasks, callMCPToolWithClient } from './mcp-tasks';\nimport { callMCPToolWithOAuth } from './mcp';\nimport { callA2ATool } from './a2a';\nimport type { AgentConfig, DebugLogEntry } from '../types';\nimport type { PushNotificationConfig } from '../types/tools.generated';\nimport { getAuthToken } from '../auth';\nimport {\n createNonInteractiveOAuthProvider,\n discoverAuthorizationRequirements,\n NeedsAuthorizationError,\n getAgentStorage,\n ensureClientCredentialsTokens,\n} from '../auth/oauth';\nimport { is401Error } from '../errors';\nimport { isLikelyPrivateUrl } from '../net';\nimport { validateAgentUrl } from '../validation';\nimport { withSpan } from '../observability/tracing';\nimport { ADCP_MAJOR_VERSION, ADCP_VERSION, parseAdcpMajorVersion } from '../version';\nimport { ConfigurationError } from '../errors';\nimport { resolveBundleKey, toReleasePrecisionWire, validateAdcpVersionWire } from '../validation/schema-loader';\nimport { buildAgentSigningContext, CAPABILITY_OP, ensureCapabilityLoaded } from '../signing/client';\nimport { withResponseSizeLimit } from './responseSizeLimit';\nimport {\n withTransportDiagnostics,\n type TransportActivityHandler as TransportActivityHandlerFn,\n} from './transportDiagnostics';\n\nexport {\n sanitizeTransportHeaders,\n sanitizeTransportUrl,\n withTransportDiagnostics,\n wrapFetchWithTransportDiagnostics,\n} from './transportDiagnostics';\nexport type { TransportActivity, TransportActivityContext, TransportActivityHandler } from './transportDiagnostics';\n\nexport type VersionEnvelopeMode = 'auto' | 'none' | 'major-only';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<\n AgentConfig,\n ReturnType<typeof createNonInteractiveOAuthProvider>\n>();\n\nfunction getNonInteractiveOAuthProvider(agent: AgentConfig): ReturnType<typeof createNonInteractiveOAuthProvider> {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n const storage = getAgentStorage(agent);\n provider = createNonInteractiveOAuthProvider(agent, {\n agentHint: agent.id,\n storage,\n });\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/**\n * Derive the wire-level `adcp_major_version` integer from a caller-supplied\n * pin. Returns the SDK default when no pin is provided; throws on a pin\n * that doesn't parse so misuse surfaces at the factory boundary instead\n * of silently emitting the SDK's major.\n *\n * Throws `ConfigurationError` (not a plain `Error`) so a typo'd pin\n * surfaces with the same error class as the construction-time gate in\n * `resolveAdcpVersion` — one shape for all pin-misuse paths.\n */\nfunction resolveWireMajor(adcpVersion: string | undefined): number {\n if (adcpVersion === undefined) return ADCP_MAJOR_VERSION;\n const parsed = parseAdcpMajorVersion(adcpVersion);\n if (!Number.isFinite(parsed)) {\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} is not a valid AdCP version. ` +\n `Expected a semver string (e.g. '3.0.1', '3.1.0-beta.1') or a legacy alias (e.g. 'v3').`,\n 'adcpVersion'\n );\n }\n return parsed;\n}\n\n/**\n * Returns true when the AdCP release that `bundleKey` identifies declares the\n * top-level `adcp_version` envelope field. The field landed in AdCP 3.1 per\n * spec PR `adcontextprotocol/adcp#3493` — 3.0 (any patch / prerelease) does\n * not carry it; 3.1+ does. Used to gate dual-emit on the wire so a 3.0-pinned\n * client doesn't emit a field its target schema doesn't define.\n */\nexport function bundleSupportsAdcpVersionField(bundleKey: string): boolean {\n const major = parseAdcpMajorVersion(bundleKey);\n if (!Number.isFinite(major)) return false;\n if (major < 3) return false;\n if (major > 3) return true;\n // Major 3 — only 3.1+ has the field. Bundle key shape is normalized by\n // `resolveBundleKey`: `'3.0'` / `'3.1'` for stable; `'3.0.0-beta.1'` /\n // `'3.1.0-beta.1'` for prereleases. Match the minor.\n const minorMatch = bundleKey.match(/^\\d+\\.(\\d+)/);\n if (!minorMatch) return false;\n return parseInt(minorMatch[1]!, 10) >= 1;\n}\n\n/**\n * Build the wire-level version envelope to merge into outgoing request args.\n *\n * Per AdCP 3.1 (spec PR `adcontextprotocol/adcp#3493`), 3.1+ requests carry\n * BOTH the integer `adcp_major_version` (deprecated through 3.x, removed in\n * 4.0) AND the release-precision string `adcp_version`. 3.0 schemas don't\n * define the string field, so a 3.0-pinned client emits the integer only —\n * matches the 3.0 spec exactly.\n *\n * Wire string is release-precision (MAJOR.MINOR with optional prerelease tag),\n * per `core/version-envelope.json`'s pattern `^\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$`.\n * Full-semver bundle keys (`'3.1.0-beta.1'`) are collapsed via\n * `toReleasePrecisionWire` to `'3.1-beta.1'` before emit — meta-field shapes\n * are explicitly NOT valid wire values per the envelope schema's own\n * normalization rule.\n *\n * Returns `{}` for v2 callers (predates the major-version field entirely).\n */\nfunction buildVersionEnvelope(\n adcpVersion: string | undefined,\n serverVersion: 'v2' | 'v3' | undefined\n): Record<string, unknown> {\n if (serverVersion === 'v2') return {};\n const wireMajor = resolveWireMajor(adcpVersion);\n const bundleKey = resolveBundleKey(adcpVersion ?? ADCP_VERSION);\n if (!bundleSupportsAdcpVersionField(bundleKey)) {\n return { adcp_major_version: wireMajor };\n }\n const wireValue = toReleasePrecisionWire(bundleKey);\n // Defensive postcondition — should never throw in well-formed code, but\n // if a future refactor breaks the normalization the error message tells\n // the developer to call `toReleasePrecisionWire` instead of silently\n // emitting a non-spec wire string.\n validateAdcpVersionWire(wireValue);\n return { adcp_major_version: wireMajor, adcp_version: wireValue };\n}\n\nfunction buildVersionEnvelopeForMode(\n mode: VersionEnvelopeMode,\n adcpVersion: string | undefined,\n serverVersion: 'v2' | 'v3' | undefined\n): Record<string, unknown> {\n if (mode === 'none' || serverVersion === 'v2') return {};\n if (mode === 'major-only') return { adcp_major_version: resolveWireMajor(adcpVersion) };\n return buildVersionEnvelope(adcpVersion, serverVersion);\n}\n\n/**\n * Merge the wire-level version envelope into a caller-supplied args object.\n * Caller args win: an explicit `adcp_major_version` / `adcp_version` in\n * `args` (e.g. a conformance harness probing `VERSION_UNSUPPORTED`) passes\n * through unchanged. The envelope only fills fields the caller didn't set.\n *\n * Single chokepoint for all four wire-injection sites so a future refactor\n * can't silently flip the spread order on one branch and leave the others\n * intact. Stale dual-field drift is caught at the server boundary by\n * `createAdcpServer`'s field-disagreement check (spec PR\n * `adcontextprotocol/adcp#3493`).\n *\n * @internal\n */\nexport function applyVersionEnvelope(\n args: Record<string, unknown>,\n envelope: Record<string, unknown>\n): Record<string, unknown> {\n return { ...envelope, ...args };\n}\n\n/**\n * Transport-level safeguards applied to a call.\n *\n * Wired into the SDK's internal fetch chain via AsyncLocalStorage, so the\n * cap takes effect even when the underlying transport's connection cache\n * reuses a fetch that was created on an earlier call with different limits.\n */\nexport interface TransportOptions {\n /**\n * Maximum response body size (in octets) the SDK will read before aborting\n * with `ResponseTooLargeError`. When unset, the SDK does not impose a cap —\n * matches the underlying MCP / A2A transport defaults.\n *\n * Set this when crawling **untrusted** agents (registries, federated\n * discovery layers, monitoring tools) to prevent a hostile vendor from\n * buffering a large reply before any application-layer schema validation\n * runs. Counted across response chunks; pre-cancels when `Content-Length`\n * exceeds the cap. Applies to A2A agent-card discovery\n * (`/.well-known/agent.json`) on the same call as well.\n *\n * Per-call override (`TaskOptions.transport.maxResponseBytes`) beats the\n * value set on the client constructor (`SingleAgentClientConfig.transport`).\n *\n * @remarks\n * **Safe to set on all calls.** SSE responses (`text/event-stream`) are\n * passed through unchanged — a single tool call legitimately emits N status\n * frames + a final result, bounded by protocol-level framing rather than\n * cumulative byte counts. The cap applies to one-shot JSON responses\n * (`get_adcp_capabilities`, agent-card lookup, tool result payloads on\n * non-streaming transports) where the body is bounded by definition.\n *\n * @remarks\n * **Hostile-peer note:** A peer can opt itself out of this cap by responding\n * with `Content-Type: text/event-stream`. SSE is bypassed because cumulative\n * event-frame bytes are unbounded by spec — MCP and A2A both stream tool\n * responses this way. The MCP/A2A SDKs consume SSE incrementally and frame\n * termination bounds memory in practice, so this is not a memory-bomb risk\n * for well-formed transports. Adopters relying on `maxResponseBytes` as a\n * hostile-server defense should treat it as best-effort for non-SSE\n * responses only.\n *\n * @remarks\n * Future hardening knobs (DNS-rebind defense, scheme allow-list, request\n * timeout overrides) will land here as additional fields rather than\n * forcing callers to compose their own `fetch` — wrap order with the SDK's\n * existing signing / capture wrappers is non-obvious and a footgun.\n */\n maxResponseBytes?: number;\n /**\n * Timeout in milliseconds for bounded one-shot transport requests such as\n * A2A agent-card discovery and MCP read-path probes. Defaults to 60 seconds\n * for A2A discovery so an unresponsive card endpoint cannot hang forever.\n * Set to `0` to disable the SDK-imposed discovery timeout.\n */\n requestTimeoutMs?: number;\n}\n\n/**\n * Options for {@link ProtocolClient.callTool}. All fields are optional.\n *\n * `webhookUrl` / `webhookSecret` / `webhookToken` are for ASYNC TASK STATUS\n * notifications (push_notification_config). For reporting webhooks\n * (reporting_webhook), include them directly in `args` — they stay in skill\n * parameters and are sent verbatim to the agent.\n */\nexport interface CallToolOptions {\n /** Debug log array. Mutated in place by the protocol layer. */\n debugLogs?: DebugLogEntry[];\n /** URL for async task status notifications. */\n webhookUrl?: string;\n /** HMAC-SHA256 secret for push_notification_config authentication. */\n webhookSecret?: string;\n /** Bearer token for push_notification_config validation. */\n webhookToken?: string;\n /** Pinned protocol generation when the agent advertises both v2 and v3. */\n serverVersion?: 'v2' | 'v3';\n /** A2A session continuity (contextId carries conversation, taskId resumes a task). */\n session?: { contextId?: string; taskId?: string };\n /**\n * AdCP version pin from the calling client/server instance. Sets the\n * wire-level `adcp_major_version` field per-call instead of from the\n * SDK-pinned `ADCP_MAJOR_VERSION` constant. Default falls back to the\n * constant so call sites that don't plumb a per-instance version keep\n * their existing behavior. An explicit `adcp_major_version` /\n * `adcp_version` in `args` overrides this — conformance harnesses use\n * that path to probe seller version negotiation.\n */\n adcpVersion?: string;\n /**\n * Optional wire-only version override. Schema selection and client\n * construction can remain pinned to `adcpVersion`; the request envelope is\n * emitted for this release-precision line.\n */\n wireAdcpVersion?: string;\n /**\n * Controls whether the SDK injects AdCP version envelope fields into the\n * outgoing request. Defaults to `auto`. 3.0 pins emit only the legacy\n * `adcp_major_version`; 3.1+ pins emit both the legacy major and exact\n * `adcp_version` marker. `major-only` forces the legacy integer marker\n * without the 3.1 string marker for strict pre-3.1 peers discovered at\n * runtime.\n */\n versionEnvelope?: VersionEnvelopeMode;\n /**\n * Transport-level safeguards (size caps, etc.). Per-call override of any\n * matching field on the client constructor's `transport` option.\n */\n transport?: TransportOptions;\n /** Caller-owned cancellation signal for the in-flight protocol call. */\n signal?: AbortSignal;\n /** Transport-level diagnostics callback for outbound HTTP requests. */\n onTransportActivity?: TransportActivityHandlerFn;\n /**\n * Correlation metadata attached to transport diagnostics events emitted\n * while this protocol call is active.\n */\n transportActivityContext?: {\n operationId?: string;\n taskId?: string;\n contextId?: string;\n idempotencyKey?: string;\n };\n}\n\n/**\n * Universal protocol client - automatically routes to the correct protocol implementation\n */\nexport class ProtocolClient {\n /**\n * Call a tool on an agent using the appropriate protocol.\n *\n * @param agent - Agent configuration\n * @param toolName - Name of the tool/skill to call\n * @param args - Tool arguments (includes reporting_webhook if needed - NOT removed)\n * @param options - Optional call-level configuration. See {@link CallToolOptions}.\n */\n static async callTool(\n agent: AgentConfig,\n toolName: string,\n args: Record<string, unknown>,\n options: CallToolOptions = {}\n ): Promise<unknown> {\n const {\n debugLogs = [],\n webhookUrl,\n webhookSecret,\n webhookToken,\n serverVersion,\n session,\n adcpVersion,\n wireAdcpVersion,\n versionEnvelope: versionEnvelopeMode = 'auto',\n transport,\n signal,\n onTransportActivity,\n transportActivityContext,\n } = options;\n // Per-instance version envelope. Throws on unparseable pins via\n // `resolveWireMajor`; construction-time `resolveAdcpVersion` is the\n // primary gate but this is the failsafe for callers reaching\n // `ProtocolClient.callTool` directly (test harnesses, the in-process\n // MCP path). Returns `{ adcp_major_version }` for 3.0 pins and\n // `{ adcp_major_version, adcp_version }` for 3.1+ pins.\n const versionEnvelope = buildVersionEnvelopeForMode(\n versionEnvelopeMode,\n wireAdcpVersion ?? adcpVersion,\n serverVersion\n );\n // Enter the response-size-limit ALS slot once for this call. The slot is\n // read by `wrapFetchWithSizeLimit` in both protocol transports, so the\n // cap applies regardless of which path (MCP / A2A / OAuth refresh) the\n // call ends up taking. No-op when the cap is unset or non-positive.\n return withResponseSizeLimit(transport?.maxResponseBytes, () =>\n withTransportDiagnostics(\n {\n agentId: agent.id,\n protocol: agent.protocol,\n tool: toolName,\n taskType: toolName,\n ...transportActivityContext,\n onTransportActivity,\n },\n () =>\n withSpan(\n `adcp.${agent.protocol}.call_tool`,\n {\n 'adcp.agent_id': agent.id,\n 'adcp.protocol': agent.protocol,\n 'adcp.tool': toolName,\n 'http.url': agent.agent_uri,\n },\n async () => {\n // In-process MCP path: pre-connected client, no HTTP transport.\n // Idempotency injection, schema validation, and governance middleware all\n // still apply (they run in SingleAgentClient above this call). We skip\n // URL validation, OAuth refresh, and signing — none apply in-process.\n if (agent.protocol === 'mcp' && agent._inProcessMcpClient) {\n const inProcArgs = applyVersionEnvelope(args, versionEnvelope);\n return callMCPToolWithClient(agent._inProcessMcpClient, toolName, inProcArgs, debugLogs, {\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n });\n }\n\n validateAgentUrl(agent.agent_uri);\n\n // OAuth 2.0 client credentials (RFC 6749 §4.4): re-exchange the\n // secret for a fresh access token whenever the cached one is within\n // its expiration skew. Runs before every call so mid-session expiry\n // can't leave the caller with a stale bearer. No-op if the agent\n // doesn't declare client credentials. Cheap on warm cache (single\n // `Date.now()` compare); a single POST to the token endpoint on miss.\n //\n // `allowPrivateIp` inherits the trust the caller already placed in\n // `agent.agent_uri` — if they're making a call to a private-IP agent,\n // they've authorized this process to talk to private-IP hosts, so\n // the token endpoint on the same network is reachable too. Public\n // agent URLs with private-IP token endpoints still require an\n // explicit opt-in via the library API.\n if (agent.oauth_client_credentials) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, allowPrivateIp });\n }\n\n const authToken = getAuthToken(agent);\n\n // RFC 9421 signing context. Built once per call and passed through\n // to each protocol-layer entry (`callMCPToolWithTasks`, `callA2ATool`,\n // `callMCPToolWithOAuth`) — those entries seed `signingContextStorage`\n // (AsyncLocalStorage) so the internal transport helpers read it\n // without an explicit parameter. Keep the explicit arg here: it's the\n // ALS seed, not incidental plumbing. `get_adcp_capabilities` is\n // exempt from signing (it's the discovery call itself) and also\n // triggers cache priming for any other op on agents with\n // `request_signing` configured.\n const signingContext = buildAgentSigningContext(agent);\n if (signingContext && toolName !== CAPABILITY_OP) {\n await ensureCapabilityLoaded(agent, signingContext, primeArgs =>\n ProtocolClient.callTool(agent, CAPABILITY_OP, primeArgs, {\n debugLogs,\n serverVersion,\n adcpVersion,\n ...(versionEnvelopeMode !== 'auto' && { versionEnvelope: versionEnvelopeMode }),\n transport,\n signal,\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n onTransportActivity,\n transportActivityContext,\n })\n );\n }\n\n // Inject the version envelope on every request so sellers can validate\n // compatibility. Skip for v2 servers — they don't recognise the\n // version fields and strict-schema agents reject them. The envelope\n // shape is per-pin: 3.0 pins get the integer `adcp_major_version`\n // alone; 3.1+ pins get both that and the release-precision string\n // `adcp_version` (`'3.1'` / `'3.1.0-beta.1'`) per spec PR\n // `adcontextprotocol/adcp#3493`.\n const argsWithVersion = applyVersionEnvelope(args, versionEnvelope);\n\n // Build push_notification_config for ASYNC TASK STATUS notifications\n // (NOT for reporting_webhook - that stays in args)\n // Schema: https://adcontextprotocol.org/schemas/v1/core/push-notification-config.json\n const pushNotificationConfig: PushNotificationConfig | undefined = webhookUrl\n ? {\n url: webhookUrl,\n ...(webhookToken && { token: webhookToken }),\n authentication: {\n schemes: ['HMAC-SHA256'],\n credentials: webhookSecret || 'placeholder_secret_min_32_characters_required',\n },\n }\n : undefined;\n\n if (agent.protocol === 'mcp') {\n // For MCP, include push_notification_config in tool arguments (MCP spec)\n const argsWithWebhook = pushNotificationConfig\n ? { ...argsWithVersion, push_notification_config: pushNotificationConfig }\n : argsWithVersion;\n\n // If the agent config carries authorization-code OAuth tokens,\n // route through the OAuth provider path so the MCP SDK can refresh\n // on 401 instead of hard-failing. Excludes client-credentials\n // agents: they have a cached access token but no refresh_token,\n // and their refresh path is a secret re-exchange (handled above),\n // not the SDK's refresh_token grant.\n if (agent.oauth_tokens && !agent.oauth_client_credentials) {\n const authProvider = getNonInteractiveOAuthProvider(agent);\n try {\n return await callMCPToolWithOAuth({\n agentUrl: agent.agent_uri,\n toolName,\n args: argsWithWebhook,\n authProvider,\n debugLogs,\n customHeaders: agent.headers,\n signingContext,\n signal,\n requestTimeoutMs: transport?.requestTimeoutMs,\n });\n } catch (err) {\n // Refresh failed or server rejected the refreshed token — walk the\n // discovery chain so the caller can distinguish \"re-auth needed\"\n // from other failure modes.\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n }\n\n // Use callMCPToolWithTasks which auto-detects server tasks capability\n // and falls back to standard callTool when tasks are not supported\n try {\n return await callMCPToolWithTasks(\n agent.agent_uri,\n toolName,\n argsWithWebhook,\n authToken,\n debugLogs,\n agent.headers,\n {\n ...(signingContext && { signingContext }),\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: transport.requestTimeoutMs,\n }),\n }\n );\n } catch (err) {\n // Client-credentials agents: on 401, the AS may have rotated\n // something out-of-band. Force a fresh exchange and retry once\n // before surfacing the error. Bounded (single retry) so we don't\n // loop if the credentials are genuinely wrong.\n if (agent.oauth_client_credentials && is401Error(err)) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, force: true, allowPrivateIp });\n const retryAuthToken = agent.oauth_tokens?.access_token ?? authToken;\n try {\n return await callMCPToolWithTasks(\n agent.agent_uri,\n toolName,\n argsWithWebhook,\n retryAuthToken,\n debugLogs,\n agent.headers,\n {\n ...(signingContext && { signingContext }),\n ...(signal && { signal }),\n ...(transport?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: transport.requestTimeoutMs,\n }),\n }\n );\n } catch (retryErr) {\n await rethrowAsNeedsAuthorization(retryErr, agent.agent_uri);\n throw retryErr;\n }\n }\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n } else if (agent.protocol === 'a2a') {\n // For A2A, pass pushNotificationConfig separately (not in skill parameters)\n try {\n return await callA2ATool(\n agent.agent_uri,\n toolName,\n argsWithVersion,\n authToken,\n debugLogs,\n pushNotificationConfig,\n agent.headers,\n signingContext,\n session,\n signal,\n transport?.requestTimeoutMs\n );\n } catch (err) {\n // Same single-retry-on-401 for client-credentials agents as the\n // MCP path above. Kept symmetric so A2A CC agents aren't a\n // second-class experience — including the NeedsAuthorizationError\n // rewrap on a retry that still 401s.\n if (agent.oauth_client_credentials && is401Error(err)) {\n const ccStorage = getAgentStorage(agent);\n const allowPrivateIp = isLikelyPrivateUrl(agent.agent_uri);\n await ensureClientCredentialsTokens(agent, { storage: ccStorage, force: true, allowPrivateIp });\n const retryAuthToken = agent.oauth_tokens?.access_token ?? authToken;\n try {\n return await callA2ATool(\n agent.agent_uri,\n toolName,\n argsWithVersion,\n retryAuthToken,\n debugLogs,\n pushNotificationConfig,\n agent.headers,\n signingContext,\n session,\n signal,\n transport?.requestTimeoutMs\n );\n } catch (retryErr) {\n await rethrowAsNeedsAuthorization(retryErr, agent.agent_uri);\n throw retryErr;\n }\n }\n await rethrowAsNeedsAuthorization(err, agent.agent_uri);\n throw err;\n }\n } else {\n throw new Error(`Unsupported protocol: ${agent.protocol}`);\n }\n }\n )\n )\n );\n }\n}\n\n/**\n * If `err` looks like a 401 from the MCP transport, probe the agent for a\n * Bearer challenge and throw a {@link NeedsAuthorizationError} carrying\n * walked discovery metadata. If the error isn't a 401 or we can't build a\n * requirements record, return silently so the caller re-throws the original.\n *\n * Keeping this off the hot path: we only probe on error, and the probe is\n * a single unauthenticated `tools/list` POST — no retries, no DNS rebind.\n */\nasync function rethrowAsNeedsAuthorization(err: unknown, agentUrl: string): Promise<void> {\n if (err instanceof NeedsAuthorizationError) throw err;\n if (!is401Error(err)) return;\n\n // If the caller has already connected to the agent URL, they've implicitly\n // trusted it — inherit that trust for the discovery probe so loopback /\n // private-IP development agents work the same way as public ones.\n const allowPrivateIp = isLikelyPrivateUrl(agentUrl);\n\n // discoverAuthorizationRequirements internally catches network failures and\n // returns null rather than throwing — anything that escapes is a genuine\n // bug we want to surface rather than mask the 401 with.\n const requirements = await discoverAuthorizationRequirements(agentUrl, { allowPrivateIp });\n if (requirements) {\n throw new NeedsAuthorizationError(requirements);\n }\n // No requirements walked; let the caller re-throw the original error.\n}\n\n/**\n * Simple factory functions for protocol-specific clients.\n *\n * Both factories accept a `transport` argument that flows through to the\n * size-cap surface so callers reaching the factory exports honor the same\n * `maxResponseBytes` contract as `ProtocolClient.callTool`. Without it,\n * the factories would silently bypass the cap, which the public API\n * (`TransportOptions`) implies they honor.\n */\nexport const createMCPClient = (\n agentUrl: string,\n authToken?: string,\n headers?: Record<string, string>,\n serverVersion?: 'v2' | 'v3',\n adcpVersion?: string,\n transport?: TransportOptions,\n versionEnvelopeMode: VersionEnvelopeMode = 'auto'\n) => {\n // Validate the pin at factory time so a typo surfaces here rather than at\n // first call. `buildVersionEnvelope` throws via `resolveWireMajor` on bad\n // input — call it once to surface, then close over the envelope.\n const versionEnvelope = buildVersionEnvelopeForMode(versionEnvelopeMode, adcpVersion, serverVersion);\n return {\n callTool: (toolName: string, args: Record<string, unknown>, debugLogs?: DebugLogEntry[]) =>\n withResponseSizeLimit(transport?.maxResponseBytes, () =>\n callMCPToolWithTasks(\n agentUrl,\n toolName,\n applyVersionEnvelope(args, versionEnvelope),\n authToken,\n debugLogs,\n headers,\n {\n ...(transport?.requestTimeoutMs !== undefined && { requestTimeoutMs: transport.requestTimeoutMs }),\n }\n )\n ),\n };\n};\n\nexport const createA2AClient = (\n agentUrl: string,\n authToken?: string,\n headers?: Record<string, string>,\n serverVersion?: 'v2' | 'v3',\n adcpVersion?: string,\n transport?: TransportOptions,\n versionEnvelopeMode: VersionEnvelopeMode = 'auto'\n) => {\n const versionEnvelope = buildVersionEnvelopeForMode(versionEnvelopeMode, adcpVersion, serverVersion);\n return {\n callTool: (toolName: string, parameters: Record<string, unknown>, debugLogs?: DebugLogEntry[]) =>\n withResponseSizeLimit(transport?.maxResponseBytes, () =>\n callA2ATool(\n agentUrl,\n toolName,\n applyVersionEnvelope(parameters, versionEnvelope),\n authToken,\n debugLogs,\n undefined,\n headers,\n undefined,\n undefined,\n undefined,\n transport?.requestTimeoutMs\n )\n ),\n };\n};\n"],"mappings":"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","names":["require","closeMCPConnections","callMCPToolWithTasks","callMCPToolWithOAuth","callA2ATool","withTransportDiagnostics"]}
@@ -1,3 +1,8 @@
1
+ import { fileURLToPath as __adcpFileURLToPath } from "node:url";
2
+ import { dirname as __adcpDirname } from "node:path";
3
+ import { createRequire as __adcpCreateRequire } from "node:module";
4
+ const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
5
+ const require2 = __adcpCreateRequire(import.meta.url);
1
6
  import {
2
7
  Client,
3
8
  StreamableHTTPClientTransport
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/protocols/mcp-modern.ts"],"sourcesContent":["/**\n * MCP 2026-07-28 client path.\n *\n * The v2 SDK removed the experimental 2025 Tasks interception API. During the\n * migration window we therefore negotiate with the v2 client first and use it\n * only when the peer selects the modern protocol era. Legacy peers fall back\n * to mcp-tasks.ts, which keeps the existing v1 Tasks behavior intact.\n */\n\nimport {\n Client,\n StreamableHTTPClientTransport,\n type OAuthClientProvider as ModernOAuthClientProvider,\n type Tool,\n} from '@modelcontextprotocol/client';\nimport { createHmac } from 'node:crypto';\nimport { createMCPAuthHeaders } from '../auth';\nimport { is401Error } from '../errors';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport type { DebugLogEntry } from '../types/adcp';\nimport {\n isAbortOrTimeoutError,\n resolveClientRequestTimeoutMs,\n resolveRequestTimeoutMs,\n withAbortSignal,\n} from './abort';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\n\ntype CallToolResponse = {\n isError?: boolean;\n content?: Array<{ type: string; text?: string }>;\n [key: string]: unknown;\n};\n\nexport type ModernMCPAttempt = { handled: false } | { handled: true; response: CallToolResponse };\nexport type ModernMCPListAttempt = { handled: false } | { handled: true; tools: Tool[] };\n\nexport interface ModernMCPConnectionOptions {\n signingContext?: AgentSigningContext;\n authProvider?: object;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n /** Use the v2 SDK's negotiated legacy client instead of handing off to v1. */\n handleLegacy?: boolean;\n}\n\ninterface ModernConnectionOptions {\n agentUrl: string;\n authToken?: string;\n customHeaders?: Record<string, string>;\n debugLogs: DebugLogEntry[];\n signingContext?: AgentSigningContext;\n authProvider?: object;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n handleLegacy?: boolean;\n}\n\nconst modernConnections = new Map<string, Client>();\nconst legacyConnectionExpiresAt = new Map<string, number>();\nconst pendingModernConnections = new Map<string, Promise<Client>>();\nconst knownLegacyConnections = new Map<string, number>();\nconst MAX_CACHED_CONNECTIONS = 20;\nconst LEGACY_CLASSIFICATION_TTL_MS = 5 * 60 * 1000;\nconst modernOAuthProviderIds = new WeakMap<object, string>();\nconst modernFetchFnIds = new WeakMap<typeof fetch, string>();\nlet nextModernOAuthProviderId = 0;\nlet nextModernFetchFnId = 0;\nlet connectionGeneration = 0;\n\nfunction cacheDisambiguator(value: string): string {\n return createHmac('sha256', '').update(value).digest('hex');\n}\n\nfunction buildAuthHeaders(\n authToken: string | undefined,\n customHeaders: Record<string, string> | undefined,\n authProvider?: object\n): Record<string, string> {\n const filteredHeaders =\n authProvider || authToken\n ? Object.fromEntries(\n Object.entries(customHeaders ?? {}).filter(keyValue => {\n const key = keyValue[0].toLowerCase();\n return key !== 'authorization' && key !== 'x-adcp-auth';\n })\n )\n : customHeaders;\n return {\n ...filteredHeaders,\n ...(!authProvider && authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n}\n\nfunction oauthProviderCacheKey(provider: object | undefined): string | undefined {\n if (!provider) return undefined;\n let key = modernOAuthProviderIds.get(provider);\n if (!key) {\n key = `oauth-provider:${++nextModernOAuthProviderId}`;\n modernOAuthProviderIds.set(provider, key);\n }\n return key;\n}\n\nfunction fetchFnCacheKey(fetchFn: typeof fetch | undefined): string | undefined {\n if (!fetchFn) return undefined;\n let key = modernFetchFnIds.get(fetchFn);\n if (!key) {\n key = `fetch:${++nextModernFetchFnId}`;\n modernFetchFnIds.set(fetchFn, key);\n }\n return key;\n}\n\nfunction connectionCacheKey(\n agentUrl: string,\n headers: Record<string, string>,\n signingCacheKey?: string,\n authProvider?: object,\n fetchFn?: typeof fetch\n): string {\n const normalizedHeaders = Object.entries(headers)\n .map(([key, value]) => [key.toLowerCase(), value] as const)\n .sort(([left], [right]) => left.localeCompare(right));\n const parts = [agentUrl, `headers:${cacheDisambiguator(JSON.stringify(normalizedHeaders))}`];\n if (signingCacheKey) parts.push(signingCacheKey);\n const providerKey = oauthProviderCacheKey(authProvider);\n if (providerKey) parts.push(providerKey);\n const fetchKey = fetchFnCacheKey(fetchFn);\n if (fetchKey) parts.push(fetchKey);\n return parts.join('::');\n}\n\nfunction isKnownLegacy(cacheKey: string): boolean {\n const classifiedAt = knownLegacyConnections.get(cacheKey);\n if (classifiedAt === undefined) return false;\n if (Date.now() - classifiedAt > LEGACY_CLASSIFICATION_TTL_MS) {\n knownLegacyConnections.delete(cacheKey);\n return false;\n }\n knownLegacyConnections.delete(cacheKey);\n knownLegacyConnections.set(cacheKey, classifiedAt);\n return true;\n}\n\nfunction markKnownLegacy(cacheKey: string): void {\n knownLegacyConnections.delete(cacheKey);\n knownLegacyConnections.set(cacheKey, Date.now());\n while (knownLegacyConnections.size > MAX_CACHED_CONNECTIONS) {\n const oldest = knownLegacyConnections.keys().next().value;\n if (!oldest) break;\n knownLegacyConnections.delete(oldest);\n }\n}\n\nfunction httpStatusOf(error: unknown, depth = 0): number | undefined {\n if (!error || typeof error !== 'object' || depth > 4) return undefined;\n const candidate = error as { status?: unknown; code?: unknown; cause?: unknown; response?: { status?: unknown } };\n if (typeof candidate.status === 'number') return candidate.status;\n if (typeof candidate.response?.status === 'number') return candidate.response.status;\n if (typeof candidate.code === 'number' && candidate.code >= 100 && candidate.code <= 599) return candidate.code;\n return httpStatusOf(candidate.cause, depth + 1);\n}\n\nfunction withPerRequestTraceHeaders(fetchImpl: typeof fetch): typeof fetch {\n return (input, init) => {\n const headers = new Headers(input instanceof Request ? input.headers : undefined);\n new Headers(init?.headers).forEach((value, key) => headers.set(key, value));\n for (const [key, value] of Object.entries(injectTraceHeaders())) headers.set(key, value);\n return fetchImpl(input, { ...init, headers });\n };\n}\n\nfunction getCachedConnection(cacheKey: string): Client | undefined {\n const client = modernConnections.get(cacheKey);\n if (client) {\n const legacyExpiry = legacyConnectionExpiresAt.get(cacheKey);\n if (legacyExpiry !== undefined && legacyExpiry <= Date.now()) {\n modernConnections.delete(cacheKey);\n legacyConnectionExpiresAt.delete(cacheKey);\n void client.close().catch(() => {});\n return undefined;\n }\n modernConnections.delete(cacheKey);\n modernConnections.set(cacheKey, client);\n }\n return client;\n}\n\nfunction evictLeastRecentlyUsed(): void {\n if (modernConnections.size <= MAX_CACHED_CONNECTIONS) return;\n const oldestKey = modernConnections.keys().next().value;\n if (!oldestKey) return;\n const client = modernConnections.get(oldestKey);\n modernConnections.delete(oldestKey);\n legacyConnectionExpiresAt.delete(oldestKey);\n void client?.close().catch(() => {});\n}\n\nasync function createNegotiatedClient(\n options: ModernConnectionOptions,\n authHeaders: Record<string, string>\n): Promise<Client> {\n const requestTimeoutMs = resolveRequestTimeoutMs(options.requestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(options.requestTimeoutMs);\n const rawNetworkFetch: typeof fetch = options.fetchFn ?? ((input, init) => fetch(input, init));\n const networkFetch: typeof fetch = (input, init) =>\n withAbortSignal<Response>([options.signal, init?.signal], requestTimeoutMs, signal =>\n rawNetworkFetch(input, { ...init, signal })\n );\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(wrapFetchWithSizeLimit(networkFetch));\n const signedFetch: typeof fetch = options.signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: options.signingContext.signing,\n getCapability: options.signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n const transport = new StreamableHTTPClientTransport(new URL(options.agentUrl), {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(withPerRequestTraceHeaders(signedFetch)),\n ...(options.authProvider && {\n authProvider: options.authProvider as ModernOAuthClientProvider,\n }),\n });\n const client = new Client(\n { name: 'AdCP-Client', version: '1.0.0' },\n {\n versionNegotiation: {\n mode: 'auto',\n ...(clientRequestTimeoutMs !== undefined && { probe: { timeoutMs: clientRequestTimeoutMs } }),\n },\n }\n );\n\n try {\n await client.connect(transport, {\n ...(options.signal && { signal: options.signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n });\n return client;\n } catch (error) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n throw error;\n }\n}\n\nasync function getOrCreateModernConnection(\n cacheKey: string,\n options: ModernConnectionOptions,\n authHeaders: Record<string, string>\n): Promise<Client> {\n const cached = getCachedConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingModernConnections.get(cacheKey);\n if (pending) return pending;\n\n const generation = connectionGeneration;\n const promise = createNegotiatedClient(options, authHeaders)\n .then(client => {\n if (\n (client.getProtocolEra() === 'modern' || options.handleLegacy === true) &&\n generation === connectionGeneration\n ) {\n modernConnections.set(cacheKey, client);\n if (client.getProtocolEra() === 'legacy') {\n legacyConnectionExpiresAt.set(cacheKey, Date.now() + LEGACY_CLASSIFICATION_TTL_MS);\n } else {\n legacyConnectionExpiresAt.delete(cacheKey);\n }\n evictLeastRecentlyUsed();\n } else if (generation !== connectionGeneration) {\n void client.close().catch(() => {});\n }\n return client;\n })\n .finally(() => {\n if (pendingModernConnections.get(cacheKey) === promise) pendingModernConnections.delete(cacheKey);\n });\n pendingModernConnections.set(cacheKey, promise);\n return promise;\n}\n\nasync function callOnModernClient(\n client: Client,\n toolName: string,\n args: Record<string, unknown>,\n signal?: AbortSignal,\n requestTimeoutMs?: number\n): Promise<CallToolResponse> {\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestTimeoutMs);\n return (await client.callTool(\n { name: toolName, arguments: args },\n {\n ...(signal && { signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n }\n )) as CallToolResponse;\n}\n\nasync function attemptModernCall(\n options: ModernConnectionOptions,\n toolName: string,\n args: Record<string, unknown>\n): Promise<ModernMCPAttempt> {\n const authHeaders = buildAuthHeaders(options.authToken, options.customHeaders, options.authProvider);\n const cacheKey = connectionCacheKey(\n options.agentUrl,\n authHeaders,\n options.signingContext?.cacheKey,\n options.authProvider,\n options.fetchFn\n );\n if (isKnownLegacy(cacheKey)) return { handled: false };\n\n const guardedConnection =\n options.signal !== undefined || options.requestTimeoutMs !== undefined || options.fetchFn !== undefined;\n let client: Client;\n try {\n client = guardedConnection\n ? await createNegotiatedClient(options, authHeaders)\n : await getOrCreateModernConnection(cacheKey, options, authHeaders);\n } catch (error) {\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) {\n markKnownLegacy(cacheKey);\n options.debugLogs.push({\n type: 'info',\n message: `MCP: Modern Streamable HTTP is unavailable (HTTP ${status}); preserving the v1 transport path`,\n timestamp: new Date().toISOString(),\n });\n return { handled: false };\n }\n throw error;\n }\n\n if (client.getProtocolEra() !== 'modern') {\n if (options.handleLegacy === true) {\n options.debugLogs.push({\n type: 'info',\n message: `MCP: v2 client selected the legacy protocol era for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n } else {\n markKnownLegacy(cacheKey);\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n options.debugLogs.push({\n type: 'info',\n message: `MCP: Server selected the legacy protocol era for ${toolName}; preserving the v1 Tasks path`,\n timestamp: new Date().toISOString(),\n });\n return { handled: false };\n }\n }\n\n options.debugLogs.push({\n type: 'success',\n message: `MCP: Negotiated protocol ${client.getNegotiatedProtocolVersion()} for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n\n try {\n const response = await callOnModernClient(client, toolName, args, options.signal, options.requestTimeoutMs);\n return { handled: true, response };\n } catch (error) {\n // A tool request may have reached the server even when its response was\n // lost. Never replay automatically: mutating AdCP tools depend on the\n // caller's explicit idempotency policy, not transport guesswork.\n modernConnections.delete(cacheKey);\n legacyConnectionExpiresAt.delete(cacheKey);\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n throw error;\n } finally {\n if (guardedConnection) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n }\n}\n\n/**\n * Try a tool call using the MCP 2026-07-28 protocol era.\n *\n * `handled: false` means the caller must use the existing v1 client. This is\n * deliberately a result rather than an exception because legacy negotiation\n * is normal during the transition window.\n */\nexport async function tryCallModernMCPTool(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<ModernMCPAttempt> {\n return withSpan('adcp.mcp.negotiate', { 'adcp.tool': toolName, 'http.url': agentUrl }, () =>\n signingContextStorage.run(options.signingContext, () =>\n attemptModernCall(\n {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs,\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n handleLegacy: options.handleLegacy,\n },\n toolName,\n args\n )\n )\n );\n}\n\n/**\n * Probe an endpoint with the official v2 client's auto negotiation.\n * `connected: false` lets endpoint discovery retain its v1 SSE fallback.\n */\nexport async function probeModernMCPConnection(\n agentUrl: string,\n authToken?: string,\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<{ connected: boolean; era?: 'legacy' | 'modern' }> {\n const connectionOptions: ModernConnectionOptions = {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs: [],\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n handleLegacy: options.handleLegacy,\n };\n const authHeaders = buildAuthHeaders(authToken, customHeaders, options.authProvider);\n let client: Client | undefined;\n try {\n client = await createNegotiatedClient(connectionOptions, authHeaders);\n return { connected: true, era: client.getProtocolEra() };\n } catch (error) {\n if (is401Error(error) || isAbortOrTimeoutError(error)) throw error;\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) return { connected: false };\n throw error;\n } finally {\n await client?.close().catch(() => {});\n }\n}\n\n/** List tools when the endpoint selected the modern era; otherwise let the v1 caller continue. */\nexport async function tryListModernMCPTools(\n agentUrl: string,\n authToken?: string,\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<ModernMCPListAttempt> {\n const connectionOptions: ModernConnectionOptions = {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs: [],\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n };\n const authHeaders = buildAuthHeaders(authToken, customHeaders, options.authProvider);\n let client: Client | undefined;\n try {\n client = await createNegotiatedClient(connectionOptions, authHeaders);\n if (client.getProtocolEra() !== 'modern') return { handled: false };\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(options.requestTimeoutMs);\n const result = await client.listTools(undefined, {\n ...(options.signal && { signal: options.signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n });\n return { handled: true, tools: result.tools };\n } catch (error) {\n if (is401Error(error) || isAbortOrTimeoutError(error)) throw error;\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) return { handled: false };\n throw error;\n } finally {\n await client?.close().catch(() => {});\n }\n}\n\nexport async function closeModernMCPConnections(): Promise<void> {\n connectionGeneration++;\n const pending = [...pendingModernConnections.values()];\n pendingModernConnections.clear();\n const settled = await Promise.allSettled(pending);\n const clients = new Set(modernConnections.values());\n for (const result of settled) {\n if (result.status === 'fulfilled') clients.add(result.value);\n }\n modernConnections.clear();\n legacyConnectionExpiresAt.clear();\n knownLegacyConnections.clear();\n for (const client of clients) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/protocols/mcp-modern.ts"],"sourcesContent":["import { fileURLToPath as __adcpFileURLToPath } from 'node:url';\nimport { dirname as __adcpDirname } from 'node:path';\nimport { createRequire as __adcpCreateRequire } from 'node:module';\nconst __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));\nconst require = __adcpCreateRequire(import.meta.url);\n/**\n * MCP 2026-07-28 client path.\n *\n * The v2 SDK removed the experimental 2025 Tasks interception API. During the\n * migration window we therefore negotiate with the v2 client first and use it\n * only when the peer selects the modern protocol era. Legacy peers fall back\n * to mcp-tasks.ts, which keeps the existing v1 Tasks behavior intact.\n */\n\nimport {\n Client,\n StreamableHTTPClientTransport,\n type OAuthClientProvider as ModernOAuthClientProvider,\n type Tool,\n} from '@modelcontextprotocol/client';\nimport { createHmac } from 'node:crypto';\nimport { createMCPAuthHeaders } from '../auth';\nimport { is401Error } from '../errors';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport type { DebugLogEntry } from '../types/adcp';\nimport {\n isAbortOrTimeoutError,\n resolveClientRequestTimeoutMs,\n resolveRequestTimeoutMs,\n withAbortSignal,\n} from './abort';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\n\ntype CallToolResponse = {\n isError?: boolean;\n content?: Array<{ type: string; text?: string }>;\n [key: string]: unknown;\n};\n\nexport type ModernMCPAttempt = { handled: false } | { handled: true; response: CallToolResponse };\nexport type ModernMCPListAttempt = { handled: false } | { handled: true; tools: Tool[] };\n\nexport interface ModernMCPConnectionOptions {\n signingContext?: AgentSigningContext;\n authProvider?: object;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n /** Use the v2 SDK's negotiated legacy client instead of handing off to v1. */\n handleLegacy?: boolean;\n}\n\ninterface ModernConnectionOptions {\n agentUrl: string;\n authToken?: string;\n customHeaders?: Record<string, string>;\n debugLogs: DebugLogEntry[];\n signingContext?: AgentSigningContext;\n authProvider?: object;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n handleLegacy?: boolean;\n}\n\nconst modernConnections = new Map<string, Client>();\nconst legacyConnectionExpiresAt = new Map<string, number>();\nconst pendingModernConnections = new Map<string, Promise<Client>>();\nconst knownLegacyConnections = new Map<string, number>();\nconst MAX_CACHED_CONNECTIONS = 20;\nconst LEGACY_CLASSIFICATION_TTL_MS = 5 * 60 * 1000;\nconst modernOAuthProviderIds = new WeakMap<object, string>();\nconst modernFetchFnIds = new WeakMap<typeof fetch, string>();\nlet nextModernOAuthProviderId = 0;\nlet nextModernFetchFnId = 0;\nlet connectionGeneration = 0;\n\nfunction cacheDisambiguator(value: string): string {\n return createHmac('sha256', '').update(value).digest('hex');\n}\n\nfunction buildAuthHeaders(\n authToken: string | undefined,\n customHeaders: Record<string, string> | undefined,\n authProvider?: object\n): Record<string, string> {\n const filteredHeaders =\n authProvider || authToken\n ? Object.fromEntries(\n Object.entries(customHeaders ?? {}).filter(keyValue => {\n const key = keyValue[0].toLowerCase();\n return key !== 'authorization' && key !== 'x-adcp-auth';\n })\n )\n : customHeaders;\n return {\n ...filteredHeaders,\n ...(!authProvider && authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n}\n\nfunction oauthProviderCacheKey(provider: object | undefined): string | undefined {\n if (!provider) return undefined;\n let key = modernOAuthProviderIds.get(provider);\n if (!key) {\n key = `oauth-provider:${++nextModernOAuthProviderId}`;\n modernOAuthProviderIds.set(provider, key);\n }\n return key;\n}\n\nfunction fetchFnCacheKey(fetchFn: typeof fetch | undefined): string | undefined {\n if (!fetchFn) return undefined;\n let key = modernFetchFnIds.get(fetchFn);\n if (!key) {\n key = `fetch:${++nextModernFetchFnId}`;\n modernFetchFnIds.set(fetchFn, key);\n }\n return key;\n}\n\nfunction connectionCacheKey(\n agentUrl: string,\n headers: Record<string, string>,\n signingCacheKey?: string,\n authProvider?: object,\n fetchFn?: typeof fetch\n): string {\n const normalizedHeaders = Object.entries(headers)\n .map(([key, value]) => [key.toLowerCase(), value] as const)\n .sort(([left], [right]) => left.localeCompare(right));\n const parts = [agentUrl, `headers:${cacheDisambiguator(JSON.stringify(normalizedHeaders))}`];\n if (signingCacheKey) parts.push(signingCacheKey);\n const providerKey = oauthProviderCacheKey(authProvider);\n if (providerKey) parts.push(providerKey);\n const fetchKey = fetchFnCacheKey(fetchFn);\n if (fetchKey) parts.push(fetchKey);\n return parts.join('::');\n}\n\nfunction isKnownLegacy(cacheKey: string): boolean {\n const classifiedAt = knownLegacyConnections.get(cacheKey);\n if (classifiedAt === undefined) return false;\n if (Date.now() - classifiedAt > LEGACY_CLASSIFICATION_TTL_MS) {\n knownLegacyConnections.delete(cacheKey);\n return false;\n }\n knownLegacyConnections.delete(cacheKey);\n knownLegacyConnections.set(cacheKey, classifiedAt);\n return true;\n}\n\nfunction markKnownLegacy(cacheKey: string): void {\n knownLegacyConnections.delete(cacheKey);\n knownLegacyConnections.set(cacheKey, Date.now());\n while (knownLegacyConnections.size > MAX_CACHED_CONNECTIONS) {\n const oldest = knownLegacyConnections.keys().next().value;\n if (!oldest) break;\n knownLegacyConnections.delete(oldest);\n }\n}\n\nfunction httpStatusOf(error: unknown, depth = 0): number | undefined {\n if (!error || typeof error !== 'object' || depth > 4) return undefined;\n const candidate = error as { status?: unknown; code?: unknown; cause?: unknown; response?: { status?: unknown } };\n if (typeof candidate.status === 'number') return candidate.status;\n if (typeof candidate.response?.status === 'number') return candidate.response.status;\n if (typeof candidate.code === 'number' && candidate.code >= 100 && candidate.code <= 599) return candidate.code;\n return httpStatusOf(candidate.cause, depth + 1);\n}\n\nfunction withPerRequestTraceHeaders(fetchImpl: typeof fetch): typeof fetch {\n return (input, init) => {\n const headers = new Headers(input instanceof Request ? input.headers : undefined);\n new Headers(init?.headers).forEach((value, key) => headers.set(key, value));\n for (const [key, value] of Object.entries(injectTraceHeaders())) headers.set(key, value);\n return fetchImpl(input, { ...init, headers });\n };\n}\n\nfunction getCachedConnection(cacheKey: string): Client | undefined {\n const client = modernConnections.get(cacheKey);\n if (client) {\n const legacyExpiry = legacyConnectionExpiresAt.get(cacheKey);\n if (legacyExpiry !== undefined && legacyExpiry <= Date.now()) {\n modernConnections.delete(cacheKey);\n legacyConnectionExpiresAt.delete(cacheKey);\n void client.close().catch(() => {});\n return undefined;\n }\n modernConnections.delete(cacheKey);\n modernConnections.set(cacheKey, client);\n }\n return client;\n}\n\nfunction evictLeastRecentlyUsed(): void {\n if (modernConnections.size <= MAX_CACHED_CONNECTIONS) return;\n const oldestKey = modernConnections.keys().next().value;\n if (!oldestKey) return;\n const client = modernConnections.get(oldestKey);\n modernConnections.delete(oldestKey);\n legacyConnectionExpiresAt.delete(oldestKey);\n void client?.close().catch(() => {});\n}\n\nasync function createNegotiatedClient(\n options: ModernConnectionOptions,\n authHeaders: Record<string, string>\n): Promise<Client> {\n const requestTimeoutMs = resolveRequestTimeoutMs(options.requestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(options.requestTimeoutMs);\n const rawNetworkFetch: typeof fetch = options.fetchFn ?? ((input, init) => fetch(input, init));\n const networkFetch: typeof fetch = (input, init) =>\n withAbortSignal<Response>([options.signal, init?.signal], requestTimeoutMs, signal =>\n rawNetworkFetch(input, { ...init, signal })\n );\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(wrapFetchWithSizeLimit(networkFetch));\n const signedFetch: typeof fetch = options.signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: options.signingContext.signing,\n getCapability: options.signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n const transport = new StreamableHTTPClientTransport(new URL(options.agentUrl), {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(withPerRequestTraceHeaders(signedFetch)),\n ...(options.authProvider && {\n authProvider: options.authProvider as ModernOAuthClientProvider,\n }),\n });\n const client = new Client(\n { name: 'AdCP-Client', version: '1.0.0' },\n {\n versionNegotiation: {\n mode: 'auto',\n ...(clientRequestTimeoutMs !== undefined && { probe: { timeoutMs: clientRequestTimeoutMs } }),\n },\n }\n );\n\n try {\n await client.connect(transport, {\n ...(options.signal && { signal: options.signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n });\n return client;\n } catch (error) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n throw error;\n }\n}\n\nasync function getOrCreateModernConnection(\n cacheKey: string,\n options: ModernConnectionOptions,\n authHeaders: Record<string, string>\n): Promise<Client> {\n const cached = getCachedConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingModernConnections.get(cacheKey);\n if (pending) return pending;\n\n const generation = connectionGeneration;\n const promise = createNegotiatedClient(options, authHeaders)\n .then(client => {\n if (\n (client.getProtocolEra() === 'modern' || options.handleLegacy === true) &&\n generation === connectionGeneration\n ) {\n modernConnections.set(cacheKey, client);\n if (client.getProtocolEra() === 'legacy') {\n legacyConnectionExpiresAt.set(cacheKey, Date.now() + LEGACY_CLASSIFICATION_TTL_MS);\n } else {\n legacyConnectionExpiresAt.delete(cacheKey);\n }\n evictLeastRecentlyUsed();\n } else if (generation !== connectionGeneration) {\n void client.close().catch(() => {});\n }\n return client;\n })\n .finally(() => {\n if (pendingModernConnections.get(cacheKey) === promise) pendingModernConnections.delete(cacheKey);\n });\n pendingModernConnections.set(cacheKey, promise);\n return promise;\n}\n\nasync function callOnModernClient(\n client: Client,\n toolName: string,\n args: Record<string, unknown>,\n signal?: AbortSignal,\n requestTimeoutMs?: number\n): Promise<CallToolResponse> {\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestTimeoutMs);\n return (await client.callTool(\n { name: toolName, arguments: args },\n {\n ...(signal && { signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n }\n )) as CallToolResponse;\n}\n\nasync function attemptModernCall(\n options: ModernConnectionOptions,\n toolName: string,\n args: Record<string, unknown>\n): Promise<ModernMCPAttempt> {\n const authHeaders = buildAuthHeaders(options.authToken, options.customHeaders, options.authProvider);\n const cacheKey = connectionCacheKey(\n options.agentUrl,\n authHeaders,\n options.signingContext?.cacheKey,\n options.authProvider,\n options.fetchFn\n );\n if (isKnownLegacy(cacheKey)) return { handled: false };\n\n const guardedConnection =\n options.signal !== undefined || options.requestTimeoutMs !== undefined || options.fetchFn !== undefined;\n let client: Client;\n try {\n client = guardedConnection\n ? await createNegotiatedClient(options, authHeaders)\n : await getOrCreateModernConnection(cacheKey, options, authHeaders);\n } catch (error) {\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) {\n markKnownLegacy(cacheKey);\n options.debugLogs.push({\n type: 'info',\n message: `MCP: Modern Streamable HTTP is unavailable (HTTP ${status}); preserving the v1 transport path`,\n timestamp: new Date().toISOString(),\n });\n return { handled: false };\n }\n throw error;\n }\n\n if (client.getProtocolEra() !== 'modern') {\n if (options.handleLegacy === true) {\n options.debugLogs.push({\n type: 'info',\n message: `MCP: v2 client selected the legacy protocol era for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n } else {\n markKnownLegacy(cacheKey);\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n options.debugLogs.push({\n type: 'info',\n message: `MCP: Server selected the legacy protocol era for ${toolName}; preserving the v1 Tasks path`,\n timestamp: new Date().toISOString(),\n });\n return { handled: false };\n }\n }\n\n options.debugLogs.push({\n type: 'success',\n message: `MCP: Negotiated protocol ${client.getNegotiatedProtocolVersion()} for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n\n try {\n const response = await callOnModernClient(client, toolName, args, options.signal, options.requestTimeoutMs);\n return { handled: true, response };\n } catch (error) {\n // A tool request may have reached the server even when its response was\n // lost. Never replay automatically: mutating AdCP tools depend on the\n // caller's explicit idempotency policy, not transport guesswork.\n modernConnections.delete(cacheKey);\n legacyConnectionExpiresAt.delete(cacheKey);\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n throw error;\n } finally {\n if (guardedConnection) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n }\n}\n\n/**\n * Try a tool call using the MCP 2026-07-28 protocol era.\n *\n * `handled: false` means the caller must use the existing v1 client. This is\n * deliberately a result rather than an exception because legacy negotiation\n * is normal during the transition window.\n */\nexport async function tryCallModernMCPTool(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<ModernMCPAttempt> {\n return withSpan('adcp.mcp.negotiate', { 'adcp.tool': toolName, 'http.url': agentUrl }, () =>\n signingContextStorage.run(options.signingContext, () =>\n attemptModernCall(\n {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs,\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n handleLegacy: options.handleLegacy,\n },\n toolName,\n args\n )\n )\n );\n}\n\n/**\n * Probe an endpoint with the official v2 client's auto negotiation.\n * `connected: false` lets endpoint discovery retain its v1 SSE fallback.\n */\nexport async function probeModernMCPConnection(\n agentUrl: string,\n authToken?: string,\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<{ connected: boolean; era?: 'legacy' | 'modern' }> {\n const connectionOptions: ModernConnectionOptions = {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs: [],\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n handleLegacy: options.handleLegacy,\n };\n const authHeaders = buildAuthHeaders(authToken, customHeaders, options.authProvider);\n let client: Client | undefined;\n try {\n client = await createNegotiatedClient(connectionOptions, authHeaders);\n return { connected: true, era: client.getProtocolEra() };\n } catch (error) {\n if (is401Error(error) || isAbortOrTimeoutError(error)) throw error;\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) return { connected: false };\n throw error;\n } finally {\n await client?.close().catch(() => {});\n }\n}\n\n/** List tools when the endpoint selected the modern era; otherwise let the v1 caller continue. */\nexport async function tryListModernMCPTools(\n agentUrl: string,\n authToken?: string,\n customHeaders?: Record<string, string>,\n options: ModernMCPConnectionOptions = {}\n): Promise<ModernMCPListAttempt> {\n const connectionOptions: ModernConnectionOptions = {\n agentUrl,\n authToken,\n customHeaders,\n debugLogs: [],\n signingContext: options.signingContext,\n authProvider: options.authProvider,\n signal: options.signal,\n requestTimeoutMs: options.requestTimeoutMs,\n fetchFn: options.fetchFn,\n };\n const authHeaders = buildAuthHeaders(authToken, customHeaders, options.authProvider);\n let client: Client | undefined;\n try {\n client = await createNegotiatedClient(connectionOptions, authHeaders);\n if (client.getProtocolEra() !== 'modern') return { handled: false };\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(options.requestTimeoutMs);\n const result = await client.listTools(undefined, {\n ...(options.signal && { signal: options.signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n });\n return { handled: true, tools: result.tools };\n } catch (error) {\n if (is401Error(error) || isAbortOrTimeoutError(error)) throw error;\n const status = httpStatusOf(error);\n if (status === 404 || status === 405) return { handled: false };\n throw error;\n } finally {\n await client?.close().catch(() => {});\n }\n}\n\nexport async function closeModernMCPConnections(): Promise<void> {\n connectionGeneration++;\n const pending = [...pendingModernConnections.values()];\n pendingModernConnections.clear();\n const settled = await Promise.allSettled(pending);\n const clients = new Set(modernConnections.values());\n for (const result of settled) {\n if (result.status === 'fulfilled') clients.add(result.value);\n }\n modernConnections.clear();\n legacyConnectionExpiresAt.clear();\n knownLegacyConnections.clear();\n for (const client of clients) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n}\n"],"mappings":"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","names":["require"]}