@adcp/sdk 15.4.0 → 15.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +15 -0
  2. package/dist/lib/advanced.d.mts +2 -2
  3. package/dist/lib/advanced.d.ts +2 -2
  4. package/dist/lib/advanced.js +8 -2
  5. package/dist/lib/advanced.mjs +8 -2
  6. package/dist/lib/auth/oauth/index.d.mts +1 -0
  7. package/dist/lib/auth/oauth/index.d.ts +1 -0
  8. package/dist/lib/auth/oauth/index.js +5 -0
  9. package/dist/lib/auth/oauth/index.mjs +3 -0
  10. package/dist/lib/auth/oauth/pending-web-flow.d.mts +16 -0
  11. package/dist/lib/auth/oauth/pending-web-flow.d.ts +16 -0
  12. package/dist/lib/auth/oauth/pending-web-flow.js +66 -0
  13. package/dist/lib/auth/oauth/pending-web-flow.mjs +41 -0
  14. package/dist/lib/auth/oauth/web-flow.js +3 -3
  15. package/dist/lib/auth/oauth/web-flow.mjs +3 -3
  16. package/dist/lib/core/AgentClient.d.mts +4 -0
  17. package/dist/lib/core/AgentClient.d.ts +4 -0
  18. package/dist/lib/core/AgentClient.js +8 -0
  19. package/dist/lib/core/AgentClient.mjs +8 -0
  20. package/dist/lib/core/SingleAgentClient.d.mts +154 -0
  21. package/dist/lib/core/SingleAgentClient.d.ts +154 -0
  22. package/dist/lib/core/SingleAgentClient.js +661 -23
  23. package/dist/lib/core/SingleAgentClient.mjs +666 -23
  24. package/dist/lib/core/agent-discovery-cache.d.mts +103 -0
  25. package/dist/lib/core/agent-discovery-cache.d.ts +103 -0
  26. package/dist/lib/core/agent-discovery-cache.js +121 -0
  27. package/dist/lib/core/agent-discovery-cache.mjs +92 -0
  28. package/dist/lib/index.d.mts +5 -3
  29. package/dist/lib/index.d.ts +5 -3
  30. package/dist/lib/index.js +7 -0
  31. package/dist/lib/index.mjs +6 -0
  32. package/dist/lib/protocols/index.d.mts +2 -2
  33. package/dist/lib/protocols/index.d.ts +2 -2
  34. package/dist/lib/protocols/index.js +1 -1
  35. package/dist/lib/protocols/index.mjs +1 -1
  36. package/dist/lib/protocols/mcp-call-context.d.mts +109 -0
  37. package/dist/lib/protocols/mcp-call-context.d.ts +109 -0
  38. package/dist/lib/protocols/mcp-call-context.js +221 -0
  39. package/dist/lib/protocols/mcp-call-context.mjs +186 -0
  40. package/dist/lib/protocols/mcp-modern.d.mts +9 -1
  41. package/dist/lib/protocols/mcp-modern.d.ts +9 -1
  42. package/dist/lib/protocols/mcp-modern.js +180 -104
  43. package/dist/lib/protocols/mcp-modern.mjs +193 -104
  44. package/dist/lib/protocols/mcp-scope.d.mts +15 -0
  45. package/dist/lib/protocols/mcp-scope.d.ts +15 -0
  46. package/dist/lib/protocols/mcp.d.mts +4 -2
  47. package/dist/lib/protocols/mcp.d.ts +4 -2
  48. package/dist/lib/protocols/mcp.js +178 -154
  49. package/dist/lib/protocols/mcp.mjs +189 -153
  50. package/dist/lib/protocols/transportDiagnostics.d.mts +33 -1
  51. package/dist/lib/protocols/transportDiagnostics.d.ts +33 -1
  52. package/dist/lib/protocols/transportDiagnostics.js +128 -12
  53. package/dist/lib/protocols/transportDiagnostics.mjs +128 -12
  54. package/dist/lib/registry/types.generated.d.mts +63 -1
  55. package/dist/lib/registry/types.generated.d.ts +63 -1
  56. package/dist/lib/reporting/azure/index.d.mts +26 -0
  57. package/dist/lib/reporting/azure/index.d.ts +26 -0
  58. package/dist/lib/reporting/azure/index.js +247 -0
  59. package/dist/lib/reporting/azure/index.mjs +230 -0
  60. package/dist/lib/reporting/bigquery/index.d.mts +127 -0
  61. package/dist/lib/reporting/bigquery/index.d.ts +127 -0
  62. package/dist/lib/reporting/bigquery/index.js +379 -0
  63. package/dist/lib/reporting/bigquery/index.mjs +341 -0
  64. package/dist/lib/reporting/gcs/index.d.mts +2 -0
  65. package/dist/lib/reporting/gcs/index.d.ts +2 -0
  66. package/dist/lib/reporting/gcs/index.js +3 -0
  67. package/dist/lib/reporting/gcs/index.mjs +2 -0
  68. package/dist/lib/reporting/gcs/row-provider.d.mts +32 -0
  69. package/dist/lib/reporting/gcs/row-provider.d.ts +32 -0
  70. package/dist/lib/reporting/gcs/row-provider.js +205 -0
  71. package/dist/lib/reporting/gcs/row-provider.mjs +188 -0
  72. package/dist/lib/reporting/ledger/change-feed.d.mts +41 -0
  73. package/dist/lib/reporting/ledger/change-feed.d.ts +41 -0
  74. package/dist/lib/reporting/ledger/change-feed.js +101 -0
  75. package/dist/lib/reporting/ledger/change-feed.mjs +74 -0
  76. package/dist/lib/reporting/ledger/handler.js +22 -8
  77. package/dist/lib/reporting/ledger/handler.mjs +22 -8
  78. package/dist/lib/reporting/ledger/index.d.mts +4 -0
  79. package/dist/lib/reporting/ledger/index.d.ts +4 -0
  80. package/dist/lib/reporting/ledger/index.js +9 -1
  81. package/dist/lib/reporting/ledger/index.mjs +4 -0
  82. package/dist/lib/reporting/ledger/managed-postgres.d.mts +2 -0
  83. package/dist/lib/reporting/ledger/managed-postgres.d.ts +2 -0
  84. package/dist/lib/reporting/ledger/managed-postgres.js +21 -1
  85. package/dist/lib/reporting/ledger/managed-postgres.mjs +21 -1
  86. package/dist/lib/reporting/ledger/managed.d.mts +9 -0
  87. package/dist/lib/reporting/ledger/managed.d.ts +9 -0
  88. package/dist/lib/reporting/ledger/managed.js +18 -0
  89. package/dist/lib/reporting/ledger/managed.mjs +18 -0
  90. package/dist/lib/reporting/ledger/postgres.d.mts +185 -0
  91. package/dist/lib/reporting/ledger/postgres.d.ts +185 -0
  92. package/dist/lib/reporting/ledger/postgres.js +872 -26
  93. package/dist/lib/reporting/ledger/postgres.mjs +880 -26
  94. package/dist/lib/reporting/ledger/producer.js +10 -1
  95. package/dist/lib/reporting/ledger/producer.mjs +10 -1
  96. package/dist/lib/reporting/ledger/row-storage-errors.d.mts +7 -0
  97. package/dist/lib/reporting/ledger/row-storage-errors.d.ts +7 -0
  98. package/dist/lib/reporting/ledger/row-storage-errors.js +41 -0
  99. package/dist/lib/reporting/ledger/row-storage-errors.mjs +16 -0
  100. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +41 -0
  101. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +41 -0
  102. package/dist/lib/reporting/ledger/row-storage-migration.js +234 -0
  103. package/dist/lib/reporting/ledger/row-storage-migration.mjs +208 -0
  104. package/dist/lib/reporting/ledger/row-storage-object.d.mts +112 -0
  105. package/dist/lib/reporting/ledger/row-storage-object.d.ts +112 -0
  106. package/dist/lib/reporting/ledger/row-storage-object.js +304 -0
  107. package/dist/lib/reporting/ledger/row-storage-object.mjs +262 -0
  108. package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +44 -0
  109. package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +44 -0
  110. package/dist/lib/reporting/ledger/row-storage-provider-io.js +142 -0
  111. package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +111 -0
  112. package/dist/lib/reporting/ledger/row-storage.d.mts +224 -0
  113. package/dist/lib/reporting/ledger/row-storage.d.ts +224 -0
  114. package/dist/lib/reporting/ledger/row-storage.js +692 -0
  115. package/dist/lib/reporting/ledger/row-storage.mjs +680 -0
  116. package/dist/lib/reporting/ledger/types.d.mts +8 -0
  117. package/dist/lib/reporting/ledger/types.d.ts +8 -0
  118. package/dist/lib/reporting/s3/index.d.mts +29 -0
  119. package/dist/lib/reporting/s3/index.d.ts +29 -0
  120. package/dist/lib/reporting/s3/index.js +324 -0
  121. package/dist/lib/reporting/s3/index.mjs +317 -0
  122. package/dist/lib/reporting/service/index.d.mts +43 -1
  123. package/dist/lib/reporting/service/index.d.ts +43 -1
  124. package/dist/lib/reporting/service/index.js +69 -1
  125. package/dist/lib/reporting/service/index.mjs +71 -1
  126. package/dist/lib/schemas/browser.d.mts +14 -0
  127. package/dist/lib/schemas/browser.d.ts +14 -0
  128. package/dist/lib/schemas/browser.js +48 -0
  129. package/dist/lib/schemas/browser.mjs +20 -0
  130. package/dist/lib/schemas/index.d.mts +2 -120
  131. package/dist/lib/schemas/index.d.ts +2 -120
  132. package/dist/lib/schemas/index.js +3 -11
  133. package/dist/lib/schemas/index.mjs +1 -9
  134. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  135. package/dist/lib/testing/index.d.mts +1 -0
  136. package/dist/lib/testing/index.d.ts +1 -0
  137. package/dist/lib/testing/index.js +3 -0
  138. package/dist/lib/testing/index.mjs +2 -0
  139. package/dist/lib/testing/pending-web-flow-store.d.mts +20 -0
  140. package/dist/lib/testing/pending-web-flow-store.d.ts +20 -0
  141. package/dist/lib/testing/pending-web-flow-store.js +132 -0
  142. package/dist/lib/testing/pending-web-flow-store.mjs +98 -0
  143. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  144. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  145. package/dist/lib/validation/get-products-request.d.mts +122 -0
  146. package/dist/lib/validation/get-products-request.d.ts +122 -0
  147. package/dist/lib/validation/get-products-request.js +39 -0
  148. package/dist/lib/validation/get-products-request.mjs +14 -0
  149. package/dist/lib/version.d.mts +3 -3
  150. package/dist/lib/version.d.ts +3 -3
  151. package/dist/lib/version.js +3 -3
  152. package/dist/lib/version.mjs +3 -3
  153. package/docs/README.md +1 -1
  154. package/docs/TYPE-SUMMARY.md +35 -2
  155. package/docs/ZOD-SCHEMAS.md +13 -1
  156. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +142 -0
  157. package/docs/guides/EXISTING-PLATFORM.md +43 -12
  158. package/docs/guides/OAUTH-ISSUER-BINDING.md +6 -0
  159. package/docs/guides/REPORTING-LEDGER.md +374 -0
  160. package/docs/guides/REPORTING-OPERATIONS.md +76 -1
  161. package/docs/guides/WEB-OAUTH.md +48 -1
  162. package/docs/llms.txt +4 -2
  163. package/docs/migration-14.x-rc-worksheet.md +6 -4
  164. package/package.json +64 -1
