@adcp/sdk 15.4.0 → 15.5.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 (115) hide show
  1. package/dist/lib/advanced.d.mts +2 -2
  2. package/dist/lib/advanced.d.ts +2 -2
  3. package/dist/lib/advanced.js +8 -2
  4. package/dist/lib/advanced.mjs +8 -2
  5. package/dist/lib/core/AgentClient.d.mts +4 -0
  6. package/dist/lib/core/AgentClient.d.ts +4 -0
  7. package/dist/lib/core/AgentClient.js +8 -0
  8. package/dist/lib/core/AgentClient.mjs +8 -0
  9. package/dist/lib/core/SingleAgentClient.d.mts +154 -0
  10. package/dist/lib/core/SingleAgentClient.d.ts +154 -0
  11. package/dist/lib/core/SingleAgentClient.js +661 -23
  12. package/dist/lib/core/SingleAgentClient.mjs +666 -23
  13. package/dist/lib/core/agent-discovery-cache.d.mts +103 -0
  14. package/dist/lib/core/agent-discovery-cache.d.ts +103 -0
  15. package/dist/lib/core/agent-discovery-cache.js +121 -0
  16. package/dist/lib/core/agent-discovery-cache.mjs +92 -0
  17. package/dist/lib/index.d.mts +5 -3
  18. package/dist/lib/index.d.ts +5 -3
  19. package/dist/lib/index.js +7 -0
  20. package/dist/lib/index.mjs +6 -0
  21. package/dist/lib/protocols/index.d.mts +2 -2
  22. package/dist/lib/protocols/index.d.ts +2 -2
  23. package/dist/lib/protocols/index.js +1 -1
  24. package/dist/lib/protocols/index.mjs +1 -1
  25. package/dist/lib/protocols/mcp-call-context.d.mts +109 -0
  26. package/dist/lib/protocols/mcp-call-context.d.ts +109 -0
  27. package/dist/lib/protocols/mcp-call-context.js +221 -0
  28. package/dist/lib/protocols/mcp-call-context.mjs +186 -0
  29. package/dist/lib/protocols/mcp-modern.d.mts +9 -1
  30. package/dist/lib/protocols/mcp-modern.d.ts +9 -1
  31. package/dist/lib/protocols/mcp-modern.js +180 -104
  32. package/dist/lib/protocols/mcp-modern.mjs +193 -104
  33. package/dist/lib/protocols/mcp-scope.d.mts +15 -0
  34. package/dist/lib/protocols/mcp-scope.d.ts +15 -0
  35. package/dist/lib/protocols/mcp.d.mts +4 -2
  36. package/dist/lib/protocols/mcp.d.ts +4 -2
  37. package/dist/lib/protocols/mcp.js +178 -154
  38. package/dist/lib/protocols/mcp.mjs +189 -153
  39. package/dist/lib/protocols/transportDiagnostics.d.mts +33 -1
  40. package/dist/lib/protocols/transportDiagnostics.d.ts +33 -1
  41. package/dist/lib/protocols/transportDiagnostics.js +128 -12
  42. package/dist/lib/protocols/transportDiagnostics.mjs +128 -12
  43. package/dist/lib/reporting/gcs/index.d.mts +2 -0
  44. package/dist/lib/reporting/gcs/index.d.ts +2 -0
  45. package/dist/lib/reporting/gcs/index.js +3 -0
  46. package/dist/lib/reporting/gcs/index.mjs +2 -0
  47. package/dist/lib/reporting/gcs/row-provider.d.mts +32 -0
  48. package/dist/lib/reporting/gcs/row-provider.d.ts +32 -0
  49. package/dist/lib/reporting/gcs/row-provider.js +205 -0
  50. package/dist/lib/reporting/gcs/row-provider.mjs +188 -0
  51. package/dist/lib/reporting/ledger/change-feed.d.mts +41 -0
  52. package/dist/lib/reporting/ledger/change-feed.d.ts +41 -0
  53. package/dist/lib/reporting/ledger/change-feed.js +101 -0
  54. package/dist/lib/reporting/ledger/change-feed.mjs +74 -0
  55. package/dist/lib/reporting/ledger/handler.js +22 -8
  56. package/dist/lib/reporting/ledger/handler.mjs +22 -8
  57. package/dist/lib/reporting/ledger/index.d.mts +4 -0
  58. package/dist/lib/reporting/ledger/index.d.ts +4 -0
  59. package/dist/lib/reporting/ledger/index.js +9 -1
  60. package/dist/lib/reporting/ledger/index.mjs +4 -0
  61. package/dist/lib/reporting/ledger/managed-postgres.d.mts +2 -0
  62. package/dist/lib/reporting/ledger/managed-postgres.d.ts +2 -0
  63. package/dist/lib/reporting/ledger/managed-postgres.js +21 -1
  64. package/dist/lib/reporting/ledger/managed-postgres.mjs +21 -1
  65. package/dist/lib/reporting/ledger/managed.d.mts +9 -0
  66. package/dist/lib/reporting/ledger/managed.d.ts +9 -0
  67. package/dist/lib/reporting/ledger/managed.js +18 -0
  68. package/dist/lib/reporting/ledger/managed.mjs +18 -0
  69. package/dist/lib/reporting/ledger/postgres.d.mts +175 -0
  70. package/dist/lib/reporting/ledger/postgres.d.ts +175 -0
  71. package/dist/lib/reporting/ledger/postgres.js +851 -26
  72. package/dist/lib/reporting/ledger/postgres.mjs +859 -26
  73. package/dist/lib/reporting/ledger/producer.js +10 -1
  74. package/dist/lib/reporting/ledger/producer.mjs +10 -1
  75. package/dist/lib/reporting/ledger/row-storage-errors.d.mts +7 -0
  76. package/dist/lib/reporting/ledger/row-storage-errors.d.ts +7 -0
  77. package/dist/lib/reporting/ledger/row-storage-errors.js +41 -0
  78. package/dist/lib/reporting/ledger/row-storage-errors.mjs +16 -0
  79. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +41 -0
  80. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +41 -0
  81. package/dist/lib/reporting/ledger/row-storage-migration.js +234 -0
  82. package/dist/lib/reporting/ledger/row-storage-migration.mjs +208 -0
  83. package/dist/lib/reporting/ledger/row-storage-object.d.mts +112 -0
  84. package/dist/lib/reporting/ledger/row-storage-object.d.ts +112 -0
  85. package/dist/lib/reporting/ledger/row-storage-object.js +281 -0
  86. package/dist/lib/reporting/ledger/row-storage-object.mjs +239 -0
  87. package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +51 -0
  88. package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +51 -0
  89. package/dist/lib/reporting/ledger/row-storage-provider-io.js +152 -0
  90. package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +119 -0
  91. package/dist/lib/reporting/ledger/row-storage.d.mts +224 -0
  92. package/dist/lib/reporting/ledger/row-storage.d.ts +224 -0
  93. package/dist/lib/reporting/ledger/row-storage.js +692 -0
  94. package/dist/lib/reporting/ledger/row-storage.mjs +680 -0
  95. package/dist/lib/reporting/ledger/types.d.mts +8 -0
  96. package/dist/lib/reporting/ledger/types.d.ts +8 -0
  97. package/dist/lib/reporting/service/index.d.mts +41 -1
  98. package/dist/lib/reporting/service/index.d.ts +41 -1
  99. package/dist/lib/reporting/service/index.js +68 -1
  100. package/dist/lib/reporting/service/index.mjs +70 -1
  101. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  102. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  103. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  104. package/dist/lib/version.d.mts +3 -3
  105. package/dist/lib/version.d.ts +3 -3
  106. package/dist/lib/version.js +3 -3
  107. package/dist/lib/version.mjs +3 -3
  108. package/docs/README.md +1 -1
  109. package/docs/TYPE-SUMMARY.md +35 -2
  110. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +142 -0
  111. package/docs/guides/EXISTING-PLATFORM.md +43 -12
  112. package/docs/guides/REPORTING-LEDGER.md +209 -0
  113. package/docs/llms.txt +4 -2
  114. package/docs/migration-14.x-rc-worksheet.md +4 -4
  115. package/package.json +1 -1
