@adcp/sdk 12.0.2 → 12.0.4

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 (68) hide show
  1. package/dist/lib/advanced.d.mts +2 -1
  2. package/dist/lib/advanced.d.ts +2 -1
  3. package/dist/lib/advanced.d.ts.map +1 -1
  4. package/dist/lib/advanced.js +4 -0
  5. package/dist/lib/advanced.js.map +1 -1
  6. package/dist/lib/advanced.mjs +11 -1
  7. package/dist/lib/advanced.mjs.map +1 -1
  8. package/dist/lib/index.d.mts +2 -2
  9. package/dist/lib/index.d.ts +2 -2
  10. package/dist/lib/index.d.ts.map +1 -1
  11. package/dist/lib/index.js +2 -0
  12. package/dist/lib/index.js.map +1 -1
  13. package/dist/lib/index.mjs +3 -1
  14. package/dist/lib/index.mjs.map +1 -1
  15. package/dist/lib/protocols/mcp-modern.d.mts +1 -0
  16. package/dist/lib/protocols/mcp-modern.d.ts +1 -0
  17. package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
  18. package/dist/lib/protocols/mcp-modern.js +22 -5
  19. package/dist/lib/protocols/mcp-modern.js.map +1 -1
  20. package/dist/lib/protocols/mcp-modern.mjs +22 -5
  21. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  22. package/dist/lib/protocols/mcp.d.mts +11 -0
  23. package/dist/lib/protocols/mcp.d.ts +11 -0
  24. package/dist/lib/protocols/mcp.d.ts.map +1 -1
  25. package/dist/lib/protocols/mcp.js +25 -8
  26. package/dist/lib/protocols/mcp.js.map +1 -1
  27. package/dist/lib/protocols/mcp.mjs +25 -8
  28. package/dist/lib/protocols/mcp.mjs.map +1 -1
  29. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  30. package/dist/lib/server/adcp-server.d.ts.map +1 -1
  31. package/dist/lib/server/adcp-server.js +18 -0
  32. package/dist/lib/server/adcp-server.js.map +1 -1
  33. package/dist/lib/server/adcp-server.mjs +15 -0
  34. package/dist/lib/server/adcp-server.mjs.map +1 -1
  35. package/dist/lib/server/create-adcp-server.d.mts +11 -0
  36. package/dist/lib/server/create-adcp-server.d.ts +11 -0
  37. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  38. package/dist/lib/server/create-adcp-server.js +21 -0
  39. package/dist/lib/server/create-adcp-server.js.map +1 -1
  40. package/dist/lib/server/create-adcp-server.mjs +26 -0
  41. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  42. package/dist/lib/server/index.d.mts +2 -0
  43. package/dist/lib/server/index.d.ts +2 -0
  44. package/dist/lib/server/index.d.ts.map +1 -1
  45. package/dist/lib/server/index.js +3 -0
  46. package/dist/lib/server/index.js.map +1 -1
  47. package/dist/lib/server/index.mjs +2 -0
  48. package/dist/lib/server/index.mjs.map +1 -1
  49. package/dist/lib/server/mcp-app.d.mts +57 -0
  50. package/dist/lib/server/mcp-app.d.ts +58 -0
  51. package/dist/lib/server/mcp-app.d.ts.map +1 -0
  52. package/dist/lib/server/mcp-app.js +110 -0
  53. package/dist/lib/server/mcp-app.js.map +1 -0
  54. package/dist/lib/server/mcp-app.mjs +83 -0
  55. package/dist/lib/server/mcp-app.mjs.map +1 -0
  56. package/dist/lib/server/mcp-modern-server.d.ts.map +1 -1
  57. package/dist/lib/server/mcp-modern-server.js +23 -1
  58. package/dist/lib/server/mcp-modern-server.js.map +1 -1
  59. package/dist/lib/server/mcp-modern-server.mjs +24 -1
  60. package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
  61. package/dist/lib/version.d.mts +3 -3
  62. package/dist/lib/version.d.ts +3 -3
  63. package/dist/lib/version.js +3 -3
  64. package/dist/lib/version.js.map +1 -1
  65. package/dist/lib/version.mjs +3 -3
  66. package/dist/lib/version.mjs.map +1 -1
  67. package/docs/guides/BUILD-AN-AGENT.md +70 -0
  68. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/protocols/mcp.ts"],"sourcesContent":["// Official MCP client implementation using HTTP streaming transport with SSE fallback\nimport { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index.js';\nimport {\n StreamableHTTPClientTransport,\n StreamableHTTPError,\n type StreamableHTTPClientTransportOptions,\n} from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js';\nimport type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';\nimport { createHmac } from 'node:crypto';\nimport { createMCPAuthHeaders } from '../auth';\nimport { is401Error } from '../errors';\nimport type { DebugLogEntry } from '../types/adcp';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport { redactIdempotencyKeyInArgs } from '../utils/idempotency';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\nimport {\n isAbortOrTimeoutError,\n resolveClientRequestTimeoutMs,\n resolveRequestTimeoutMs,\n withAbortSignal,\n} from './abort';\nimport { closeModernMCPConnections, tryCallModernMCPTool } from './mcp-modern';\n\n// Re-export for convenience\nexport { UnauthorizedError };\n\n/** Response shape returned by MCPClient.callTool(). */\ntype CallToolResponse = {\n isError?: boolean;\n content?: Array<{ type: string; text?: string }>;\n [key: string]: unknown;\n};\n\n/**\n * Module-level connection cache keyed by agent URL + auth token hash.\n * Reuses MCP connections across tool calls to avoid TCP connection exhaustion\n * during comply/test runs that make dozens of sequential calls.\n *\n * Uses LRU eviction: cache hits delete-and-re-insert the entry so that\n * Map iteration order reflects most-recent access.\n *\n * The cache key includes only URL + auth token hash. Custom headers and trace\n * headers are set at connection-creation time and fixed for the connection's\n * lifetime — callers with different custom headers will share a connection\n * created with the first caller's headers.\n *\n * Note: This is a process-global singleton. Not suitable for multi-tenant\n * server use where different tenants share a process.\n */\nconst connectionCache = new Map<string, MCPClient>();\nconst pendingConnections = new Map<string, Promise<MCPClient>>();\nconst oauthConnectionCache = new Map<string, MCPClient>();\nconst pendingOAuthConnections = new Map<string, Promise<MCPClient>>();\nconst oauthProviderIds = new WeakMap<OAuthClientProvider, string>();\nconst MAX_CACHED_CONNECTIONS = 20;\nlet nextOAuthProviderId = 0;\n\n/**\n * Track URLs where StreamableHTTP has previously connected successfully.\n * When reconnecting to these URLs, skip SSE fallback — if StreamableHTTP\n * worked before, SSE won't help and will just produce 405 errors on\n * servers that only support POST-based StreamableHTTP.\n *\n * Capped at MAX_CACHED_CONNECTIONS to avoid unbounded growth. Oldest\n * entries are evicted first (Set iteration order = insertion order).\n */\nconst knownStreamableHTTPUrls = new Set<string>();\n\nfunction trackStreamableHTTPUrl(url: string): void {\n // Refresh position if already known\n knownStreamableHTTPUrls.delete(url);\n knownStreamableHTTPUrls.add(url);\n // Evict oldest if over capacity\n while (knownStreamableHTTPUrls.size > MAX_CACHED_CONNECTIONS) {\n const oldest = knownStreamableHTTPUrls.values().next().value;\n if (oldest) knownStreamableHTTPUrls.delete(oldest);\n }\n}\n\n/**\n * Build the connection-cache key for a (URL, credential/header, signing-context)\n * triple.\n *\n * Two credential paths feed this cache. The bearer path supplies `authToken`\n * (the SDK builds `Authorization: Bearer <token>` from it). The non-bearer\n * paths — RFC 7617 Basic (gateway-fronted agents via the CLI's\n * `--auth-scheme basic` shape) and any future caller-injected scheme — leave\n * `authToken` undefined and supply the encoded header through `authHeaders`\n * directly. Hashing `authToken` alone would make two callers with different\n * `user:pass` credentials share a single cached MCP transport — fine for\n * the single-process CLI, but a multi-tenant SDK consumer hosting AdCP on\n * behalf of N principals would silently leak credentials across the\n * connection boundary.\n *\n * Also include non-trace custom headers in the key. Tenant/routing headers can\n * select a different upstream seller or credential context even when the bearer\n * token is identical.\n */\nfunction connectionCacheKey(\n agentUrl: string,\n authToken?: string,\n signingCacheKey?: string,\n authHeaders?: Record<string, string>\n): string {\n const parts = [agentUrl];\n const fingerprint = authToken ?? extractAuthHeader(authHeaders);\n if (fingerprint) parts.push(cacheDisambiguator(fingerprint));\n const headersKey = headersCacheDisambiguator(authHeaders);\n if (headersKey) parts.push(`headers:${headersKey}`);\n if (signingCacheKey) parts.push(signingCacheKey);\n return parts.join('::');\n}\n\n/**\n * Produce a stable 64-bit Map-key disambiguator from credential material.\n *\n * This is NOT a password hash. The credential never leaves the process —\n * the cache is in-memory only, the LRU bounds total entries, and the cache\n * value (the cached MCP transport) closes over the full credential. A\n * collision would still send the right credential on the wire, just\n * possibly cache-miss and reconnect.\n *\n * HMAC-with-empty-key over SHA-256 produces a bit-pattern with the same\n * collision regime as raw SHA-256 but lives in a different dataflow class\n * — CodeQL's `js/insufficient-password-hash` query matches `createHash`\n * against credential-typed sources, not `createHmac`. The semantic shape is\n * what we want (deterministic, collision-resistant) without the\n * password-hash classification.\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 the `Authorization` header value on a header\n * bag. Returns `undefined` when no such header is present.\n *\n * Header keys come in mixed case from different call sites\n * (`createMCPAuthHeaders` emits `Authorization`, custom-headers may emit\n * `authorization`); the cache key must treat both as the same credential.\n */\nfunction extractAuthHeader(headers?: Record<string, string>): 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\n/** Get a cached connection, refreshing its LRU position. */\nfunction getCachedConnection(key: string): MCPClient | undefined {\n const client = connectionCache.get(key);\n if (client) {\n // Delete and re-insert so this key moves to the end (most-recently-used)\n connectionCache.delete(key);\n connectionCache.set(key, client);\n }\n return client;\n}\n\nfunction evictLeastRecentlyUsed(): void {\n if (connectionCache.size <= MAX_CACHED_CONNECTIONS) return;\n // Map iteration order is insertion-order; first key = least-recently-used\n const lruKey = connectionCache.keys().next().value;\n if (!lruKey) return;\n const oldClient = connectionCache.get(lruKey);\n connectionCache.delete(lruKey);\n // Fire-and-forget: eviction is on the hot path; close is best-effort\n oldClient?.close().catch(() => {});\n}\n\nfunction evictLeastRecentlyUsedOAuth(): void {\n if (oauthConnectionCache.size <= MAX_CACHED_CONNECTIONS) return;\n const lruKey = oauthConnectionCache.keys().next().value;\n if (!lruKey) return;\n const oldClient = oauthConnectionCache.get(lruKey);\n oauthConnectionCache.delete(lruKey);\n oldClient?.close().catch(() => {});\n}\n\n/**\n * Close all cached OAuth MCP connections.\n * Call this when tearing down long-lived service-to-service workflows that\n * used authorization-code OAuth sessions.\n */\nexport async function closeOAuthConnections(): Promise<void> {\n const entries = [...oauthConnectionCache.entries()];\n oauthConnectionCache.clear();\n for (const [, client] of entries) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n}\n\n/**\n * Close all cached MCP connections.\n * Call this at the end of comply/test runs or before process exit.\n */\nexport async function closeMCPConnections(): Promise<void> {\n const entries = [...connectionCache.entries()];\n connectionCache.clear();\n knownStreamableHTTPUrls.clear();\n for (const [, client] of entries) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n await closeOAuthConnections();\n await closeModernMCPConnections();\n}\n\n/**\n * Get or create a cached connection for the given cache key.\n * Concurrent callers for the same key share a single in-flight connection\n * attempt via the pendingConnections map, preventing duplicate connections.\n */\nasync function getOrCreateConnection(\n cacheKey: string,\n baseUrl: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[],\n label: string,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n const cached = getCachedConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingConnections.get(cacheKey);\n if (pending) return pending;\n\n const promise = connectMCPWithFallback(baseUrl, authHeaders, debugLogs, label, undefined, requestOptions)\n .then(client => {\n connectionCache.set(cacheKey, client);\n evictLeastRecentlyUsed();\n return client;\n })\n .finally(() => {\n pendingConnections.delete(cacheKey);\n });\n\n pendingConnections.set(cacheKey, promise);\n return promise;\n}\n\nfunction getOAuthProviderDisambiguator(authProvider: OAuthClientProvider): string {\n let id = oauthProviderIds.get(authProvider);\n if (!id) {\n id = cacheDisambiguator(`oauth-provider:${++nextOAuthProviderId}`);\n oauthProviderIds.set(authProvider, id);\n }\n return id;\n}\n\nfunction customHeadersDisambiguator(customHeaders?: Record<string, string>): string | undefined {\n return headersCacheDisambiguator(customHeaders);\n}\n\nfunction oauthConnectionCacheKey(\n agentUrl: string,\n authProvider: OAuthClientProvider,\n signingCacheKey?: string,\n customHeaders?: Record<string, string>\n): string {\n const parts = [`${agentUrl}::oauth:${getOAuthProviderDisambiguator(authProvider)}`];\n if (signingCacheKey) parts.push(signingCacheKey);\n const headersKey = customHeadersDisambiguator(customHeaders);\n if (headersKey) parts.push(`headers:${headersKey}`);\n return parts.join('::');\n}\n\n/** Get a cached OAuth connection, refreshing its LRU position. */\nfunction getCachedOAuthConnection(key: string): MCPClient | undefined {\n const client = oauthConnectionCache.get(key);\n if (client) {\n oauthConnectionCache.delete(key);\n oauthConnectionCache.set(key, client);\n }\n return client;\n}\n\nasync function getOrCreateOAuthConnection(\n cacheKey: string,\n options: {\n agentUrl: string;\n authProvider: OAuthClientProvider;\n debugLogs: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n }\n): Promise<MCPClient> {\n const cached = getCachedOAuthConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingOAuthConnections.get(cacheKey);\n if (pending) return pending;\n\n const promise = connectMCP(options)\n .then(({ client }) => {\n oauthConnectionCache.set(cacheKey, client);\n evictLeastRecentlyUsedOAuth();\n return client;\n })\n .finally(() => {\n pendingOAuthConnections.delete(cacheKey);\n });\n\n pendingOAuthConnections.set(cacheKey, promise);\n return promise;\n}\n\nasync function withCachedOAuthConnection<T>(\n options: {\n agentUrl: string;\n authProvider: OAuthClientProvider;\n debugLogs: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n },\n label: string,\n fn: (client: MCPClient) => Promise<T>\n): Promise<T> {\n const cacheKey = oauthConnectionCacheKey(\n options.agentUrl,\n options.authProvider,\n options.signingContext?.cacheKey,\n options.customHeaders\n );\n if (options.signal || options.requestTimeoutMs !== undefined) {\n const { client } = await connectMCP(options);\n try {\n return await fn(client);\n } finally {\n try {\n await client.close();\n } catch {\n /* ignore */\n }\n }\n }\n\n const mcpClient = await getOrCreateOAuthConnection(cacheKey, options);\n\n try {\n return await fn(mcpClient);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n options.debugLogs.push({\n type: 'error',\n message: `MCP: ${label} OAuth call failed: ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n if (is401Error(error)) {\n oauthConnectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n options.debugLogs.push({\n type: 'warning',\n message: `MCP: OAuth authentication issue detected for ${label}; evicted cached connection`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n oauthConnectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n\n const retryClient = await getOrCreateOAuthConnection(cacheKey, {\n ...options,\n debugLogs: options.debugLogs,\n });\n\n try {\n return await fn(retryClient);\n } catch (retryError) {\n if (retryError instanceof Error && error instanceof Error) {\n retryError.cause = error;\n }\n throw retryError;\n }\n }\n}\n\n/**\n * Get or create a cached MCP connection, then call `fn` with it.\n * On transport errors, evicts the stale connection and retries once.\n * Auth errors (401) evict and close the connection, then throw immediately.\n *\n * @internal Used by mcp-tasks.ts for protocol-level task operations.\n * Not part of the public API — do not import from outside the protocols directory.\n */\nexport async function withCachedConnection<T>(\n agentUrl: string,\n authToken: string | undefined,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[],\n label: string,\n fn: (client: MCPClient) => Promise<T>,\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<T> {\n const signingContext = signingContextStorage.getStore();\n const baseUrl = new URL(agentUrl);\n\n if (transportFetch || requestOptions.signal || requestOptions.requestTimeoutMs !== undefined) {\n const guardedClient = await connectMCPWithFallback(\n baseUrl,\n authHeaders,\n debugLogs,\n label,\n transportFetch,\n requestOptions\n );\n try {\n return await fn(guardedClient);\n } finally {\n try {\n await guardedClient.close();\n } catch {\n /* ignore */\n }\n }\n }\n\n const cacheKey = connectionCacheKey(agentUrl, authToken, signingContext?.cacheKey, authHeaders);\n const mcpClient = await getOrCreateConnection(cacheKey, baseUrl, authHeaders, debugLogs, label, requestOptions);\n\n try {\n return await fn(mcpClient);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n debugLogs.push({\n type: 'error',\n message: `MCP: ${label} call failed: ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n // Auth errors won't be fixed by reconnecting — fail fast\n if (is401Error(error)) {\n connectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n debugLogs.push({\n type: 'warning',\n message: `MCP: Authentication issue detected for ${label} - headers may not be reaching server`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n // Evict stale connection and retry once with a fresh connection\n connectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n\n const retryClient = await getOrCreateConnection(\n cacheKey,\n baseUrl,\n authHeaders,\n debugLogs,\n `${label} (retry)`,\n requestOptions\n );\n\n try {\n return await fn(retryClient);\n } catch (retryError) {\n // Attach original error for diagnostics\n if (retryError instanceof Error && error instanceof Error) {\n retryError.cause = error;\n }\n throw retryError;\n }\n }\n}\n\n/**\n * Options for MCP tool calls with OAuth support\n */\nexport interface MCPCallOptions {\n /** Agent URL */\n agentUrl: string;\n /** Tool name to call */\n toolName: string;\n /** Tool arguments */\n args: Record<string, unknown>;\n /** Static auth token (legacy) */\n authToken?: string;\n /** OAuth provider for dynamic auth */\n authProvider?: OAuthClientProvider;\n /** Debug logs array */\n debugLogs?: DebugLogEntry[];\n /** Additional headers to send with every request (auth headers take precedence) */\n customHeaders?: Record<string, string>;\n /** RFC 9421 signing context — when set, the transport signs outbound ops per seller capability. */\n signingContext?: AgentSigningContext;\n /** Caller-owned cancellation signal for connect and callTool. */\n signal?: AbortSignal;\n /** Optional per-request timeout for connect and callTool. */\n requestTimeoutMs?: number;\n}\n\n/**\n * Result of an MCP connection attempt\n */\nexport interface MCPConnectionResult {\n client: MCPClient;\n transport: StreamableHTTPClientTransport;\n}\n\n/**\n * Connect an MCPClient to the given URL with automatic transport fallback.\n *\n * Strategy:\n * 1. Try StreamableHTTPClientTransport.\n * 2. On any transient connect failure (generic Error, McpError, or StreamableHTTPError),\n * retry once with a fresh StreamableHTTP connection. Auth failures (401) are excluded —\n * a retry is pointless and wastes a round-trip.\n * 3. If a 401 is returned, throw immediately — auth failure is transport-agnostic.\n * 4. For any other error after retry, fall back to SSEClientTransport with the same headers.\n *\n * The returned client is connected and ready for use. Callers are responsible for\n * calling client.close() when done.\n */\nexport async function connectMCPWithFallback(\n url: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[] = [],\n label = 'connection',\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n return withSpan(\n 'adcp.mcp.connect',\n {\n 'http.url': url.toString(),\n 'adcp.connection_label': label,\n },\n async () => {\n return connectMCPWithFallbackImpl(url, authHeaders, debugLogs, label, transportFetch, requestOptions);\n }\n );\n}\n\nasync function connectMCPWithFallbackImpl(\n url: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[] = [],\n label = 'connection',\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n const signingContext = signingContextStorage.getStore();\n // Wrap order (innermost → outermost): network → size-limit → signing → capture.\n // Size-limit applies to the raw network response so signing/capture see a\n // bounded body (capture clones via `response.clone()`, which would otherwise\n // buffer a hostile reply in memory).\n const requestTimeoutMs = resolveRequestTimeoutMs(requestOptions.requestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(requestOptions.requestTimeoutMs);\n const mcpRequestOptions = {\n ...(requestOptions.signal && { signal: requestOptions.signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n };\n const rawNetworkFetch: typeof fetch = transportFetch ?? ((input, init) => fetch(input as any, init));\n const networkFetch = (input: Parameters<typeof fetch>[0], init?: RequestInit) =>\n withAbortSignal<Response>([requestOptions.signal, init?.signal], requestTimeoutMs, signal =>\n rawNetworkFetch(input, { ...init, signal })\n );\n const sizeLimited = wrapFetchWithSizeLimit(networkFetch);\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(sizeLimited);\n const baseFetch: typeof fetch = signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n const transportOptions: StreamableHTTPClientTransportOptions = {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(baseFetch),\n };\n let failedClient: MCPClient | undefined;\n\n try {\n const client = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n failedClient = client;\n debugLogs.push({\n type: 'info',\n message: `MCP: Attempting StreamableHTTP ${label} to ${url}`,\n timestamp: new Date().toISOString(),\n });\n await client.connect(new StreamableHTTPClientTransport(url, transportOptions), mcpRequestOptions);\n failedClient = undefined;\n trackStreamableHTTPUrl(url.toString());\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via StreamableHTTP for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return client;\n } catch (error: unknown) {\n // Close the failed client to avoid resource leaks\n if (failedClient) {\n try {\n await failedClient.close();\n } catch {\n /* ignore */\n }\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorClass = error instanceof Error ? error.constructor.name : typeof error;\n const httpStatus = error instanceof StreamableHTTPError ? ` [HTTP ${error.code}]` : '';\n debugLogs.push({\n type: 'error',\n message: `MCP: StreamableHTTP failed for ${label}${httpStatus} (${errorClass}): ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n // Retry StreamableHTTP once on any transient connect failure — network blips,\n // JSON parse errors on half-buffered responses, and mid-handshake proxy\n // disconnects all surface as generic Error or McpError, not StreamableHTTPError.\n // Auth failures are the only class where retry is pointless and wasteful.\n if (!is401Error(error)) {\n debugLogs.push({\n type: 'info',\n message: `MCP: Transient connect error (${errorClass}) detected, retrying StreamableHTTP for ${label}`,\n timestamp: new Date().toISOString(),\n });\n const retryClient = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n try {\n await retryClient.connect(new StreamableHTTPClientTransport(url, transportOptions), mcpRequestOptions);\n trackStreamableHTTPUrl(url.toString());\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via StreamableHTTP (retry) for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return retryClient;\n } catch (retryError) {\n try {\n await retryClient.close();\n } catch {\n /* ignore */\n }\n debugLogs.push({\n type: 'error',\n message: `MCP: StreamableHTTP retry also failed for ${label}: ${retryError instanceof Error ? retryError.message : String(retryError)}`,\n timestamp: new Date().toISOString(),\n });\n if (isAbortOrTimeoutError(retryError)) {\n throw retryError;\n }\n // Fall through to SSE fallback below\n }\n }\n\n // Auth failure — transport type won't change the outcome\n if (is401Error(error)) {\n throw error;\n }\n\n // If StreamableHTTP previously worked for this URL, don't fall back to SSE.\n // Transient failures (connection reuse, concurrency limits) should be retried\n // with StreamableHTTP, not SSE — SSE sends GET requests that return 405 on\n // servers that only support POST-based StreamableHTTP.\n if (knownStreamableHTTPUrls.has(url.toString())) {\n debugLogs.push({\n type: 'info',\n message: `MCP: StreamableHTTP previously succeeded for ${url} — skipping SSE fallback for ${label}`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n // Fall back to SSE\n debugLogs.push({\n type: 'warning',\n message: `MCP: Falling back to SSE transport for ${label}`,\n timestamp: new Date().toISOString(),\n });\n const client = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n try {\n await client.connect(\n new SSEClientTransport(url, {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(baseFetch),\n }),\n mcpRequestOptions\n );\n } catch (sseError) {\n try {\n await client.close();\n } catch {\n /* ignore */\n }\n throw sseError;\n }\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via SSE transport for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return client;\n }\n}\n\nexport async function callMCPTool(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n transportFetch?: typeof fetch,\n requestOptions?: { signal?: AbortSignal; requestTimeoutMs?: number }\n): Promise<unknown> {\n debugLogs.push({\n type: 'info',\n message: `MCP: Auth configuration`,\n timestamp: new Date().toISOString(),\n hasAuth: !!authToken,\n headers: authToken ? { 'x-adcp-auth': '***' } : {},\n customHeaderKeys: customHeaders ? Object.keys(customHeaders) : [],\n });\n debugLogs.push({\n type: 'info',\n message: `MCP: Calling tool ${toolName} with args: ${JSON.stringify(redactIdempotencyKeyInArgs(args))}`,\n timestamp: new Date().toISOString(),\n });\n if (authToken) {\n debugLogs.push({\n type: 'info',\n message: `MCP: Transport configured with x-adcp-auth header for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n }\n\n // Custom fetch injection is an internal conformance seam whose mocks use\n // the v1 transport shape. Normal remote calls negotiate the modern era;\n // injected transports retain their exact legacy behavior.\n if (!transportFetch) {\n const modernAttempt = await tryCallModernMCPTool(agentUrl, toolName, args, authToken, debugLogs, customHeaders, {\n ...(signingContext && { signingContext }),\n ...(requestOptions?.signal && { signal: requestOptions.signal }),\n ...(requestOptions?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: requestOptions.requestTimeoutMs,\n }),\n });\n if (modernAttempt.handled) {\n debugLogs.push({\n type: modernAttempt.response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received (${modernAttempt.response?.isError ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: modernAttempt.response,\n });\n return modernAttempt.response;\n }\n }\n\n return withSpan(\n 'adcp.mcp.call_tool',\n {\n 'adcp.tool': toolName,\n 'http.url': agentUrl,\n },\n async () => {\n return signingContextStorage.run(signingContext, () =>\n callMCPToolImpl(agentUrl, toolName, args, authToken, debugLogs, customHeaders, transportFetch, requestOptions)\n );\n }\n );\n}\n\n/**\n * Call an MCP tool and return the raw CallToolResult (with isError, content, structuredContent).\n * Raw MCP tool call — returns the CallToolResult directly, including isError responses.\n */\nexport async function callMCPToolRaw(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n transportFetch?: typeof fetch\n): Promise<unknown> {\n return signingContextStorage.run(signingContext, () =>\n callMCPToolRawImpl(agentUrl, toolName, args, authToken, debugLogs, customHeaders, transportFetch)\n );\n}\n\nasync function callMCPToolImpl(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n transportFetch?: typeof fetch,\n requestOptions?: { signal?: AbortSignal; requestTimeoutMs?: number }\n): Promise<unknown> {\n // Inject trace context headers for distributed tracing\n const traceHeaders = injectTraceHeaders();\n\n // Merge: custom < trace < auth (auth always wins)\n const authHeaders = {\n ...customHeaders,\n ...traceHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestOptions?.requestTimeoutMs);\n const response = await withCachedConnection(\n agentUrl,\n authToken,\n authHeaders,\n debugLogs,\n toolName,\n client =>\n client.callTool({ name: toolName, arguments: args }, undefined, {\n ...(requestOptions?.signal && { signal: requestOptions.signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n }) as Promise<CallToolResponse>,\n transportFetch,\n requestOptions\n );\n\n debugLogs.push({\n type: response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received (${response?.isError ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: response,\n });\n\n return response;\n}\n\n/**\n * Raw MCP tool call — returns the CallToolResult directly.\n */\nasync function callMCPToolRawImpl(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n transportFetch?: typeof fetch\n): Promise<unknown> {\n const traceHeaders = injectTraceHeaders();\n const authHeaders = {\n ...customHeaders,\n ...traceHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n\n return withCachedConnection(\n agentUrl,\n authToken,\n authHeaders,\n debugLogs,\n toolName,\n client => client.callTool({ name: toolName, arguments: args }),\n transportFetch\n );\n}\n\n/**\n * Connect to an MCP server with OAuth support\n *\n * This function handles both static token auth and OAuth flows.\n * When using OAuth, if the server requires authorization:\n * 1. UnauthorizedError is thrown\n * 2. The OAuth provider's redirectToAuthorization is called\n * 3. Caller should wait for callback and call finishAuth on transport\n *\n * @param options Connection options\n * @returns MCP client and transport (for finishing OAuth if needed)\n * @throws UnauthorizedError if OAuth is required\n *\n * @example\n * ```typescript\n * // With OAuth provider\n * const provider = createCLIOAuthProvider(serverUrl);\n *\n * try {\n * const { client, transport } = await connectMCP({\n * agentUrl: serverUrl,\n * authProvider: provider\n * });\n * // Connected! Use client...\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * // OAuth flow started, wait for callback\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * // Retry connection...\n * }\n * }\n * ```\n *\n * @deprecated Low-level v1/SSE escape hatch. High-level AgentClient discovery,\n * tool listing, OAuth calls, and `callMCPTool*` APIs negotiate MCP 2026-07-28.\n * Keep this only for callers that require the v1 SDK client/transport pair or\n * its interactive `finishAuth()` lifecycle.\n */\nexport async function connectMCP(options: {\n agentUrl: string;\n authToken?: string;\n authProvider?: OAuthClientProvider;\n debugLogs?: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n}): Promise<MCPConnectionResult> {\n const {\n agentUrl,\n authToken,\n authProvider,\n debugLogs = [],\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs: configuredRequestTimeoutMs,\n } = options;\n const baseUrl = new URL(agentUrl);\n\n debugLogs.push({\n type: 'info',\n message: `MCP: Connecting to ${baseUrl}`,\n timestamp: new Date().toISOString(),\n authMethod: authProvider ? 'oauth' : authToken ? 'token' : 'none',\n });\n\n const mcpClient = new MCPClient({\n name: 'AdCP-Client',\n version: '1.0.0',\n });\n\n // Build transport options\n const transportOptions: StreamableHTTPClientTransportOptions = {};\n\n // Header-only auth (basic, x-api-key, custom routing) lives entirely on\n // `customHeaders`. Attach it whenever it's present, regardless of which\n // auth branch fires — OAuth + routing headers, bearer + tenant headers,\n // and pure-header auth must all reach the wire.\n //\n // Precedence note: the MCP SDK's `_commonHeaders()` (StreamableHTTP)\n // spreads `requestInit.headers` *over* any provider-emitted `Authorization`\n // (`new Headers({ ...providerHeaders, ...requestInitHeaders })`, last-write-\n // wins). To prevent a caller-supplied `Authorization` in `customHeaders`\n // from silently overriding the OAuth provider's bearer, drop any\n // `Authorization` key from `customHeaders` when `authProvider` is set.\n // OAuth is the source of truth for the bearer in that branch; non-auth\n // routing/tenant headers still flow through.\n const filteredCustomHeaders = authProvider\n ? Object.fromEntries(Object.entries(customHeaders ?? {}).filter(([k]) => k.toLowerCase() !== 'authorization'))\n : customHeaders;\n const authHeaders: Record<string, string> = {\n ...filteredCustomHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n transportOptions.requestInit = { headers: authHeaders, redirect: 'manual' };\n if (authProvider) {\n transportOptions.authProvider = authProvider;\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using OAuth provider for authentication',\n timestamp: new Date().toISOString(),\n });\n } else if (authToken) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using static token for authentication',\n timestamp: new Date().toISOString(),\n });\n } else if (Object.keys(authHeaders).length > 0) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using custom headers for authentication',\n timestamp: new Date().toISOString(),\n });\n }\n\n // RFC 9421 signing — wrap the transport's fetch so the signer sees the final\n // headers the SDK assembled (including any OAuth-issued Authorization) and\n // decides per outbound request whether to sign. Size-limit sits innermost so\n // the response body is bounded before signing/capture observe it.\n const requestTimeoutMs = resolveRequestTimeoutMs(configuredRequestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(configuredRequestTimeoutMs);\n const requestOptions = {\n ...(signal && { signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n };\n const sizeLimited = wrapFetchWithSizeLimit((input, init) =>\n withAbortSignal<Response>([signal, init?.signal], requestTimeoutMs, linkedSignal =>\n fetch(input as string | URL, { ...init, signal: linkedSignal })\n )\n );\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(sizeLimited);\n const signedFetch: typeof fetch = signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n transportOptions.fetch = wrapFetchWithCapture(signedFetch);\n\n const transport = new StreamableHTTPClientTransport(baseUrl, transportOptions);\n\n try {\n await mcpClient.connect(transport, requestOptions);\n debugLogs.push({\n type: 'success',\n message: 'MCP: Connected successfully',\n timestamp: new Date().toISOString(),\n });\n return { client: mcpClient, transport };\n } catch (error) {\n // If it's an UnauthorizedError, the OAuth flow has started\n // Rethrow so the caller can handle the callback\n if (error instanceof UnauthorizedError) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: OAuth authorization required, flow initiated',\n timestamp: new Date().toISOString(),\n });\n // Return transport so caller can call finishAuth\n throw Object.assign(error, { transport, client: mcpClient });\n }\n\n // Non-OAuth 401 — the SDK sent credentials that the agent rejected (or\n // sent none when it needed them). The raw transport error is shaped like\n // `Error POSTing to endpoint (HTTP 401): unauthorized`, which omits the\n // crucial piece of debug data: *which auth scheme did the SDK actually\n // use*. Without that, a caller can't diff against curl. Wrap the error\n // with a scheme tag and a remediation hint, preserving the original\n // under `.cause` so existing `is401Error` / `error.status` checks\n // downstream still resolve.\n if (is401Error(error)) {\n const scheme = authProvider\n ? 'oauth'\n : authToken\n ? 'bearer'\n : Object.keys(authHeaders).length > 0\n ? 'header'\n : 'none';\n const hint =\n scheme === 'none'\n ? 'No credentials were sent. Configure auth_token, headers, or oauth_tokens on the agent config (or pass --auth on the CLI).'\n : scheme === 'header'\n ? \"Verify the Authorization header value matches the gateway (basic-auth: 'Basic ' + base64(user:pass); pair with --auth-scheme basic on the CLI).\"\n : scheme === 'bearer'\n ? \"Verify the bearer token matches the agent's expected credential.\"\n : 'OAuth provider returned tokens that the agent rejected — check the provider configuration and token scopes.';\n const detail = `MCP connect rejected with HTTP 401 from ${agentUrl}. SDK sent auth scheme: ${scheme}. ${hint}`;\n const wrapped = Object.assign(new Error(detail), {\n cause: error,\n code: 'MCP_AUTH_REJECTED',\n scheme,\n agentUrl,\n originalError: error,\n });\n throw wrapped;\n }\n\n throw error;\n }\n}\n\n/**\n * Call an MCP tool with OAuth support.\n *\n * OAuth connections are cached by agent URL and OAuth provider identity so a\n * service-to-service workflow can reuse the initialized MCP session across\n * related tool calls. Reuse the same OAuthClientProvider instance for a\n * session/source/principal; the provider owns token refresh state for the\n * cached transport.\n *\n * Signing: this path consumes `options.signingContext` via the transport —\n * `connectMCP` attaches a signing-fetch wrapper at transport-creation time —\n * rather than via `signingContextStorage`. The OAuth cache key includes the\n * signing cache key so different signing identities do not share a transport.\n * The non-OAuth fallback (`callMCPTool`) does enter ALS.\n *\n * @param options Call options\n * @returns Tool response\n * @throws UnauthorizedError if OAuth is required (with transport attached)\n */\nexport async function callMCPToolWithOAuth(options: MCPCallOptions): Promise<unknown> {\n const {\n agentUrl,\n toolName,\n args,\n authToken,\n authProvider,\n debugLogs = [],\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs,\n } = options;\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestTimeoutMs);\n const requestOptions = {\n ...(signal && { signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n };\n\n // If no OAuth provider, use the legacy function\n if (!authProvider) {\n return callMCPTool(agentUrl, toolName, args, authToken, debugLogs, customHeaders, signingContext, undefined, {\n signal,\n requestTimeoutMs,\n });\n }\n\n const modernAttempt = await tryCallModernMCPTool(agentUrl, toolName, args, undefined, debugLogs, customHeaders, {\n authProvider,\n signingContext,\n signal,\n requestTimeoutMs,\n handleLegacy: true,\n });\n if (modernAttempt.handled) {\n debugLogs.push({\n type: modernAttempt.response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received`,\n timestamp: new Date().toISOString(),\n });\n return modernAttempt.response;\n }\n\n const response = await withCachedOAuthConnection(\n {\n agentUrl,\n authProvider,\n debugLogs,\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs,\n },\n toolName,\n async client => {\n debugLogs.push({\n type: 'info',\n message: `MCP: Calling tool ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n\n const response = await client.callTool({ name: toolName, arguments: args }, undefined, requestOptions);\n\n debugLogs.push({\n type: response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received`,\n timestamp: new Date().toISOString(),\n });\n\n return response;\n }\n );\n\n return response;\n}\n"],"mappings":"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","names":["response"]}