@@ -26,7 +26,8 @@ __export(mcp_exports, {
26
26
  closeOAuthConnections: () => closeOAuthConnections,
27
27
  connectMCP: () => connectMCP,
28
28
  connectMCPWithFallback: () => connectMCPWithFallback,
29
- withCachedConnection: () => withCachedConnection
29
+ withCachedConnection: () => withCachedConnection,
30
+ withScopedLegacyConnection: () => withScopedLegacyConnection
30
31
  });
31
32
  module.exports = __toCommonJS(mcp_exports);
32
33
  var import_client = require("@modelcontextprotocol/sdk/client/index.js");
@@ -48,6 +49,7 @@ var import_abort = require('./abort.js');
48
49
  var import_mcp_modern = require('./mcp-modern.js');
49
50
  var import_mcp_scope = require('./mcp-scope.js');
50
51
  var import_session_termination = require('./session-termination.js');
52
+ var import_mcp_call_context = require('./mcp-call-context.js');
51
53
  var import_agent_transport_fetch = require('../net/agent-transport-fetch.js');
52
54
  const connectionCache = /* @__PURE__ */ new Map();
53
55
  const pendingConnections = /* @__PURE__ */ new Map();
@@ -56,11 +58,9 @@ const pendingOAuthConnections = /* @__PURE__ */ new Map();
56
58
  const streamableTransports = /* @__PURE__ */ new WeakMap();