@@ -31,6 +31,7 @@ var import_errors = require('../errors/index.js');
31
31
  var import_tracing = require('../observability/tracing.js');
32
32
  var import_mcp_scope = require('./mcp-scope.js');
33
33
  var import_session_termination = require('./session-termination.js');
34
+ var import_mcp_call_context = require('./mcp-call-context.js');
34
35
  var import_client2 = require('../signing/client.js');
35
36
  var import_abort = require('./abort.js');
36
37
  var import_rawResponseCapture = require('./rawResponseCapture.js');
@@ -50,10 +51,8 @@ const LEGACY_CLASSIFICATION_TTL_MS = 5 * 60 * 1e3;
50
51
  const MODERN_DISCOVERY_TTL_MS = 5 * 60 * 1e3;
51
52
  const modernOAuthProviderIds = /* @__PURE__ */ new WeakMap();
52
53
  const modernFetchFnIds = /* @__PURE__ */ new WeakMap();
53
- const modernSignalIds = /* @__PURE__ */ new WeakMap();
54
54
  let nextModernOAuthProviderId = 0;
55
55
  let nextModernFetchFnId = 0;
56
- let nextModernSignalId = 0;
57
56
  let connectionGeneration = 0;
58
57
  async function closeModernClient(client, terminateSession = true) {
59
58
  const transport = modernTransports.get(client);
@@ -73,7 +72,7 @@ function buildAuthHeaders(authToken, customHeaders, authProvider) {
73
72
  return key !== "authorization" && key !== "x-adcp-auth";
74
73
  })