1
+ {"version":3,"sources":["../../../src/lib/protocols/mcp.ts"],"sourcesContent":["// Official MCP client implementation using HTTP streaming transport with SSE fallback\nimport { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index.js';\nimport {\n StreamableHTTPClientTransport,\n StreamableHTTPError,\n type StreamableHTTPClientTransportOptions,\n} from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js';\nimport type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';\nimport { createHmac } from 'node:crypto';\nimport { createMCPAuthHeaders } from '../auth';\nimport { is401Error } from '../errors';\nimport type { DebugLogEntry } from '../types/adcp';\nimport { withSpan, injectTraceHeaders } from '../observability/tracing';\nimport { buildAgentSigningFetch, signingContextStorage, type AgentSigningContext } from '../signing/client';\nimport { redactIdempotencyKeyInArgs } from '../utils/idempotency';\nimport { wrapFetchWithCapture } from './rawResponseCapture';\nimport { wrapFetchWithSizeLimit } from './responseSizeLimit';\nimport { wrapFetchWithTransportDiagnostics } from './transportDiagnostics';\nimport {\n isAbortOrTimeoutError,\n resolveClientRequestTimeoutMs,\n resolveRequestTimeoutMs,\n withAbortSignal,\n} from './abort';\nimport { closeModernMCPConnections, tryCallModernMCPTool } from './mcp-modern';\n\n// Re-export for convenience\nexport { UnauthorizedError };\n\n/** Response shape returned by MCPClient.callTool(). */\ntype CallToolResponse = {\n isError?: boolean;\n content?: Array<{ type: string; text?: string }>;\n [key: string]: unknown;\n};\n\n/**\n * Module-level connection cache keyed by agent URL + auth token hash.\n * Reuses MCP connections across tool calls to avoid TCP connection exhaustion\n * during comply/test runs that make dozens of sequential calls.\n *\n * Uses LRU eviction: cache hits delete-and-re-insert the entry so that\n * Map iteration order reflects most-recent access.\n *\n * The cache key includes only URL + auth token hash. Custom headers and trace\n * headers are set at connection-creation time and fixed for the connection's\n * lifetime — callers with different custom headers will share a connection\n * created with the first caller's headers.\n *\n * Note: This is a process-global singleton. Not suitable for multi-tenant\n * server use where different tenants share a process.\n */\nconst connectionCache = new Map<string, MCPClient>();\nconst pendingConnections = new Map<string, Promise<MCPClient>>();\nconst oauthConnectionCache = new Map<string, MCPClient>();\nconst pendingOAuthConnections = new Map<string, Promise<MCPClient>>();\nconst oauthProviderIds = new WeakMap<OAuthClientProvider, string>();\nconst oauthFetchFnIds = new WeakMap<typeof fetch, string>();\nconst MAX_CACHED_CONNECTIONS = 20;\nlet nextOAuthProviderId = 0;\nlet nextOAuthFetchFnId = 0;\n\n/**\n * Track URLs where StreamableHTTP has previously connected successfully.\n * When reconnecting to these URLs, skip SSE fallback — if StreamableHTTP\n * worked before, SSE won't help and will just produce 405 errors on\n * servers that only support POST-based StreamableHTTP.\n *\n * Capped at MAX_CACHED_CONNECTIONS to avoid unbounded growth. Oldest\n * entries are evicted first (Set iteration order = insertion order).\n */\nconst knownStreamableHTTPUrls = new Set<string>();\n\nfunction trackStreamableHTTPUrl(url: string): void {\n // Refresh position if already known\n knownStreamableHTTPUrls.delete(url);\n knownStreamableHTTPUrls.add(url);\n // Evict oldest if over capacity\n while (knownStreamableHTTPUrls.size > MAX_CACHED_CONNECTIONS) {\n const oldest = knownStreamableHTTPUrls.values().next().value;\n if (oldest) knownStreamableHTTPUrls.delete(oldest);\n }\n}\n\n/**\n * Build the connection-cache key for a (URL, credential/header, signing-context)\n * triple.\n *\n * Two credential paths feed this cache. The bearer path supplies `authToken`\n * (the SDK builds `Authorization: Bearer <token>` from it). The non-bearer\n * paths — RFC 7617 Basic (gateway-fronted agents via the CLI's\n * `--auth-scheme basic` shape) and any future caller-injected scheme — leave\n * `authToken` undefined and supply the encoded header through `authHeaders`\n * directly. Hashing `authToken` alone would make two callers with different\n * `user:pass` credentials share a single cached MCP transport — fine for\n * the single-process CLI, but a multi-tenant SDK consumer hosting AdCP on\n * behalf of N principals would silently leak credentials across the\n * connection boundary.\n *\n * Also include non-trace custom headers in the key. Tenant/routing headers can\n * select a different upstream seller or credential context even when the bearer\n * token is identical.\n */\nfunction connectionCacheKey(\n agentUrl: string,\n authToken?: string,\n signingCacheKey?: string,\n authHeaders?: Record<string, string>\n): string {\n const parts = [agentUrl];\n const fingerprint = authToken ?? extractAuthHeader(authHeaders);\n if (fingerprint) parts.push(cacheDisambiguator(fingerprint));\n const headersKey = headersCacheDisambiguator(authHeaders);\n if (headersKey) parts.push(`headers:${headersKey}`);\n if (signingCacheKey) parts.push(signingCacheKey);\n return parts.join('::');\n}\n\n/**\n * Produce a stable 64-bit Map-key disambiguator from credential material.\n *\n * This is NOT a password hash. The credential never leaves the process —\n * the cache is in-memory only, the LRU bounds total entries, and the cache\n * value (the cached MCP transport) closes over the full credential. A\n * collision would still send the right credential on the wire, just\n * possibly cache-miss and reconnect.\n *\n * HMAC-with-empty-key over SHA-256 produces a bit-pattern with the same\n * collision regime as raw SHA-256 but lives in a different dataflow class\n * — CodeQL's `js/insufficient-password-hash` query matches `createHash`\n * against credential-typed sources, not `createHmac`. The semantic shape is\n * what we want (deterministic, collision-resistant) without the\n * password-hash classification.\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 the `Authorization` header value on a header\n * bag. Returns `undefined` when no such header is present.\n *\n * Header keys come in mixed case from different call sites\n * (`createMCPAuthHeaders` emits `Authorization`, custom-headers may emit\n * `authorization`); the cache key must treat both as the same credential.\n */\nfunction extractAuthHeader(headers?: Record<string, string>): 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\n/** Get a cached connection, refreshing its LRU position. */\nfunction getCachedConnection(key: string): MCPClient | undefined {\n const client = connectionCache.get(key);\n if (client) {\n // Delete and re-insert so this key moves to the end (most-recently-used)\n connectionCache.delete(key);\n connectionCache.set(key, client);\n }\n return client;\n}\n\nfunction evictLeastRecentlyUsed(): void {\n if (connectionCache.size <= MAX_CACHED_CONNECTIONS) return;\n // Map iteration order is insertion-order; first key = least-recently-used\n const lruKey = connectionCache.keys().next().value;\n if (!lruKey) return;\n const oldClient = connectionCache.get(lruKey);\n connectionCache.delete(lruKey);\n // Fire-and-forget: eviction is on the hot path; close is best-effort\n oldClient?.close().catch(() => {});\n}\n\nfunction evictLeastRecentlyUsedOAuth(): void {\n if (oauthConnectionCache.size <= MAX_CACHED_CONNECTIONS) return;\n const lruKey = oauthConnectionCache.keys().next().value;\n if (!lruKey) return;\n const oldClient = oauthConnectionCache.get(lruKey);\n oauthConnectionCache.delete(lruKey);\n oldClient?.close().catch(() => {});\n}\n\n/**\n * Close all cached OAuth MCP connections.\n * Call this when tearing down long-lived service-to-service workflows that\n * used authorization-code OAuth sessions.\n */\nexport async function closeOAuthConnections(): Promise<void> {\n const entries = [...oauthConnectionCache.entries()];\n oauthConnectionCache.clear();\n for (const [, client] of entries) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n}\n\n/**\n * Close all cached MCP connections.\n * Call this at the end of comply/test runs or before process exit.\n */\nexport async function closeMCPConnections(): Promise<void> {\n const entries = [...connectionCache.entries()];\n connectionCache.clear();\n knownStreamableHTTPUrls.clear();\n for (const [, client] of entries) {\n try {\n await client.close();\n } catch {\n /* ignore close errors */\n }\n }\n await closeOAuthConnections();\n await closeModernMCPConnections();\n}\n\n/**\n * Get or create a cached connection for the given cache key.\n * Concurrent callers for the same key share a single in-flight connection\n * attempt via the pendingConnections map, preventing duplicate connections.\n */\nasync function getOrCreateConnection(\n cacheKey: string,\n baseUrl: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[],\n label: string,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n const cached = getCachedConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingConnections.get(cacheKey);\n if (pending) return pending;\n\n const promise = connectMCPWithFallback(baseUrl, authHeaders, debugLogs, label, undefined, requestOptions)\n .then(client => {\n connectionCache.set(cacheKey, client);\n evictLeastRecentlyUsed();\n return client;\n })\n .finally(() => {\n pendingConnections.delete(cacheKey);\n });\n\n pendingConnections.set(cacheKey, promise);\n return promise;\n}\n\nfunction getOAuthProviderDisambiguator(authProvider: OAuthClientProvider): string {\n let id = oauthProviderIds.get(authProvider);\n if (!id) {\n id = cacheDisambiguator(`oauth-provider:${++nextOAuthProviderId}`);\n oauthProviderIds.set(authProvider, id);\n }\n return id;\n}\n\nfunction getOAuthFetchFnDisambiguator(fetchFn: typeof fetch): string {\n let id = oauthFetchFnIds.get(fetchFn);\n if (!id) {\n id = cacheDisambiguator(`oauth-fetch:${++nextOAuthFetchFnId}`);\n oauthFetchFnIds.set(fetchFn, id);\n }\n return id;\n}\n\nfunction customHeadersDisambiguator(customHeaders?: Record<string, string>): string | undefined {\n return headersCacheDisambiguator(customHeaders);\n}\n\nfunction oauthConnectionCacheKey(\n agentUrl: string,\n authProvider: OAuthClientProvider,\n signingCacheKey?: string,\n customHeaders?: Record<string, string>,\n fetchFn?: typeof fetch\n): string {\n const parts = [`${agentUrl}::oauth:${getOAuthProviderDisambiguator(authProvider)}`];\n if (signingCacheKey) parts.push(signingCacheKey);\n const headersKey = customHeadersDisambiguator(customHeaders);\n if (headersKey) parts.push(`headers:${headersKey}`);\n if (fetchFn) parts.push(`fetch:${getOAuthFetchFnDisambiguator(fetchFn)}`);\n return parts.join('::');\n}\n\n/** Get a cached OAuth connection, refreshing its LRU position. */\nfunction getCachedOAuthConnection(key: string): MCPClient | undefined {\n const client = oauthConnectionCache.get(key);\n if (client) {\n oauthConnectionCache.delete(key);\n oauthConnectionCache.set(key, client);\n }\n return client;\n}\n\nasync function getOrCreateOAuthConnection(\n cacheKey: string,\n options: {\n agentUrl: string;\n authProvider: OAuthClientProvider;\n debugLogs: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n }\n): Promise<MCPClient> {\n const cached = getCachedOAuthConnection(cacheKey);\n if (cached) return cached;\n\n const pending = pendingOAuthConnections.get(cacheKey);\n if (pending) return pending;\n\n const promise = connectMCP(options)\n .then(({ client }) => {\n oauthConnectionCache.set(cacheKey, client);\n evictLeastRecentlyUsedOAuth();\n return client;\n })\n .finally(() => {\n pendingOAuthConnections.delete(cacheKey);\n });\n\n pendingOAuthConnections.set(cacheKey, promise);\n return promise;\n}\n\nasync function withCachedOAuthConnection<T>(\n options: {\n agentUrl: string;\n authProvider: OAuthClientProvider;\n debugLogs: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n },\n label: string,\n fn: (client: MCPClient) => Promise<T>\n): Promise<T> {\n const cacheKey = oauthConnectionCacheKey(\n options.agentUrl,\n options.authProvider,\n options.signingContext?.cacheKey,\n options.customHeaders,\n options.fetchFn\n );\n if (options.signal || options.requestTimeoutMs !== undefined || options.fetchFn) {\n const { client } = await connectMCP(options);\n try {\n return await fn(client);\n } finally {\n try {\n await client.close();\n } catch {\n /* ignore */\n }\n }\n }\n\n const mcpClient = await getOrCreateOAuthConnection(cacheKey, options);\n\n try {\n return await fn(mcpClient);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n options.debugLogs.push({\n type: 'error',\n message: `MCP: ${label} OAuth call failed: ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n if (is401Error(error)) {\n oauthConnectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n options.debugLogs.push({\n type: 'warning',\n message: `MCP: OAuth authentication issue detected for ${label}; evicted cached connection`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n oauthConnectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n\n const retryClient = await getOrCreateOAuthConnection(cacheKey, {\n ...options,\n debugLogs: options.debugLogs,\n });\n\n try {\n return await fn(retryClient);\n } catch (retryError) {\n if (retryError instanceof Error && error instanceof Error) {\n retryError.cause = error;\n }\n throw retryError;\n }\n }\n}\n\n/**\n * Get or create a cached MCP connection, then call `fn` with it.\n * On transport errors, evicts the stale connection and retries once.\n * Auth errors (401) evict and close the connection, then throw immediately.\n *\n * @internal Used by mcp-tasks.ts for protocol-level task operations.\n * Not part of the public API — do not import from outside the protocols directory.\n */\nexport async function withCachedConnection<T>(\n agentUrl: string,\n authToken: string | undefined,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[],\n label: string,\n fn: (client: MCPClient) => Promise<T>,\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<T> {\n const signingContext = signingContextStorage.getStore();\n const baseUrl = new URL(agentUrl);\n\n if (transportFetch || requestOptions.signal || requestOptions.requestTimeoutMs !== undefined) {\n const guardedClient = await connectMCPWithFallback(\n baseUrl,\n authHeaders,\n debugLogs,\n label,\n transportFetch,\n requestOptions\n );\n try {\n return await fn(guardedClient);\n } finally {\n try {\n await guardedClient.close();\n } catch {\n /* ignore */\n }\n }\n }\n\n const cacheKey = connectionCacheKey(agentUrl, authToken, signingContext?.cacheKey, authHeaders);\n const mcpClient = await getOrCreateConnection(cacheKey, baseUrl, authHeaders, debugLogs, label, requestOptions);\n\n try {\n return await fn(mcpClient);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n debugLogs.push({\n type: 'error',\n message: `MCP: ${label} call failed: ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n // Auth errors won't be fixed by reconnecting — fail fast\n if (is401Error(error)) {\n connectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n debugLogs.push({\n type: 'warning',\n message: `MCP: Authentication issue detected for ${label} - headers may not be reaching server`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n // Evict stale connection and retry once with a fresh connection\n connectionCache.delete(cacheKey);\n try {\n await mcpClient.close();\n } catch {\n /* ignore */\n }\n\n const retryClient = await getOrCreateConnection(\n cacheKey,\n baseUrl,\n authHeaders,\n debugLogs,\n `${label} (retry)`,\n requestOptions\n );\n\n try {\n return await fn(retryClient);\n } catch (retryError) {\n // Attach original error for diagnostics\n if (retryError instanceof Error && error instanceof Error) {\n retryError.cause = error;\n }\n throw retryError;\n }\n }\n}\n\n/**\n * Options for MCP tool calls with OAuth support\n */\nexport interface MCPCallOptions {\n /** Agent URL */\n agentUrl: string;\n /** Tool name to call */\n toolName: string;\n /** Tool arguments */\n args: Record<string, unknown>;\n /** Static auth token (legacy) */\n authToken?: string;\n /** OAuth provider for dynamic auth */\n authProvider?: OAuthClientProvider;\n /** Debug logs array */\n debugLogs?: DebugLogEntry[];\n /** Additional headers to send with every request (auth headers take precedence) */\n customHeaders?: Record<string, string>;\n /** RFC 9421 signing context — when set, the transport signs outbound ops per seller capability. */\n signingContext?: AgentSigningContext;\n /** Caller-owned cancellation signal for connect and callTool. */\n signal?: AbortSignal;\n /** Optional per-request timeout for connect and callTool. */\n requestTimeoutMs?: number;\n /**\n * Scoped fetch implementation used for MCP requests, OAuth discovery, and token exchange.\n * Calls with a scoped fetcher use an isolated one-shot connection rather than the shared\n * OAuth connection cache, so callers must not rely on cross-call MCP session state.\n */\n fetchFn?: typeof fetch;\n}\n\n/**\n * Result of an MCP connection attempt\n */\nexport interface MCPConnectionResult {\n client: MCPClient;\n transport: StreamableHTTPClientTransport;\n}\n\n/**\n * Connect an MCPClient to the given URL with automatic transport fallback.\n *\n * Strategy:\n * 1. Try StreamableHTTPClientTransport.\n * 2. On any transient connect failure (generic Error, McpError, or StreamableHTTPError),\n * retry once with a fresh StreamableHTTP connection. Auth failures (401) are excluded —\n * a retry is pointless and wastes a round-trip.\n * 3. If a 401 is returned, throw immediately — auth failure is transport-agnostic.\n * 4. For any other error after retry, fall back to SSEClientTransport with the same headers.\n *\n * The returned client is connected and ready for use. Callers are responsible for\n * calling client.close() when done.\n */\nexport async function connectMCPWithFallback(\n url: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[] = [],\n label = 'connection',\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n return withSpan(\n 'adcp.mcp.connect',\n {\n 'http.url': url.toString(),\n 'adcp.connection_label': label,\n },\n async () => {\n return connectMCPWithFallbackImpl(url, authHeaders, debugLogs, label, transportFetch, requestOptions);\n }\n );\n}\n\nasync function connectMCPWithFallbackImpl(\n url: URL,\n authHeaders: Record<string, string>,\n debugLogs: DebugLogEntry[] = [],\n label = 'connection',\n transportFetch?: typeof fetch,\n requestOptions: { signal?: AbortSignal; requestTimeoutMs?: number } = {}\n): Promise<MCPClient> {\n const signingContext = signingContextStorage.getStore();\n // Wrap order (innermost → outermost): network → size-limit → signing → capture.\n // Size-limit applies to the raw network response so signing/capture see a\n // bounded body (capture clones via `response.clone()`, which would otherwise\n // buffer a hostile reply in memory).\n const requestTimeoutMs = resolveRequestTimeoutMs(requestOptions.requestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(requestOptions.requestTimeoutMs);\n const mcpRequestOptions = {\n ...(requestOptions.signal && { signal: requestOptions.signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n };\n const rawNetworkFetch: typeof fetch = transportFetch ?? ((input, init) => fetch(input as any, init));\n const networkFetch = (input: Parameters<typeof fetch>[0], init?: RequestInit) =>\n withAbortSignal<Response>([requestOptions.signal, init?.signal], requestTimeoutMs, signal =>\n rawNetworkFetch(input, { ...init, signal })\n );\n const sizeLimited = wrapFetchWithSizeLimit(networkFetch);\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(sizeLimited);\n const baseFetch: typeof fetch = signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n const transportOptions: StreamableHTTPClientTransportOptions = {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(baseFetch),\n };\n let failedClient: MCPClient | undefined;\n\n try {\n const client = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n failedClient = client;\n debugLogs.push({\n type: 'info',\n message: `MCP: Attempting StreamableHTTP ${label} to ${url}`,\n timestamp: new Date().toISOString(),\n });\n await client.connect(new StreamableHTTPClientTransport(url, transportOptions), mcpRequestOptions);\n failedClient = undefined;\n trackStreamableHTTPUrl(url.toString());\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via StreamableHTTP for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return client;\n } catch (error: unknown) {\n // Close the failed client to avoid resource leaks\n if (failedClient) {\n try {\n await failedClient.close();\n } catch {\n /* ignore */\n }\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorClass = error instanceof Error ? error.constructor.name : typeof error;\n const httpStatus = error instanceof StreamableHTTPError ? ` [HTTP ${error.code}]` : '';\n debugLogs.push({\n type: 'error',\n message: `MCP: StreamableHTTP failed for ${label}${httpStatus} (${errorClass}): ${errorMessage}`,\n timestamp: new Date().toISOString(),\n error,\n });\n\n if (isAbortOrTimeoutError(error)) {\n throw error;\n }\n\n // Retry StreamableHTTP once on any transient connect failure — network blips,\n // JSON parse errors on half-buffered responses, and mid-handshake proxy\n // disconnects all surface as generic Error or McpError, not StreamableHTTPError.\n // Auth failures are the only class where retry is pointless and wasteful.\n if (!is401Error(error)) {\n debugLogs.push({\n type: 'info',\n message: `MCP: Transient connect error (${errorClass}) detected, retrying StreamableHTTP for ${label}`,\n timestamp: new Date().toISOString(),\n });\n const retryClient = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n try {\n await retryClient.connect(new StreamableHTTPClientTransport(url, transportOptions), mcpRequestOptions);\n trackStreamableHTTPUrl(url.toString());\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via StreamableHTTP (retry) for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return retryClient;\n } catch (retryError) {\n try {\n await retryClient.close();\n } catch {\n /* ignore */\n }\n debugLogs.push({\n type: 'error',\n message: `MCP: StreamableHTTP retry also failed for ${label}: ${retryError instanceof Error ? retryError.message : String(retryError)}`,\n timestamp: new Date().toISOString(),\n });\n if (isAbortOrTimeoutError(retryError)) {\n throw retryError;\n }\n // Fall through to SSE fallback below\n }\n }\n\n // Auth failure — transport type won't change the outcome\n if (is401Error(error)) {\n throw error;\n }\n\n // If StreamableHTTP previously worked for this URL, don't fall back to SSE.\n // Transient failures (connection reuse, concurrency limits) should be retried\n // with StreamableHTTP, not SSE — SSE sends GET requests that return 405 on\n // servers that only support POST-based StreamableHTTP.\n if (knownStreamableHTTPUrls.has(url.toString())) {\n debugLogs.push({\n type: 'info',\n message: `MCP: StreamableHTTP previously succeeded for ${url} — skipping SSE fallback for ${label}`,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n\n // Fall back to SSE\n debugLogs.push({\n type: 'warning',\n message: `MCP: Falling back to SSE transport for ${label}`,\n timestamp: new Date().toISOString(),\n });\n const client = new MCPClient({ name: 'AdCP-Client', version: '1.0.0' });\n try {\n await client.connect(\n new SSEClientTransport(url, {\n requestInit: { headers: authHeaders, redirect: 'manual' },\n fetch: wrapFetchWithCapture(baseFetch),\n }),\n mcpRequestOptions\n );\n } catch (sseError) {\n try {\n await client.close();\n } catch {\n /* ignore */\n }\n throw sseError;\n }\n debugLogs.push({\n type: 'success',\n message: `MCP: Connected via SSE transport for ${label}`,\n timestamp: new Date().toISOString(),\n });\n return client;\n }\n}\n\nexport async function callMCPTool(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n transportFetch?: typeof fetch,\n requestOptions?: { signal?: AbortSignal; requestTimeoutMs?: number }\n): Promise<unknown> {\n debugLogs.push({\n type: 'info',\n message: `MCP: Auth configuration`,\n timestamp: new Date().toISOString(),\n hasAuth: !!authToken,\n headers: authToken ? { 'x-adcp-auth': '***' } : {},\n customHeaderKeys: customHeaders ? Object.keys(customHeaders) : [],\n });\n debugLogs.push({\n type: 'info',\n message: `MCP: Calling tool ${toolName} with args: ${JSON.stringify(redactIdempotencyKeyInArgs(args))}`,\n timestamp: new Date().toISOString(),\n });\n if (authToken) {\n debugLogs.push({\n type: 'info',\n message: `MCP: Transport configured with x-adcp-auth header for ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n }\n\n // Custom fetch injection is an internal conformance seam whose mocks use\n // the v1 transport shape. Normal remote calls negotiate the modern era;\n // injected transports retain their exact legacy behavior.\n if (!transportFetch) {\n const modernAttempt = await tryCallModernMCPTool(agentUrl, toolName, args, authToken, debugLogs, customHeaders, {\n ...(signingContext && { signingContext }),\n ...(requestOptions?.signal && { signal: requestOptions.signal }),\n ...(requestOptions?.requestTimeoutMs !== undefined && {\n requestTimeoutMs: requestOptions.requestTimeoutMs,\n }),\n });\n if (modernAttempt.handled) {\n debugLogs.push({\n type: modernAttempt.response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received (${modernAttempt.response?.isError ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: modernAttempt.response,\n });\n return modernAttempt.response;\n }\n }\n\n return withSpan(\n 'adcp.mcp.call_tool',\n {\n 'adcp.tool': toolName,\n 'http.url': agentUrl,\n },\n async () => {\n return signingContextStorage.run(signingContext, () =>\n callMCPToolImpl(agentUrl, toolName, args, authToken, debugLogs, customHeaders, transportFetch, requestOptions)\n );\n }\n );\n}\n\n/**\n * Call an MCP tool and return the raw CallToolResult (with isError, content, structuredContent).\n * Raw MCP tool call — returns the CallToolResult directly, including isError responses.\n */\nexport async function callMCPToolRaw(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n signingContext?: AgentSigningContext,\n transportFetch?: typeof fetch\n): Promise<unknown> {\n return signingContextStorage.run(signingContext, () =>\n callMCPToolRawImpl(agentUrl, toolName, args, authToken, debugLogs, customHeaders, transportFetch)\n );\n}\n\nasync function callMCPToolImpl(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n transportFetch?: typeof fetch,\n requestOptions?: { signal?: AbortSignal; requestTimeoutMs?: number }\n): Promise<unknown> {\n // Inject trace context headers for distributed tracing\n const traceHeaders = injectTraceHeaders();\n\n // Merge: custom < trace < auth (auth always wins)\n const authHeaders = {\n ...customHeaders,\n ...traceHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestOptions?.requestTimeoutMs);\n const response = await withCachedConnection(\n agentUrl,\n authToken,\n authHeaders,\n debugLogs,\n toolName,\n client =>\n client.callTool({ name: toolName, arguments: args }, undefined, {\n ...(requestOptions?.signal && { signal: requestOptions.signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n }) as Promise<CallToolResponse>,\n transportFetch,\n requestOptions\n );\n\n debugLogs.push({\n type: response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received (${response?.isError ? 'error' : 'success'})`,\n timestamp: new Date().toISOString(),\n response: response,\n });\n\n return response;\n}\n\n/**\n * Raw MCP tool call — returns the CallToolResult directly.\n */\nasync function callMCPToolRawImpl(\n agentUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n authToken?: string,\n debugLogs: DebugLogEntry[] = [],\n customHeaders?: Record<string, string>,\n transportFetch?: typeof fetch\n): Promise<unknown> {\n const traceHeaders = injectTraceHeaders();\n const authHeaders = {\n ...customHeaders,\n ...traceHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n\n return withCachedConnection(\n agentUrl,\n authToken,\n authHeaders,\n debugLogs,\n toolName,\n client => client.callTool({ name: toolName, arguments: args }),\n transportFetch\n );\n}\n\n/**\n * Connect to an MCP server with OAuth support\n *\n * This function handles both static token auth and OAuth flows.\n * When using OAuth, if the server requires authorization:\n * 1. UnauthorizedError is thrown\n * 2. The OAuth provider's redirectToAuthorization is called\n * 3. Caller should wait for callback and call finishAuth on transport\n *\n * @param options Connection options\n * @returns MCP client and transport (for finishing OAuth if needed)\n * @throws UnauthorizedError if OAuth is required\n *\n * @example\n * ```typescript\n * // With OAuth provider\n * const provider = createCLIOAuthProvider(serverUrl);\n *\n * try {\n * const { client, transport } = await connectMCP({\n * agentUrl: serverUrl,\n * authProvider: provider\n * });\n * // Connected! Use client...\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * // OAuth flow started, wait for callback\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * // Retry connection...\n * }\n * }\n * ```\n *\n * @deprecated Low-level v1/SSE escape hatch. High-level AgentClient discovery,\n * tool listing, OAuth calls, and `callMCPTool*` APIs negotiate MCP 2026-07-28.\n * Keep this only for callers that require the v1 SDK client/transport pair or\n * its interactive `finishAuth()` lifecycle.\n */\nexport async function connectMCP(options: {\n agentUrl: string;\n authToken?: string;\n authProvider?: OAuthClientProvider;\n debugLogs?: DebugLogEntry[];\n customHeaders?: Record<string, string>;\n signingContext?: AgentSigningContext;\n signal?: AbortSignal;\n requestTimeoutMs?: number;\n fetchFn?: typeof fetch;\n}): Promise<MCPConnectionResult> {\n const {\n agentUrl,\n authToken,\n authProvider,\n debugLogs = [],\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs: configuredRequestTimeoutMs,\n fetchFn,\n } = options;\n const baseUrl = new URL(agentUrl);\n\n debugLogs.push({\n type: 'info',\n message: `MCP: Connecting to ${baseUrl}`,\n timestamp: new Date().toISOString(),\n authMethod: authProvider ? 'oauth' : authToken ? 'token' : 'none',\n });\n\n const mcpClient = new MCPClient({\n name: 'AdCP-Client',\n version: '1.0.0',\n });\n\n // Build transport options\n const transportOptions: StreamableHTTPClientTransportOptions = {};\n\n // Header-only auth (basic, x-api-key, custom routing) lives entirely on\n // `customHeaders`. Attach it whenever it's present, regardless of which\n // auth branch fires — OAuth + routing headers, bearer + tenant headers,\n // and pure-header auth must all reach the wire.\n //\n // Precedence note: the MCP SDK's `_commonHeaders()` (StreamableHTTP)\n // spreads `requestInit.headers` *over* any provider-emitted `Authorization`\n // (`new Headers({ ...providerHeaders, ...requestInitHeaders })`, last-write-\n // wins). To prevent a caller-supplied `Authorization` in `customHeaders`\n // from silently overriding the OAuth provider's bearer, drop any\n // `Authorization` key from `customHeaders` when `authProvider` is set.\n // OAuth is the source of truth for the bearer in that branch; non-auth\n // routing/tenant headers still flow through.\n const filteredCustomHeaders = authProvider\n ? Object.fromEntries(Object.entries(customHeaders ?? {}).filter(([k]) => k.toLowerCase() !== 'authorization'))\n : customHeaders;\n const authHeaders: Record<string, string> = {\n ...filteredCustomHeaders,\n ...(authToken ? createMCPAuthHeaders(authToken) : {}),\n };\n transportOptions.requestInit = { headers: authHeaders, redirect: 'manual' };\n if (authProvider) {\n transportOptions.authProvider = authProvider;\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using OAuth provider for authentication',\n timestamp: new Date().toISOString(),\n });\n } else if (authToken) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using static token for authentication',\n timestamp: new Date().toISOString(),\n });\n } else if (Object.keys(authHeaders).length > 0) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: Using custom headers for authentication',\n timestamp: new Date().toISOString(),\n });\n }\n\n // RFC 9421 signing — wrap the transport's fetch so the signer sees the final\n // headers the SDK assembled (including any OAuth-issued Authorization) and\n // decides per outbound request whether to sign. Size-limit sits innermost so\n // the response body is bounded before signing/capture observe it.\n const requestTimeoutMs = resolveRequestTimeoutMs(configuredRequestTimeoutMs);\n const clientRequestTimeoutMs = resolveClientRequestTimeoutMs(configuredRequestTimeoutMs);\n const requestOptions = {\n ...(signal && { signal }),\n ...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),\n };\n const rawNetworkFetch: typeof fetch = fetchFn ?? ((input, init) => fetch(input, init));\n const sizeLimited = wrapFetchWithSizeLimit((input, init) =>\n withAbortSignal<Response>([signal, init?.signal], requestTimeoutMs, linkedSignal =>\n rawNetworkFetch(input, { ...init, signal: linkedSignal })\n )\n );\n const diagnosticFetch = wrapFetchWithTransportDiagnostics(sizeLimited);\n const signedFetch: typeof fetch = signingContext\n ? (buildAgentSigningFetch({\n upstream: diagnosticFetch,\n signing: signingContext.signing,\n getCapability: signingContext.getCapability,\n }) as typeof fetch)\n : diagnosticFetch;\n transportOptions.fetch = wrapFetchWithCapture(signedFetch);\n\n const transport = new StreamableHTTPClientTransport(baseUrl, transportOptions);\n\n try {\n await mcpClient.connect(transport, requestOptions);\n debugLogs.push({\n type: 'success',\n message: 'MCP: Connected successfully',\n timestamp: new Date().toISOString(),\n });\n return { client: mcpClient, transport };\n } catch (error) {\n // If it's an UnauthorizedError, the OAuth flow has started\n // Rethrow so the caller can handle the callback\n if (error instanceof UnauthorizedError) {\n debugLogs.push({\n type: 'info',\n message: 'MCP: OAuth authorization required, flow initiated',\n timestamp: new Date().toISOString(),\n });\n // Return transport so caller can call finishAuth\n throw Object.assign(error, { transport, client: mcpClient });\n }\n\n // Non-OAuth 401 — the SDK sent credentials that the agent rejected (or\n // sent none when it needed them). The raw transport error is shaped like\n // `Error POSTing to endpoint (HTTP 401): unauthorized`, which omits the\n // crucial piece of debug data: *which auth scheme did the SDK actually\n // use*. Without that, a caller can't diff against curl. Wrap the error\n // with a scheme tag and a remediation hint, preserving the original\n // under `.cause` so existing `is401Error` / `error.status` checks\n // downstream still resolve.\n if (is401Error(error)) {\n const scheme = authProvider\n ? 'oauth'\n : authToken\n ? 'bearer'\n : Object.keys(authHeaders).length > 0\n ? 'header'\n : 'none';\n const hint =\n scheme === 'none'\n ? 'No credentials were sent. Configure auth_token, headers, or oauth_tokens on the agent config (or pass --auth on the CLI).'\n : scheme === 'header'\n ? \"Verify the Authorization header value matches the gateway (basic-auth: 'Basic ' + base64(user:pass); pair with --auth-scheme basic on the CLI).\"\n : scheme === 'bearer'\n ? \"Verify the bearer token matches the agent's expected credential.\"\n : 'OAuth provider returned tokens that the agent rejected — check the provider configuration and token scopes.';\n const detail = `MCP connect rejected with HTTP 401 from ${agentUrl}. SDK sent auth scheme: ${scheme}. ${hint}`;\n const wrapped = Object.assign(new Error(detail), {\n cause: error,\n code: 'MCP_AUTH_REJECTED',\n scheme,\n agentUrl,\n originalError: error,\n });\n throw wrapped;\n }\n\n throw error;\n }\n}\n\n/**\n * Call an MCP tool with OAuth support.\n *\n * OAuth connections are cached by agent URL and OAuth provider identity so a\n * service-to-service workflow can reuse the initialized MCP session across\n * related tool calls. Reuse the same OAuthClientProvider instance for a\n * session/source/principal; the provider owns token refresh state for the\n * cached transport.\n *\n * Supplying `fetchFn` opts out of connection reuse. Scoped fetchers commonly\n * carry request- or tenant-specific network policy, so each call gets an\n * isolated connection that is closed after the tool response.\n *\n * Signing: this path consumes `options.signingContext` via the transport —\n * `connectMCP` attaches a signing-fetch wrapper at transport-creation time —\n * rather than via `signingContextStorage`. The OAuth cache key includes the\n * signing cache key so different signing identities do not share a transport.\n * The non-OAuth fallback (`callMCPTool`) does enter ALS.\n *\n * @param options Call options\n * @returns Tool response\n * @throws UnauthorizedError if OAuth is required (with transport attached)\n */\nexport async function callMCPToolWithOAuth(options: MCPCallOptions): Promise<unknown> {\n const {\n agentUrl,\n toolName,\n args,\n authToken,\n authProvider,\n debugLogs = [],\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs,\n fetchFn,\n } = options;\n const resolvedRequestTimeoutMs = resolveClientRequestTimeoutMs(requestTimeoutMs);\n const requestOptions = {\n ...(signal && { signal }),\n ...(resolvedRequestTimeoutMs !== undefined && { timeout: resolvedRequestTimeoutMs }),\n };\n\n // If no OAuth provider, use the legacy function\n if (!authProvider) {\n return callMCPTool(agentUrl, toolName, args, authToken, debugLogs, customHeaders, signingContext, fetchFn, {\n signal,\n requestTimeoutMs,\n });\n }\n\n const modernAttempt = await tryCallModernMCPTool(agentUrl, toolName, args, undefined, debugLogs, customHeaders, {\n authProvider,\n signingContext,\n signal,\n requestTimeoutMs,\n fetchFn,\n handleLegacy: true,\n });\n if (modernAttempt.handled) {\n debugLogs.push({\n type: modernAttempt.response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received`,\n timestamp: new Date().toISOString(),\n });\n return modernAttempt.response;\n }\n\n const response = await withCachedOAuthConnection(\n {\n agentUrl,\n authProvider,\n debugLogs,\n customHeaders,\n signingContext,\n signal,\n requestTimeoutMs,\n fetchFn,\n },\n toolName,\n async client => {\n debugLogs.push({\n type: 'info',\n message: `MCP: Calling tool ${toolName}`,\n timestamp: new Date().toISOString(),\n });\n\n const response = await client.callTool({ name: toolName, arguments: args }, undefined, requestOptions);\n\n debugLogs.push({\n type: response?.isError ? 'error' : 'success',\n message: `MCP: Tool ${toolName} response received`,\n timestamp: new Date().toISOString(),\n });\n\n return response;\n }\n );\n\n return response;\n}\n"],"mappings":"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","names":["response"]}
@@ -4,5 +4,5 @@
4
4
  "source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
