agents 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +24 -19
  2. package/dist/{agent-tool-types-BNUGGBzQ.d.ts → agent-tool-types-Btk9ETS-.d.ts} +997 -356
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-BFbzVLFc.d.ts → agent-tools-UuScsJg3.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/browser/ai.js +1 -1
  7. package/dist/browser/index.js +1 -1
  8. package/dist/chat/index.d.ts +2 -2
  9. package/dist/chat-sdk/index.d.ts +1 -1
  10. package/dist/client-invoker-BNSZxAkv.d.ts +20 -0
  11. package/dist/client-invoker-VNZ7X0nn.js +57 -0
  12. package/dist/client-invoker-VNZ7X0nn.js.map +1 -0
  13. package/dist/{client-CcjiFpTf.js → client-zqKcsyFa.js} +434 -168
  14. package/dist/client-zqKcsyFa.js.map +1 -0
  15. package/dist/client.d.ts +1 -1
  16. package/dist/{connector-CdldGF3h.js → connector-KEJnl6e5.js} +2 -2
  17. package/dist/connector-KEJnl6e5.js.map +1 -0
  18. package/dist/{do-oauth-client-provider-D4ZwyBDu.d.ts → do-oauth-client-provider-VTZj2VtM.d.ts} +23 -11
  19. package/dist/experimental/webmcp.js +1 -1
  20. package/dist/handler-stateless-8hQN_kC3.js +367 -0
  21. package/dist/handler-stateless-8hQN_kC3.js.map +1 -0
  22. package/dist/handler-stateless-C_bo-Ytq.d.ts +107 -0
  23. package/dist/index.d.ts +12 -12
  24. package/dist/index.js +3 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp/client.d.ts +22 -18
  27. package/dist/mcp/client.js +1 -1
  28. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  29. package/dist/mcp/do-oauth-client-provider.js +25 -12
  30. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  31. package/dist/mcp/index.d.ts +48 -34
  32. package/dist/mcp/index.js +84 -79
  33. package/dist/mcp/index.js.map +1 -1
  34. package/dist/mcp/server.d.ts +17 -0
  35. package/dist/mcp/server.js +2 -0
  36. package/dist/mcp/x402.d.ts +21 -9
  37. package/dist/mcp/x402.js +8 -7
  38. package/dist/mcp/x402.js.map +1 -1
  39. package/dist/react.d.ts +1 -1
  40. package/dist/serializable.d.ts +1 -1
  41. package/dist/sub-routing.d.ts +6 -6
  42. package/dist/workflows.d.ts +1 -1
  43. package/docs/human-in-the-loop.md +63 -82
  44. package/docs/mcp-client.md +31 -7
  45. package/docs/mcp-servers.md +125 -88
  46. package/docs/securing-mcp-servers.md +9 -6
  47. package/package.json +28 -7
  48. package/dist/client-CcjiFpTf.js.map +0 -1
  49. package/dist/connector-CdldGF3h.js.map +0 -1
@@ -1,13 +1,12 @@
1
1
  import { tryN } from "./retries.js";
2
+ import { n as callV2Tool } from "./client-invoker-VNZ7X0nn.js";
2
3
  import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider.js";
3
4
  import { nanoid } from "nanoid";
4
5
  import { getServerByName } from "partyserver";
5
6
  import { z } from "zod";