75
74
  ) : customHeaders;
76
- return (0, import_auth.createMCPRequestHeaders)(filteredHeaders, authProvider ? void 0 : authToken);
75
+ return (0, import_mcp_call_context.withAmbientIdentityHeaders)((0, import_auth.createMCPRequestHeaders)(filteredHeaders, authProvider ? void 0 : authToken));
77
76
  }
78
77
  function oauthProviderCacheKey(provider) {
79
78
  if (!provider) return void 0;
@@ -93,33 +92,26 @@ function fetchFnCacheKey(fetchFn) {
93
92
  }
94
93
  return key;
95
94
  }
96
- function signalCacheKey(signal) {
97
- if (!signal) return void 0;
98
- let key = modernSignalIds.get(signal);
99
- if (!key) {
100
- key = `signal:${++nextModernSignalId}`;
101
- modernSignalIds.set(signal, key);
102
- }
103
- return key;
104
- }
105
- function connectionCacheKey(agentUrl, headers, signingCacheKey, authProvider, fetchFn, signal, requestTimeoutMs, handleLegacy, allowPrivateIp) {
106
- const normalizedHeaders = Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]).sort(([left], [right]) => left.localeCompare(right));
95
+ function connectionCacheKey(agentUrl, headers, signingCacheKey, authProvider, fetchFn, handleLegacy, allowPrivateIp) {
96
+ const normalizedHeaders = Object.entries((0, import_mcp_call_context.splitConnectionHeaders)(headers).identity).map(([key, value]) => [key.toLowerCase(), value]).sort(([left], [right]) => left.localeCompare(right));
107
97
  const parts = [agentUrl, `headers:${cacheDisambiguator(JSON.stringify(normalizedHeaders))}`];
108
98
  if (signingCacheKey) parts.push(signingCacheKey);
109
99
  const providerKey = oauthProviderCacheKey(authProvider);
110
100
  if (providerKey) parts.push(providerKey);
111
101
  const fetchKey = fetchFnCacheKey(fetchFn);
112
102
  if (fetchKey) parts.push(fetchKey);
113
- const signalKey = signalCacheKey(signal);
114
- if (signalKey) parts.push(signalKey);
115
- if (requestTimeoutMs !== void 0) parts.push(`timeout:${requestTimeoutMs}`);
116
103
  if (handleLegacy !== void 0) parts.push(`handle-legacy:${handleLegacy}`);
117
104
  if (allowPrivateIp !== void 0) parts.push(`allow-private-ip:${allowPrivateIp}`);
118
105
  const scopeKey = (0, import_mcp_scope.currentMCPConnectionScopeKey)();
119
106
  if (scopeKey) parts.push(scopeKey);
120
107
  return parts.join("::");
121
108
  }