57
59
  const oauthProviderIds = /* @__PURE__ */ new WeakMap();
58
60
  const transportFetchFnIds = /* @__PURE__ */ new WeakMap();
59
- const transportSignalIds = /* @__PURE__ */ new WeakMap();
60
61
  const MAX_CACHED_CONNECTIONS = 20;
61
62
  let nextOAuthProviderId = 0;
62
63
  let nextTransportFetchFnId = 0;
63
- let nextTransportSignalId = 0;
64
64
  let connectionGeneration = 0;
65
65
  let oauthConnectionGeneration = 0;
66
66
  async function closeMCPClient(client, terminateSession = true) {
@@ -80,7 +80,7 @@ function trackStreamableHTTPUrl(url) {
80
80
  if (oldest) knownStreamableHTTPUrls.delete(oldest);
81
81
  }
82
82
  }
83
- function connectionCacheKey(agentUrl, authToken, signingCacheKey, authHeaders, transportFetch, signal, requestTimeoutMs, allowPrivateIp) {
83
+ function connectionCacheKey(agentUrl, authToken, signingCacheKey, authHeaders, transportFetch, allowPrivateIp) {
84
84
  const parts = [agentUrl];
85
85
  const fingerprint = authToken ?? extractAuthHeader(authHeaders);
86
86
  if (fingerprint) parts.push(cacheDisambiguator(fingerprint));
@@ -88,8 +88,6 @@ function connectionCacheKey(agentUrl, authToken, signingCacheKey, authHeaders, t
88
88
  if (headersKey) parts.push(`headers:${headersKey}`);
89
89
  if (signingCacheKey) parts.push(signingCacheKey);
90
90
  if (transportFetch) parts.push(`fetch:${getTransportFetchFnDisambiguator(transportFetch)}`);
91
- if (signal) parts.push(`signal:${getTransportSignalDisambiguator(signal)}`);
92
- if (requestTimeoutMs !== void 0) parts.push(`timeout:${requestTimeoutMs}`);
93
91
  if (allowPrivateIp !== void 0) parts.push(`allow-private-ip:${allowPrivateIp}`);
94
92
  const scopeKey = (0, import_mcp_scope.currentMCPConnectionScopeKey)();
95
93
  if (scopeKey) parts.push(scopeKey);
@@ -107,18 +105,19 @@ function extractAuthHeader(headers) {
107
105
  return void 0;
108
106
  }
109
107
  function headersCacheDisambiguator(headers) {
110
- const entries = Object.entries(headers ?? {}).filter(([key]) => {
111
- const lower = key.toLowerCase();
112
- return lower !== "traceparent" && lower !== "tracestate" && lower !== "baggage";
113
- }).map(([key, value]) => [key.toLowerCase(), value]).sort(([a], [b]) => a.localeCompare(b));
108
+ const entries = Object.entries((0, import_mcp_call_context.splitConnectionHeaders)(headers).identity).map(([key, value]) => [key.toLowerCase(), value]).sort(([a], [b]) => a.localeCompare(b));
114
109
  return entries.length > 0 ? cacheDisambiguator(JSON.stringify(entries)) : void 0;
115
110
  }
116
- function withPerRequestTraceHeaders(fetchImpl) {
111
+ function withPerRequestTraceHeaders(fetchImpl, directDefaults) {
117
112
  return (input, init) => {
118
113
  const headers = new Headers(input instanceof Request ? input.headers : void 0);
119
114
  new Headers(init?.headers).forEach((value, key) => headers.set(key, value));
120
- for (const [key, value] of Object.entries((0, import_tracing.injectTraceHeaders)())) headers.set(key, value);
121
- return fetchImpl(input, { ...init, headers });
115
+ (0, import_mcp_call_context.applyMCPCallHeaders)(headers, directDefaults);
116
+ if (headers.has("traceparent")) return fetchImpl(input, { ...init, headers, ...(0, import_mcp_call_context.linkedCallSignal)(init) });
117
+ for (const [key, value] of Object.entries((0, import_tracing.injectTraceHeaders)())) {
118
+ if ((0, import_mcp_call_context.isCorrelationHeader)(key) && !headers.has(key)) headers.set(key, value);
119
+ }
120
+ return fetchImpl(input, { ...init, headers, ...(0, import_mcp_call_context.linkedCallSignal)(init) });
122
121
  };
123
122
  }
124
123
  function getCachedConnection(key) {
@@ -135,7 +134,7 @@ function evictLeastRecentlyUsed() {
135
134
  if (!lruKey) return;
136
135
  const oldClient = connectionCache.get(lruKey);
137
136
  connectionCache.delete(lruKey);
138
- if (oldClient) void closeMCPClient(oldClient).catch(() => {
137
+ if (oldClient) void (0, import_mcp_call_context.closeWhenIdle)(oldClient, () => closeMCPClient(oldClient)).catch(() => {
139
138
  });
140
139
  }
141
140
  function evictLeastRecentlyUsedOAuth() {
@@ -144,7 +143,7 @@ function evictLeastRecentlyUsedOAuth() {
144
143
  if (!lruKey) return;
145
144
  const oldClient = oauthConnectionCache.get(lruKey);
146
145
  oauthConnectionCache.delete(lruKey);
147
- if (oldClient) void closeMCPClient(oldClient).catch(() => {
146
+ if (oldClient) void (0, import_mcp_call_context.closeWhenIdle)(oldClient, () => closeMCPClient(oldClient)).catch(() => {
148
147
  });
149
148
  }
150
149
  async function closeOAuthConnections() {
@@ -185,31 +184,37 @@ async function closeMCPConnections() {
185
184
  await (0, import_mcp_modern.closeModernMCPConnections)();
186
185
  }
187
186
  async function getOrCreateConnection(cacheKey, baseUrl, authHeaders, debugLogs, label, transportFetch, requestOptions = {}) {
188
- const cached = getCachedConnection(cacheKey);
189
- if (cached) return cached;
190
- const pending = pendingConnections.get(cacheKey);
191
- if (pending) return pending;
192
- const generation = connectionGeneration;
193
- const promise = connectMCPWithFallback(baseUrl, authHeaders, debugLogs, label, transportFetch, requestOptions).then(async (client) => {
194
- if (generation !== connectionGeneration) {
195
- await closeMCPClient(client).catch(() => {
196
- });
197
- throw new Error(`MCP ${label} completed after connection teardown`);
187
+ for (let attempt = 0; ; attempt++) {
188
+ const cached = getCachedConnection(cacheKey);
189
+ if (cached) return cached;
190
+ const pending = pendingConnections.get(cacheKey);
191
+ if (pending) {
192
+ const joined = await (0, import_mcp_call_context.joinPendingConnection)(pending, requestOptions, attempt);
193
+ if (joined === import_mcp_call_context.RETRY_CONNECT) continue;
194
+ return joined;
198
195
  }
199
- connectionCache.set(cacheKey, client);
200
- (0, import_mcp_scope.registerMCPConnectionScopeCleanup)("legacy", cacheKey, async () => {
201
- if (connectionCache.get(cacheKey) !== client) return;
202
- connectionCache.delete(cacheKey);
203
- await closeMCPClient(client);
196
+ const generation = connectionGeneration;
197
+ const promise = connectMCPWithFallback(baseUrl, authHeaders, debugLogs, label, transportFetch, requestOptions).then(async (client) => {
198
+ if (generation !== connectionGeneration) {
199
+ await closeMCPClient(client).catch(() => {
200
+ });
201
+ throw new Error(`MCP ${label} completed after connection teardown`);
202
+ }
203
+ connectionCache.set(cacheKey, client);
204
+ (0, import_mcp_scope.registerMCPConnectionScopeCleanup)("legacy", cacheKey, async () => {
205
+ if (connectionCache.get(cacheKey) !== client) return;
206
+ connectionCache.delete(cacheKey);
207
+ await closeMCPClient(client);
208
+ });
209
+ evictLeastRecentlyUsed();
210
+ return client;
211
+ }).finally(() => {
212
+ if (pendingConnections.get(cacheKey) === promise) pendingConnections.delete(cacheKey);
204
213
  });
205
- evictLeastRecentlyUsed();
206
- return client;
207
- }).finally(() => {
208
- if (pendingConnections.get(cacheKey) === promise) pendingConnections.delete(cacheKey);
209
- });
210
- pendingConnections.set(cacheKey, promise);
211
- (0, import_mcp_scope.registerMCPConnectionScopePending)(promise);
212
- return promise;
214
+ pendingConnections.set(cacheKey, promise);
215
+ (0, import_mcp_scope.registerMCPConnectionScopePending)(promise);
216
+ return promise;
217
+ }
213
218
  }
214
219
  function getOAuthProviderDisambiguator(authProvider) {
215
220
  let id = oauthProviderIds.get(authProvider);
@@ -227,25 +232,15 @@ function getTransportFetchFnDisambiguator(fetchFn) {
227
232
  }
228
233
  return id;
229
234
  }
230
- function getTransportSignalDisambiguator(signal) {
231
- let id = transportSignalIds.get(signal);
232
- if (!id) {
233
- id = cacheDisambiguator(`transport-signal:${++nextTransportSignalId}`);
234
- transportSignalIds.set(signal, id);
235
- }
236
- return id;
237
- }
238
235
  function customHeadersDisambiguator(customHeaders) {
239
236
  return headersCacheDisambiguator(customHeaders);
240
237
  }
241
- function oauthConnectionCacheKey(agentUrl, authProvider, signingCacheKey, customHeaders, fetchFn, signal, requestTimeoutMs, allowPrivateIp) {
238
+ function oauthConnectionCacheKey(agentUrl, authProvider, signingCacheKey, customHeaders, fetchFn, allowPrivateIp) {
242
239
  const parts = [`${agentUrl}::oauth:${getOAuthProviderDisambiguator(authProvider)}`];
243
240
  if (signingCacheKey) parts.push(signingCacheKey);
244
241
  const headersKey = customHeadersDisambiguator(customHeaders);
245
242
  if (headersKey) parts.push(`headers:${headersKey}`);
246
243
  if (fetchFn) parts.push(`fetch:${getTransportFetchFnDisambiguator(fetchFn)}`);
247
- if (signal) parts.push(`signal:${getTransportSignalDisambiguator(signal)}`);
248
- if (requestTimeoutMs !== void 0) parts.push(`timeout:${requestTimeoutMs}`);
249
244
  if (allowPrivateIp !== void 0) parts.push(`allow-private-ip:${allowPrivateIp}`);
250
245
  const scopeKey = (0, import_mcp_scope.currentMCPConnectionScopeKey)();
251
246
  if (scopeKey) parts.push(scopeKey);
@@ -260,39 +255,52 @@ function getCachedOAuthConnection(key) {
260
255
  return client;
261
256
  }
262
257
  async function getOrCreateOAuthConnection(cacheKey, options) {
263
- const cached = getCachedOAuthConnection(cacheKey);
264
- if (cached) return cached;
265
- const pending = pendingOAuthConnections.get(cacheKey);
266
- if (pending) return pending;
267
- const generation = oauthConnectionGeneration;
268
- const promise = connectMCP(options).then(async ({ client }) => {
269
- if (generation !== oauthConnectionGeneration) {
270
- await closeMCPClient(client).catch(() => {
271
- });
272
- throw new Error("OAuth MCP connection completed after connection teardown");
258
+ for (let attempt = 0; ; attempt++) {
259
+ const cached = getCachedOAuthConnection(cacheKey);
260
+ if (cached) return cached;
261
+ const pending = pendingOAuthConnections.get(cacheKey);
262
+ if (pending) {
263
+ const joined = await (0, import_mcp_call_context.joinPendingConnection)(pending, options, attempt);
264
+ if (joined === import_mcp_call_context.RETRY_CONNECT) continue;
265
+ return joined;
273
266
  }
274
- oauthConnectionCache.set(cacheKey, client);
275
- (0, import_mcp_scope.registerMCPConnectionScopeCleanup)("oauth", cacheKey, async () => {
276
- if (oauthConnectionCache.get(cacheKey) !== client) return;
277
- oauthConnectionCache.delete(cacheKey);
278
- await closeMCPClient(client);
267
+ const generation = oauthConnectionGeneration;
268
+ const promise = connectMCP(options).then(async ({ client }) => {
269
+ if (generation !== oauthConnectionGeneration) {
270
+ await closeMCPClient(client).catch(() => {
271
+ });
272
+ throw new Error("OAuth MCP connection completed after connection teardown");
273
+ }
274
+ oauthConnectionCache.set(cacheKey, client);
275
+ (0, import_mcp_scope.registerMCPConnectionScopeCleanup)("oauth", cacheKey, async () => {
276
+ if (oauthConnectionCache.get(cacheKey) !== client) return;
277
+ oauthConnectionCache.delete(cacheKey);
278
+ await closeMCPClient(client);
279
+ });
280
+ evictLeastRecentlyUsedOAuth();
281
+ return client;
282
+ }).finally(() => {
283
+ if (pendingOAuthConnections.get(cacheKey) === promise) pendingOAuthConnections.delete(cacheKey);
279
284
  });
280
- evictLeastRecentlyUsedOAuth();
281
- return client;
282
- }).finally(() => {
283
- if (pendingOAuthConnections.get(cacheKey) === promise) pendingOAuthConnections.delete(cacheKey);
284
- });
285
- pendingOAuthConnections.set(cacheKey, promise);
286
- (0, import_mcp_scope.registerMCPConnectionScopePending)(promise);
287
- return promise;
285
+ pendingOAuthConnections.set(cacheKey, promise);
286
+ (0, import_mcp_scope.registerMCPConnectionScopePending)(promise);
287
+ return promise;
288
+ }
288
289
  }
289
290
  async function withCachedOAuthConnection(options, label, fn) {
290
- const guardedConnection = options.signal !== void 0 || options.requestTimeoutMs !== void 0 || options.fetchFn !== void 0;
291
+ options = { ...options, customHeaders: (0, import_mcp_call_context.withAmbientIdentityHeaders)(options.customHeaders) };
292
+ return (0, import_mcp_call_context.runWithMCPCallContext)(
293
+ callContextFor(options.customHeaders, options.requestTimeoutMs),
294
+ () => withCachedOAuthConnectionImpl(options, label, fn)
295
+ );
296
+ }
297
+ async function withCachedOAuthConnectionImpl(options, label, fn) {
298
+ const guardedConnection = options.fetchFn !== void 0;
291
299
  if (guardedConnection && (0, import_mcp_scope.currentMCPConnectionScopeKey)() === void 0) {
292
300
  const { client } = await connectMCP(options);
293
301
  let succeeded = false;
294
302
  try {
295
- const result = await fn(client);
303
+ const result = await (0, import_mcp_call_context.runCallPhase)(options.signal, () => fn(client));
296
304
  succeeded = true;
297
305
  return result;
298
306
  } finally {
@@ -306,13 +314,11 @@ async function withCachedOAuthConnection(options, label, fn) {
306
314
  options.signingContext?.cacheKey,
307
315
  options.customHeaders,
308
316
  options.fetchFn,
309
- options.signal,
310
- options.requestTimeoutMs,
311
317
  options.allowPrivateIp
312
318
  );
313
319
  const mcpClient = await getOrCreateOAuthConnection(cacheKey, options);
314
320
  try {
315
- return await fn(mcpClient);
321
+ return await (0, import_mcp_call_context.trackConnectionUse)(mcpClient, () => (0, import_mcp_call_context.runCallPhase)(options.signal, () => fn(mcpClient)));
316
322
  } catch (error) {
317
323
  const errorMessage = error instanceof Error ? error.message : String(error);
318
324
  options.debugLogs.push({
@@ -321,52 +327,38 @@ async function withCachedOAuthConnection(options, label, fn) {
321
327
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
322
328
  error
323
329
  });
330
+ if ((0, import_abort.isAbortOrTimeoutError)(error)) throw error;
324
331
  if ((0, import_errors.is401Error)(error)) {
325
- oauthConnectionCache.delete(cacheKey);
326
- try {
327
- await closeMCPClient(mcpClient, false);
328
- } catch {
329
- }
330
332
  options.debugLogs.push({
331
333
  type: "warning",
332
334
  message: `MCP: OAuth authentication issue detected for ${label}; evicted cached connection`,
333
335
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
334
336
  });
335
- throw error;
336
- }
337
- if ((0, import_abort.isAbortOrTimeoutError)(error)) {
338
- oauthConnectionCache.delete(cacheKey);
339
- try {
340
- await closeMCPClient(mcpClient, false);
341
- } catch {
342
- }
343
- throw error;
344
- }
345
- if (httpStatusOf(error) === 404) {
346
- oauthConnectionCache.delete(cacheKey);
347
- try {
348
- await closeMCPClient(mcpClient, false);
349
- } catch {
350
- }
351
- throw error;
352
- }
353
- oauthConnectionCache.delete(cacheKey);
354
- try {
355
- await closeMCPClient(mcpClient, false);
356
- } catch {
357
337
  }
338
+ await retireLegacyConnection(oauthConnectionCache, cacheKey, mcpClient);
358
339
  throw error;
359
340
  }
360
341
  }
361
342
  async function withCachedConnection(agentUrl, authToken, authHeaders, debugLogs, label, fn, transportFetch, requestOptions = {}) {
343
+ authHeaders = (0, import_mcp_call_context.withAmbientIdentityHeaders)(authHeaders);
344
+ return (0, import_mcp_call_context.runWithMCPCallContext)(
345
+ callContextFor(authHeaders, requestOptions.requestTimeoutMs),
346
+ () => withCachedConnectionImpl(agentUrl, authToken, authHeaders, debugLogs, label, fn, transportFetch, requestOptions)
347
+ );
348
+ }
349
+ async function withCachedConnectionImpl(agentUrl, authToken, authHeaders, debugLogs, label, fn, transportFetch, requestOptions) {
362
350
  const signingContext = import_client2.signingContextStorage.getStore();
363
351
  const baseUrl = new URL(agentUrl);
364
- const guardedConnection = transportFetch !== void 0 || requestOptions.signal !== void 0 || requestOptions.requestTimeoutMs !== void 0;
352
+ const guardedConnection = transportFetch !== void 0;
365
353
  if (guardedConnection && (0, import_mcp_scope.currentMCPConnectionScopeKey)() === void 0) {
366
354
  const client = await connectMCPWithFallback(baseUrl, authHeaders, debugLogs, label, transportFetch, requestOptions);
367
355
  let succeeded = false;
368
356
  try {
369
- const result = await (0, import_abort.withAbortSignal)([requestOptions.signal], void 0, () => fn(client));
357
+ const result = await (0, import_abort.withAbortSignal)(
358
+ [requestOptions.signal],
359
+ void 0,
360
+ () => (0, import_mcp_call_context.runCallPhase)(requestOptions.signal, () => fn(client))
361
+ );
370
362
  succeeded = true;
371
363
  return result;
372
364
  } finally {
@@ -380,8 +372,6 @@ async function withCachedConnection(agentUrl, authToken, authHeaders, debugLogs,
380
372
  signingContext?.cacheKey,
381
373
  authHeaders,
382
374
  transportFetch,
383
- requestOptions.signal,
384
- requestOptions.requestTimeoutMs,
385
375
  requestOptions.allowPrivateIp
386
376
  );
387
377
  const mcpClient = await getOrCreateConnection(
@@ -394,7 +384,7 @@ async function withCachedConnection(agentUrl, authToken, authHeaders, debugLogs,
394
384
  requestOptions
395
385
  );
396
386
  try {
397
- return await fn(mcpClient);
387
+ return await (0, import_mcp_call_context.trackConnectionUse)(mcpClient, () => (0, import_mcp_call_context.runCallPhase)(requestOptions.signal, () => fn(mcpClient)));
398
388
  } catch (error) {
399
389
  const errorMessage = error instanceof Error ? error.message : String(error);
400
390
  debugLogs.push({
@@ -403,48 +393,63 @@ async function withCachedConnection(agentUrl, authToken, authHeaders, debugLogs,
403
393
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
404
394
  error
405
395
  });
396
+ if ((0, import_abort.isAbortOrTimeoutError)(error)) throw error;
406
397
  if ((0, import_errors.is401Error)(error)) {
407
- connectionCache.delete(cacheKey);
408
- try {
409
- await closeMCPClient(mcpClient, false);
410
- } catch {
411
- }
412
398
  debugLogs.push({
413
399
  type: "warning",
414
400
  message: `MCP: Authentication issue detected for ${label} - headers may not be reaching server`,
415
401
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
416
402
  });
417
- throw error;
418
- }
419
- if ((0, import_abort.isAbortOrTimeoutError)(error)) {
420
- connectionCache.delete(cacheKey);
421
- try {
422
- await closeMCPClient(mcpClient, false);
423
- } catch {
424
- }
425
- throw error;
426
- }
427
- if (httpStatusOf(error) === 404) {
428
- connectionCache.delete(cacheKey);
429
- try {
430
- await closeMCPClient(mcpClient, false);
431
- } catch {
432
- }
403
+ } else if (httpStatusOf(error) === 404) {
433
404
  debugLogs.push({
434
405
  type: "warning",
435
406
  message: `MCP: Session not found for ${label}; evicted cached connection without retry`,
436
407
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
437
408
  });
438
- throw error;
439
- }
440
- connectionCache.delete(cacheKey);
441
- try {
442
- await closeMCPClient(mcpClient, false);
443
- } catch {
444
409
  }
410
+ await retireLegacyConnection(connectionCache, cacheKey, mcpClient);
445
411
  throw error;
446
412
  }
447
413
  }
414
+ async function withScopedLegacyConnection(options, label, fn) {
415
+ if ((0, import_mcp_scope.currentMCPConnectionScopeKey)() === void 0) return void 0;
416
+ const debugLogs = options.debugLogs ?? [];
417
+ if (options.authProvider) {
418
+ return {
419
+ value: await withCachedOAuthConnection({ ...options, authProvider: options.authProvider, debugLogs }, label, fn)
420
+ };
421
+ }
422
+ const authHeaders = (0, import_auth2.createMCPRequestHeaders)(options.customHeaders, options.authToken);
423
+ return {
424
+ value: await withCachedConnection(
425
+ options.agentUrl,
426
+ options.authToken,
427
+ authHeaders,
428
+ debugLogs,
429
+ label,
430
+ fn,
431
+ options.fetchFn,
432
+ {
433
+ signal: options.signal,
434
+ requestTimeoutMs: options.requestTimeoutMs,
435
+ allowPrivateIp: options.allowPrivateIp
436
+ }
437
+ )
438
+ };
439
+ }
440
+ function callContextFor(headers, requestTimeoutMs) {
441
+ const { perRequest } = (0, import_mcp_call_context.splitConnectionHeaders)(headers);
442
+ const timeoutMs = (0, import_abort.resolveRequestTimeoutMs)(requestTimeoutMs);
443
+ return {
444
+ ...Object.keys(perRequest).length > 0 && { headers: perRequest },
445
+ ...timeoutMs !== void 0 && { requestTimeoutMs: timeoutMs }
446
+ };
447
+ }
448
+ async function retireLegacyConnection(cache, cacheKey, client) {
449
+ if (cache.get(cacheKey) === client) cache.delete(cacheKey);
450
+ await (0, import_mcp_call_context.closeWhenIdle)(client, () => closeMCPClient(client, false)).catch(() => {
451
+ });
452
+ }
448
453
  function httpStatusOf(error, depth = 0) {
449
454
  if (!error || typeof error !== "object" || depth > 4) return void 0;
450
455
  const candidate = error;
@@ -454,6 +459,7 @@ function httpStatusOf(error, depth = 0) {
454
459
  return httpStatusOf(candidate.cause, depth + 1);
455
460
  }
456
461
  async function connectMCPWithFallback(url, authHeaders, debugLogs = [], label = "connection", transportFetch, requestOptions = {}) {
462
+ authHeaders = (0, import_mcp_call_context.withAmbientIdentityHeaders)(authHeaders);
457
463
  return (0, import_tracing.withSpan)(
458
464
  "adcp.mcp.connect",
459
465
  {
@@ -476,11 +482,15 @@ async function connectMCPWithFallbackImpl(url, authHeaders, debugLogs = [], labe
476
482
  trustedFetchFn: transportFetch,
477
483
  allowPrivateIp: requestOptions.allowPrivateIp
478
484
  });
479
- const networkFetch = (input, init) => {
480
- const signals = [init?.signal ?? void 0].filter((signal2) => signal2 !== void 0);
481
- const signal = signals.length === 0 ? void 0 : signals.length === 1 ? signals[0] : AbortSignal.any(signals);
482
- return rawNetworkFetch(input, { ...init, signal });
483
- };
485
+ const networkFetch = (input, init) => (
486
+ // Cancellation stays linked for the entire response-body lifetime, through
487
+ // `init.signal`: the v1 transport does not forward a request's own signal, so
488
+ // the active call's signal is linked to that call's POST at the outermost
489
+ // transport wrapper (aborting one call cancels its HTTP request without
490
+ // closing a session other calls share). The background GET/SSE listener
491
+ // never carries a call signal.
492
+ rawNetworkFetch(input, { ...init, signal: init?.signal ?? void 0 })
493
+ );
484
494
  const sizeLimited = (0, import_responseSizeLimit.wrapFetchWithSizeLimit)(networkFetch);
485
495
  const diagnosticFetch = (0, import_transportDiagnostics.wrapFetchWithTransportDiagnostics)(sizeLimited);
486
496
  const baseFetch = signingContext ? (0, import_client2.buildAgentSigningFetch)({
@@ -490,8 +500,8 @@ async function connectMCPWithFallbackImpl(url, authHeaders, debugLogs = [], labe
490
500
  adcpVersion: signingContext.adcpVersion
491
501
  }) : diagnosticFetch;
492
502
  const transportOptions = {
493
- requestInit: { headers: authHeaders, redirect: "manual" },
494
- fetch: (0, import_rawResponseCapture.wrapFetchWithCapture)(withPerRequestTraceHeaders(baseFetch))
503
+ requestInit: { headers: (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).identity, redirect: "manual" },
504
+ fetch: (0, import_rawResponseCapture.wrapFetchWithCapture)(withPerRequestTraceHeaders(baseFetch, (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).perRequest))
495
505
  };
496
506
  let failedClient;
497
507
  try {
@@ -585,8 +595,10 @@ async function connectMCPWithFallbackImpl(url, authHeaders, debugLogs = [], labe
585
595
  try {
586
596
  await client.connect(
587
597
  new import_sse.SSEClientTransport(url, {
588
- requestInit: { headers: authHeaders, redirect: "manual" },
589
- fetch: (0, import_rawResponseCapture.wrapFetchWithCapture)(withPerRequestTraceHeaders(baseFetch))
598
+ requestInit: { headers: (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).identity, redirect: "manual" },
599
+ fetch: (0, import_rawResponseCapture.wrapFetchWithCapture)(
600
+ withPerRequestTraceHeaders(baseFetch, (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).perRequest)
601
+ )
590
602
  }),
591
603
  mcpRequestOptions
592
604
  );
@@ -733,11 +745,11 @@ async function connectMCP(options) {
733
745
  return normalized !== "authorization" && normalized !== "x-adcp-auth";
734
746
  })
735
747
  ) : customHeaders;
736
- const authHeaders = (0, import_auth2.createMCPRequestHeaders)(filteredCustomHeaders, authToken);
748
+ const authHeaders = (0, import_mcp_call_context.withAmbientIdentityHeaders)((0, import_auth2.createMCPRequestHeaders)(filteredCustomHeaders, authToken));
737
749
  const hasNonAcceptCustomHeaders = Object.keys(filteredCustomHeaders ?? {}).some(
738
750
  (key) => key.toLowerCase() !== "accept"
739
751
  );
740
- transportOptions.requestInit = { headers: authHeaders, redirect: "manual" };
752
+ transportOptions.requestInit = { headers: (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).identity, redirect: "manual" };
741
753
  if (authProvider) {
742
754
  transportOptions.authProvider = authProvider;
743
755
  debugLogs.push({
@@ -758,18 +770,27 @@ async function connectMCP(options) {
758
770
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
759
771
  });
760
772
  }
761
- const requestTimeoutMs = (0, import_abort.resolveRequestTimeoutMs)(configuredRequestTimeoutMs);
762
773
  const clientRequestTimeoutMs = (0, import_abort.resolveClientRequestTimeoutMs)(configuredRequestTimeoutMs);
774
+ const directRequestTimeoutMs = (0, import_abort.resolveRequestTimeoutMs)(configuredRequestTimeoutMs);
763
775
  const requestOptions = {
764
776
  ...signal && { signal },
765
777
  ...clientRequestTimeoutMs !== void 0 && { timeout: clientRequestTimeoutMs }
766
778
  };
767
779
  const rawNetworkFetch = (0, import_agent_transport_fetch.createAgentTransportFetch)(agentUrl, { trustedFetchFn: fetchFn, allowPrivateIp });
768
780
  const sizeLimited = (0, import_responseSizeLimit.wrapFetchWithSizeLimit)(
769
- (input, init) => (0, import_abort.withAbortSignal)(
770
- [init?.signal],
771
- requestTimeoutMs,
772
- (linkedSignal) => rawNetworkFetch(input, { ...init, signal: linkedSignal })
781
+ (input, init) => (
782
+ // Inside a call context the deadline is that call's; a direct caller who
783
+ // holds the returned client keeps the timeout configured on connect. The
784
+ // call's own signal is already linked into `init.signal` for the whole
785
+ // response body, so aborting one call cancels its streamed POST only.
786
+ (0, import_abort.withAbortSignal)(
787
+ [init?.signal],
788
+ (0, import_mcp_call_context.requestTimeoutFor)(init, directRequestTimeoutMs),
789
+ (deadline) => rawNetworkFetch(input, {
790
+ ...init,
791
+ signal: init?.signal && deadline ? AbortSignal.any([init.signal, deadline]) : deadline ?? init?.signal
792
+ })
793
+ )
773
794
  )
774
795
  );
775
796
  const diagnosticFetch = (0, import_transportDiagnostics.wrapFetchWithTransportDiagnostics)(sizeLimited);
@@ -779,7 +800,9 @@ async function connectMCP(options) {
779
800
  getCapability: signingContext.getCapability,
780
801
  adcpVersion: signingContext.adcpVersion
781
802
  }) : diagnosticFetch;
782
- transportOptions.fetch = (0, import_rawResponseCapture.wrapFetchWithCapture)(withPerRequestTraceHeaders(signedFetch));
803
+ transportOptions.fetch = (0, import_rawResponseCapture.wrapFetchWithCapture)(
804
+ withPerRequestTraceHeaders(signedFetch, (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).perRequest)
805
+ );
783
806
  const transport = new import_streamableHttp.StreamableHTTPClientTransport(baseUrl, transportOptions);
784
807
  try {
785
808
  await mcpClient.connect(transport, requestOptions);
@@ -903,5 +926,6 @@ async function callMCPToolWithOAuth(options) {
903
926
  closeOAuthConnections,
904
927
  connectMCP,
905
928
  connectMCPWithFallback,
906
- withCachedConnection
929
+ withCachedConnection,
930
+ withScopedLegacyConnection
907
931
  });