6
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
- import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker-provider.js";
8
- import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
9
- import { StreamableHTTPClientTransport, StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
10
- import { ElicitRequestSchema, JSONRPCMessageSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, isJSONRPCErrorResponse, isJSONRPCResultResponse } from "@modelcontextprotocol/sdk/types.js";
7
+ import { Client, SSEClientTransport, SdkHttpError, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
8
+ import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/client/validators/cf-worker";
9
+ import { JSONRPCMessageSchema, isJSONRPCErrorResponse, isJSONRPCResultResponse } from "@modelcontextprotocol/sdk/types.js";
11
10
  //#region src/core/events.ts
12
11
  function toDisposable(fn) {
13
12
  return { dispose: fn };
@@ -46,23 +45,187 @@ var Emitter = class {
46
45
  }
47
46
  };
48
47
  //#endregion
48
+ //#region src/mcp/abort.ts
49
+ function abortError(signal) {
50
+ return signal.reason instanceof Error ? signal.reason : new Error(String(signal.reason ?? "Aborted"));
51
+ }
52
+ /**
53
+ * Stop awaiting an operation when its owner aborts. The underlying operation
54
+ * remains responsible for observing the same signal and cancelling its work.
55
+ */
56
+ async function raceWithSignal(promise, signal) {
57
+ if (!signal) return promise;
58
+ if (signal.aborted) throw abortError(signal);
59
+ return new Promise((resolve, reject) => {
60
+ const onAbort = () => reject(abortError(signal));
61
+ signal.addEventListener("abort", onAbort, { once: true });
62
+ promise.then(resolve, reject).finally(() => {
63
+ signal.removeEventListener("abort", onAbort);
64
+ });
65
+ });
66
+ }
67
+ //#endregion
68
+ //#region src/mcp/client-catalog.ts
69
+ async function fetchMcpTools(client, options) {
70
+ let aggregate = [];
71
+ let page = { tools: [] };
72
+ do {
73
+ const params = { cursor: page.nextCursor };
74
+ page = await (options.probing ? client.request({
75
+ method: "tools/list",
76
+ params
77
+ }) : client.listTools(params)).catch(options.onCapabilityError({ tools: [] }, "tools/list"));
78
+ aggregate = aggregate.concat(page.tools);
79
+ } while (page.nextCursor);
80
+ return aggregate;
81
+ }
82
+ async function fetchMcpResources(client, options) {
83
+ let aggregate = [];
84
+ let page = { resources: [] };
85
+ do {
86
+ const params = { cursor: page.nextCursor };
87
+ page = await (options.probing ? client.request({
88
+ method: "resources/list",
89
+ params
90
+ }) : client.listResources(params)).catch(options.onCapabilityError({ resources: [] }, "resources/list"));
91
+ aggregate = aggregate.concat(page.resources);
92
+ } while (page.nextCursor);
93
+ return aggregate;
94
+ }
95
+ async function fetchMcpPrompts(client, options) {
96
+ let aggregate = [];
97
+ let page = { prompts: [] };
98
+ do {
99
+ const params = { cursor: page.nextCursor };
100
+ page = await (options.probing ? client.request({
101
+ method: "prompts/list",
102
+ params
103
+ }) : client.listPrompts(params)).catch(options.onCapabilityError({ prompts: [] }, "prompts/list"));
104
+ aggregate = aggregate.concat(page.prompts);
105
+ } while (page.nextCursor);
106
+ return aggregate;
107
+ }
108
+ async function fetchMcpResourceTemplates(client, options) {
109
+ let aggregate = [];
110
+ let page = { resourceTemplates: [] };
111
+ do {
112
+ const params = { cursor: page.nextCursor };
113
+ page = await (options.probing ? client.request({
114
+ method: "resources/templates/list",
115
+ params
116
+ }) : client.listResourceTemplates(params)).catch(options.onCapabilityError({ resourceTemplates: [] }, "resources/templates/list"));
117
+ aggregate = aggregate.concat(page.resourceTemplates);
118
+ } while (page.nextCursor);
119
+ return aggregate;
120
+ }
121
+ //#endregion
122
+ //#region src/mcp/client-runtime.ts
123
+ var CompatibleWorkerJsonSchemaValidator = class extends CfWorkerJsonSchemaValidator {
124
+ constructor(..._args) {
125
+ super(..._args);
126
+ this.legacy = new CfWorkerJsonSchemaValidator({ draft: "7" });
127
+ }
128
+ getValidator(schema) {
129
+ const dialect = schema.$schema;
130
+ return typeof dialect === "string" && /draft-0?7/i.test(dialect) ? this.legacy.getValidator(schema) : super.getValidator(schema);
131
+ }
132
+ };
133
+ const DEFAULT_CLIENT_OPTIONS = {
134
+ jsonSchemaValidator: new CompatibleWorkerJsonSchemaValidator(),
135
+ versionNegotiation: { mode: "auto" },
136
+ inputRequired: { autoFulfill: true }
137
+ };
138
+ function normalizeMcpClientOptions(options) {
139
+ return {
140
+ ...DEFAULT_CLIENT_OPTIONS,
141
+ ...options,
142
+ versionNegotiation: {
143
+ ...DEFAULT_CLIENT_OPTIONS.versionNegotiation,
144
+ ...options?.versionNegotiation
145
+ },
146
+ inputRequired: {
147
+ ...DEFAULT_CLIENT_OPTIONS.inputRequired,
148
+ ...options?.inputRequired
149
+ }
150
+ };
151
+ }
152
+ function elicitationCapabilitiesFromHandlers(handlers) {
153
+ if (!handlers) return void 0;
154
+ const elicitation = {};
155
+ if (handlers.form) elicitation.form = {};
156
+ if (handlers.url) elicitation.url = {};
157
+ return elicitation.form || elicitation.url ? elicitation : void 0;
158
+ }
159
+ function listChangedHandlers(configured, callbacks) {
160
+ return {
161
+ tools: {
162
+ ...configured?.tools,
163
+ onChanged: (error, tools) => {
164
+ callbacks.tools(error, tools);
165
+ configured?.tools?.onChanged(error, tools);
166
+ }
167
+ },
168
+ prompts: {
169
+ ...configured?.prompts,
170
+ onChanged: (error, prompts) => {
171
+ callbacks.prompts(error, prompts);
172
+ configured?.prompts?.onChanged(error, prompts);
173
+ }
174
+ },
175
+ resources: {
176
+ ...configured?.resources,
177
+ onChanged: (error, resources) => {
178
+ callbacks.resources(error, resources);
179
+ configured?.resources?.onChanged(error, resources);
180
+ }
181
+ }
182
+ };
183
+ }
184
+ function createMcpSdkClient(info, options, capabilitySeed, handlerModes, callbacks) {
185
+ const elicitation = options.capabilities?.elicitation ?? elicitationCapabilitiesFromHandlers(handlerModes) ?? capabilitySeed?.elicitation;
186
+ return {
187
+ client: new Client(info, {
188
+ ...options,
189
+ capabilities: {
190
+ ...capabilitySeed,
191
+ ...options.capabilities,
192
+ ...elicitation ? { elicitation } : {}
193
+ },
194
+ listChanged: listChangedHandlers(options.listChanged, callbacks)
195
+ }),
196
+ elicitationEnabled: elicitation !== void 0
197
+ };
198
+ }
199
+ //#endregion
49
200
  //#region src/mcp/errors.ts
50
201
  function toErrorMessage(error) {
51
202
  return error instanceof Error ? error.message : String(error);
52
203
  }
53
- function getErrorCode(error) {
54
- if (error && typeof error === "object" && "code" in error && typeof error.code === "number") return error.code;
204
+ function getErrorStatus(error) {
205
+ if (!error || typeof error !== "object") return void 0;
206
+ const record = error;
207
+ if (typeof record.code === "number") return record.code;
208
+ if (typeof record.status === "number") return record.status;
209
+ if (typeof record.data?.status === "number") return record.data.status;
210
+ }
211
+ function getErrorCause(error) {
212
+ if (!error || typeof error !== "object") return void 0;
213
+ return error.cause ?? error.data?.cause;
55
214
  }
56
215
  function isUnauthorized(error) {
57
- if (getErrorCode(error) === 401) return true;
216
+ if (getErrorStatus(error) === 401) return true;
217
+ const cause = getErrorCause(error);
218
+ if (cause && cause !== error && isUnauthorized(cause)) return true;
58
219
  const msg = toErrorMessage(error);
59
220
  return msg.includes("Unauthorized") || msg.includes("401");
60
221
  }
61
222
  function isTransportNotImplemented(error) {
62
- const code = getErrorCode(error);
63
- if (code === 404 || code === 405) return true;
223
+ const status = getErrorStatus(error);
224
+ if (status === 404 || status === 405) return true;
225
+ const cause = getErrorCause(error);
226
+ if (cause && cause !== error && isTransportNotImplemented(cause)) return true;
64
227
  const msg = toErrorMessage(error);
65
- return msg.includes("404") || msg.includes("405") || msg.includes("Not Implemented") || msg.includes("not implemented");
228
+ return msg.includes("404") || msg.includes("405") || msg.includes("Error POSTing to endpoint: Not Found") || msg.includes("Not Implemented") || msg.includes("not implemented");
66
229
  }
67
230
  //#endregion
68
231
  //#region src/mcp/rpc.ts
@@ -107,9 +270,9 @@ var RPCClientTransport = class {
107
270
  async send(message, options) {
108
271
  if (!this._started || !this._stub) throw new Error("Transport not started");
109
272
  try {
110
- const result = await this._stub.handleMcpMessage(message);
111
- if (!result) return;
112
- const extra = options?.relatedRequestId ? { requestInfo: { headers: {} } } : void 0;
273
+ const result = await raceWithSignal(this._stub.handleMcpMessage(message), options?.requestSignal);
274
+ if (!result || options?.requestSignal?.aborted) return;
275
+ const extra = void 0;
113
276
  const messages = Array.isArray(result) ? result : [result];
114
277
  for (const msg of messages) this.onmessage?.(msg, extra);
115
278
  } catch (error) {
@@ -282,7 +445,6 @@ var RPCServerTransport = class {
282
445
  };
283
446
  //#endregion
284
447
  //#region src/mcp/client-connection.ts
285
- const defaultClientOptions = { jsonSchemaValidator: new CfWorkerJsonSchemaValidator() };
286
448
  /**
287
449
  * Connection state machine for MCP client connections.
288
450
  *
@@ -305,14 +467,6 @@ const MCPConnectionState = {
305
467
  /** Connection failed at some point */
306
468
  FAILED: "failed"
307
469
  };
308
- /** Derive the elicitation capability to advertise from the handler keys. */
309
- function elicitationCapabilitiesFromHandlers(handlers) {
310
- if (!handlers) return void 0;
311
- const elicitation = {};
312
- if (handlers.form) elicitation.form = {};
313
- if (handlers.url) elicitation.url = {};
314
- return elicitation.form || elicitation.url ? elicitation : void 0;
315
- }
316
470
  var MCPClientConnection = class {
317
471
  constructor(url, _info, options = {
318
472
  client: {},
@@ -330,29 +484,32 @@ var MCPClientConnection = class {
330
484
  this._probingCapabilities = false;
331
485
  this._onObservabilityEvent = new Emitter();
332
486
  this.onObservabilityEvent = this._onObservabilityEvent.event;
487
+ this._onListChanged = new Emitter();
488
+ this.onListChanged = this._onListChanged.event;
333
489
  this._elicitationEnabled = false;
334
490
  this.options = {
335
491
  ...options,
336
- client: {
337
- ...defaultClientOptions,
338
- ...options.client
339
- }
492
+ client: normalizeMcpClientOptions(options.client)
340
493
  };
341
494
  this.client = this.createClient();
342
495
  }
343
496
  createClient() {
344
- const seed = this.options.capabilitySeed;
345
- const elicitation = this.options.client?.capabilities?.elicitation ?? elicitationCapabilitiesFromHandlers(this.options.elicitationHandlers) ?? seed?.elicitation;
346
- this._elicitationEnabled = elicitation !== void 0;
347
- const clientOptions = {
348
- ...this.options.client,
349
- capabilities: {
350
- ...seed,
351
- ...this.options.client?.capabilities,
352
- ...elicitation ? { elicitation } : {}
497
+ const created = createMcpSdkClient(this._info, this.options.client, this.options.capabilitySeed, this.options.elicitationHandlers, {
498
+ tools: (error, tools) => {
499
+ if (!error && tools) this.tools = tools;
500
+ this._onListChanged.fire();
501
+ },
502
+ prompts: (error, prompts) => {
503
+ if (!error && prompts) this.prompts = prompts;
504
+ this._onListChanged.fire();
505
+ },
506
+ resources: (error, resources) => {
507
+ if (!error && resources) this.resources = resources;
508
+ this._onListChanged.fire();
353
509
  }
354
- };
355
- return new Client(this._info, clientOptions);
510
+ });
511
+ this._elicitationEnabled = created.elicitationEnabled;
512
+ return created.client;
356
513
  }
357
514
  /**
358
515
  * Configure the handler used for server-initiated elicitation requests.
@@ -367,7 +524,7 @@ var MCPClientConnection = class {
367
524
  configureElicitationHandlers(handlers) {
368
525
  this.options.elicitationHandlers = handlers;
369
526
  this.options.capabilitySeed = void 0;
370
- if (!this.client.transport) this.client = this.createClient();
527
+ if (!this._transport) this.client = this.createClient();
371
528
  }
372
529
  /**
373
530
  * Initialize a client connection, if authentication is required, the connection will be in the AUTHENTICATING state
@@ -378,7 +535,7 @@ var MCPClientConnection = class {
378
535
  async init() {
379
536
  const transportType = this.options.transport.type;
380
537
  if (!transportType) throw new Error("Transport type must be specified");
381
- if (this.client.transport) {
538
+ if (this._transport) {
382
539
  this._transport = void 0;
383
540
  try {
384
541
  await this.client.close();
@@ -388,9 +545,7 @@ var MCPClientConnection = class {
388
545
  const res = await this.tryConnect(transportType);
389
546
  this.connectionState = res.state;
390
547
  if (res.state === MCPConnectionState.CONNECTED && res.transport) {
391
- if (this._elicitationEnabled) this.client.setRequestHandler(ElicitRequestSchema, async (request) => {
392
- return await this.handleElicitationRequest(request);
393
- });
548
+ if (this._elicitationEnabled) this.client.setRequestHandler("elicitation/create", async (request, context) => await this.handleElicitationRequest(request, context.mcpReq.signal));
394
549
  this.lastConnectedTransport = res.transport;
395
550
  this._onObservabilityEvent.fire({
396
551
  type: "mcp:client:connect",
@@ -422,19 +577,36 @@ var MCPClientConnection = class {
422
577
  * - Explicit: finish on that transport
423
578
  * - Auto: try streamable-http, then sse on 404/405/Not Implemented
424
579
  */
425
- async finishAuthProbe(code) {
580
+ async finishAuthProbe(callbackParams) {
426
581
  if (!this.options.transport.authProvider) throw new Error("No auth provider configured");
427
582
  const configuredType = this.options.transport.type;
428
583
  if (!configuredType) throw new Error("Transport type must be specified");
429
584
  const finishAuth = async (base) => {
430
585
  const transport = this.getTransport(base);
431
- if ("finishAuth" in transport && typeof transport.finishAuth === "function") await transport.finishAuth(code);
586
+ let completed = false;
587
+ try {
588
+ if ("finishAuth" in transport && typeof transport.finishAuth === "function") {
589
+ await transport.finishAuth(callbackParams);
590
+ completed = true;
591
+ }
592
+ } finally {
593
+ if (typeof transport.close === "function") await transport.close().catch(() => {});
594
+ }
595
+ if (completed) this.client = this.createClient();
432
596
  };
433
597
  if (configuredType === "rpc") throw new Error("RPC transport does not support authentication");
434
598
  const authTransport = this._pendingAuthTransport ?? this._transport;
435
599
  this._pendingAuthTransport = void 0;
436
600
  if (authTransport && "finishAuth" in authTransport && typeof authTransport.finishAuth === "function") {
437
- await authTransport.finishAuth(code);
601
+ let completed = false;
602
+ try {
603
+ await authTransport.finishAuth(callbackParams);
604
+ completed = true;
605
+ } finally {
606
+ if (typeof authTransport.close === "function") await authTransport.close().catch(() => {});
607
+ if (this._transport === authTransport) this._transport = void 0;
608
+ }
609
+ if (completed) this.client = this.createClient();
438
610
  return;
439
611
  }
440
612
  if (configuredType === "sse" || configuredType === "streamable-http") {
@@ -454,12 +626,13 @@ var MCPClientConnection = class {
454
626
  /**
455
627
  * Complete OAuth authorization
456
628
  */
457
- async completeAuthorization(code, options = {}) {
629
+ async completeAuthorization(callback, options = {}) {
458
630
  const expectedState = options.alreadyAccepted ? MCPConnectionState.CONNECTING : MCPConnectionState.AUTHENTICATING;
459
631
  if (this.connectionState !== expectedState) throw new Error(`Connection must be in ${expectedState} state to complete authorization`);
460
632
  if (!options.alreadyAccepted) this.connectionState = MCPConnectionState.CONNECTING;
461
633
  try {
462
- await this.finishAuthProbe(code);
634
+ const callbackParams = typeof callback === "string" ? new URLSearchParams({ code: callback }) : callback;
635
+ await this.finishAuthProbe(callbackParams);
463
636
  } catch (error) {
464
637
  this.connectionState = MCPConnectionState.FAILED;
465
638
  throw error;
@@ -587,11 +760,11 @@ var MCPClientConnection = class {
587
760
  return { success: true };
588
761
  } catch (e) {
589
762
  if (timeoutId !== void 0) clearTimeout(timeoutId);
590
- this.connectionState = MCPConnectionState.CONNECTED;
763
+ this.connectionState = isUnauthorized(e) ? MCPConnectionState.AUTHENTICATING : MCPConnectionState.CONNECTED;
591
764
  const error = e instanceof Error ? e.message : String(e);
592
765
  return {
593
766
  success: false,
594
- reason: this._probingCapabilities && e instanceof StreamableHTTPError && e.code === 404 ? "stale-session" : "error",
767
+ reason: this._probingCapabilities && e instanceof SdkHttpError && e.status === 404 ? "stale-session" : "error",
595
768
  error
596
769
  };
597
770
  } finally {
@@ -613,8 +786,9 @@ var MCPClientConnection = class {
613
786
  * Should only be called if serverCapabilities.tools exists
614
787
  */
615
788
  async registerTools() {
616
- if (this.serverCapabilities?.tools?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(ToolListChangedNotificationSchema, async (_notification) => {
789
+ if (this._probingCapabilities) this.client.setNotificationHandler("notifications/tools/list_changed", async () => {
617
790
  this.tools = await this.fetchTools();
791
+ this._onListChanged.fire();
618
792
  });
619
793
  return this.fetchTools();
620
794
  }
@@ -623,8 +797,9 @@ var MCPClientConnection = class {
623
797
  * Should only be called if serverCapabilities.resources exists
624
798
  */
625
799
  async registerResources() {
626
- if (this.serverCapabilities?.resources?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async (_notification) => {
800
+ if (this._probingCapabilities) this.client.setNotificationHandler("notifications/resources/list_changed", async () => {
627
801
  this.resources = await this.fetchResources();
802
+ this._onListChanged.fire();
628
803
  });
629
804
  return this.fetchResources();
630
805
  }
@@ -633,49 +808,32 @@ var MCPClientConnection = class {
633
808
  * Should only be called if serverCapabilities.prompts exists
634
809
  */
635
810
  async registerPrompts() {
636
- if (this.serverCapabilities?.prompts?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(PromptListChangedNotificationSchema, async (_notification) => {
811
+ if (this._probingCapabilities) this.client.setNotificationHandler("notifications/prompts/list_changed", async () => {
637
812
  this.prompts = await this.fetchPrompts();
813
+ this._onListChanged.fire();
638
814
  });
639
815
  return this.fetchPrompts();
640
816
  }
641
817
  async registerResourceTemplates() {
642
818
  return this.fetchResourceTemplates();
643
819
  }
820
+ catalogFetchOptions() {
821
+ return {
822
+ probing: this._probingCapabilities,
823
+ onCapabilityError: this._capabilityErrorHandler.bind(this)
824
+ };
825
+ }
644
826
  async fetchTools() {
645
- let toolsAgg = [];
646
- let toolsResult = { tools: [] };
647
- do {
648
- toolsResult = await this.client.listTools({ cursor: toolsResult.nextCursor }).catch(this._capabilityErrorHandler({ tools: [] }, "tools/list"));
649
- toolsAgg = toolsAgg.concat(toolsResult.tools);
650
- } while (toolsResult.nextCursor);
651
- return toolsAgg;
827
+ return fetchMcpTools(this.client, this.catalogFetchOptions());
652
828
  }
653
829
  async fetchResources() {
654
- let resourcesAgg = [];
655
- let resourcesResult = { resources: [] };
656
- do {
657
- resourcesResult = await this.client.listResources({ cursor: resourcesResult.nextCursor }).catch(this._capabilityErrorHandler({ resources: [] }, "resources/list"));
658
- resourcesAgg = resourcesAgg.concat(resourcesResult.resources);
659
- } while (resourcesResult.nextCursor);
660
- return resourcesAgg;
830
+ return fetchMcpResources(this.client, this.catalogFetchOptions());
661
831
  }
662
832
  async fetchPrompts() {
663
- let promptsAgg = [];
664
- let promptsResult = { prompts: [] };
665
- do {
666
- promptsResult = await this.client.listPrompts({ cursor: promptsResult.nextCursor }).catch(this._capabilityErrorHandler({ prompts: [] }, "prompts/list"));
667
- promptsAgg = promptsAgg.concat(promptsResult.prompts);
668
- } while (promptsResult.nextCursor);
669
- return promptsAgg;
833
+ return fetchMcpPrompts(this.client, this.catalogFetchOptions());
670
834
  }
671
835
  async fetchResourceTemplates() {
672
- let templatesAgg = [];
673
- let templatesResult = { resourceTemplates: [] };
674
- do {
675
- templatesResult = await this.client.listResourceTemplates({ cursor: templatesResult.nextCursor }).catch(this._capabilityErrorHandler({ resourceTemplates: [] }, "resources/templates/list"));
676
- templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);
677
- } while (templatesResult.nextCursor);
678
- return templatesAgg;
836
+ return fetchMcpResourceTemplates(this.client, this.catalogFetchOptions());
679
837
  }
680
838
  /**
681
839
  * Handle elicitation request from server.
@@ -685,10 +843,10 @@ var MCPClientConnection = class {
685
843
  * @deprecated Overriding or instance-patching this method directly is
686
844
  * deprecated — pass the `elicitationHandlers` connection option instead.
687
845
  */
688
- async handleElicitationRequest(request) {
846
+ async handleElicitationRequest(request, signal) {
689
847
  const mode = request.params.mode === "url" ? "url" : "form";
690
848
  const handler = this.options.elicitationHandlers?.[mode];
691
- if (handler) return handler(request);
849
+ if (handler) return raceWithSignal(signal ? handler(request, signal) : handler(request), signal);
692
850
  if (this.options.elicitationHandlers) throw new Error(`No MCP ${mode}-mode elicitation handler configured for this connection.`);
693
851
  throw new Error("Elicitation handler must be implemented for your platform. Provide the MCPClientConnection elicitationHandlers option, or register handlers through the MCP client manager before connecting.");
694
852
  }
@@ -702,6 +860,26 @@ var MCPClientConnection = class {
702
860
  clearResumedSession() {
703
861
  if ("sessionId" in this.options.transport) delete this.options.transport.sessionId;
704
862
  }
863
+ get protocolVersion() {
864
+ if (this._transport instanceof StreamableHTTPClientTransport) return this._transport.protocolVersion;
865
+ }
866
+ get discoverResult() {
867
+ return this.client.getDiscoverResult();
868
+ }
869
+ async openRestoredListSubscription() {
870
+ const capabilities = this.client.getServerCapabilities();
871
+ const filter = {
872
+ ...capabilities?.tools?.listChanged && { toolsListChanged: true },
873
+ ...capabilities?.prompts?.listChanged && { promptsListChanged: true },
874
+ ...capabilities?.resources?.listChanged && { resourcesListChanged: true }
875
+ };
876
+ if (Object.keys(filter).length === 0) return;
877
+ try {
878
+ this._restoredListSubscription = await this.client.listen(filter);
879
+ } catch (error) {
880
+ this.client.onerror?.(error instanceof Error ? error : new Error(String(error)));
881
+ }
882
+ }
705
883
  getTransportName(transport) {
706
884
  if (transport instanceof StreamableHTTPClientTransport) return "streamable-http";
707
885
  if (transport instanceof SSEClientTransport) return "sse";
@@ -711,6 +889,8 @@ var MCPClientConnection = class {
711
889
  async close() {
712
890
  const transport = this._transport;
713
891
  this._transport = void 0;
892
+ await this._restoredListSubscription?.close().catch(() => {});
893
+ this._restoredListSubscription = void 0;
714
894
  const url = this.url.toString();
715
895
  const transportName = this.getTransportName(transport);
716
896
  if (transport instanceof StreamableHTTPClientTransport && transport.sessionId) try {
@@ -774,9 +954,14 @@ var MCPClientConnection = class {
774
954
  const hasFallback = transportType === "auto" && currentTransportType === "streamable-http" && !isLastTransport;
775
955
  const transport = this.getTransport(currentTransportType);
776
956
  try {
777
- await this.client.connect(transport);
957
+ const prior = transport instanceof StreamableHTTPClientTransport && transport.sessionId && this.options.discoverResult ? {
958
+ kind: "modern",
959
+ discover: this.options.discoverResult
960
+ } : void 0;
961
+ await this.client.connect(transport, prior ? { prior } : void 0);
778
962
  this._transport = transport;
779
963
  this._pendingAuthTransport = void 0;
964
+ if (prior) await this.openRestoredListSubscription();
780
965
  return {
781
966
  state: MCPConnectionState.CONNECTED,
782
967
  transport: currentTransportType
@@ -819,6 +1004,87 @@ var MCPClientConnection = class {
819
1004
  }
820
1005
  };
821
1006
  //#endregion
1007
+ //#region src/mcp/client-storage.ts
1008
+ function persistClientOptions(client) {
1009
+ if (!client) return void 0;
1010
+ return {
1011
+ capabilities: client.capabilities,
1012
+ supportedProtocolVersions: client.supportedProtocolVersions,
1013
+ enforceStrictCapabilities: client.enforceStrictCapabilities,
1014
+ debouncedNotificationMethods: client.debouncedNotificationMethods,
1015
+ versionNegotiation: client.versionNegotiation,
1016
+ inputRequired: client.inputRequired,
1017
+ listMaxPages: client.listMaxPages,
1018
+ cachePartition: client.cachePartition,
1019
+ defaultCacheTtlMs: client.defaultCacheTtlMs
1020
+ };
1021
+ }
1022
+ function persistTransportOptions(value) {
1023
+ if (!value) return void 0;
1024
+ return {
1025
+ type: value.type,
1026
+ headers: value.headers,
1027
+ requestInit: value.requestInit,
1028
+ reconnectionOptions: value.reconnectionOptions,
1029
+ skipIssuerMetadataValidation: value.skipIssuerMetadataValidation,
1030
+ onInsufficientScope: value.onInsufficientScope,
1031
+ maxStepUpRetries: value.maxStepUpRetries,
1032
+ sessionId: value.sessionId,
1033
+ protocolVersion: value.protocolVersion
1034
+ };
1035
+ }
1036
+ function encodeMcpServerOptions(options) {
1037
+ return JSON.stringify({
1038
+ client: persistClientOptions(options.client),
1039
+ transport: persistTransportOptions(options.transport),
1040
+ discoverResult: options.discoverResult,
1041
+ retry: options.retry,
1042
+ bindingName: options.bindingName,
1043
+ props: options.props,
1044
+ capabilities: options.capabilities
1045
+ });
1046
+ }
1047
+ function decodeMcpServerOptions(value) {
1048
+ if (!value) return {};
1049
+ const parsed = JSON.parse(value);
1050
+ const transport = persistTransportOptions(parsed.transport);
1051
+ const statelessWithoutPrior = transport?.protocolVersion === "2026-07-28" && !parsed.discoverResult;
1052
+ if (transport?.sessionId && (!transport.protocolVersion || statelessWithoutPrior)) {
1053
+ delete transport.sessionId;
1054
+ delete transport.protocolVersion;
1055
+ delete parsed.discoverResult;
1056
+ }
1057
+ return {
1058
+ client: persistClientOptions(parsed.client),
1059
+ transport,
1060
+ discoverResult: parsed.discoverResult,
1061
+ retry: parsed.retry,
1062
+ ...parsed.bindingName !== void 0 && { bindingName: parsed.bindingName },
1063
+ ...parsed.props !== void 0 && { props: parsed.props },
1064
+ capabilities: parsed.capabilities
1065
+ };
1066
+ }
1067
+ function withMcpSession(options, session) {
1068
+ const transport = { ...options.transport ?? {} };
1069
+ if (!session) {
1070
+ delete transport.sessionId;
1071
+ delete transport.protocolVersion;
1072
+ const next = {
1073
+ ...options,
1074
+ transport
1075
+ };
1076
+ delete next.discoverResult;
1077
+ return next;
1078
+ }
1079
+ transport.sessionId = session.id;
1080
+ transport.protocolVersion = session.protocolVersion;
1081
+ return {
1082
+ ...options,
1083
+ transport,
1084
+ ...session.discoverResult ? { discoverResult: session.discoverResult } : { discoverResult: void 0 }
1085
+ };
1086
+ }
1087
+ //#endregion
822
1088
  //#region src/mcp/client.ts
823
1089
  /** Maximum length of a normalized MCP server id. */
824
1090
  const MCP_SERVER_ID_MAX_LENGTH = 64;
@@ -986,8 +1252,8 @@ var MCPClientManager = class {
986
1252
  const form = handlers.form;
987
1253
  const url = handlers.url;
988
1254
  return {
989
- form: form ? (request) => form(request, serverId) : void 0,
990
- url: url ? (request) => url(request, serverId) : void 0
1255
+ form: form ? (request, signal) => signal ? form(request, serverId, signal) : form(request, serverId) : void 0,
1256
+ url: url ? (request, signal) => signal ? url(request, serverId, signal) : url(request, serverId) : void 0
991
1257
  };
992
1258
  }
993
1259
  sql(query, ...bindings) {
@@ -1097,7 +1363,7 @@ var MCPClientManager = class {
1097
1363
  getStoredServerOptions(serverId) {
1098
1364
  const rows = this.sql("SELECT server_options FROM cf_agents_mcp_servers WHERE id = ?", serverId);
1099
1365
  if (!rows.length || !rows[0].server_options) return void 0;
1100
- return JSON.parse(rows[0].server_options);
1366
+ return decodeMcpServerOptions(rows[0].server_options);
1101
1367
  }
1102
1368
  /**
1103
1369
  * Clear the capabilities persisted on a stored server row. Called once a
@@ -1110,12 +1376,12 @@ var MCPClientManager = class {
1110
1376
  clearStoredCapabilities(serverId) {
1111
1377
  const row = this.sql("SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers WHERE id = ?", serverId)[0];
1112
1378
  if (!row?.server_options) return;
1113
- const options = JSON.parse(row.server_options);
1379
+ const options = decodeMcpServerOptions(row.server_options);
1114
1380
  if (!options.capabilities) return;
1115
1381
  options.capabilities = void 0;
1116
1382
  this.saveServerToStorage({
1117
1383
  ...row,
1118
- server_options: JSON.stringify(options)
1384
+ server_options: encodeMcpServerOptions(options)
1119
1385
  });
1120
1386
  }
1121
1387
  /**
@@ -1127,22 +1393,18 @@ var MCPClientManager = class {
1127
1393
  clearServerAuthUrl(serverId) {
1128
1394
  this.sql("UPDATE cf_agents_mcp_servers SET auth_url = NULL WHERE id = ?", serverId);
1129
1395
  }
1130
- updateStoredSessionId(id, sessionId) {
1396
+ updateStoredSession(id, sessionId, protocolVersion, discoverResult) {
1131
1397
  const serverRow = this.getServersFromStorage().find((server) => server.id === id);
1132
1398
  if (!serverRow) return;
1133
- const parsedOptions = serverRow.server_options ? JSON.parse(serverRow.server_options) : {};
1134
- if (parsedOptions.transport?.sessionId === sessionId) return;
1135
- const nextTransport = {
1136
- ...parsedOptions.transport ?? {},
1137
- ...sessionId ? { sessionId } : {}
1138
- };
1139
- if (!sessionId) delete nextTransport.sessionId;
1399
+ const options = decodeMcpServerOptions(serverRow.server_options);
1400
+ const next = sessionId && protocolVersion ? withMcpSession(options, {
1401
+ id: sessionId,
1402
+ protocolVersion,
1403
+ discoverResult
1404
+ }) : withMcpSession(options);
1140
1405
  this.saveServerToStorage({
1141
1406
  ...serverRow,
1142
- server_options: JSON.stringify({
1143
- ...parsedOptions,
1144
- transport: nextTransport
1145
- })
1407
+ server_options: encodeMcpServerOptions(next)
1146
1408
  });
1147
1409
  }
1148
1410
  failConnection(serverId, error) {
@@ -1201,12 +1463,12 @@ var MCPClientManager = class {
1201
1463
  console.warn(`[MCPClientManager] Failed to clean up stale OAuth callback state for server "${serverId}":`, cleanupError);
1202
1464
  }
1203
1465
  }
1204
- async completeAuthorizationAndCleanupVerifier(serverId, conn, authProvider, state, code) {
1466
+ async completeAuthorizationAndCleanupVerifier(serverId, conn, authProvider, state, callbackParams) {
1205
1467
  await this.runWithCodeVerifierState(authProvider, state, async () => {
1206
1468
  let completeError;
1207
1469
  let cleanupError;
1208
1470
  try {
1209
- await conn.completeAuthorization(code, { alreadyAccepted: true });
1471
+ await conn.completeAuthorization(callbackParams, { alreadyAccepted: true });
1210
1472
  } catch (error) {
1211
1473
  completeError = error;
1212
1474
  }
@@ -1253,7 +1515,7 @@ var MCPClientManager = class {
1253
1515
  client_id: null,
1254
1516
  auth_url: null,
1255
1517
  callback_url: "",
1256
- server_options: JSON.stringify({
1518
+ server_options: encodeMcpServerOptions({
1257
1519
  bindingName,
1258
1520
  props,
1259
1521
  capabilities: this.advertisedHandlerCapabilities()
@@ -1292,8 +1554,7 @@ var MCPClientManager = class {
1292
1554
  this.cleanupClosedConnection(server.id);
1293
1555
  }
1294
1556
  }
1295
- const parsedOptions = server.server_options ? JSON.parse(server.server_options) : null;
1296
- if (parsedOptions?.client) delete parsedOptions.client.jsonSchemaValidator;
1557
+ const parsedOptions = decodeMcpServerOptions(server.server_options);
1297
1558
  let authProvider;
1298
1559
  if (server.callback_url) {
1299
1560
  authProvider = this._createAuthProviderFn ? this._createAuthProviderFn(server.callback_url) : this.createAuthProvider(server.id, server.callback_url, clientName, server.client_id ?? void 0);
@@ -1306,7 +1567,8 @@ var MCPClientManager = class {
1306
1567
  ...parsedOptions?.transport ?? {},
1307
1568
  type: parsedOptions?.transport?.type ?? "auto",
1308
1569
  authProvider
1309
- }
1570
+ },
1571
+ discoverResult: parsedOptions?.discoverResult
1310
1572
  });
1311
1573
  if (server.auth_url) {
1312
1574
  conn.connectionState = MCPConnectionState.AUTHENTICATING;
@@ -1403,7 +1665,7 @@ var MCPClientManager = class {
1403
1665
  if (replaced) {
1404
1666
  delete this.mcpConnections[id];
1405
1667
  await replaced.close().catch(() => {});
1406
- this.updateStoredSessionId(id, void 0);
1668
+ this.updateStoredSession(id, void 0);
1407
1669
  }
1408
1670
  this.createConnection(id, url, {
1409
1671
  client: options.client,
@@ -1468,7 +1730,8 @@ var MCPClientManager = class {
1468
1730
  client: options.client ?? {},
1469
1731
  transport: normalizedTransport,
1470
1732
  elicitationHandlers: this.scopedElicitationHandlers(id),
1471
- capabilitySeed
1733
+ capabilitySeed,
1734
+ discoverResult: options.discoverResult
1472
1735
  });
1473
1736
  const store = new DisposableStore();
1474
1737
  const existing = this._connectionDisposables.get(id);
@@ -1477,6 +1740,9 @@ var MCPClientManager = class {
1477
1740
  store.add(this.mcpConnections[id].onObservabilityEvent((event) => {
1478
1741
  this._onObservabilityEvent.fire(event);
1479
1742
  }));
1743
+ store.add(this.mcpConnections[id].onListChanged(() => {
1744
+ this._onServerStateChanged.fire();
1745
+ }));
1480
1746
  if (capabilitySeed) {
1481
1747
  const conn = this.mcpConnections[id];
1482
1748
  const seedClear = conn.onObservabilityEvent((event) => {
@@ -1507,8 +1773,6 @@ var MCPClientManager = class {
1507
1773
  type: options.transport?.type ?? "auto"
1508
1774
  }
1509
1775
  });
1510
- const { authProvider: _, ...transportWithoutAuth } = options.transport ?? {};
1511
- const { jsonSchemaValidator: _validator, ...serializableClient } = options.client ?? {};
1512
1776
  this.saveServerToStorage({
1513
1777
  id,
1514
1778
  name: options.name,
@@ -1516,9 +1780,9 @@ var MCPClientManager = class {
1516
1780
  callback_url: options.callbackUrl ?? "",
1517
1781
  client_id: options.clientId ?? null,
1518
1782
  auth_url: options.authUrl ?? null,
1519
- server_options: JSON.stringify({
1520
- client: serializableClient,
1521
- transport: transportWithoutAuth,
1783
+ server_options: encodeMcpServerOptions({
1784
+ client: options.client,
1785
+ transport: options.transport,
1522
1786
  retry: options.retry,
1523
1787
  capabilities: this.advertisedHandlerCapabilities()
1524
1788
  })
@@ -1526,6 +1790,32 @@ var MCPClientManager = class {
1526
1790
  this._onServerStateChanged.fire();
1527
1791
  return id;
1528
1792
  }
1793
+ /** Persist and emit an OAuth continuation produced by connect or discovery. */
1794
+ persistAuthContinuation(id, conn) {
1795
+ const authProvider = conn.options.transport.authProvider;
1796
+ const authUrl = authProvider?.authUrl;
1797
+ if (!authUrl || !authProvider.redirectUrl) return void 0;
1798
+ const clientId = authProvider.clientId;
1799
+ const serverRow = this.getServersFromStorage().find((s) => s.id === id);
1800
+ if (serverRow) this.saveServerToStorage({
1801
+ ...serverRow,
1802
+ auth_url: authUrl,
1803
+ client_id: clientId ?? null
1804
+ });
1805
+ this._onObservabilityEvent.fire({
1806
+ type: "mcp:client:authorize",
1807
+ payload: {
1808
+ serverId: id,
1809
+ authUrl,
1810
+ clientId
1811
+ },
1812
+ timestamp: Date.now()
1813
+ });
1814
+ return {
1815
+ authUrl,
1816
+ clientId
1817
+ };
1818
+ }
1529
1819
  /**
1530
1820
  * Connect to an already registered MCP server and initialize the connection.
1531
1821
  *
@@ -1544,7 +1834,7 @@ var MCPClientManager = class {
1544
1834
  const conn = this.mcpConnections[id];
1545
1835
  if (!conn) throw new Error(`Server ${id} is not registered. Call registerServer() first.`);
1546
1836
  const error = await conn.init();
1547
- this.updateStoredSessionId(id, conn.sessionId);
1837
+ this.updateStoredSession(id, conn.sessionId, conn.protocolVersion, conn.discoverResult);
1548
1838
  this._onServerStateChanged.fire();
1549
1839
  switch (conn.connectionState) {
1550
1840
  case MCPConnectionState.FAILED: return {
@@ -1552,35 +1842,18 @@ var MCPClientManager = class {
1552
1842
  error: error ?? "Unknown connection error"
1553
1843
  };
1554
1844
  case MCPConnectionState.AUTHENTICATING: {
1555
- const authUrl = conn.options.transport.authProvider?.authUrl;
1556
- const redirectUrl = conn.options.transport.authProvider?.redirectUrl;
1557
- if (!authUrl || !redirectUrl) return {
1558
- state: MCPConnectionState.FAILED,
1559
- error: `OAuth configuration incomplete: missing ${!authUrl ? "authUrl" : "redirectUrl"}`
1560
- };
1561
- const clientId = conn.options.transport.authProvider?.clientId;
1562
- const serverRow = this.getServersFromStorage().find((s) => s.id === id);
1563
- if (serverRow) {
1564
- this.saveServerToStorage({
1565
- ...serverRow,
1566
- auth_url: authUrl,
1567
- client_id: clientId ?? null
1568
- });
1569
- this._onServerStateChanged.fire();
1845
+ const auth = this.persistAuthContinuation(id, conn);
1846
+ if (!auth) {
1847
+ const provider = conn.options.transport.authProvider;
1848
+ return {
1849
+ state: MCPConnectionState.FAILED,
1850
+ error: `OAuth configuration incomplete: missing ${!provider?.authUrl ? "authUrl" : "redirectUrl"}`
1851
+ };
1570
1852
  }
1571
- this._onObservabilityEvent.fire({
1572
- type: "mcp:client:authorize",
1573
- payload: {
1574
- serverId: id,
1575
- authUrl,
1576
- clientId
1577
- },
1578
- timestamp: Date.now()
1579
- });
1853
+ this._onServerStateChanged.fire();
1580
1854
  return {
1581
1855
  state: conn.connectionState,
1582
- authUrl,
1583
- clientId
1856
+ ...auth
1584
1857
  };
1585
1858
  }
1586
1859
  case MCPConnectionState.CONNECTED: return { state: conn.connectionState };
@@ -1616,7 +1889,6 @@ var MCPClientManager = class {
1616
1889
  const code = url.searchParams.get("code");
1617
1890
  const state = url.searchParams.get("state");
1618
1891
  const error = url.searchParams.get("error");
1619
- const errorDescription = url.searchParams.get("error_description");
1620
1892
  if (!state) return {
1621
1893
  valid: false,
1622
1894
  error: "Unauthorized: no state provided"
@@ -1626,13 +1898,7 @@ var MCPClientManager = class {
1626
1898
  valid: false,
1627
1899
  error: "No serverId found in state parameter. Expected format: {nonce}.{serverId}"
1628
1900
  };
1629
- if (error) return {
1630
- serverId,
1631
- state,
1632
- valid: false,
1633
- error: errorDescription || error
1634
- };
1635
- if (!code) return {
1901
+ if (!code && !error) return {
1636
1902
  serverId,
1637
1903
  state,
1638
1904
  valid: false,
@@ -1651,8 +1917,8 @@ var MCPClientManager = class {
1651
1917
  return {
1652
1918
  valid: true,
1653
1919
  serverId,
1654
- code,
1655
- state
1920
+ state,
1921
+ callbackParams: url.searchParams
1656
1922
  };
1657
1923
  }
1658
1924
  async handleCallbackRequest(req) {
@@ -1678,7 +1944,7 @@ var MCPClientManager = class {
1678
1944
  authError: validation.error
1679
1945
  };
1680
1946
  }
1681
- const { serverId, code, state } = validation;
1947
+ const { serverId, state, callbackParams } = validation;
1682
1948
  const conn = this.mcpConnections[serverId];
1683
1949
  try {
1684
1950
  if (!conn.options.transport.authProvider) throw new Error("Trying to finalize authentication for a server connection without an authProvider");
@@ -1690,7 +1956,7 @@ var MCPClientManager = class {
1690
1956
  await this.consumeStaleOAuthState(serverId, authProvider, state);
1691
1957
  return this.oauthCallbackSuccess(serverId, conn);
1692
1958
  }
1693
- return this.ignoreUnverifiedCallback(serverId, stateValidation.error || "Invalid state");
1959
+ return this.ignoreUnverifiedCallback(serverId, callbackParams.get("error_description") ?? callbackParams.get("error") ?? stateValidation.error ?? "Invalid state");
1694
1960
  }
1695
1961
  if (this.isAuthAcceptedConnection(conn)) {
1696
1962
  await this.consumeStaleOAuthState(serverId, authProvider, state);
@@ -1699,8 +1965,8 @@ var MCPClientManager = class {
1699
1965
  if (conn.connectionState !== MCPConnectionState.AUTHENTICATING && conn.connectionState !== MCPConnectionState.FAILED) throw new Error(`Failed to authenticate from "${conn.connectionState}" state`);
1700
1966
  conn.connectionState = MCPConnectionState.CONNECTING;
1701
1967
  await authProvider.consumeState(state);
1702
- await this.completeAuthorizationAndCleanupVerifier(serverId, conn, authProvider, state, code);
1703
- this.updateStoredSessionId(serverId, conn.sessionId);
1968
+ await this.completeAuthorizationAndCleanupVerifier(serverId, conn, authProvider, state, callbackParams);
1969
+ this.updateStoredSession(serverId, conn.sessionId, conn.protocolVersion, conn.discoverResult);
1704
1970
  const result = this.oauthCallbackSuccess(serverId, conn);
1705
1971
  this._onServerStateChanged.fire();
1706
1972
  return result;
@@ -1734,6 +2000,7 @@ var MCPClientManager = class {
1734
2000
  }
1735
2001
  const result = await conn.discover(options);
1736
2002
  if (!result.success && result.reason === "stale-session") return this._recoverStaleSession(conn, serverId, options);
2003
+ if (conn.connectionState === MCPConnectionState.AUTHENTICATING) this.persistAuthContinuation(serverId, conn);
1737
2004
  this._onServerStateChanged.fire();
1738
2005
  return this._toDiscoverResult(conn, result);
1739
2006
  }
@@ -1749,7 +2016,7 @@ var MCPClientManager = class {
1749
2016
  }
1750
2017
  async _recoverStaleSession(conn, serverId, options) {
1751
2018
  conn.clearResumedSession();
1752
- this.updateStoredSessionId(serverId, void 0);
2019
+ this.updateStoredSession(serverId, void 0);
1753
2020
  let connectResult;
1754
2021
  try {
1755
2022
  connectResult = await this.connectToServer(serverId);
@@ -1860,12 +2127,12 @@ var MCPClientManager = class {
1860
2127
  persistAdvertisedCapabilities() {
1861
2128
  const capabilities = this.advertisedHandlerCapabilities();
1862
2129
  for (const server of this.getServersFromStorage()) {
1863
- const options = server.server_options ? JSON.parse(server.server_options) : {};
2130
+ const options = decodeMcpServerOptions(server.server_options);
1864
2131
  if (JSON.stringify(options.capabilities) === JSON.stringify(capabilities)) continue;
1865
2132
  options.capabilities = capabilities;
1866
2133
  this.saveServerToStorage({
1867
2134
  ...server,
1868
- server_options: JSON.stringify(options)
2135
+ server_options: encodeMcpServerOptions(options)
1869
2136
  });
1870
2137
  }
1871
2138
  }
@@ -1991,7 +2258,7 @@ var MCPClientManager = class {
1991
2258
  * (closes connection AND removes from storage).
1992
2259
  */
1993
2260
  cleanupClosedConnection(id) {
1994
- this.updateStoredSessionId(id, void 0);
2261
+ this.updateStoredSession(id, void 0);
1995
2262
  const store = this._connectionDisposables.get(id);
1996
2263
  if (store) store.dispose();
1997
2264
  this._connectionDisposables.delete(id);
@@ -2074,28 +2341,27 @@ var MCPClientManager = class {
2074
2341
  listResourceTemplates(filter) {
2075
2342
  return getNamespacedData(this.filterConnections(filter), "resourceTemplates");
2076
2343
  }
2077
- /**
2078
- * Namespaced version of callTool
2079
- */
2080
- async callTool(params, resultSchema, options) {
2344
+ async callTool(params, schemaOrOptions, options) {
2081
2345
  const { serverId, ...mcpParams } = params;
2082
2346
  const unqualifiedName = mcpParams.name.replace(`${serverId}.`, "");
2083
- return this.mcpConnections[serverId].client.callTool({
2347
+ return callV2Tool(this.mcpConnections[serverId].client, {
2084
2348
  ...mcpParams,
2085
2349
  name: unqualifiedName
2086
- }, resultSchema, options);
2350
+ }, schemaOrOptions, options);
2087
2351
  }
2088
2352
  /**
2089
2353
  * Namespaced version of readResource
2090
2354
  */
2091
2355
  readResource(params, options) {
2092
- return this.mcpConnections[params.serverId].client.readResource(params, options);
2356
+ const { serverId, ...mcpParams } = params;
2357
+ return this.mcpConnections[serverId].client.readResource(mcpParams, options);
2093
2358
  }
2094
2359
  /**
2095
2360
  * Namespaced version of getPrompt
2096
2361
  */
2097
2362
  getPrompt(params, options) {
2098
- return this.mcpConnections[params.serverId].client.getPrompt(params, options);
2363
+ const { serverId, ...mcpParams } = params;
2364
+ return this.mcpConnections[serverId].client.getPrompt(mcpParams, options);
2099
2365
  }
2100
2366
  };
2101
2367
  function getNamespacedData(mcpClients, type) {
@@ -2116,4 +2382,4 @@ function getNamespacedData(mcpClients, type) {
2116
2382
  //#endregion
2117
2383
  export { MCPConnectionState as a, RPC_DO_PREFIX as c, normalizeServerId as i, DisposableStore as l, MCP_SERVER_ID_MAX_LENGTH as n, RPCClientTransport as o, getNamespacedData as r, RPCServerTransport as s, MCPClientManager as t };
2118
2384
 
2119
- //# sourceMappingURL=client-CcjiFpTf.js.map
2385
+ //# sourceMappingURL=client-zqKcsyFa.js.map