122
- function isKnownLegacy(cacheKey) {
109
+ function classificationKey(cacheKey) {
110
+ const marker = cacheKey.lastIndexOf("::scope:");
111
+ return marker >= 0 ? cacheKey.slice(0, marker) : cacheKey;
112
+ }
113
+ function isKnownLegacy(connectionKey) {
114
+ const cacheKey = classificationKey(connectionKey);
123
115
  const classifiedAt = knownLegacyConnections.get(cacheKey);
124
116
  if (classifiedAt === void 0) return false;
125
117
  if (Date.now() - classifiedAt > LEGACY_CLASSIFICATION_TTL_MS) {
@@ -130,7 +122,9 @@ function isKnownLegacy(cacheKey) {
130
122
  knownLegacyConnections.set(cacheKey, classifiedAt);
131
123
  return true;
132
124
  }
133
- function markKnownLegacy(cacheKey) {
125
+ function markKnownLegacy(connectionKey) {
126
+ const cacheKey = classificationKey(connectionKey);
127
+ modernDiscoveries.delete(connectionKey);
134
128
  modernDiscoveries.delete(cacheKey);
135
129
  knownLegacyConnections.delete(cacheKey);
136
130
  knownLegacyConnections.set(cacheKey, Date.now());
@@ -152,6 +146,7 @@ function getCachedModernDiscovery(cacheKey) {
152
146
  return { kind: "modern", discover: cached.discover };
153
147
  }
154
148
  function cacheModernDiscovery(cacheKey, discover) {
149
+ knownLegacyConnections.delete(classificationKey(cacheKey));
155
150
  modernDiscoveries.delete(cacheKey);
156
151
  modernDiscoveries.set(cacheKey, {
157
152
  discover,
@@ -178,8 +173,12 @@ function withPerRequestTraceHeaders(fetchImpl) {
178
173
  return (input, init) => {
179
174
  const headers = new Headers(input instanceof Request ? input.headers : void 0);
180
175
  new Headers(init?.headers).forEach((value, key) => headers.set(key, value));
181
- for (const [key, value] of Object.entries((0, import_tracing.injectTraceHeaders)())) headers.set(key, value);
182
- return fetchImpl(input, { ...init, headers });
176
+ (0, import_mcp_call_context.applyMCPCallHeaders)(headers);
177
+ if (headers.has("traceparent")) return fetchImpl(input, { ...init, headers, ...(0, import_mcp_call_context.linkedCallSignal)(init) });
178
+ for (const [key, value] of Object.entries((0, import_tracing.injectTraceHeaders)())) {
179
+ if ((0, import_mcp_call_context.isCorrelationHeader)(key) && !headers.has(key)) headers.set(key, value);
180
+ }
181
+ return fetchImpl(input, { ...init, headers, ...(0, import_mcp_call_context.linkedCallSignal)(init) });
183
182
  };
184
183
  }
185
184
  function getCachedConnection(cacheKey) {
@@ -189,7 +188,7 @@ function getCachedConnection(cacheKey) {
189
188
  if (legacyExpiry !== void 0 && legacyExpiry <= Date.now()) {
190
189
  modernConnections.delete(cacheKey);
191
190
  legacyConnectionExpiresAt.delete(cacheKey);
192
- void closeModernClient(client).catch(() => {
191
+ void (0, import_mcp_call_context.closeWhenIdle)(client, () => closeModernClient(client)).catch(() => {
193
192
  });
194
193
  return void 0;
195
194
  }
@@ -205,7 +204,7 @@ function evictLeastRecentlyUsed() {
205
204
  const client = modernConnections.get(oldestKey);
206
205
  modernConnections.delete(oldestKey);
207
206
  legacyConnectionExpiresAt.delete(oldestKey);
208
- if (client) void closeModernClient(client).catch(() => {
207
+ if (client) void (0, import_mcp_call_context.closeWhenIdle)(client, () => closeModernClient(client)).catch(() => {
209
208
  });
210
209
  }
211
210
  function isNegotiationAuthFailure(error) {
@@ -220,13 +219,24 @@ function presentedStaticCredential(authHeaders, authProvider) {
220
219
  }
221
220
  async function createNegotiatedClient(cacheKey, options, authHeaders, useCachedDiscovery = true, skipProbe = false) {
222
221
  const generation = connectionGeneration;
223
- const requestTimeoutMs = (0, import_abort.resolveRequestTimeoutMs)(options.requestTimeoutMs);
224
222
  const clientRequestTimeoutMs = (0, import_abort.resolveClientRequestTimeoutMs)(options.requestTimeoutMs);
225
223
  const rawNetworkFetch = (0, import_agent_transport_fetch.createAgentTransportFetch)(options.agentUrl, {
226
224
  trustedFetchFn: options.fetchFn,
227
225
  allowPrivateIp: options.allowPrivateIp
228
226
  });
229
- const networkFetch = (input, init) => (0, import_abort.withAbortSignal)([init?.signal], requestTimeoutMs, (signal) => rawNetworkFetch(input, { ...init, signal }));
227
+ const networkFetch = (input, init) => (
228
+ // `init.signal` already carries the active call's cancellation (linked at the
229
+ // outermost transport wrapper), including on legacy-era sessions where the
230
+ // v2 client cancels with a notification and leaves the HTTP stream open.
231
+ (0, import_abort.withAbortSignal)(
232
+ [init?.signal],
233
+ (0, import_mcp_call_context.requestTimeoutFor)(init),
234
+ (deadline) => rawNetworkFetch(input, {
235
+ ...init,
236
+ signal: init?.signal && deadline ? AbortSignal.any([init.signal, deadline]) : deadline ?? init?.signal
237
+ })
238
+ )
239
+ );
230
240
  const diagnosticFetch = (0, import_transportDiagnostics.wrapFetchWithTransportDiagnostics)((0, import_responseSizeLimit.wrapFetchWithSizeLimit)(networkFetch));
231
241
  const signedFetch = options.signingContext ? (0, import_client2.buildAgentSigningFetch)({
232
242
  upstream: (0, import_signedRequestRejection.wrapFetchWithSignedRequestRejection)(diagnosticFetch, options.agentUrl),
@@ -235,7 +245,7 @@ async function createNegotiatedClient(cacheKey, options, authHeaders, useCachedD
235
245
  adcpVersion: options.signingContext.adcpVersion
236
246
  }) : diagnosticFetch;
237
247
  const transport = new import_client.StreamableHTTPClientTransport(new URL(options.agentUrl), {
238
- requestInit: { headers: authHeaders, redirect: "manual" },
248
+ requestInit: { headers: (0, import_mcp_call_context.splitConnectionHeaders)(authHeaders).identity, redirect: "manual" },
239
249
  fetch: (0, import_rawResponseCapture.wrapFetchWithCapture)(withPerRequestTraceHeaders(signedFetch)),
240
250
  ...options.authProvider && {
241
251
  authProvider: options.authProvider
@@ -283,10 +293,19 @@ async function createNegotiatedClient(cacheKey, options, authHeaders, useCachedD
283
293
  }
284
294
  }
285
295
  async function getOrCreateModernConnection(cacheKey, options, authHeaders) {
286
- const cached = getCachedConnection(cacheKey);
287
- if (cached) return cached;
288
- const pending = pendingModernConnections.get(cacheKey);
289
- if (pending) return pending;
296
+ for (let attempt = 0; ; attempt++) {
297
+ const cached = getCachedConnection(cacheKey);
298
+ if (cached) return cached;
299
+ const pending = pendingModernConnections.get(cacheKey);
300
+ if (pending) {
301
+ const joined = await (0, import_mcp_call_context.joinPendingConnection)(pending, options, attempt);
302
+ if (joined === import_mcp_call_context.RETRY_CONNECT) continue;
303
+ return joined;
304
+ }
305
+ return createSharedModernConnection(cacheKey, options, authHeaders);
306
+ }
307
+ }
308
+ function createSharedModernConnection(cacheKey, options, authHeaders) {
290
309
  const generation = connectionGeneration;
291
310
  const promise = createNegotiatedClient(cacheKey, options, authHeaders).then(async (client) => {
292
311
  if ((client.getProtocolEra() === "modern" || options.handleLegacy === true) && generation === connectionGeneration) {
@@ -317,6 +336,16 @@ async function getOrCreateModernConnection(cacheKey, options, authHeaders) {
317
336
  (0, import_mcp_scope.registerMCPConnectionScopePending)(promise);
318
337
  return promise;
319
338
  }
339
+ async function retireFailedConnection(cacheKey, client, error) {
340
+ if ((0, import_abort.isAbortOrTimeoutError)(error)) return;
341
+ if (modernConnections.get(cacheKey) === client) {
342
+ modernConnections.delete(cacheKey);
343
+ legacyConnectionExpiresAt.delete(cacheKey);
344
+ }
345
+ modernDiscoveries.delete(cacheKey);
346
+ await (0, import_mcp_call_context.closeWhenIdle)(client, () => closeModernClient(client, true)).catch(() => {
347
+ });
348
+ }
320
349
  async function callOnModernClient(client, toolName, args, signal, requestTimeoutMs) {
321
350
  const resolvedRequestTimeoutMs = (0, import_abort.resolveClientRequestTimeoutMs)(requestTimeoutMs);
322
351
  return await client.callTool(
@@ -335,14 +364,11 @@ async function attemptModernCall(options, toolName, args) {
335
364
  options.signingContext?.cacheKey,
336
365
  options.authProvider,
337
366
  options.fetchFn,
338
- options.signal,
339
- options.requestTimeoutMs,
340
367
  options.handleLegacy,
341
368
  options.allowPrivateIp
342
369
  );
343
370
  if (isKnownLegacy(cacheKey)) return { handled: false };
344
- const guardedConnection = options.signal !== void 0 || options.requestTimeoutMs !== void 0 || options.fetchFn !== void 0;
345
- const oneShot = guardedConnection && (0, import_mcp_scope.currentMCPConnectionScopeKey)() === void 0;
371
+ const oneShot = options.fetchFn !== void 0 && (0, import_mcp_scope.currentMCPConnectionScopeKey)() === void 0;
346
372
  let client;
347
373
  let callSucceeded = false;
348
374
  try {
@@ -396,16 +422,21 @@ async function attemptModernCall(options, toolName, args) {
396
422
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
397
423
  });
398
424
  try {
399
- const response = await callOnModernClient(client, toolName, args, options.signal, options.requestTimeoutMs);
425
+ const response = await (0, import_mcp_call_context.trackConnectionUse)(
426
+ client,
427
+ () => (0, import_mcp_call_context.runCallPhase)(
428
+ options.signal,
429
+ () => callOnModernClient(client, toolName, args, options.signal, options.requestTimeoutMs)
430
+ )
431
+ );
400
432
  callSucceeded = true;
401
433
  return { handled: true, response };
402
434
  } catch (error) {
403
- modernConnections.delete(cacheKey);
404
- legacyConnectionExpiresAt.delete(cacheKey);
405
- modernDiscoveries.delete(cacheKey);
406
- try {
407
- await closeModernClient(client, !(0, import_abort.isAbortOrTimeoutError)(error));
408
- } catch {
435
+ if (oneShot) {
436
+ await closeModernClient(client, !(0, import_abort.isAbortOrTimeoutError)(error)).catch(() => {
437
+ });
438
+ } else {
439
+ await retireFailedConnection(cacheKey, client, error);
409
440
  }
410
441
  throw error;
411
442
  } finally {
@@ -413,28 +444,39 @@ async function attemptModernCall(options, toolName, args) {
413
444
  });
414
445
  }
415
446
  }
447
+ function callContextFor(options) {
448
+ const { perRequest } = (0, import_mcp_call_context.splitConnectionHeaders)(options.customHeaders);
449
+ const requestTimeoutMs = (0, import_abort.resolveRequestTimeoutMs)(options.requestTimeoutMs);
450
+ return {
451
+ ...Object.keys(perRequest).length > 0 && { headers: perRequest },
452
+ ...requestTimeoutMs !== void 0 && { requestTimeoutMs }
453
+ };
454
+ }
416
455
  async function tryCallModernMCPTool(agentUrl, toolName, args, authToken, debugLogs = [], customHeaders, options = {}) {
417
456
  return (0, import_tracing.withSpan)(
418
457
  "adcp.mcp.negotiate",
419
458
  { "adcp.tool": toolName, "http.url": agentUrl },
420
459
  () => import_client2.signingContextStorage.run(
421
460
  options.signingContext,
422
- () => attemptModernCall(
423
- {
424
- agentUrl,
425
- authToken,
426
- customHeaders,
427
- debugLogs,
428
- signingContext: options.signingContext,
429
- authProvider: options.authProvider,
430
- signal: options.signal,
431
- requestTimeoutMs: options.requestTimeoutMs,
432
- fetchFn: options.fetchFn,
433
- allowPrivateIp: options.allowPrivateIp,
434
- handleLegacy: options.handleLegacy
435
- },
436
- toolName,
437
- args
461
+ () => (0, import_mcp_call_context.runWithMCPCallContext)(
462
+ callContextFor({ customHeaders, requestTimeoutMs: options.requestTimeoutMs }),
463
+ () => attemptModernCall(
464
+ {
465
+ agentUrl,
466
+ authToken,
467
+ customHeaders,
468
+ debugLogs,
469
+ signingContext: options.signingContext,
470
+ authProvider: options.authProvider,
471
+ signal: options.signal,
472
+ requestTimeoutMs: options.requestTimeoutMs,
473
+ fetchFn: options.fetchFn,
474
+ allowPrivateIp: options.allowPrivateIp,
475
+ handleLegacy: options.handleLegacy
476
+ },
477
+ toolName,
478
+ args
479
+ )
438
480
  )
439
481
  )
440
482
  );
@@ -460,26 +502,34 @@ async function probeModernMCPConnection(agentUrl, authToken, customHeaders, opti
460
502
  options.signingContext?.cacheKey,
461
503
  options.authProvider,
462
504
  options.fetchFn,
463
- options.signal,
464
- options.requestTimeoutMs,
465
505
  options.handleLegacy,
466
506
  options.allowPrivateIp
467
507
  );
508
+ const scoped = (0, import_mcp_scope.currentMCPConnectionScopeKey)() !== void 0;
468
509
  let client;
469
- try {
470
- client = await createNegotiatedClient(cacheKey, connectionOptions, authHeaders, false);
471
- return { connected: true, era: client.getProtocolEra() };
472
- } catch (error) {
473
- modernDiscoveries.delete(cacheKey);
474
- if ((0, import_errors.is401Error)(error) || (0, import_abort.isAbortOrTimeoutError)(error)) throw error;
475
- const status = httpStatusOf(error);
476
- if (status === 404 || status === 405) return { connected: false };
477
- if (isLegacyEraNegotiationFailure(error, status)) return { connected: false };
478
- throw error;
479
- } finally {
480
- if (client) await closeModernClient(client).catch(() => {
481
- });
482
- }
510
+ return (0, import_mcp_call_context.runWithMCPCallContext)(
511
+ callContextFor({ customHeaders, requestTimeoutMs: options.requestTimeoutMs }),
512
+ async () => {
513
+ try {
514
+ client = scoped ? await getOrCreateModernConnection(cacheKey, connectionOptions, authHeaders) : await createNegotiatedClient(cacheKey, connectionOptions, authHeaders, false);
515
+ const era = client.getProtocolEra();
516
+ if (scoped && era === "legacy" && connectionOptions.handleLegacy !== true) markKnownLegacy(cacheKey);
517
+ return { connected: true, era };
518
+ } catch (error) {
519
+ modernDiscoveries.delete(cacheKey);
520
+ if ((0, import_errors.is401Error)(error) || (0, import_abort.isAbortOrTimeoutError)(error)) throw error;
521
+ const status = httpStatusOf(error);
522
+ if (status === 404 || status === 405) return { connected: false };
523
+ if (isLegacyEraNegotiationFailure(error, status)) return { connected: false };
524
+ throw error;
525
+ } finally {
526
+ if (client && !(scoped && modernConnections.get(cacheKey) === client)) {
527
+ await closeModernClient(client).catch(() => {
528
+ });
529
+ }
530
+ }
531
+ }
532
+ );
483
533
  }
484
534
  async function tryListModernMCPTools(agentUrl, authToken, customHeaders, options = {}) {
485
535
  const connectionOptions = {
@@ -492,7 +542,8 @@ async function tryListModernMCPTools(agentUrl, authToken, customHeaders, options
492
542
  signal: options.signal,
493
543
  requestTimeoutMs: options.requestTimeoutMs,
494
544
  fetchFn: options.fetchFn,
495
- allowPrivateIp: options.allowPrivateIp
545
+ allowPrivateIp: options.allowPrivateIp,
546
+ handleLegacy: options.handleLegacy
496
547
  };
497
548
  const authHeaders = buildAuthHeaders(authToken, customHeaders, options.authProvider);
498
549
  const cacheKey = connectionCacheKey(
@@ -501,50 +552,75 @@ async function tryListModernMCPTools(agentUrl, authToken, customHeaders, options
501
552
  options.signingContext?.cacheKey,
502
553
  options.authProvider,
503
554
  options.fetchFn,
504
- options.signal,
505
- options.requestTimeoutMs,
506
555
  options.handleLegacy,
507
556
  options.allowPrivateIp
508
557
  );
558
+ const scoped = (0, import_mcp_scope.currentMCPConnectionScopeKey)() !== void 0;
559
+ if (scoped && isKnownLegacy(cacheKey)) return { handled: false };
509
560
  let client;
561
+ const sharedClients = /* @__PURE__ */ new WeakSet();
562
+ const acquire = async (create) => {
563
+ const acquired = await create();
564
+ if (scoped && modernConnections.get(cacheKey) === acquired) sharedClients.add(acquired);
565
+ return acquired;
566
+ };
510
567
  const listTools = async (connectedClient) => {
511
- if (connectedClient.getProtocolEra() !== "modern") return { handled: false };
568
+ if (connectedClient.getProtocolEra() !== "modern" && connectionOptions.handleLegacy !== true) {
569
+ if (scoped) markKnownLegacy(cacheKey);
570
+ return { handled: false };
571
+ }
512
572
  const resolvedRequestTimeoutMs = (0, import_abort.resolveClientRequestTimeoutMs)(options.requestTimeoutMs);
513
- const result = await connectedClient.listTools(
514
- options.adcpVersion === void 0 ? void 0 : { _meta: { adcp_version: options.adcpVersion } },
515
- {
516
- ...options.signal && { signal: options.signal },
517
- ...resolvedRequestTimeoutMs !== void 0 && { timeout: resolvedRequestTimeoutMs }
518
- }
573
+ const result = await (0, import_mcp_call_context.trackConnectionUse)(
574
+ connectedClient,
575
+ () => (0, import_mcp_call_context.runCallPhase)(
576
+ options.signal,
577
+ () => connectedClient.listTools(
578
+ options.adcpVersion === void 0 ? void 0 : { _meta: { adcp_version: options.adcpVersion } },
579
+ {
580
+ ...options.signal && { signal: options.signal },
581
+ ...resolvedRequestTimeoutMs !== void 0 && { timeout: resolvedRequestTimeoutMs }
582
+ }
583
+ )
584
+ )
519
585
  );
520
586
  return { handled: true, tools: result.tools };
521
587
  };
522
- try {
523
- client = await createNegotiatedClient(cacheKey, connectionOptions, authHeaders);
524
- return await listTools(client);
525
- } catch (error) {
526
- let failure = error;
527
- modernDiscoveries.delete(cacheKey);
528
- if (!(0, import_errors.is401Error)(failure) && !(0, import_abort.isAbortOrTimeoutError)(failure) && client && clientsUsingCachedDiscovery.has(client)) {
529
- await closeModernClient(client, false).catch(() => {
530
- });
588
+ return (0, import_mcp_call_context.runWithMCPCallContext)(
589
+ callContextFor({ customHeaders, requestTimeoutMs: options.requestTimeoutMs }),
590
+ async () => {
531
591
  try {
532
- client = await createNegotiatedClient(cacheKey, connectionOptions, authHeaders, false);
592
+ client = await acquire(
593
+ () => scoped ? getOrCreateModernConnection(cacheKey, connectionOptions, authHeaders) : createNegotiatedClient(cacheKey, connectionOptions, authHeaders)
594
+ );
533
595
  return await listTools(client);
534
- } catch (retryError) {
535
- failure = retryError;
596
+ } catch (error) {
597
+ let failure = error;
536
598
  modernDiscoveries.delete(cacheKey);
599
+ if (client && sharedClients.has(client)) {
600
+ await retireFailedConnection(cacheKey, client, failure);
601
+ }
602
+ if (!(0, import_errors.is401Error)(failure) && !(0, import_abort.isAbortOrTimeoutError)(failure) && client && clientsUsingCachedDiscovery.has(client)) {
603
+ if (!sharedClients.has(client)) await closeModernClient(client, false).catch(() => {
604
+ });
605
+ try {
606
+ client = await acquire(() => createNegotiatedClient(cacheKey, connectionOptions, authHeaders, false));
607
+ return await listTools(client);
608
+ } catch (retryError) {
609
+ failure = retryError;
610
+ modernDiscoveries.delete(cacheKey);
611
+ }
612
+ }
613
+ if ((0, import_errors.is401Error)(failure) || (0, import_abort.isAbortOrTimeoutError)(failure)) throw failure;
614
+ const status = httpStatusOf(failure);
615
+ if (status === 404 || status === 405) return { handled: false };
616
+ if (isLegacyEraNegotiationFailure(failure, status)) return { handled: false };
617
+ throw failure;
618
+ } finally {
619
+ if (client && !sharedClients.has(client)) await closeModernClient(client).catch(() => {
620
+ });
537
621
  }
538
622
  }
539
- if ((0, import_errors.is401Error)(failure) || (0, import_abort.isAbortOrTimeoutError)(failure)) throw failure;
540
- const status = httpStatusOf(failure);
541
- if (status === 404 || status === 405) return { handled: false };
542
- if (isLegacyEraNegotiationFailure(failure, status)) return { handled: false };
543
- throw failure;
544
- } finally {
545
- if (client) await closeModernClient(client).catch(() => {
546
- });
547
- }
623
+ );
548
624
  }
549
625
  async function closeModernMCPConnections() {
550
626
  connectionGeneration++;