agents 0.0.0-88ea3a1 → 0.0.0-90db5ba

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.
@@ -1,32 +1,49 @@
1
1
  import * as zod from 'zod';
2
- import { Tool, Prompt as Prompt$1, Resource, ResourceTemplate, ServerCapabilities, ClientCapabilities, CallToolRequest, CallToolResultSchema, CompatibilityCallToolResultSchema, ReadResourceRequest, GetPromptRequest } from '@modelcontextprotocol/sdk/types.js';
2
+ import { ClientCapabilities, Tool, Prompt, Resource, ResourceTemplate, ServerCapabilities, CallToolRequest, CallToolResultSchema, CompatibilityCallToolResultSchema, ReadResourceRequest, GetPromptRequest } from '@modelcontextprotocol/sdk/types.js';
3
3
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
- import { SSEClientTransport, SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
4
+ import { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
5
+ import { AgentsOAuthProvider } from './do-oauth-client-provider.js';
5
6
  import { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
7
+ import '@modelcontextprotocol/sdk/client/auth.js';
8
+ import '@modelcontextprotocol/sdk/shared/auth.js';
6
9
 
7
10
  declare class MCPClientConnection {
8
- private info;
11
+ url: URL;
12
+ options: {
13
+ transport: SSEClientTransportOptions & {
14
+ authProvider?: AgentsOAuthProvider;
15
+ };
16
+ client: ConstructorParameters<typeof Client>[1];
17
+ capabilities: ClientCapabilities;
18
+ };
9
19
  client: Client;
10
- transport: SSEClientTransport;
11
- connected: boolean;
20
+ connectionState: "authenticating" | "connecting" | "ready" | "discovering" | "failed";
12
21
  instructions?: string;
13
22
  tools: Tool[];
14
- prompts: Prompt$1[];
23
+ prompts: Prompt[];
15
24
  resources: Resource[];
16
25
  resourceTemplates: ResourceTemplate[];
17
26
  serverCapabilities: ServerCapabilities | undefined;
18
- constructor(url: URL, info: ConstructorParameters<typeof Client>[0], opts?: {
19
- transport: SSEClientTransportOptions;
27
+ constructor(url: URL, info: ConstructorParameters<typeof Client>[0], options?: {
28
+ transport: SSEClientTransportOptions & {
29
+ authProvider?: AgentsOAuthProvider;
30
+ };
20
31
  client: ConstructorParameters<typeof Client>[1];
21
32
  capabilities: ClientCapabilities;
22
33
  });
23
- init(): Promise<void>;
34
+ /**
35
+ * Initialize a client connection
36
+ *
37
+ * @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized
38
+ * @returns
39
+ */
40
+ init(code?: string, clientId?: string): Promise<void>;
24
41
  /**
25
42
  * Notification handler registration
26
43
  */
27
44
  registerTools(): Promise<Tool[]>;
28
45
  registerResources(): Promise<Resource[]>;
29
- registerPrompts(): Promise<Prompt$1[]>;
46
+ registerPrompts(): Promise<Prompt[]>;
30
47
  registerResourceTemplates(): Promise<ResourceTemplate[]>;
31
48
  fetchTools(): Promise<{
32
49
  [x: string]: unknown;
@@ -71,7 +88,16 @@ declare class MCPClientConnection {
71
88
  * Utility class that aggregates multiple MCP clients into one
72
89
  */
73
90
  declare class MCPClientManager {
91
+ private name;
92
+ private version;
74
93
  mcpConnections: Record<string, MCPClientConnection>;
94
+ private callbackUrls;
95
+ /**
96
+ * @param name Name of the MCP client
97
+ * @param version Version of the MCP Client
98
+ * @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider
99
+ */
100
+ constructor(name: string, version: string);
75
101
  /**
76
102
  * Connect to and register an MCP server
77
103
  *
@@ -79,11 +105,25 @@ declare class MCPClientManager {
79
105
  * @param clientConfig Client config
80
106
  * @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
81
107
  */
82
- connectToServer(url: URL, info: ConstructorParameters<typeof Client>[0], opts?: {
83
- transport: SSEClientTransportOptions;
84
- client: ConstructorParameters<typeof Client>[1];
85
- capabilities: ClientCapabilities;
86
- }): Promise<void>;
108
+ connect(url: string, options?: {
109
+ reconnect?: {
110
+ id: string;
111
+ oauthClientId?: string;
112
+ oauthCode?: string;
113
+ };
114
+ transport?: SSEClientTransportOptions & {
115
+ authProvider?: AgentsOAuthProvider;
116
+ };
117
+ client?: ConstructorParameters<typeof Client>[1];
118
+ capabilities?: ClientCapabilities;
119
+ }): Promise<{
120
+ id: string;
121
+ authUrl: string | undefined;
122
+ }>;
123
+ isCallbackRequest(req: Request): boolean;
124
+ handleCallbackRequest(req: Request): Promise<{
125
+ serverId: string;
126
+ }>;
87
127
  /**
88
128
  * @returns namespaced list of tools
89
129
  */
@@ -104,10 +144,10 @@ declare class MCPClientManager {
104
144
  * Namespaced version of callTool
105
145
  */
106
146
  callTool(params: CallToolRequest["params"] & {
107
- serverName: string;
108
- }, resultSchema: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options: RequestOptions): Promise<zod.objectOutputType<zod.objectUtil.extendShape<{
147
+ serverId: string;
148
+ }, resultSchema: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options: RequestOptions): Promise<zod.objectOutputType<{
109
149
  _meta: zod.ZodOptional<zod.ZodObject<{}, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{}, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{}, zod.ZodTypeAny, "passthrough">>>;
110
- }, {
150
+ } & {
111
151
  content: zod.ZodArray<zod.ZodUnion<[zod.ZodObject<{
112
152
  type: zod.ZodLiteral<"text">;
113
153
  text: zod.ZodString;
@@ -129,6 +169,18 @@ declare class MCPClientManager {
129
169
  type: zod.ZodLiteral<"image">;
130
170
  data: zod.ZodString;
131
171
  mimeType: zod.ZodString;
172
+ }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
173
+ type: zod.ZodLiteral<"audio">;
174
+ data: zod.ZodString;
175
+ mimeType: zod.ZodString;
176
+ }, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{
177
+ type: zod.ZodLiteral<"audio">;
178
+ data: zod.ZodString;
179
+ mimeType: zod.ZodString;
180
+ }, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{
181
+ type: zod.ZodLiteral<"audio">;
182
+ data: zod.ZodString;
183
+ mimeType: zod.ZodString;
132
184
  }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
133
185
  type: zod.ZodLiteral<"resource">;
134
186
  resource: zod.ZodUnion<[zod.ZodObject<zod.objectUtil.extendShape<{
@@ -230,19 +282,19 @@ declare class MCPClientManager {
230
282
  }>, zod.ZodTypeAny, "passthrough">>]>;
231
283
  }, zod.ZodTypeAny, "passthrough">>]>, "many">;
232
284
  isError: zod.ZodOptional<zod.ZodDefault<zod.ZodBoolean>>;
233
- }>, zod.ZodTypeAny, "passthrough"> | zod.objectOutputType<zod.objectUtil.extendShape<{
285
+ }, zod.ZodTypeAny, "passthrough"> | zod.objectOutputType<{
234
286
  _meta: zod.ZodOptional<zod.ZodObject<{}, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{}, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{}, zod.ZodTypeAny, "passthrough">>>;
235
- }, {
287
+ } & {
236
288
  toolResult: zod.ZodUnknown;
237
- }>, zod.ZodTypeAny, "passthrough">>;
289
+ }, zod.ZodTypeAny, "passthrough">>;
238
290
  /**
239
291
  * Namespaced version of readResource
240
292
  */
241
293
  readResource(params: ReadResourceRequest["params"] & {
242
- serverName: string;
243
- }, options: RequestOptions): Promise<zod.objectOutputType<zod.objectUtil.extendShape<{
294
+ serverId: string;
295
+ }, options: RequestOptions): Promise<zod.objectOutputType<{
244
296
  _meta: zod.ZodOptional<zod.ZodObject<{}, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{}, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{}, zod.ZodTypeAny, "passthrough">>>;
245
- }, {
297
+ } & {
246
298
  contents: zod.ZodArray<zod.ZodUnion<[zod.ZodObject<zod.objectUtil.extendShape<{
247
299
  uri: zod.ZodString;
248
300
  mimeType: zod.ZodOptional<zod.ZodString>;
@@ -274,15 +326,15 @@ declare class MCPClientManager {
274
326
  }, {
275
327
  blob: zod.ZodString;
276
328
  }>, zod.ZodTypeAny, "passthrough">>]>, "many">;
277
- }>, zod.ZodTypeAny, "passthrough">>;
329
+ }, zod.ZodTypeAny, "passthrough">>;
278
330
  /**
279
331
  * Namespaced version of getPrompt
280
332
  */
281
333
  getPrompt(params: GetPromptRequest["params"] & {
282
- serverName: string;
283
- }, options: RequestOptions): Promise<zod.objectOutputType<zod.objectUtil.extendShape<{
334
+ serverId: string;
335
+ }, options: RequestOptions): Promise<zod.objectOutputType<{
284
336
  _meta: zod.ZodOptional<zod.ZodObject<{}, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{}, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{}, zod.ZodTypeAny, "passthrough">>>;
285
- }, {
337
+ } & {
286
338
  description: zod.ZodOptional<zod.ZodString>;
287
339
  messages: zod.ZodArray<zod.ZodObject<{
288
340
  role: zod.ZodEnum<["user", "assistant"]>;
@@ -307,6 +359,18 @@ declare class MCPClientManager {
307
359
  type: zod.ZodLiteral<"image">;
308
360
  data: zod.ZodString;
309
361
  mimeType: zod.ZodString;
362
+ }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
363
+ type: zod.ZodLiteral<"audio">;
364
+ data: zod.ZodString;
365
+ mimeType: zod.ZodString;
366
+ }, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{
367
+ type: zod.ZodLiteral<"audio">;
368
+ data: zod.ZodString;
369
+ mimeType: zod.ZodString;
370
+ }, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{
371
+ type: zod.ZodLiteral<"audio">;
372
+ data: zod.ZodString;
373
+ mimeType: zod.ZodString;
310
374
  }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
311
375
  type: zod.ZodLiteral<"resource">;
312
376
  resource: zod.ZodUnion<[zod.ZodObject<zod.objectUtil.extendShape<{
@@ -430,6 +494,18 @@ declare class MCPClientManager {
430
494
  type: zod.ZodLiteral<"image">;
431
495
  data: zod.ZodString;
432
496
  mimeType: zod.ZodString;
497
+ }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
498
+ type: zod.ZodLiteral<"audio">;
499
+ data: zod.ZodString;
500
+ mimeType: zod.ZodString;
501
+ }, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{
502
+ type: zod.ZodLiteral<"audio">;
503
+ data: zod.ZodString;
504
+ mimeType: zod.ZodString;
505
+ }, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{
506
+ type: zod.ZodLiteral<"audio">;
507
+ data: zod.ZodString;
508
+ mimeType: zod.ZodString;
433
509
  }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
434
510
  type: zod.ZodLiteral<"resource">;
435
511
  resource: zod.ZodUnion<[zod.ZodObject<zod.objectUtil.extendShape<{
@@ -553,6 +629,18 @@ declare class MCPClientManager {
553
629
  type: zod.ZodLiteral<"image">;
554
630
  data: zod.ZodString;
555
631
  mimeType: zod.ZodString;
632
+ }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
633
+ type: zod.ZodLiteral<"audio">;
634
+ data: zod.ZodString;
635
+ mimeType: zod.ZodString;
636
+ }, "passthrough", zod.ZodTypeAny, zod.objectOutputType<{
637
+ type: zod.ZodLiteral<"audio">;
638
+ data: zod.ZodString;
639
+ mimeType: zod.ZodString;
640
+ }, zod.ZodTypeAny, "passthrough">, zod.objectInputType<{
641
+ type: zod.ZodLiteral<"audio">;
642
+ data: zod.ZodString;
643
+ mimeType: zod.ZodString;
556
644
  }, zod.ZodTypeAny, "passthrough">>, zod.ZodObject<{
557
645
  type: zod.ZodLiteral<"resource">;
558
646
  resource: zod.ZodUnion<[zod.ZodObject<zod.objectUtil.extendShape<{
@@ -654,20 +742,20 @@ declare class MCPClientManager {
654
742
  }>, zod.ZodTypeAny, "passthrough">>]>;
655
743
  }, zod.ZodTypeAny, "passthrough">>]>;
656
744
  }, zod.ZodTypeAny, "passthrough">>, "many">;
657
- }>, zod.ZodTypeAny, "passthrough">>;
745
+ }, zod.ZodTypeAny, "passthrough">>;
658
746
  }
659
747
  type NamespacedData = {
660
748
  tools: (Tool & {
661
- serverName: string;
749
+ serverId: string;
662
750
  })[];
663
751
  prompts: (Prompt & {
664
- serverName: string;
752
+ serverId: string;
665
753
  })[];
666
754
  resources: (Resource & {
667
- serverName: string;
755
+ serverId: string;
668
756
  })[];
669
757
  resourceTemplates: (ResourceTemplate & {
670
- serverName: string;
758
+ serverId: string;
671
759
  })[];
672
760
  };
673
761
  declare function getNamespacedData<T extends keyof NamespacedData>(mcpClients: Record<string, MCPClientConnection>, type: T): NamespacedData[T];
@@ -9,12 +9,17 @@ var SSEEdgeClientTransport = class extends SSEClientTransport {
9
9
  * Creates a new EdgeSSEClientTransport, which overrides fetch to be compatible with the CF workers environment
10
10
  */
11
11
  constructor(url, options) {
12
- const fetchOverride = (url2, options2 = {}) => {
12
+ const fetchOverride = async (fetchUrl, fetchInit = {}) => {
13
+ const headers = await this.authHeaders();
13
14
  const workerOptions = {
14
- ...options2
15
+ ...fetchInit,
16
+ headers: {
17
+ ...fetchInit?.headers,
18
+ ...headers
19
+ }
15
20
  };
16
21
  delete workerOptions.mode;
17
- return global.fetch(url2, workerOptions);
22
+ return fetch(fetchUrl, workerOptions);
18
23
  };
19
24
  super(url, {
20
25
  ...options,
@@ -22,7 +27,17 @@ var SSEEdgeClientTransport = class extends SSEClientTransport {
22
27
  fetch: fetchOverride
23
28
  }
24
29
  });
25
- this.url = url;
30
+ this.authProvider = options.authProvider;
31
+ }
32
+ async authHeaders() {
33
+ if (this.authProvider) {
34
+ const tokens = await this.authProvider.tokens();
35
+ if (tokens) {
36
+ return {
37
+ Authorization: `Bearer ${tokens.access_token}`
38
+ };
39
+ }
40
+ }
26
41
  }
27
42
  };
28
43
 
@@ -34,24 +49,45 @@ import {
34
49
  } from "@modelcontextprotocol/sdk/types.js";
35
50
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
36
51
  var MCPClientConnection = class {
37
- constructor(url, info, opts = { transport: {}, client: {}, capabilities: {} }) {
38
- this.info = info;
39
- this.transport = new SSEEdgeClientTransport(url, opts.transport);
40
- this.client = new Client(info, opts.client);
41
- this.client.registerCapabilities(opts.capabilities);
42
- this.connected = false;
52
+ constructor(url, info, options = { transport: {}, client: {}, capabilities: {} }) {
53
+ this.url = url;
54
+ this.options = options;
55
+ this.connectionState = "connecting";
43
56
  this.tools = [];
44
57
  this.prompts = [];
45
58
  this.resources = [];
46
59
  this.resourceTemplates = [];
60
+ this.client = new Client(info, options.client);
61
+ this.client.registerCapabilities(options.capabilities);
47
62
  }
48
- async init() {
49
- await this.client.connect(this.transport);
63
+ /**
64
+ * Initialize a client connection
65
+ *
66
+ * @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized
67
+ * @returns
68
+ */
69
+ async init(code, clientId) {
70
+ try {
71
+ const transport = new SSEEdgeClientTransport(
72
+ this.url,
73
+ this.options.transport
74
+ );
75
+ if (code) {
76
+ await transport.finishAuth(code);
77
+ }
78
+ await this.client.connect(transport);
79
+ } catch (e) {
80
+ if (e.toString().includes("Unauthorized")) {
81
+ this.connectionState = "authenticating";
82
+ return;
83
+ }
84
+ this.connectionState = "failed";
85
+ throw e;
86
+ }
87
+ this.connectionState = "discovering";
50
88
  this.serverCapabilities = await this.client.getServerCapabilities();
51
89
  if (!this.serverCapabilities) {
52
- throw new Error(
53
- `The MCP Server ${this.info.name} failed to return server capabilities`
54
- );
90
+ throw new Error("The MCP Server failed to return server capabilities");
55
91
  }
56
92
  const [instructions, tools, resources, prompts, resourceTemplates] = await Promise.all([
57
93
  this.client.getInstructions(),
@@ -65,6 +101,7 @@ var MCPClientConnection = class {
65
101
  this.resources = resources;
66
102
  this.prompts = prompts;
67
103
  this.resourceTemplates = resourceTemplates;
104
+ this.connectionState = "ready";
68
105
  }
69
106
  /**
70
107
  * Notification handler registration
@@ -123,7 +160,7 @@ var MCPClientConnection = class {
123
160
  do {
124
161
  toolsResult = await this.client.listTools({
125
162
  cursor: toolsResult.nextCursor
126
- });
163
+ }).catch(capabilityErrorHandler({ tools: [] }, "tools/list"));
127
164
  toolsAgg = toolsAgg.concat(toolsResult.tools);
128
165
  } while (toolsResult.nextCursor);
129
166
  return toolsAgg;
@@ -134,7 +171,7 @@ var MCPClientConnection = class {
134
171
  do {
135
172
  resourcesResult = await this.client.listResources({
136
173
  cursor: resourcesResult.nextCursor
137
- });
174
+ }).catch(capabilityErrorHandler({ resources: [] }, "resources/list"));
138
175
  resourcesAgg = resourcesAgg.concat(resourcesResult.resources);
139
176
  } while (resourcesResult.nextCursor);
140
177
  return resourcesAgg;
@@ -145,7 +182,7 @@ var MCPClientConnection = class {
145
182
  do {
146
183
  promptsResult = await this.client.listPrompts({
147
184
  cursor: promptsResult.nextCursor
148
- });
185
+ }).catch(capabilityErrorHandler({ prompts: [] }, "prompts/list"));
149
186
  promptsAgg = promptsAgg.concat(promptsResult.prompts);
150
187
  } while (promptsResult.nextCursor);
151
188
  return promptsAgg;
@@ -158,17 +195,41 @@ var MCPClientConnection = class {
158
195
  do {
159
196
  templatesResult = await this.client.listResourceTemplates({
160
197
  cursor: templatesResult.nextCursor
161
- });
198
+ }).catch(
199
+ capabilityErrorHandler(
200
+ { resourceTemplates: [] },
201
+ "resources/templates/list"
202
+ )
203
+ );
162
204
  templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);
163
205
  } while (templatesResult.nextCursor);
164
206
  return templatesAgg;
165
207
  }
166
208
  };
209
+ function capabilityErrorHandler(empty, method) {
210
+ return (e) => {
211
+ if (e.code === -32601) {
212
+ console.error(
213
+ `The server advertised support for the capability ${method.split("/")[0]}, but returned "Method not found" for '${method}'.`
214
+ );
215
+ return empty;
216
+ }
217
+ throw e;
218
+ };
219
+ }
167
220
 
168
221
  // src/mcp/client.ts
169
222
  var MCPClientManager = class {
170
- constructor() {
223
+ /**
224
+ * @param name Name of the MCP client
225
+ * @param version Version of the MCP Client
226
+ * @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider
227
+ */
228
+ constructor(name, version) {
229
+ this.name = name;
230
+ this.version = version;
171
231
  this.mcpConnections = {};
232
+ this.callbackUrls = [];
172
233
  }
173
234
  /**
174
235
  * Connect to and register an MCP server
@@ -177,14 +238,96 @@ var MCPClientManager = class {
177
238
  * @param clientConfig Client config
178
239
  * @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
179
240
  */
180
- async connectToServer(url, info, opts = { transport: {}, client: {}, capabilities: {} }) {
181
- if (info.name in this.mcpConnections) {
241
+ async connect(url, options = {}) {
242
+ const id = options.reconnect?.id ?? crypto.randomUUID();
243
+ if (!options.transport?.authProvider) {
244
+ console.warn(
245
+ "No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers"
246
+ );
247
+ } else {
248
+ options.transport.authProvider.serverId = id;
249
+ }
250
+ this.mcpConnections[id] = new MCPClientConnection(
251
+ new URL(url),
252
+ {
253
+ name: this.name,
254
+ version: this.version
255
+ },
256
+ {
257
+ transport: options.transport ?? {},
258
+ client: options.client ?? {},
259
+ capabilities: options.client ?? {}
260
+ }
261
+ );
262
+ await this.mcpConnections[id].init(
263
+ options.reconnect?.oauthCode,
264
+ options.reconnect?.oauthClientId
265
+ );
266
+ const authUrl = options.transport?.authProvider?.authUrl;
267
+ if (authUrl && options.transport?.authProvider?.redirectUrl) {
268
+ this.callbackUrls.push(
269
+ options.transport.authProvider.redirectUrl.toString()
270
+ );
271
+ }
272
+ return {
273
+ id,
274
+ authUrl
275
+ };
276
+ }
277
+ isCallbackRequest(req) {
278
+ return req.method === "GET" && !!this.callbackUrls.find((url) => {
279
+ return req.url.startsWith(url);
280
+ });
281
+ }
282
+ async handleCallbackRequest(req) {
283
+ const url = new URL(req.url);
284
+ const urlMatch = this.callbackUrls.find((url2) => {
285
+ return req.url.startsWith(url2);
286
+ });
287
+ if (!urlMatch) {
182
288
  throw new Error(
183
- `An existing MCP client has already been registered under the name "${info.name}". The MCP client name must be unique.`
289
+ `No callback URI match found for the request url: ${req.url}. Was the request matched with \`isCallbackRequest()\`?`
184
290
  );
185
291
  }
186
- this.mcpConnections[info.name] = new MCPClientConnection(url, info, opts);
187
- await this.mcpConnections[info.name].init();
292
+ const code = url.searchParams.get("code");
293
+ const clientId = url.searchParams.get("state");
294
+ const urlParams = urlMatch.split("/");
295
+ const serverId = urlParams[urlParams.length - 1];
296
+ if (!code) {
297
+ throw new Error("Unauthorized: no code provided");
298
+ }
299
+ if (!clientId) {
300
+ throw new Error("Unauthorized: no state provided");
301
+ }
302
+ if (this.mcpConnections[serverId] === void 0) {
303
+ throw new Error(`Could not find serverId: ${serverId}`);
304
+ }
305
+ if (this.mcpConnections[serverId].connectionState !== "authenticating") {
306
+ throw new Error(
307
+ "Failed to authenticate: the client isn't in the `authenticating` state"
308
+ );
309
+ }
310
+ const conn = this.mcpConnections[serverId];
311
+ if (!conn.options.transport.authProvider) {
312
+ throw new Error(
313
+ "Trying to finalize authentication for a server connection without an authProvider"
314
+ );
315
+ }
316
+ conn.options.transport.authProvider.clientId = clientId;
317
+ conn.options.transport.authProvider.serverId = serverId;
318
+ const serverUrl = conn.url.toString();
319
+ await this.connect(serverUrl, {
320
+ reconnect: {
321
+ id: serverId,
322
+ oauthClientId: clientId,
323
+ oauthCode: code
324
+ },
325
+ ...conn.options
326
+ });
327
+ if (this.mcpConnections[serverId].connectionState === "authenticating") {
328
+ throw new Error("Failed to authenticate: client failed to initialize");
329
+ }
330
+ return { serverId };
188
331
  }
189
332
  /**
190
333
  * @returns namespaced list of tools
@@ -214,8 +357,8 @@ var MCPClientManager = class {
214
357
  * Namespaced version of callTool
215
358
  */
216
359
  callTool(params, resultSchema, options) {
217
- const unqualifiedName = params.name.replace(`${params.serverName}.`, "");
218
- return this.mcpConnections[params.serverName].client.callTool(
360
+ const unqualifiedName = params.name.replace(`${params.serverId}.`, "");
361
+ return this.mcpConnections[params.serverId].client.callTool(
219
362
  {
220
363
  ...params,
221
364
  name: unqualifiedName
@@ -228,7 +371,7 @@ var MCPClientManager = class {
228
371
  * Namespaced version of readResource
229
372
  */
230
373
  readResource(params, options) {
231
- return this.mcpConnections[params.serverName].client.readResource(
374
+ return this.mcpConnections[params.serverId].client.readResource(
232
375
  params,
233
376
  options
234
377
  );
@@ -237,7 +380,7 @@ var MCPClientManager = class {
237
380
  * Namespaced version of getPrompt
238
381
  */
239
382
  getPrompt(params, options) {
240
- return this.mcpConnections[params.serverName].client.getPrompt(
383
+ return this.mcpConnections[params.serverId].client.getPrompt(
241
384
  params,
242
385
  options
243
386
  );
@@ -247,15 +390,12 @@ function getNamespacedData(mcpClients, type) {
247
390
  const sets = Object.entries(mcpClients).map(([name, conn]) => {
248
391
  return { name, data: conn[type] };
249
392
  });
250
- const namespacedData = sets.flatMap(({ name: serverName, data }) => {
393
+ const namespacedData = sets.flatMap(({ name: serverId, data }) => {
251
394
  return data.map((item) => {
252
395
  return {
253
396
  ...item,
254
- // we add a servername so we can easily pull it out and convert between qualified<->unqualified name
255
- // just in case the server name or item name includes a "."
256
- serverName: `${serverName}`,
257
- // qualified name
258
- name: `${serverName}.${item.name}`
397
+ // we add a serverId so we can easily pull it out and send the tool call to the right server
398
+ serverId
259
399
  };
260
400
  });
261
401
  });