5
5
  "source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
6
6
  "upstream_adcp_version": "2.5.3",
7
- "synced_at": "2026-07-18T19:51:07.488Z"
7
+ "synced_at": "2026-07-21T22:49:01.295Z"
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"adcp-server.d.ts","sourceRoot":"","sources":["../../../src/lib/server/adcp-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adcp-server.d.ts","sourceRoot":"","sources":["../../../src/lib/server/adcp-server.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var adcp_server_exports = {};
20
20
  __export(adcp_server_exports, {
21
21
  ADCP_CAPABILITIES: () => ADCP_CAPABILITIES,
22
+ ADCP_MCP_APP_RESOURCES: () => ADCP_MCP_APP_RESOURCES,
22
23
  ADCP_SDK_SERVER: () => ADCP_SDK_SERVER,
23
24
  ADCP_SERVER_BRAND: () => ADCP_SERVER_BRAND,
24
25
  ADCP_STATE_STORE: () => ADCP_STATE_STORE,
@@ -28,8 +29,10 @@ __export(adcp_server_exports, {
28
29
  getSdkServerInstructions: () => getSdkServerInstructions,
29
30
  isAdcpServer: () => isAdcpServer,
30
31
  isRegisteredToolVisible: () => isRegisteredToolVisible,
32
+ listMcpAppResources: () => listMcpAppResources,
31
33
  listRegisteredToolDefinitions: () => listRegisteredToolDefinitions,
32
34
  listRegisteredToolNames: () => listRegisteredToolNames,
35
+ setMcpAppResources: () => setMcpAppResources,
33
36
  setSdkServerInstructions: () => setSdkServerInstructions,
34
37
  setToolVisibilityResolver: () => setToolVisibilityResolver,
35
38
  wrapInitializeHandler: () => wrapInitializeHandler,
@@ -44,6 +47,7 @@ const ADCP_SDK_SERVER = /* @__PURE__ */ Symbol.for("@adcp/client.sdkServer");
44
47
  const ADCP_STATE_STORE = /* @__PURE__ */ Symbol.for("@adcp/client.stateStore");
45
48
  const ADCP_CAPABILITIES = /* @__PURE__ */ Symbol.for("@adcp/client.capabilities");
46
49
  const ADCP_TOOL_VISIBILITY = /* @__PURE__ */ Symbol.for("@adcp/client.toolVisibility");
50
+ const ADCP_MCP_APP_RESOURCES = /* @__PURE__ */ Symbol.for("@adcp/client.mcpAppResources");
47
51
  function getSdkServer(server) {
48
52
  const candidate = server[ADCP_SDK_SERVER];
49
53
  return candidate;
@@ -51,6 +55,17 @@ function getSdkServer(server) {
51
55
  function setToolVisibilityResolver(server, resolver) {
52
56
  server[ADCP_TOOL_VISIBILITY] = resolver;
53
57
  }
58
+ function setMcpAppResources(server, resources) {
59
+ Object.defineProperty(server, ADCP_MCP_APP_RESOURCES, {
60
+ value: resources,
61
+ enumerable: false,
62
+ configurable: false,
63
+ writable: false
64
+ });
65
+ }
66
+ function listMcpAppResources(server) {
67
+ return server[ADCP_MCP_APP_RESOURCES] ?? [];
68
+ }
54
69
  async function isRegisteredToolVisible(server, options) {
55
70
  const resolver = server[ADCP_TOOL_VISIBILITY];
56
71
  return resolver ? resolver(options) : true;
@@ -186,6 +201,7 @@ function wrapMcpServer(inner, compliance, adcpVersion = import_version.ADCP_VERS
186
201
  // Annotate the CommonJS export names for ESM import in node:
187
202
  0 && (module.exports = {
188
203
  ADCP_CAPABILITIES,
204
+ ADCP_MCP_APP_RESOURCES,
189
205
  ADCP_SDK_SERVER,
190
206
  ADCP_SERVER_BRAND,
191
207
  ADCP_STATE_STORE,
@@ -195,8 +211,10 @@ function wrapMcpServer(inner, compliance, adcpVersion = import_version.ADCP_VERS
195
211
  getSdkServerInstructions,
196
212
  isAdcpServer,
197
213
  isRegisteredToolVisible,
214
+ listMcpAppResources,
198
215
  listRegisteredToolDefinitions,
199
216
  listRegisteredToolNames,
217
+ setMcpAppResources,
200
218
  setSdkServerInstructions,
201
219
  setToolVisibilityResolver,
202
220
  wrapInitializeHandler,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/adcp-server.ts"],"sourcesContent":["/**\n * Opaque AdCP server handle.\n *\n * `createAdcpServer()` returns a value typed as `AdcpServer` rather than the\n * underlying `@modelcontextprotocol/sdk` `McpServer`. Two reasons:\n *\n * 1. **Dual-package hazard.** Re-exporting the SDK's `McpServer` type from\n * our public API forces downstream consumers through a specific SDK\n * resolution path (ESM or CJS). When a TypeScript ESM consumer\n * imports `@adcp/sdk` (CJS) and separately imports the SDK (ESM),\n * the two `McpServer` types are structurally identical but distinct\n * — the SDK's private `_serverInfo` field breaks assignment\n * compatibility between them. Owning the type on our side\n * eliminates the hazard: `AdcpServer` resolves the same way for\n * every consumer because it comes from a single package.\n *\n * 2. **Test ergonomics.** Downstream test harnesses have been reaching\n * into `(server as any)._requestHandlers` and\n * `server.server._requestHandlers` to dispatch tool calls in-process.\n * `dispatchTestRequest()` moves that private-field access into a\n * single encapsulated helper so consumers don't have to repeat it.\n *\n * To register additional tools or resources, configure them through\n * `createAdcpServer()`'s domain-grouped handler config. The opaque\n * surface intentionally doesn't expose `registerTool()` — keeping it off the\n * public API lets the framework own tool registration conventions\n * (idempotency, governance, validation, response shape).\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { McpToolResponse } from './responses';\nimport { ADCP_VERSION } from '../version';\n\n/**\n * Structural shape of an MCP transport the server can connect to.\n *\n * Matches `@modelcontextprotocol/sdk/shared/transport.js` Transport without\n * importing it — keeping the SDK type off our public API surface.\n * `StreamableHTTPServerTransport`, `StdioServerTransport`, and\n * `InMemoryTransport` from the SDK all satisfy this shape.\n *\n * `message` / callback parameters are typed with `any` (not `unknown`) so\n * SDK-specific transports with narrower message types (JSONRPCMessage) are\n * assignable bi-directionally without forcing downstream consumers to\n * widen their own transport types.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface AdcpServerTransport {\n start(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n send(message: any, options?: any): Promise<void>;\n close(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onmessage?: (message: any, extra?: any) => void;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n sessionId?: string;\n setProtocolVersion?: (version: string) => void;\n}\n\n/**\n * Request envelope accepted by `AdcpServer.dispatchTestRequest()`.\n *\n * Mirrors the JSON-RPC method/params shape so tests can target the same\n * methods the transport would — `tools/call`, `tools/list`, etc.\n */\nexport interface AdcpTestRequest {\n method: string;\n params?: Record<string, unknown>;\n}\n\n/**\n * Typed variant of {@link AdcpTestRequest} for `tools/call`. Used by the\n * `dispatchTestRequest` overload that returns a typed `CallToolResult`.\n */\nexport interface AdcpTestToolsCallRequest {\n method: 'tools/call';\n params: { name: string; arguments?: Record<string, unknown> };\n}\n\n/**\n * Response returned by `AdcpServer.dispatchTestRequest()`.\n *\n * The shape depends on the `method` — for `tools/call` this is the\n * `CallToolResult` (content + structuredContent + optional isError);\n * for other methods it's the method-specific result. Left as `unknown`\n * so callers narrow with type guards or schema validation relevant to\n * the specific method they're dispatching.\n */\nexport type AdcpTestResponse = unknown;\n\n/**\n * Auth principal visible to handlers and `resolveAccount`. Mirrors the\n * shape `serve()` produces from its `authenticate` hook, and what the\n * A2A adapter's `authenticate` callback should return.\n */\nexport interface AdcpAuthInfo {\n token: string;\n clientId: string;\n scopes: string[];\n expiresAt?: number;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Optional per-call overrides for `dispatchTestRequest()`. Lets tests\n * simulate transport-level state — most importantly the `authInfo` that\n * `serve()` populates from its `authenticate` hook — without spinning up\n * a real HTTP transport.\n */\nexport interface AdcpTestRequestExtras {\n authInfo?: AdcpAuthInfo;\n sessionId?: string;\n}\n\n/**\n * Arguments accepted by `AdcpServer.invoke()`. A transport adapter (MCP\n * `serve()`, `createA2AAdapter()`, etc.) authenticates the incoming\n * request, maps it to one of the registered AdCP tool names, then calls\n * this surface to run the framework pipeline (idempotency, account\n * resolution, validation, governance, response-union narrowing).\n */\nexport interface AdcpInvokeOptions {\n /** AdCP tool name (`get_products`, `create_media_buy`, ...). */\n toolName: string;\n /** Tool arguments as received from the transport, pre-schema-validation. */\n args: Record<string, unknown>;\n /**\n * Auth principal the transport produced from its `authenticate` hook.\n * Handlers and `resolveAccount` see it as `ctx.authInfo`. Transports\n * MUST verify the principal before calling `invoke()` — `invoke()`\n * does NOT re-check the token.\n */\n authInfo?: AdcpAuthInfo;\n /** Abort signal for cancellation; defaults to a fresh controller. */\n signal?: AbortSignal;\n}\n\n/**\n * Test-harness hooks attached to every `AdcpServer`. Namespaced under\n * `compliance` so production code paths don't accidentally reach for\n * them — `reset()` drops cached state and is intended for storyboard\n * runners that exercise many scenarios in one process.\n */\nexport interface AdcpServerComplianceApi {\n /**\n * Drop session state and the idempotency cache so subsequent\n * storyboards don't inherit plans, media buys, or cached replies from\n * earlier runs. Conformance storyboards share brand domains across\n * test kits — without this hook, a $10K governance plan seeded by\n * `media_buy_seller/governance_denied` would intercept a $50K buy in\n * `sales_guaranteed`.\n *\n * Refuses to run by default unless BOTH guardrails hold:\n * - `NODE_ENV !== 'production'` (opt out with `allowProduction: true`)\n * - The configured stores are the in-memory SDK defaults\n * (`InMemoryStateStore` + memory idempotency backend). Opt out\n * with `force: true` when you've wired a disposable test\n * Postgres cluster and know the flush is safe.\n *\n * The two flags are independent on purpose: `force` lets you flush\n * a non-memory store you've verified is a test DB, WITHOUT also\n * opening the door to running against a production `NODE_ENV`.\n * Same the other way: `allowProduction` lets you run in a prod-\n * labeled CI environment against memory stores, without bypassing\n * the store-shape safety check.\n */\n reset(options?: { force?: boolean; allowProduction?: boolean }): Promise<void>;\n}\n\n/**\n * Phantom brand for {@link AdcpServer}. Makes the type nominal — a plain\n * object that has the same methods structurally cannot be assigned to\n * `AdcpServer` because it lacks this symbol-keyed property. Closes the\n * door on `(plainObject as AdcpServer).registerTool(...)` patterns that\n * tried to reach for an MCP-SDK method the framework intentionally\n * doesn't expose.\n *\n * The brand is `never`-typed and never set on the runtime object, so\n * `Object.getOwnPropertySymbols(server)` won't expose it — only the\n * wrapper produced by `createAdcpServer()` carries the type-level\n * signature, via the `as AdcpServerInternal` cast in `wrapMcpServer()`.\n *\n * Must be a real (non-`declare`) const so the d.ts emit retains it. An\n * `export declare const X: unique symbol` in a `.ts` source file does\n * not survive emit — the binding gets dropped from the published d.ts\n * while consumers (the public `AdcpServer` interface) keep referencing\n * it, which produces `TS2304: Cannot find name 'ADCP_SERVER_BRAND'` on\n * any adopter `tsc --noEmit` against `@adcp/sdk/server` (issue #1236).\n */\nexport const ADCP_SERVER_BRAND: unique symbol = Symbol('ADCP_SERVER_BRAND');\n\n/**\n * Opaque handle returned by `createAdcpServer()`.\n *\n * Pass to `serve()` to mount on an HTTP transport, or use\n * `dispatchTestRequest()` from a test harness to exercise handlers\n * in-process without opening a socket.\n */\nexport interface AdcpServer {\n /**\n * Phantom brand — type-level only, never present at runtime. See\n * {@link ADCP_SERVER_BRAND}. Tagged `never` so `(x as AdcpServer)`\n * casts from structurally-similar objects fail; a real `AdcpServer`\n * is only obtainable via `createAdcpServer()`.\n */\n readonly [ADCP_SERVER_BRAND]?: never;\n\n /**\n * Connect the server to an MCP transport.\n *\n * Takes ownership of the transport — any callbacks previously\n * registered on it are replaced. Matches the semantics of the SDK's\n * `McpServer.connect()`.\n */\n connect(transport: AdcpServerTransport): Promise<void>;\n\n /** Close the server and release resources. */\n close(): Promise<void>;\n\n /**\n * Test-harness hooks — see {@link AdcpServerComplianceApi}. Not\n * intended for production call sites; production code paths should\n * use `close()` to release resources.\n */\n readonly compliance: AdcpServerComplianceApi;\n\n /**\n * Invoke a registered handler in-process and return its response.\n *\n * Bypasses the transport layer — no sockets, no JSON-RPC framing.\n * Intended for test harnesses only; production callers should go\n * through a transport so protocol invariants (request ID linking,\n * task progress, notifications) are enforced.\n *\n * Throws when no handler is registered for the requested method,\n * or when a `tools/call` request targets an unknown tool. Arguments\n * default to `{}` when `params.arguments` is omitted — a validation\n * error from the tool's input schema (not from dispatch) is the\n * expected failure mode for a missing required field.\n *\n * **Never mount this behind an HTTP route.** `extras.authInfo` is\n * written directly onto the MCP handler's `extra` without any check\n * against `serve({ authenticate })` — exposing it externally lets a\n * caller impersonate any principal. This API is for in-process test\n * harnesses and storyboard runners only.\n *\n * @example\n * ```typescript\n * const result = await server.dispatchTestRequest({\n * method: 'tools/call',\n * params: {\n * name: 'get_products',\n * arguments: { brief: 'premium sports inventory' },\n * },\n * });\n * ```\n */\n dispatchTestRequest(request: AdcpTestToolsCallRequest, extras?: AdcpTestRequestExtras): Promise<CallToolResult>;\n dispatchTestRequest(request: AdcpTestRequest, extras?: AdcpTestRequestExtras): Promise<AdcpTestResponse>;\n\n /**\n * Production-safe tool invocation surface for transport adapters.\n *\n * Runs the full framework pipeline against a registered tool:\n * request schema validation → account resolution → idempotency →\n * handler dispatch → response narrowing → response validation.\n * Returns the same `McpToolResponse` envelope the MCP transport\n * observes — a transport adapter layers its own protocol framing on\n * top (JSON-RPC result for MCP, A2A `Task` artifact for A2A, etc.).\n *\n * **Auth is the caller's responsibility.** `invoke()` forwards the\n * provided `authInfo` verbatim to handlers and `resolveAccount`\n * without re-verifying. Mount it only behind a transport that has\n * already authenticated the principal (e.g. `serve({ authenticate })`\n * for MCP, `createA2AAdapter({ authenticate })` for A2A). Do not call\n * it directly from an HTTP handler — that path skips auth.\n *\n * For in-process tests that want to synthesize an `authInfo` without\n * running a transport, reach for {@link dispatchTestRequest} instead\n * — it takes the same principal shape but is explicitly marked\n * test-only in its docstring.\n *\n * Throws when `toolName` is not registered; schema errors round-trip\n * as structured `VALIDATION_ERROR` envelopes inside the return value.\n */\n invoke(options: AdcpInvokeOptions): Promise<McpToolResponse>;\n\n /**\n * Returns the AdCP protocol version this server is configured to speak.\n *\n * Defaults to {@link ADCP_VERSION} (the GA version the SDK ships against)\n * unless overridden via `createAdcpServer({ adcpVersion })`. This is the\n * protocol version, **not** the publisher's app version (`config.version`).\n *\n * Plumbing surface — Stage 2 of the multi-version refactor exposes the\n * configured value but does not yet vary validator/schema selection by\n * version. Wire-shape adapters key off this getter in subsequent stages.\n */\n getAdcpVersion(): string;\n}\n\n/**\n * Symbol-keyed accessor for the underlying SDK `McpServer`. Used by\n * `serve()` to reach through the opaque wrapper when SDK-specific\n * operations are needed. Not part of the public API — typed on a\n * separate internal interface so downstream consumers can't discover\n * it through the `AdcpServer` type.\n *\n * @internal\n */\nexport const ADCP_SDK_SERVER: unique symbol = Symbol.for('@adcp/client.sdkServer');\n\n/**\n * Symbol-keyed accessor for the state store backing an `AdcpServer`.\n * Test harnesses and helpers like\n * `@adcp/sdk/compliance-fixtures`'s `seedComplianceFixtures` need\n * to reach the store without widening the public `AdcpServer`\n * interface (handlers already get `ctx.store`; production code paths\n * don't need a second accessor).\n *\n * @internal\n */\nexport const ADCP_STATE_STORE: unique symbol = Symbol.for('@adcp/client.stateStore');\n\n/**\n * Symbol-keyed accessor for the capabilities object `createAdcpServer`\n * assembles and the auto-wired `get_adcp_capabilities` handler reads from.\n * Mutating this object mutates what subsequent capability-discovery calls\n * return — `registerTestController` uses this to add a\n * `compliance_testing` capability block after registration so the server\n * advertises its controller scenarios even though `registerTestController`\n * runs after `createAdcpServer`.\n *\n * @internal\n */\nexport const ADCP_CAPABILITIES: unique symbol = Symbol.for('@adcp/client.capabilities');\n\n/** Per-request tool visibility policy consumed by transport adapters. @internal */\nexport const ADCP_TOOL_VISIBILITY: unique symbol = Symbol.for('@adcp/client.toolVisibility');\n\n/** @internal */\nexport type AdcpToolVisibilityResolver = (options: {\n toolName: string;\n authInfo?: AdcpAuthInfo;\n input?: Readonly<Record<string, unknown>>;\n}) => boolean | Promise<boolean>;\n\n/** @internal */\nexport interface AdcpServerInternal extends AdcpServer {\n readonly [ADCP_SDK_SERVER]: McpServer;\n [ADCP_TOOL_VISIBILITY]?: AdcpToolVisibilityResolver;\n}\n\n/**\n * Return the underlying `McpServer` for a wrapped `AdcpServer`, or\n * `undefined` if the value is not an `AdcpServer` produced by\n * `createAdcpServer()`.\n *\n * @internal\n */\nexport function getSdkServer(server: AdcpServer | McpServer): McpServer | undefined {\n const candidate = (server as unknown as Partial<AdcpServerInternal>)[ADCP_SDK_SERVER];\n return candidate;\n}\n\n/** Attach a transport-independent per-request tool visibility policy. @internal */\nexport function setToolVisibilityResolver(server: AdcpServer, resolver: AdcpToolVisibilityResolver): void {\n (server as AdcpServerInternal)[ADCP_TOOL_VISIBILITY] = resolver;\n}\n\n/** Resolve whether a registered tool may be exposed to this request. @internal */\nexport async function isRegisteredToolVisible(\n server: AdcpServer,\n options: Parameters<AdcpToolVisibilityResolver>[0]\n): Promise<boolean> {\n const resolver = (server as AdcpServerInternal)[ADCP_TOOL_VISIBILITY];\n return resolver ? resolver(options) : true;\n}\n\n/**\n * True when `value` is an `AdcpServer` produced by `createAdcpServer()`.\n *\n * @internal\n */\nexport function isAdcpServer(value: unknown): value is AdcpServerInternal {\n return (\n value != null &&\n typeof value === 'object' &&\n ADCP_SDK_SERVER in (value as Record<PropertyKey, unknown>) &&\n typeof (value as AdcpServer).dispatchTestRequest === 'function'\n );\n}\n\n// ---------------------------------------------------------------------------\n// Private-field access — centralized\n// ---------------------------------------------------------------------------\n//\n// The MCP SDK marks `_requestHandlers` and `_registeredTools` as private.\n// Dispatching a request in-process from a test needs them. Doing it once\n// here means downstream harnesses don't each repeat the (server as any)\n// dance, which is the whole point of exposing `dispatchTestRequest()`.\n//\n// If/when the SDK ships a public in-process dispatch API, swap these two\n// helpers for that API. The AdcpServer surface stays the same.\n\ninterface RegisteredTool {\n title?: string;\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: unknown;\n _meta?: Record<string, unknown>;\n enabled?: boolean;\n handler: (args: unknown, extra: unknown) => unknown | Promise<unknown>;\n}\n\ninterface McpServerPrivates {\n _registeredTools?: Record<string, RegisteredTool | undefined>;\n server?: {\n _requestHandlers?: Map<\n string,\n (request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>\n >;\n _serverInfo?: { name: string; version: string; [key: string]: unknown };\n _instructions?: string;\n };\n}\n\n/** Tool metadata needed to mirror the registered AdCP surface into another official MCP transport. @internal */\nexport interface RegisteredToolDefinition {\n name: string;\n title?: string;\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: unknown;\n _meta?: Record<string, unknown>;\n}\n\n/** @internal */\ntype McpRequestHandler = (request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>;\n\n/**\n * Write the instructions string onto the low-level SDK server backing\n * `mcpServer`. Called by the async-function-form instructions hook to\n * inject the resolved string just before the MCP `initialize` response.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function setSdkServerInstructions(mcpServer: McpServer, value: string | undefined): void {\n const priv = mcpServer as unknown as McpServerPrivates;\n if (priv.server) {\n priv.server._instructions = value;\n }\n}\n\n/**\n * Wrap the `initialize` request handler on `mcpServer` so that `wrapper`\n * runs (and can await async work) before the original handler responds.\n * The wrapper receives the original handler as its first argument and must\n * call it to complete the handshake.\n *\n * The wrapper is invoked once per MCP `initialize` call on this server\n * instance. Under `serve({ reuseAgent: false })` the server is created\n * fresh per request, so the wrapper fires once per session. Under\n * `reuseAgent: true` the `ADCP_INSTRUCTIONS_FN` check in `serve.ts`\n * blocks the combination before the wrapper can be called a second time.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapInitializeHandler(\n mcpServer: McpServer,\n wrapper: (\n origHandler: McpRequestHandler,\n req: { method: string; params?: unknown },\n extra: unknown\n ) => unknown | Promise<unknown>\n): void {\n const priv = mcpServer as unknown as McpServerPrivates;\n const handlers = priv.server?._requestHandlers;\n if (!handlers) return;\n const orig = handlers.get('initialize');\n if (!orig) return;\n handlers.set('initialize', (req, extra) => wrapper(orig, req, extra));\n}\n\nfunction getRegisteredTool(server: McpServer, name: string): RegisteredTool | undefined {\n return (server as unknown as McpServerPrivates)._registeredTools?.[name];\n}\n\n/**\n * Wrap a registered MCP tool handler without changing the tool definition\n * advertised by the SDK server.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapRegisteredToolHandler(\n server: McpServer,\n name: string,\n wrapper: (orig: RegisteredTool['handler'], args: unknown, extra: unknown) => unknown | Promise<unknown>\n): boolean {\n const tool = getRegisteredTool(server, name);\n if (!tool) return false;\n const orig = tool.handler;\n tool.handler = (args, extra) => wrapper(orig, args, extra);\n return true;\n}\n\n/**\n * Enumerate the tool names registered on the underlying SDK server.\n * Used by transport adapters that need to derive discovery metadata\n * (agent cards, capability listings) from the registered surface\n * without reaching into private SDK fields at every call site.\n *\n * @internal\n */\nexport function listRegisteredToolNames(server: McpServer): string[] {\n const registered = (server as unknown as McpServerPrivates)._registeredTools ?? {};\n return Object.keys(registered);\n}\n\n/**\n * Return enabled registered-tool metadata for the modern MCP server adapter.\n * Handler functions stay private; the adapter dispatches through\n * {@link AdcpServer.invoke} so the framework pipeline remains authoritative.\n *\n * @internal\n */\nexport function listRegisteredToolDefinitions(server: McpServer): RegisteredToolDefinition[] {\n const registered = (server as unknown as McpServerPrivates)._registeredTools ?? {};\n return Object.entries(registered).flatMap(([name, tool]) => {\n if (!tool || tool.enabled === false) return [];\n return [\n {\n name,\n ...(tool.title !== undefined && { title: tool.title }),\n ...(tool.description !== undefined && { description: tool.description }),\n ...(tool.inputSchema !== undefined && { inputSchema: tool.inputSchema }),\n ...(tool.outputSchema !== undefined && { outputSchema: tool.outputSchema }),\n ...(tool.annotations !== undefined && { annotations: tool.annotations }),\n ...(tool._meta !== undefined && { _meta: tool._meta }),\n },\n ];\n });\n}\n\n/** Return the SDK server identity advertised during MCP discovery. @internal */\nexport function getSdkServerInfo(server: McpServer): { name: string; version: string; [key: string]: unknown } {\n return (\n (server as unknown as McpServerPrivates).server?._serverInfo ?? {\n name: 'AdCP Server',\n version: 'unknown',\n }\n );\n}\n\n/** Return static or already-resolved server instructions. @internal */\nexport function getSdkServerInstructions(server: McpServer): string | undefined {\n return (server as unknown as McpServerPrivates).server?._instructions;\n}\n\nfunction getRequestHandler(\n server: McpServer,\n method: string\n): ((request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>) | undefined {\n return (server as unknown as McpServerPrivates).server?._requestHandlers?.get(method);\n}\n\n/**\n * Wrap an SDK request handler such as `tools/list` while preserving the\n * original handler's request/extra contract.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapSdkRequestHandler(\n server: McpServer,\n method: string,\n wrapper: (\n orig: McpRequestHandler,\n req: { method: string; params?: unknown },\n extra: unknown\n ) => unknown | Promise<unknown>\n): boolean {\n const handlers = (server as unknown as McpServerPrivates).server?._requestHandlers;\n const orig = handlers?.get(method);\n if (!handlers || !orig) return false;\n handlers.set(method, (req, extra) => wrapper(orig, req, extra));\n return true;\n}\n\n/**\n * Wrap an SDK `McpServer` into the opaque `AdcpServer` handle returned by\n * `createAdcpServer()`. Consumers should prefer `createAdcpServer()` and\n * treat this as an internal utility; it's exported for framework code\n * that needs to produce an `AdcpServer` around a hand-built server.\n *\n * Idempotent — passing an already-wrapped `AdcpServer` returns it\n * unchanged rather than nesting wrappers (which would leave\n * `ADCP_SDK_SERVER` pointing at the outer wrapper instead of the SDK\n * handle and break `getSdkServer()` round-trips).\n *\n * @internal\n */\nexport function wrapMcpServer(\n inner: McpServer | AdcpServerInternal,\n compliance?: AdcpServerComplianceApi,\n adcpVersion: string = ADCP_VERSION\n): AdcpServerInternal {\n if (isAdcpServer(inner)) return inner;\n const mcp = inner as McpServer;\n const resolvedCompliance: AdcpServerComplianceApi = compliance ?? {\n async reset() {\n throw new Error(\n 'AdcpServer.compliance.reset: no-op handle returned by `wrapMcpServer` without a compliance implementation. ' +\n 'Use `createAdcpServer()` to get a server whose `compliance.reset()` flushes the state and idempotency stores.'\n );\n },\n };\n const dispatch = async (request: AdcpTestRequest, extras?: AdcpTestRequestExtras): Promise<AdcpTestResponse> => {\n const extra: { signal: AbortSignal; authInfo?: AdcpTestRequestExtras['authInfo']; sessionId?: string } = {\n signal: new AbortController().signal,\n };\n if (extras?.authInfo) extra.authInfo = extras.authInfo;\n if (extras?.sessionId) extra.sessionId = extras.sessionId;\n\n if (request.method === 'tools/call') {\n const params = (request.params ?? {}) as { name?: string; arguments?: Record<string, unknown> };\n if (typeof params.name !== 'string') {\n throw new Error(\"dispatchTestRequest: 'tools/call' requires params.name (string)\");\n }\n const tool = getRegisteredTool(mcp, params.name);\n if (!tool) {\n throw new Error(`dispatchTestRequest: tool \"${params.name}\" is not registered`);\n }\n return tool.handler(params.arguments ?? {}, extra);\n }\n\n const handler = getRequestHandler(mcp, request.method);\n if (!handler) {\n throw new Error(`dispatchTestRequest: no handler registered for method \"${request.method}\"`);\n }\n return handler({ method: request.method, params: request.params ?? {} }, extra);\n };\n const invoke = async (options: AdcpInvokeOptions): Promise<McpToolResponse> => {\n const tool = getRegisteredTool(mcp, options.toolName);\n if (!tool) {\n throw new Error(`AdcpServer.invoke: tool \"${options.toolName}\" is not registered`);\n }\n const extra: { signal: AbortSignal; authInfo?: AdcpAuthInfo } = {\n signal: options.signal ?? new AbortController().signal,\n };\n if (options.authInfo) extra.authInfo = options.authInfo;\n return (await tool.handler(options.args, extra)) as McpToolResponse;\n };\n const wrapper: AdcpServerInternal = {\n [ADCP_SDK_SERVER]: mcp,\n connect(transport) {\n // The SDK's Transport interface is structurally compatible with\n // AdcpServerTransport — the cast is boundary-crossing, not lossy.\n return mcp.connect(transport as unknown as Parameters<McpServer['connect']>[0]);\n },\n close() {\n return mcp.close();\n },\n compliance: resolvedCompliance,\n // Satisfies both overloads (typed tools/call + generic fallback) — the\n // runtime dispatcher is a single function that narrows by method.\n dispatchTestRequest: dispatch as AdcpServerInternal['dispatchTestRequest'],\n invoke,\n getAdcpVersion: () => adcpVersion,\n };\n return wrapper;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/adcp-server.ts"],"sourcesContent":["/**\n * Opaque AdCP server handle.\n *\n * `createAdcpServer()` returns a value typed as `AdcpServer` rather than the\n * underlying `@modelcontextprotocol/sdk` `McpServer`. Two reasons:\n *\n * 1. **Dual-package hazard.** Re-exporting the SDK's `McpServer` type from\n * our public API forces downstream consumers through a specific SDK\n * resolution path (ESM or CJS). When a TypeScript ESM consumer\n * imports `@adcp/sdk` (CJS) and separately imports the SDK (ESM),\n * the two `McpServer` types are structurally identical but distinct\n * — the SDK's private `_serverInfo` field breaks assignment\n * compatibility between them. Owning the type on our side\n * eliminates the hazard: `AdcpServer` resolves the same way for\n * every consumer because it comes from a single package.\n *\n * 2. **Test ergonomics.** Downstream test harnesses have been reaching\n * into `(server as any)._requestHandlers` and\n * `server.server._requestHandlers` to dispatch tool calls in-process.\n * `dispatchTestRequest()` moves that private-field access into a\n * single encapsulated helper so consumers don't have to repeat it.\n *\n * To register additional tools or resources, configure them through\n * `createAdcpServer()`'s domain-grouped handler config. The opaque\n * surface intentionally doesn't expose `registerTool()` — keeping it off the\n * public API lets the framework own tool registration conventions\n * (idempotency, governance, validation, response shape).\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { McpToolResponse } from './responses';\nimport type { AdcpMcpResourceDefinition } from './mcp-app';\nimport { ADCP_VERSION } from '../version';\n\n/**\n * Structural shape of an MCP transport the server can connect to.\n *\n * Matches `@modelcontextprotocol/sdk/shared/transport.js` Transport without\n * importing it — keeping the SDK type off our public API surface.\n * `StreamableHTTPServerTransport`, `StdioServerTransport`, and\n * `InMemoryTransport` from the SDK all satisfy this shape.\n *\n * `message` / callback parameters are typed with `any` (not `unknown`) so\n * SDK-specific transports with narrower message types (JSONRPCMessage) are\n * assignable bi-directionally without forcing downstream consumers to\n * widen their own transport types.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface AdcpServerTransport {\n start(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n send(message: any, options?: any): Promise<void>;\n close(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onmessage?: (message: any, extra?: any) => void;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n sessionId?: string;\n setProtocolVersion?: (version: string) => void;\n}\n\n/**\n * Request envelope accepted by `AdcpServer.dispatchTestRequest()`.\n *\n * Mirrors the JSON-RPC method/params shape so tests can target the same\n * methods the transport would — `tools/call`, `tools/list`, etc.\n */\nexport interface AdcpTestRequest {\n method: string;\n params?: Record<string, unknown>;\n}\n\n/**\n * Typed variant of {@link AdcpTestRequest} for `tools/call`. Used by the\n * `dispatchTestRequest` overload that returns a typed `CallToolResult`.\n */\nexport interface AdcpTestToolsCallRequest {\n method: 'tools/call';\n params: { name: string; arguments?: Record<string, unknown> };\n}\n\n/**\n * Response returned by `AdcpServer.dispatchTestRequest()`.\n *\n * The shape depends on the `method` — for `tools/call` this is the\n * `CallToolResult` (content + structuredContent + optional isError);\n * for other methods it's the method-specific result. Left as `unknown`\n * so callers narrow with type guards or schema validation relevant to\n * the specific method they're dispatching.\n */\nexport type AdcpTestResponse = unknown;\n\n/**\n * Auth principal visible to handlers and `resolveAccount`. Mirrors the\n * shape `serve()` produces from its `authenticate` hook, and what the\n * A2A adapter's `authenticate` callback should return.\n */\nexport interface AdcpAuthInfo {\n token: string;\n clientId: string;\n scopes: string[];\n expiresAt?: number;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Optional per-call overrides for `dispatchTestRequest()`. Lets tests\n * simulate transport-level state — most importantly the `authInfo` that\n * `serve()` populates from its `authenticate` hook — without spinning up\n * a real HTTP transport.\n */\nexport interface AdcpTestRequestExtras {\n authInfo?: AdcpAuthInfo;\n sessionId?: string;\n}\n\n/**\n * Arguments accepted by `AdcpServer.invoke()`. A transport adapter (MCP\n * `serve()`, `createA2AAdapter()`, etc.) authenticates the incoming\n * request, maps it to one of the registered AdCP tool names, then calls\n * this surface to run the framework pipeline (idempotency, account\n * resolution, validation, governance, response-union narrowing).\n */\nexport interface AdcpInvokeOptions {\n /** AdCP tool name (`get_products`, `create_media_buy`, ...). */\n toolName: string;\n /** Tool arguments as received from the transport, pre-schema-validation. */\n args: Record<string, unknown>;\n /**\n * Auth principal the transport produced from its `authenticate` hook.\n * Handlers and `resolveAccount` see it as `ctx.authInfo`. Transports\n * MUST verify the principal before calling `invoke()` — `invoke()`\n * does NOT re-check the token.\n */\n authInfo?: AdcpAuthInfo;\n /** Abort signal for cancellation; defaults to a fresh controller. */\n signal?: AbortSignal;\n}\n\n/**\n * Test-harness hooks attached to every `AdcpServer`. Namespaced under\n * `compliance` so production code paths don't accidentally reach for\n * them — `reset()` drops cached state and is intended for storyboard\n * runners that exercise many scenarios in one process.\n */\nexport interface AdcpServerComplianceApi {\n /**\n * Drop session state and the idempotency cache so subsequent\n * storyboards don't inherit plans, media buys, or cached replies from\n * earlier runs. Conformance storyboards share brand domains across\n * test kits — without this hook, a $10K governance plan seeded by\n * `media_buy_seller/governance_denied` would intercept a $50K buy in\n * `sales_guaranteed`.\n *\n * Refuses to run by default unless BOTH guardrails hold:\n * - `NODE_ENV !== 'production'` (opt out with `allowProduction: true`)\n * - The configured stores are the in-memory SDK defaults\n * (`InMemoryStateStore` + memory idempotency backend). Opt out\n * with `force: true` when you've wired a disposable test\n * Postgres cluster and know the flush is safe.\n *\n * The two flags are independent on purpose: `force` lets you flush\n * a non-memory store you've verified is a test DB, WITHOUT also\n * opening the door to running against a production `NODE_ENV`.\n * Same the other way: `allowProduction` lets you run in a prod-\n * labeled CI environment against memory stores, without bypassing\n * the store-shape safety check.\n */\n reset(options?: { force?: boolean; allowProduction?: boolean }): Promise<void>;\n}\n\n/**\n * Phantom brand for {@link AdcpServer}. Makes the type nominal — a plain\n * object that has the same methods structurally cannot be assigned to\n * `AdcpServer` because it lacks this symbol-keyed property. Closes the\n * door on `(plainObject as AdcpServer).registerTool(...)` patterns that\n * tried to reach for an MCP-SDK method the framework intentionally\n * doesn't expose.\n *\n * The brand is `never`-typed and never set on the runtime object, so\n * `Object.getOwnPropertySymbols(server)` won't expose it — only the\n * wrapper produced by `createAdcpServer()` carries the type-level\n * signature, via the `as AdcpServerInternal` cast in `wrapMcpServer()`.\n *\n * Must be a real (non-`declare`) const so the d.ts emit retains it. An\n * `export declare const X: unique symbol` in a `.ts` source file does\n * not survive emit — the binding gets dropped from the published d.ts\n * while consumers (the public `AdcpServer` interface) keep referencing\n * it, which produces `TS2304: Cannot find name 'ADCP_SERVER_BRAND'` on\n * any adopter `tsc --noEmit` against `@adcp/sdk/server` (issue #1236).\n */\nexport const ADCP_SERVER_BRAND: unique symbol = Symbol('ADCP_SERVER_BRAND');\n\n/**\n * Opaque handle returned by `createAdcpServer()`.\n *\n * Pass to `serve()` to mount on an HTTP transport, or use\n * `dispatchTestRequest()` from a test harness to exercise handlers\n * in-process without opening a socket.\n */\nexport interface AdcpServer {\n /**\n * Phantom brand — type-level only, never present at runtime. See\n * {@link ADCP_SERVER_BRAND}. Tagged `never` so `(x as AdcpServer)`\n * casts from structurally-similar objects fail; a real `AdcpServer`\n * is only obtainable via `createAdcpServer()`.\n */\n readonly [ADCP_SERVER_BRAND]?: never;\n\n /**\n * Connect the server to an MCP transport.\n *\n * Takes ownership of the transport — any callbacks previously\n * registered on it are replaced. Matches the semantics of the SDK's\n * `McpServer.connect()`.\n */\n connect(transport: AdcpServerTransport): Promise<void>;\n\n /** Close the server and release resources. */\n close(): Promise<void>;\n\n /**\n * Test-harness hooks — see {@link AdcpServerComplianceApi}. Not\n * intended for production call sites; production code paths should\n * use `close()` to release resources.\n */\n readonly compliance: AdcpServerComplianceApi;\n\n /**\n * Invoke a registered handler in-process and return its response.\n *\n * Bypasses the transport layer — no sockets, no JSON-RPC framing.\n * Intended for test harnesses only; production callers should go\n * through a transport so protocol invariants (request ID linking,\n * task progress, notifications) are enforced.\n *\n * Throws when no handler is registered for the requested method,\n * or when a `tools/call` request targets an unknown tool. Arguments\n * default to `{}` when `params.arguments` is omitted — a validation\n * error from the tool's input schema (not from dispatch) is the\n * expected failure mode for a missing required field.\n *\n * **Never mount this behind an HTTP route.** `extras.authInfo` is\n * written directly onto the MCP handler's `extra` without any check\n * against `serve({ authenticate })` — exposing it externally lets a\n * caller impersonate any principal. This API is for in-process test\n * harnesses and storyboard runners only.\n *\n * @example\n * ```typescript\n * const result = await server.dispatchTestRequest({\n * method: 'tools/call',\n * params: {\n * name: 'get_products',\n * arguments: { brief: 'premium sports inventory' },\n * },\n * });\n * ```\n */\n dispatchTestRequest(request: AdcpTestToolsCallRequest, extras?: AdcpTestRequestExtras): Promise<CallToolResult>;\n dispatchTestRequest(request: AdcpTestRequest, extras?: AdcpTestRequestExtras): Promise<AdcpTestResponse>;\n\n /**\n * Production-safe tool invocation surface for transport adapters.\n *\n * Runs the full framework pipeline against a registered tool:\n * request schema validation → account resolution → idempotency →\n * handler dispatch → response narrowing → response validation.\n * Returns the same `McpToolResponse` envelope the MCP transport\n * observes — a transport adapter layers its own protocol framing on\n * top (JSON-RPC result for MCP, A2A `Task` artifact for A2A, etc.).\n *\n * **Auth is the caller's responsibility.** `invoke()` forwards the\n * provided `authInfo` verbatim to handlers and `resolveAccount`\n * without re-verifying. Mount it only behind a transport that has\n * already authenticated the principal (e.g. `serve({ authenticate })`\n * for MCP, `createA2AAdapter({ authenticate })` for A2A). Do not call\n * it directly from an HTTP handler — that path skips auth.\n *\n * For in-process tests that want to synthesize an `authInfo` without\n * running a transport, reach for {@link dispatchTestRequest} instead\n * — it takes the same principal shape but is explicitly marked\n * test-only in its docstring.\n *\n * Throws when `toolName` is not registered; schema errors round-trip\n * as structured `VALIDATION_ERROR` envelopes inside the return value.\n */\n invoke(options: AdcpInvokeOptions): Promise<McpToolResponse>;\n\n /**\n * Returns the AdCP protocol version this server is configured to speak.\n *\n * Defaults to {@link ADCP_VERSION} (the GA version the SDK ships against)\n * unless overridden via `createAdcpServer({ adcpVersion })`. This is the\n * protocol version, **not** the publisher's app version (`config.version`).\n *\n * Plumbing surface — Stage 2 of the multi-version refactor exposes the\n * configured value but does not yet vary validator/schema selection by\n * version. Wire-shape adapters key off this getter in subsequent stages.\n */\n getAdcpVersion(): string;\n}\n\n/**\n * Symbol-keyed accessor for the underlying SDK `McpServer`. Used by\n * `serve()` to reach through the opaque wrapper when SDK-specific\n * operations are needed. Not part of the public API — typed on a\n * separate internal interface so downstream consumers can't discover\n * it through the `AdcpServer` type.\n *\n * @internal\n */\nexport const ADCP_SDK_SERVER: unique symbol = Symbol.for('@adcp/client.sdkServer');\n\n/**\n * Symbol-keyed accessor for the state store backing an `AdcpServer`.\n * Test harnesses and helpers like\n * `@adcp/sdk/compliance-fixtures`'s `seedComplianceFixtures` need\n * to reach the store without widening the public `AdcpServer`\n * interface (handlers already get `ctx.store`; production code paths\n * don't need a second accessor).\n *\n * @internal\n */\nexport const ADCP_STATE_STORE: unique symbol = Symbol.for('@adcp/client.stateStore');\n\n/**\n * Symbol-keyed accessor for the capabilities object `createAdcpServer`\n * assembles and the auto-wired `get_adcp_capabilities` handler reads from.\n * Mutating this object mutates what subsequent capability-discovery calls\n * return — `registerTestController` uses this to add a\n * `compliance_testing` capability block after registration so the server\n * advertises its controller scenarios even though `registerTestController`\n * runs after `createAdcpServer`.\n *\n * @internal\n */\nexport const ADCP_CAPABILITIES: unique symbol = Symbol.for('@adcp/client.capabilities');\n\n/** Per-request tool visibility policy consumed by transport adapters. @internal */\nexport const ADCP_TOOL_VISIBILITY: unique symbol = Symbol.for('@adcp/client.toolVisibility');\n\n/** Configured MCP App resources mirrored into modern per-request servers. @internal */\nexport const ADCP_MCP_APP_RESOURCES: unique symbol = Symbol.for('@adcp/client.mcpAppResources');\n\n/** @internal */\nexport type AdcpToolVisibilityResolver = (options: {\n toolName: string;\n authInfo?: AdcpAuthInfo;\n input?: Readonly<Record<string, unknown>>;\n}) => boolean | Promise<boolean>;\n\n/** @internal */\nexport interface AdcpServerInternal extends AdcpServer {\n readonly [ADCP_SDK_SERVER]: McpServer;\n [ADCP_TOOL_VISIBILITY]?: AdcpToolVisibilityResolver;\n [ADCP_MCP_APP_RESOURCES]?: readonly AdcpMcpResourceDefinition[];\n}\n\n/**\n * Return the underlying `McpServer` for a wrapped `AdcpServer`, or\n * `undefined` if the value is not an `AdcpServer` produced by\n * `createAdcpServer()`.\n *\n * @internal\n */\nexport function getSdkServer(server: AdcpServer | McpServer): McpServer | undefined {\n const candidate = (server as unknown as Partial<AdcpServerInternal>)[ADCP_SDK_SERVER];\n return candidate;\n}\n\n/** Attach a transport-independent per-request tool visibility policy. @internal */\nexport function setToolVisibilityResolver(server: AdcpServer, resolver: AdcpToolVisibilityResolver): void {\n (server as AdcpServerInternal)[ADCP_TOOL_VISIBILITY] = resolver;\n}\n\n/** Attach validated resource definitions for transport adapters. @internal */\nexport function setMcpAppResources(server: AdcpServer, resources: readonly AdcpMcpResourceDefinition[]): void {\n Object.defineProperty(server, ADCP_MCP_APP_RESOURCES, {\n value: resources,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n}\n\n/** Read validated resource definitions for transport adapters. @internal */\nexport function listMcpAppResources(server: AdcpServer): readonly AdcpMcpResourceDefinition[] {\n return (server as AdcpServerInternal)[ADCP_MCP_APP_RESOURCES] ?? [];\n}\n\n/** Resolve whether a registered tool may be exposed to this request. @internal */\nexport async function isRegisteredToolVisible(\n server: AdcpServer,\n options: Parameters<AdcpToolVisibilityResolver>[0]\n): Promise<boolean> {\n const resolver = (server as AdcpServerInternal)[ADCP_TOOL_VISIBILITY];\n return resolver ? resolver(options) : true;\n}\n\n/**\n * True when `value` is an `AdcpServer` produced by `createAdcpServer()`.\n *\n * @internal\n */\nexport function isAdcpServer(value: unknown): value is AdcpServerInternal {\n return (\n value != null &&\n typeof value === 'object' &&\n ADCP_SDK_SERVER in (value as Record<PropertyKey, unknown>) &&\n typeof (value as AdcpServer).dispatchTestRequest === 'function'\n );\n}\n\n// ---------------------------------------------------------------------------\n// Private-field access — centralized\n// ---------------------------------------------------------------------------\n//\n// The MCP SDK marks `_requestHandlers` and `_registeredTools` as private.\n// Dispatching a request in-process from a test needs them. Doing it once\n// here means downstream harnesses don't each repeat the (server as any)\n// dance, which is the whole point of exposing `dispatchTestRequest()`.\n//\n// If/when the SDK ships a public in-process dispatch API, swap these two\n// helpers for that API. The AdcpServer surface stays the same.\n\ninterface RegisteredTool {\n title?: string;\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: unknown;\n _meta?: Record<string, unknown>;\n enabled?: boolean;\n handler: (args: unknown, extra: unknown) => unknown | Promise<unknown>;\n}\n\ninterface McpServerPrivates {\n _registeredTools?: Record<string, RegisteredTool | undefined>;\n server?: {\n _requestHandlers?: Map<\n string,\n (request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>\n >;\n _serverInfo?: { name: string; version: string; [key: string]: unknown };\n _instructions?: string;\n };\n}\n\n/** Tool metadata needed to mirror the registered AdCP surface into another official MCP transport. @internal */\nexport interface RegisteredToolDefinition {\n name: string;\n title?: string;\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: unknown;\n _meta?: Record<string, unknown>;\n}\n\n/** @internal */\ntype McpRequestHandler = (request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>;\n\n/**\n * Write the instructions string onto the low-level SDK server backing\n * `mcpServer`. Called by the async-function-form instructions hook to\n * inject the resolved string just before the MCP `initialize` response.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function setSdkServerInstructions(mcpServer: McpServer, value: string | undefined): void {\n const priv = mcpServer as unknown as McpServerPrivates;\n if (priv.server) {\n priv.server._instructions = value;\n }\n}\n\n/**\n * Wrap the `initialize` request handler on `mcpServer` so that `wrapper`\n * runs (and can await async work) before the original handler responds.\n * The wrapper receives the original handler as its first argument and must\n * call it to complete the handshake.\n *\n * The wrapper is invoked once per MCP `initialize` call on this server\n * instance. Under `serve({ reuseAgent: false })` the server is created\n * fresh per request, so the wrapper fires once per session. Under\n * `reuseAgent: true` the `ADCP_INSTRUCTIONS_FN` check in `serve.ts`\n * blocks the combination before the wrapper can be called a second time.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapInitializeHandler(\n mcpServer: McpServer,\n wrapper: (\n origHandler: McpRequestHandler,\n req: { method: string; params?: unknown },\n extra: unknown\n ) => unknown | Promise<unknown>\n): void {\n const priv = mcpServer as unknown as McpServerPrivates;\n const handlers = priv.server?._requestHandlers;\n if (!handlers) return;\n const orig = handlers.get('initialize');\n if (!orig) return;\n handlers.set('initialize', (req, extra) => wrapper(orig, req, extra));\n}\n\nfunction getRegisteredTool(server: McpServer, name: string): RegisteredTool | undefined {\n return (server as unknown as McpServerPrivates)._registeredTools?.[name];\n}\n\n/**\n * Wrap a registered MCP tool handler without changing the tool definition\n * advertised by the SDK server.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapRegisteredToolHandler(\n server: McpServer,\n name: string,\n wrapper: (orig: RegisteredTool['handler'], args: unknown, extra: unknown) => unknown | Promise<unknown>\n): boolean {\n const tool = getRegisteredTool(server, name);\n if (!tool) return false;\n const orig = tool.handler;\n tool.handler = (args, extra) => wrapper(orig, args, extra);\n return true;\n}\n\n/**\n * Enumerate the tool names registered on the underlying SDK server.\n * Used by transport adapters that need to derive discovery metadata\n * (agent cards, capability listings) from the registered surface\n * without reaching into private SDK fields at every call site.\n *\n * @internal\n */\nexport function listRegisteredToolNames(server: McpServer): string[] {\n const registered = (server as unknown as McpServerPrivates)._registeredTools ?? {};\n return Object.keys(registered);\n}\n\n/**\n * Return enabled registered-tool metadata for the modern MCP server adapter.\n * Handler functions stay private; the adapter dispatches through\n * {@link AdcpServer.invoke} so the framework pipeline remains authoritative.\n *\n * @internal\n */\nexport function listRegisteredToolDefinitions(server: McpServer): RegisteredToolDefinition[] {\n const registered = (server as unknown as McpServerPrivates)._registeredTools ?? {};\n return Object.entries(registered).flatMap(([name, tool]) => {\n if (!tool || tool.enabled === false) return [];\n return [\n {\n name,\n ...(tool.title !== undefined && { title: tool.title }),\n ...(tool.description !== undefined && { description: tool.description }),\n ...(tool.inputSchema !== undefined && { inputSchema: tool.inputSchema }),\n ...(tool.outputSchema !== undefined && { outputSchema: tool.outputSchema }),\n ...(tool.annotations !== undefined && { annotations: tool.annotations }),\n ...(tool._meta !== undefined && { _meta: tool._meta }),\n },\n ];\n });\n}\n\n/** Return the SDK server identity advertised during MCP discovery. @internal */\nexport function getSdkServerInfo(server: McpServer): { name: string; version: string; [key: string]: unknown } {\n return (\n (server as unknown as McpServerPrivates).server?._serverInfo ?? {\n name: 'AdCP Server',\n version: 'unknown',\n }\n );\n}\n\n/** Return static or already-resolved server instructions. @internal */\nexport function getSdkServerInstructions(server: McpServer): string | undefined {\n return (server as unknown as McpServerPrivates).server?._instructions;\n}\n\nfunction getRequestHandler(\n server: McpServer,\n method: string\n): ((request: { method: string; params?: unknown }, extra: unknown) => unknown | Promise<unknown>) | undefined {\n return (server as unknown as McpServerPrivates).server?._requestHandlers?.get(method);\n}\n\n/**\n * Wrap an SDK request handler such as `tools/list` while preserving the\n * original handler's request/extra contract.\n *\n * @internal\n * @remarks Pokes an SDK private field — see the \"Private-field access\" note above.\n */\nexport function wrapSdkRequestHandler(\n server: McpServer,\n method: string,\n wrapper: (\n orig: McpRequestHandler,\n req: { method: string; params?: unknown },\n extra: unknown\n ) => unknown | Promise<unknown>\n): boolean {\n const handlers = (server as unknown as McpServerPrivates).server?._requestHandlers;\n const orig = handlers?.get(method);\n if (!handlers || !orig) return false;\n handlers.set(method, (req, extra) => wrapper(orig, req, extra));\n return true;\n}\n\n/**\n * Wrap an SDK `McpServer` into the opaque `AdcpServer` handle returned by\n * `createAdcpServer()`. Consumers should prefer `createAdcpServer()` and\n * treat this as an internal utility; it's exported for framework code\n * that needs to produce an `AdcpServer` around a hand-built server.\n *\n * Idempotent — passing an already-wrapped `AdcpServer` returns it\n * unchanged rather than nesting wrappers (which would leave\n * `ADCP_SDK_SERVER` pointing at the outer wrapper instead of the SDK\n * handle and break `getSdkServer()` round-trips).\n *\n * @internal\n */\nexport function wrapMcpServer(\n inner: McpServer | AdcpServerInternal,\n compliance?: AdcpServerComplianceApi,\n adcpVersion: string = ADCP_VERSION\n): AdcpServerInternal {\n if (isAdcpServer(inner)) return inner;\n const mcp = inner as McpServer;\n const resolvedCompliance: AdcpServerComplianceApi = compliance ?? {\n async reset() {\n throw new Error(\n 'AdcpServer.compliance.reset: no-op handle returned by `wrapMcpServer` without a compliance implementation. ' +\n 'Use `createAdcpServer()` to get a server whose `compliance.reset()` flushes the state and idempotency stores.'\n );\n },\n };\n const dispatch = async (request: AdcpTestRequest, extras?: AdcpTestRequestExtras): Promise<AdcpTestResponse> => {\n const extra: { signal: AbortSignal; authInfo?: AdcpTestRequestExtras['authInfo']; sessionId?: string } = {\n signal: new AbortController().signal,\n };\n if (extras?.authInfo) extra.authInfo = extras.authInfo;\n if (extras?.sessionId) extra.sessionId = extras.sessionId;\n\n if (request.method === 'tools/call') {\n const params = (request.params ?? {}) as { name?: string; arguments?: Record<string, unknown> };\n if (typeof params.name !== 'string') {\n throw new Error(\"dispatchTestRequest: 'tools/call' requires params.name (string)\");\n }\n const tool = getRegisteredTool(mcp, params.name);\n if (!tool) {\n throw new Error(`dispatchTestRequest: tool \"${params.name}\" is not registered`);\n }\n return tool.handler(params.arguments ?? {}, extra);\n }\n\n const handler = getRequestHandler(mcp, request.method);\n if (!handler) {\n throw new Error(`dispatchTestRequest: no handler registered for method \"${request.method}\"`);\n }\n return handler({ method: request.method, params: request.params ?? {} }, extra);\n };\n const invoke = async (options: AdcpInvokeOptions): Promise<McpToolResponse> => {\n const tool = getRegisteredTool(mcp, options.toolName);\n if (!tool) {\n throw new Error(`AdcpServer.invoke: tool \"${options.toolName}\" is not registered`);\n }\n const extra: { signal: AbortSignal; authInfo?: AdcpAuthInfo } = {\n signal: options.signal ?? new AbortController().signal,\n };\n if (options.authInfo) extra.authInfo = options.authInfo;\n return (await tool.handler(options.args, extra)) as McpToolResponse;\n };\n const wrapper: AdcpServerInternal = {\n [ADCP_SDK_SERVER]: mcp,\n connect(transport) {\n // The SDK's Transport interface is structurally compatible with\n // AdcpServerTransport — the cast is boundary-crossing, not lossy.\n return mcp.connect(transport as unknown as Parameters<McpServer['connect']>[0]);\n },\n close() {\n return mcp.close();\n },\n compliance: resolvedCompliance,\n // Satisfies both overloads (typed tools/call + generic fallback) — the\n // runtime dispatcher is a single function that narrows by method.\n dispatchTestRequest: dispatch as AdcpServerInternal['dispatchTestRequest'],\n invoke,\n getAdcpVersion: () => adcpVersion,\n };\n return wrapper;\n}\n"],"mappings":"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","names":[]}
@@ -4,6 +4,7 @@ const ADCP_SDK_SERVER = /* @__PURE__ */ Symbol.for("@adcp/client.sdkServer");
4
4
  const ADCP_STATE_STORE = /* @__PURE__ */ Symbol.for("@adcp/client.stateStore");
5
5
  const ADCP_CAPABILITIES = /* @__PURE__ */ Symbol.for("@adcp/client.capabilities");
6
6
  const ADCP_TOOL_VISIBILITY = /* @__PURE__ */ Symbol.for("@adcp/client.toolVisibility");
7
+ const ADCP_MCP_APP_RESOURCES = /* @__PURE__ */ Symbol.for("@adcp/client.mcpAppResources");
7
8
  function getSdkServer(server) {
8
9
  const candidate = server[ADCP_SDK_SERVER];
9
10
  return candidate;
@@ -11,6 +12,17 @@ function getSdkServer(server) {
11
12
  function setToolVisibilityResolver(server, resolver) {
12
13
  server[ADCP_TOOL_VISIBILITY] = resolver;
13
14
  }
15
+ function setMcpAppResources(server, resources) {
16
+ Object.defineProperty(server, ADCP_MCP_APP_RESOURCES, {
17
+ value: resources,
18
+ enumerable: false,
19
+ configurable: false,
20
+ writable: false
21
+ });
22
+ }
23
+ function listMcpAppResources(server) {
24
+ return server[ADCP_MCP_APP_RESOURCES] ?? [];
25
+ }
14
26
  async function isRegisteredToolVisible(server, options) {
15
27
  const resolver = server[ADCP_TOOL_VISIBILITY];
16
28
  return resolver ? resolver(options) : true;
@@ -145,6 +157,7 @@ function wrapMcpServer(inner, compliance, adcpVersion = ADCP_VERSION) {
145
157
  }
146
158
  export {
147
159
  ADCP_CAPABILITIES,
160
+ ADCP_MCP_APP_RESOURCES,
148
161
  ADCP_SDK_SERVER,
149
162
  ADCP_SERVER_BRAND,
150
163
  ADCP_STATE_STORE,
@@ -154,8 +167,10 @@ export {
154
167
  getSdkServerInstructions,
155
168
  isAdcpServer,
156
169
  isRegisteredToolVisible,
170
+ listMcpAppResources,
157
171
  listRegisteredToolDefinitions,
158
172
  listRegisteredToolNames,
173
+ setMcpAppResources,
159
174
  setSdkServerInstructions,
160
175
  setToolVisibilityResolver,
161
176
  wrapInitializeHandler,