@ai-sdk/mcp 2.0.0-beta.25 → 2.0.0-beta.26

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.
package/dist/index.mjs DELETED
@@ -1,2164 +0,0 @@
1
- // src/tool/mcp-client.ts
2
- import {
3
- asSchema,
4
- dynamicTool,
5
- jsonSchema,
6
- safeParseJSON,
7
- safeValidateTypes,
8
- tool
9
- } from "@ai-sdk/provider-utils";
10
-
11
- // src/error/mcp-client-error.ts
12
- import { AISDKError } from "@ai-sdk/provider";
13
- var name = "AI_MCPClientError";
14
- var marker = `vercel.ai.error.${name}`;
15
- var symbol = Symbol.for(marker);
16
- var _a, _b;
17
- var MCPClientError = class extends (_b = AISDKError, _a = symbol, _b) {
18
- constructor({
19
- name: name3 = "MCPClientError",
20
- message,
21
- cause,
22
- data,
23
- code
24
- }) {
25
- super({ name: name3, message, cause });
26
- this[_a] = true;
27
- this.data = data;
28
- this.code = code;
29
- }
30
- static isInstance(error) {
31
- return AISDKError.hasMarker(error, marker);
32
- }
33
- };
34
-
35
- // src/tool/mcp-sse-transport.ts
36
- import {
37
- EventSourceParserStream,
38
- withUserAgentSuffix,
39
- getRuntimeEnvironmentUserAgent
40
- } from "@ai-sdk/provider-utils";
41
-
42
- // src/tool/json-rpc-message.ts
43
- import { z as z2 } from "zod/v4";
44
-
45
- // src/tool/types.ts
46
- import { z } from "zod/v4";
47
- var LATEST_PROTOCOL_VERSION = "2025-11-25";
48
- var SUPPORTED_PROTOCOL_VERSIONS = [
49
- LATEST_PROTOCOL_VERSION,
50
- "2025-06-18",
51
- "2025-03-26",
52
- "2024-11-05"
53
- ];
54
- var ToolMetaSchema = z.optional(z.record(z.string(), z.unknown()));
55
- var ClientOrServerImplementationSchema = z.looseObject({
56
- name: z.string(),
57
- version: z.string(),
58
- title: z.optional(z.string())
59
- });
60
- var BaseParamsSchema = z.looseObject({
61
- _meta: z.optional(z.object({}).loose())
62
- });
63
- var ResultSchema = BaseParamsSchema;
64
- var RequestSchema = z.object({
65
- method: z.string(),
66
- params: z.optional(BaseParamsSchema)
67
- });
68
- var ElicitationCapabilitySchema = z.object({
69
- applyDefaults: z.optional(z.boolean())
70
- }).loose();
71
- var ServerCapabilitiesSchema = z.looseObject({
72
- experimental: z.optional(z.object({}).loose()),
73
- logging: z.optional(z.object({}).loose()),
74
- prompts: z.optional(
75
- z.looseObject({
76
- listChanged: z.optional(z.boolean())
77
- })
78
- ),
79
- resources: z.optional(
80
- z.looseObject({
81
- subscribe: z.optional(z.boolean()),
82
- listChanged: z.optional(z.boolean())
83
- })
84
- ),
85
- tools: z.optional(
86
- z.looseObject({
87
- listChanged: z.optional(z.boolean())
88
- })
89
- ),
90
- elicitation: z.optional(ElicitationCapabilitySchema)
91
- });
92
- var ClientCapabilitiesSchema = z.object({
93
- elicitation: z.optional(ElicitationCapabilitySchema)
94
- }).loose();
95
- var InitializeResultSchema = ResultSchema.extend({
96
- protocolVersion: z.string(),
97
- capabilities: ServerCapabilitiesSchema,
98
- serverInfo: ClientOrServerImplementationSchema,
99
- instructions: z.optional(z.string())
100
- });
101
- var PaginatedResultSchema = ResultSchema.extend({
102
- nextCursor: z.optional(z.string())
103
- });
104
- var ToolSchema = z.object({
105
- name: z.string(),
106
- /**
107
- * @see https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool
108
- */
109
- title: z.optional(z.string()),
110
- description: z.optional(z.string()),
111
- inputSchema: z.object({
112
- type: z.literal("object"),
113
- properties: z.optional(z.object({}).loose())
114
- }).loose(),
115
- /**
116
- * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema
117
- */
118
- outputSchema: z.optional(z.object({}).loose()),
119
- annotations: z.optional(
120
- z.object({
121
- title: z.optional(z.string())
122
- }).loose()
123
- ),
124
- _meta: ToolMetaSchema
125
- }).loose();
126
- var ListToolsResultSchema = PaginatedResultSchema.extend({
127
- tools: z.array(ToolSchema)
128
- });
129
- var TextContentSchema = z.object({
130
- type: z.literal("text"),
131
- text: z.string()
132
- }).loose();
133
- var ImageContentSchema = z.object({
134
- type: z.literal("image"),
135
- data: z.base64(),
136
- mimeType: z.string()
137
- }).loose();
138
- var ResourceSchema = z.object({
139
- uri: z.string(),
140
- name: z.string(),
141
- title: z.optional(z.string()),
142
- description: z.optional(z.string()),
143
- mimeType: z.optional(z.string()),
144
- size: z.optional(z.number())
145
- }).loose();
146
- var ListResourcesResultSchema = PaginatedResultSchema.extend({
147
- resources: z.array(ResourceSchema)
148
- });
149
- var ResourceContentsSchema = z.object({
150
- /**
151
- * The URI of this resource.
152
- */
153
- uri: z.string(),
154
- /**
155
- * Optional display name of the resource content.
156
- */
157
- name: z.optional(z.string()),
158
- /**
159
- * Optional human readable title.
160
- */
161
- title: z.optional(z.string()),
162
- /**
163
- * The MIME type of this resource, if known.
164
- */
165
- mimeType: z.optional(z.string())
166
- }).loose();
167
- var TextResourceContentsSchema = ResourceContentsSchema.extend({
168
- text: z.string()
169
- });
170
- var BlobResourceContentsSchema = ResourceContentsSchema.extend({
171
- blob: z.base64()
172
- });
173
- var EmbeddedResourceSchema = z.object({
174
- type: z.literal("resource"),
175
- resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
176
- }).loose();
177
- var CallToolResultSchema = ResultSchema.extend({
178
- content: z.array(
179
- z.union([TextContentSchema, ImageContentSchema, EmbeddedResourceSchema])
180
- ),
181
- /**
182
- * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content
183
- */
184
- structuredContent: z.optional(z.unknown()),
185
- isError: z.boolean().default(false).optional()
186
- }).or(
187
- ResultSchema.extend({
188
- toolResult: z.unknown()
189
- })
190
- );
191
- var ResourceTemplateSchema = z.object({
192
- uriTemplate: z.string(),
193
- name: z.string(),
194
- title: z.optional(z.string()),
195
- description: z.optional(z.string()),
196
- mimeType: z.optional(z.string())
197
- }).loose();
198
- var ListResourceTemplatesResultSchema = ResultSchema.extend({
199
- resourceTemplates: z.array(ResourceTemplateSchema)
200
- });
201
- var ReadResourceResultSchema = ResultSchema.extend({
202
- contents: z.array(
203
- z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
204
- )
205
- });
206
- var PromptArgumentSchema = z.object({
207
- name: z.string(),
208
- description: z.optional(z.string()),
209
- required: z.optional(z.boolean())
210
- }).loose();
211
- var PromptSchema = z.object({
212
- name: z.string(),
213
- title: z.optional(z.string()),
214
- description: z.optional(z.string()),
215
- arguments: z.optional(z.array(PromptArgumentSchema))
216
- }).loose();
217
- var ListPromptsResultSchema = PaginatedResultSchema.extend({
218
- prompts: z.array(PromptSchema)
219
- });
220
- var PromptMessageSchema = z.object({
221
- role: z.union([z.literal("user"), z.literal("assistant")]),
222
- content: z.union([
223
- TextContentSchema,
224
- ImageContentSchema,
225
- EmbeddedResourceSchema
226
- ])
227
- }).loose();
228
- var GetPromptResultSchema = ResultSchema.extend({
229
- description: z.optional(z.string()),
230
- messages: z.array(PromptMessageSchema)
231
- });
232
- var ElicitationRequestParamsSchema = BaseParamsSchema.extend({
233
- message: z.string(),
234
- requestedSchema: z.unknown()
235
- });
236
- var ElicitationRequestSchema = RequestSchema.extend({
237
- method: z.literal("elicitation/create"),
238
- params: ElicitationRequestParamsSchema
239
- });
240
- var ElicitResultSchema = ResultSchema.extend({
241
- action: z.union([
242
- z.literal("accept"),
243
- z.literal("decline"),
244
- z.literal("cancel")
245
- ]),
246
- content: z.optional(z.record(z.string(), z.unknown()))
247
- });
248
-
249
- // src/tool/json-rpc-message.ts
250
- var JSONRPC_VERSION = "2.0";
251
- var JSONRPCRequestSchema = z2.object({
252
- jsonrpc: z2.literal(JSONRPC_VERSION),
253
- id: z2.union([z2.string(), z2.number().int()])
254
- }).merge(RequestSchema).strict();
255
- var JSONRPCResponseSchema = z2.object({
256
- jsonrpc: z2.literal(JSONRPC_VERSION),
257
- id: z2.union([z2.string(), z2.number().int()]),
258
- result: ResultSchema
259
- }).strict();
260
- var JSONRPCErrorSchema = z2.object({
261
- jsonrpc: z2.literal(JSONRPC_VERSION),
262
- id: z2.union([z2.string(), z2.number().int()]),
263
- error: z2.object({
264
- code: z2.number().int(),
265
- message: z2.string(),
266
- data: z2.optional(z2.unknown())
267
- })
268
- }).strict();
269
- var JSONRPCNotificationSchema = z2.object({
270
- jsonrpc: z2.literal(JSONRPC_VERSION)
271
- }).merge(
272
- z2.object({
273
- method: z2.string(),
274
- params: z2.optional(BaseParamsSchema)
275
- })
276
- ).strict();
277
- var JSONRPCMessageSchema = z2.union([
278
- JSONRPCRequestSchema,
279
- JSONRPCNotificationSchema,
280
- JSONRPCResponseSchema,
281
- JSONRPCErrorSchema
282
- ]);
283
-
284
- // src/version.ts
285
- var VERSION = typeof __PACKAGE_VERSION__ !== "undefined" ? __PACKAGE_VERSION__ : "0.0.0-test";
286
-
287
- // src/tool/oauth.ts
288
- import pkceChallenge from "pkce-challenge";
289
-
290
- // src/tool/oauth-types.ts
291
- import { z as z3 } from "zod/v4";
292
- var OAuthTokensSchema = z3.object({
293
- access_token: z3.string(),
294
- id_token: z3.string().optional(),
295
- // Optional for OAuth 2.1, but necessary in OpenID Connect
296
- token_type: z3.string(),
297
- expires_in: z3.number().optional(),
298
- scope: z3.string().optional(),
299
- refresh_token: z3.string().optional()
300
- }).strip();
301
- var SafeUrlSchema = z3.string().url().superRefine((val, ctx) => {
302
- if (!URL.canParse(val)) {
303
- ctx.addIssue({
304
- code: z3.ZodIssueCode.custom,
305
- message: "URL must be parseable",
306
- fatal: true
307
- });
308
- return z3.NEVER;
309
- }
310
- }).refine(
311
- (url) => {
312
- const u = new URL(url);
313
- return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:";
314
- },
315
- { message: "URL cannot use javascript:, data:, or vbscript: scheme" }
316
- );
317
- var OAuthProtectedResourceMetadataSchema = z3.object({
318
- resource: z3.string().url(),
319
- authorization_servers: z3.array(SafeUrlSchema).optional(),
320
- jwks_uri: z3.string().url().optional(),
321
- scopes_supported: z3.array(z3.string()).optional(),
322
- bearer_methods_supported: z3.array(z3.string()).optional(),
323
- resource_signing_alg_values_supported: z3.array(z3.string()).optional(),
324
- resource_name: z3.string().optional(),
325
- resource_documentation: z3.string().optional(),
326
- resource_policy_uri: z3.string().url().optional(),
327
- resource_tos_uri: z3.string().url().optional(),
328
- tls_client_certificate_bound_access_tokens: z3.boolean().optional(),
329
- authorization_details_types_supported: z3.array(z3.string()).optional(),
330
- dpop_signing_alg_values_supported: z3.array(z3.string()).optional(),
331
- dpop_bound_access_tokens_required: z3.boolean().optional()
332
- }).passthrough();
333
- var OAuthMetadataSchema = z3.object({
334
- issuer: z3.string(),
335
- authorization_endpoint: SafeUrlSchema,
336
- token_endpoint: SafeUrlSchema,
337
- registration_endpoint: SafeUrlSchema.optional(),
338
- scopes_supported: z3.array(z3.string()).optional(),
339
- response_types_supported: z3.array(z3.string()),
340
- grant_types_supported: z3.array(z3.string()).optional(),
341
- code_challenge_methods_supported: z3.array(z3.string()),
342
- token_endpoint_auth_methods_supported: z3.array(z3.string()).optional(),
343
- token_endpoint_auth_signing_alg_values_supported: z3.array(z3.string()).optional()
344
- }).passthrough();
345
- var OpenIdProviderMetadataSchema = z3.object({
346
- issuer: z3.string(),
347
- authorization_endpoint: SafeUrlSchema,
348
- token_endpoint: SafeUrlSchema,
349
- userinfo_endpoint: SafeUrlSchema.optional(),
350
- jwks_uri: SafeUrlSchema,
351
- registration_endpoint: SafeUrlSchema.optional(),
352
- scopes_supported: z3.array(z3.string()).optional(),
353
- response_types_supported: z3.array(z3.string()),
354
- grant_types_supported: z3.array(z3.string()).optional(),
355
- subject_types_supported: z3.array(z3.string()),
356
- id_token_signing_alg_values_supported: z3.array(z3.string()),
357
- claims_supported: z3.array(z3.string()).optional(),
358
- token_endpoint_auth_methods_supported: z3.array(z3.string()).optional()
359
- }).passthrough();
360
- var OpenIdProviderDiscoveryMetadataSchema = OpenIdProviderMetadataSchema.merge(
361
- OAuthMetadataSchema.pick({
362
- code_challenge_methods_supported: true
363
- })
364
- );
365
- var OAuthClientInformationSchema = z3.object({
366
- client_id: z3.string(),
367
- client_secret: z3.string().optional(),
368
- client_id_issued_at: z3.number().optional(),
369
- client_secret_expires_at: z3.number().optional()
370
- }).strip();
371
- var OAuthClientMetadataSchema = z3.object({
372
- redirect_uris: z3.array(SafeUrlSchema),
373
- token_endpoint_auth_method: z3.string().optional(),
374
- grant_types: z3.array(z3.string()).optional(),
375
- response_types: z3.array(z3.string()).optional(),
376
- client_name: z3.string().optional(),
377
- client_uri: SafeUrlSchema.optional(),
378
- logo_uri: SafeUrlSchema.optional(),
379
- scope: z3.string().optional(),
380
- contacts: z3.array(z3.string()).optional(),
381
- tos_uri: SafeUrlSchema.optional(),
382
- policy_uri: z3.string().optional(),
383
- jwks_uri: SafeUrlSchema.optional(),
384
- jwks: z3.any().optional(),
385
- software_id: z3.string().optional(),
386
- software_version: z3.string().optional(),
387
- software_statement: z3.string().optional()
388
- }).strip();
389
- var OAuthErrorResponseSchema = z3.object({
390
- error: z3.string(),
391
- error_description: z3.string().optional(),
392
- error_uri: z3.string().optional()
393
- });
394
- var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(
395
- OAuthClientInformationSchema
396
- );
397
-
398
- // src/error/oauth-error.ts
399
- import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
400
- var name2 = "AI_MCPClientOAuthError";
401
- var marker2 = `vercel.ai.error.${name2}`;
402
- var symbol2 = Symbol.for(marker2);
403
- var _a2, _b2;
404
- var MCPClientOAuthError = class extends (_b2 = AISDKError2, _a2 = symbol2, _b2) {
405
- constructor({
406
- name: name3 = "MCPClientOAuthError",
407
- message,
408
- cause
409
- }) {
410
- super({ name: name3, message, cause });
411
- this[_a2] = true;
412
- }
413
- static isInstance(error) {
414
- return AISDKError2.hasMarker(error, marker2);
415
- }
416
- };
417
- var ServerError = class extends MCPClientOAuthError {
418
- };
419
- ServerError.errorCode = "server_error";
420
- var InvalidClientError = class extends MCPClientOAuthError {
421
- };
422
- InvalidClientError.errorCode = "invalid_client";
423
- var InvalidGrantError = class extends MCPClientOAuthError {
424
- };
425
- InvalidGrantError.errorCode = "invalid_grant";
426
- var UnauthorizedClientError = class extends MCPClientOAuthError {
427
- };
428
- UnauthorizedClientError.errorCode = "unauthorized_client";
429
- var OAUTH_ERRORS = {
430
- [ServerError.errorCode]: ServerError,
431
- [InvalidClientError.errorCode]: InvalidClientError,
432
- [InvalidGrantError.errorCode]: InvalidGrantError,
433
- [UnauthorizedClientError.errorCode]: UnauthorizedClientError
434
- };
435
-
436
- // src/util/oauth-util.ts
437
- function resourceUrlFromServerUrl(url) {
438
- const resourceURL = typeof url === "string" ? new URL(url) : new URL(url.href);
439
- resourceURL.hash = "";
440
- return resourceURL;
441
- }
442
- function resourceUrlStripSlash(resource) {
443
- const href = resource.href;
444
- if (resource.pathname === "/" && href.endsWith("/")) {
445
- return href.slice(0, -1);
446
- }
447
- return href;
448
- }
449
- function checkResourceAllowed({
450
- requestedResource,
451
- configuredResource
452
- }) {
453
- const requested = typeof requestedResource === "string" ? new URL(requestedResource) : new URL(requestedResource.href);
454
- const configured = typeof configuredResource === "string" ? new URL(configuredResource) : new URL(configuredResource.href);
455
- if (requested.origin !== configured.origin) {
456
- return false;
457
- }
458
- if (requested.pathname.length < configured.pathname.length) {
459
- return false;
460
- }
461
- const requestedPath = requested.pathname.endsWith("/") ? requested.pathname : requested.pathname + "/";
462
- const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/";
463
- return requestedPath.startsWith(configuredPath);
464
- }
465
-
466
- // src/tool/oauth.ts
467
- var UnauthorizedError = class extends Error {
468
- constructor(message = "Unauthorized") {
469
- super(message);
470
- this.name = "UnauthorizedError";
471
- }
472
- };
473
- function extractResourceMetadataUrl(response) {
474
- var _a3;
475
- const header = (_a3 = response.headers.get("www-authenticate")) != null ? _a3 : response.headers.get("WWW-Authenticate");
476
- if (!header) {
477
- return void 0;
478
- }
479
- const [type, scheme] = header.split(" ");
480
- if (type.toLowerCase() !== "bearer" || !scheme) {
481
- return void 0;
482
- }
483
- const regex = /resource_metadata="([^"]*)"/;
484
- const match = header.match(regex);
485
- if (!match) {
486
- return void 0;
487
- }
488
- try {
489
- return new URL(match[1]);
490
- } catch (e) {
491
- return void 0;
492
- }
493
- }
494
- function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
495
- if (pathname.endsWith("/")) {
496
- pathname = pathname.slice(0, -1);
497
- }
498
- return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
499
- }
500
- async function fetchWithCorsRetry(url, headers, fetchFn = fetch) {
501
- try {
502
- return await fetchFn(url, { headers });
503
- } catch (error) {
504
- if (error instanceof TypeError) {
505
- if (headers) {
506
- return fetchWithCorsRetry(url, void 0, fetchFn);
507
- } else {
508
- return void 0;
509
- }
510
- }
511
- throw error;
512
- }
513
- }
514
- async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
515
- const headers = {
516
- "MCP-Protocol-Version": protocolVersion
517
- };
518
- return await fetchWithCorsRetry(url, headers, fetchFn);
519
- }
520
- function shouldAttemptFallback(response, pathname) {
521
- return !response || response.status >= 400 && response.status < 500 && pathname !== "/";
522
- }
523
- async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
524
- var _a3, _b3;
525
- const issuer = new URL(serverUrl);
526
- const protocolVersion = (_a3 = opts == null ? void 0 : opts.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION;
527
- let url;
528
- if (opts == null ? void 0 : opts.metadataUrl) {
529
- url = new URL(opts.metadataUrl);
530
- } else {
531
- const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
532
- url = new URL(wellKnownPath, (_b3 = opts == null ? void 0 : opts.metadataServerUrl) != null ? _b3 : issuer);
533
- url.search = issuer.search;
534
- }
535
- let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn);
536
- if (!(opts == null ? void 0 : opts.metadataUrl) && shouldAttemptFallback(response, issuer.pathname)) {
537
- const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
538
- response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
539
- }
540
- return response;
541
- }
542
- async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
543
- const response = await discoverMetadataWithFallback(
544
- serverUrl,
545
- "oauth-protected-resource",
546
- fetchFn,
547
- {
548
- protocolVersion: opts == null ? void 0 : opts.protocolVersion,
549
- metadataUrl: opts == null ? void 0 : opts.resourceMetadataUrl
550
- }
551
- );
552
- if (!response || response.status === 404) {
553
- throw new Error(
554
- `Resource server does not implement OAuth 2.0 Protected Resource Metadata.`
555
- );
556
- }
557
- if (!response.ok) {
558
- throw new Error(
559
- `HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`
560
- );
561
- }
562
- return OAuthProtectedResourceMetadataSchema.parse(await response.json());
563
- }
564
- function buildDiscoveryUrls(authorizationServerUrl) {
565
- const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
566
- const hasPath = url.pathname !== "/";
567
- const urlsToTry = [];
568
- if (!hasPath) {
569
- urlsToTry.push({
570
- url: new URL("/.well-known/oauth-authorization-server", url.origin),
571
- type: "oauth"
572
- });
573
- urlsToTry.push({
574
- url: new URL("/.well-known/openid-configuration", url.origin),
575
- type: "oidc"
576
- });
577
- return urlsToTry;
578
- }
579
- let pathname = url.pathname;
580
- if (pathname.endsWith("/")) {
581
- pathname = pathname.slice(0, -1);
582
- }
583
- urlsToTry.push({
584
- url: new URL(
585
- `/.well-known/oauth-authorization-server${pathname}`,
586
- url.origin
587
- ),
588
- type: "oauth"
589
- });
590
- urlsToTry.push({
591
- url: new URL("/.well-known/oauth-authorization-server", url.origin),
592
- type: "oauth"
593
- });
594
- urlsToTry.push({
595
- url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
596
- type: "oidc"
597
- });
598
- urlsToTry.push({
599
- url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
600
- type: "oidc"
601
- });
602
- return urlsToTry;
603
- }
604
- async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
605
- fetchFn = fetch,
606
- protocolVersion = LATEST_PROTOCOL_VERSION
607
- } = {}) {
608
- var _a3;
609
- const headers = { "MCP-Protocol-Version": protocolVersion };
610
- const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
611
- for (const { url: endpointUrl, type } of urlsToTry) {
612
- const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
613
- if (!response) {
614
- continue;
615
- }
616
- if (!response.ok) {
617
- if (response.status >= 400 && response.status < 500) {
618
- continue;
619
- }
620
- throw new Error(
621
- `HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`
622
- );
623
- }
624
- if (type === "oauth") {
625
- return OAuthMetadataSchema.parse(await response.json());
626
- } else {
627
- const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(
628
- await response.json()
629
- );
630
- if (!((_a3 = metadata.code_challenge_methods_supported) == null ? void 0 : _a3.includes("S256"))) {
631
- throw new Error(
632
- `Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`
633
- );
634
- }
635
- return metadata;
636
- }
637
- }
638
- return void 0;
639
- }
640
- async function startAuthorization(authorizationServerUrl, {
641
- metadata,
642
- clientInformation,
643
- redirectUrl,
644
- scope,
645
- state,
646
- resource
647
- }) {
648
- const responseType = "code";
649
- const codeChallengeMethod = "S256";
650
- let authorizationUrl;
651
- if (metadata) {
652
- authorizationUrl = new URL(metadata.authorization_endpoint);
653
- if (!metadata.response_types_supported.includes(responseType)) {
654
- throw new Error(
655
- `Incompatible auth server: does not support response type ${responseType}`
656
- );
657
- }
658
- if (!metadata.code_challenge_methods_supported || !metadata.code_challenge_methods_supported.includes(codeChallengeMethod)) {
659
- throw new Error(
660
- `Incompatible auth server: does not support code challenge method ${codeChallengeMethod}`
661
- );
662
- }
663
- } else {
664
- authorizationUrl = new URL("/authorize", authorizationServerUrl);
665
- }
666
- const challenge = await pkceChallenge();
667
- const codeVerifier = challenge.code_verifier;
668
- const codeChallenge = challenge.code_challenge;
669
- authorizationUrl.searchParams.set("response_type", responseType);
670
- authorizationUrl.searchParams.set("client_id", clientInformation.client_id);
671
- authorizationUrl.searchParams.set("code_challenge", codeChallenge);
672
- authorizationUrl.searchParams.set(
673
- "code_challenge_method",
674
- codeChallengeMethod
675
- );
676
- authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
677
- if (state) {
678
- authorizationUrl.searchParams.set("state", state);
679
- }
680
- if (scope) {
681
- authorizationUrl.searchParams.set("scope", scope);
682
- }
683
- if (scope == null ? void 0 : scope.includes("offline_access")) {
684
- authorizationUrl.searchParams.append("prompt", "consent");
685
- }
686
- if (resource) {
687
- authorizationUrl.searchParams.set(
688
- "resource",
689
- resourceUrlStripSlash(resource)
690
- );
691
- }
692
- return { authorizationUrl, codeVerifier };
693
- }
694
- function selectClientAuthMethod(clientInformation, supportedMethods) {
695
- const hasClientSecret = clientInformation.client_secret !== void 0;
696
- if (supportedMethods.length === 0) {
697
- return hasClientSecret ? "client_secret_post" : "none";
698
- }
699
- if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
700
- return "client_secret_basic";
701
- }
702
- if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
703
- return "client_secret_post";
704
- }
705
- if (supportedMethods.includes("none")) {
706
- return "none";
707
- }
708
- return hasClientSecret ? "client_secret_post" : "none";
709
- }
710
- function applyClientAuthentication(method, clientInformation, headers, params) {
711
- const { client_id, client_secret } = clientInformation;
712
- switch (method) {
713
- case "client_secret_basic":
714
- applyBasicAuth(client_id, client_secret, headers);
715
- return;
716
- case "client_secret_post":
717
- applyPostAuth(client_id, client_secret, params);
718
- return;
719
- case "none":
720
- applyPublicAuth(client_id, params);
721
- return;
722
- default:
723
- throw new Error(`Unsupported client authentication method: ${method}`);
724
- }
725
- }
726
- function applyBasicAuth(clientId, clientSecret, headers) {
727
- if (!clientSecret) {
728
- throw new Error(
729
- "client_secret_basic authentication requires a client_secret"
730
- );
731
- }
732
- const credentials = btoa(`${clientId}:${clientSecret}`);
733
- headers.set("Authorization", `Basic ${credentials}`);
734
- }
735
- function applyPostAuth(clientId, clientSecret, params) {
736
- params.set("client_id", clientId);
737
- if (clientSecret) {
738
- params.set("client_secret", clientSecret);
739
- }
740
- }
741
- function applyPublicAuth(clientId, params) {
742
- params.set("client_id", clientId);
743
- }
744
- async function parseErrorResponse(input) {
745
- const statusCode = input instanceof Response ? input.status : void 0;
746
- const body = input instanceof Response ? await input.text() : input;
747
- try {
748
- const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
749
- const { error, error_description, error_uri } = result;
750
- const errorClass = OAUTH_ERRORS[error] || ServerError;
751
- return new errorClass({
752
- message: error_description || "",
753
- cause: error_uri
754
- });
755
- } catch (error) {
756
- const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error}. Raw body: ${body}`;
757
- return new ServerError({ message: errorMessage });
758
- }
759
- }
760
- async function exchangeAuthorization(authorizationServerUrl, {
761
- metadata,
762
- clientInformation,
763
- authorizationCode,
764
- codeVerifier,
765
- redirectUri,
766
- resource,
767
- addClientAuthentication,
768
- fetchFn
769
- }) {
770
- var _a3;
771
- const grantType = "authorization_code";
772
- const tokenUrl = (metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
773
- if ((metadata == null ? void 0 : metadata.grant_types_supported) && !metadata.grant_types_supported.includes(grantType)) {
774
- throw new Error(
775
- `Incompatible auth server: does not support grant type ${grantType}`
776
- );
777
- }
778
- const headers = new Headers({
779
- "Content-Type": "application/x-www-form-urlencoded",
780
- Accept: "application/json"
781
- });
782
- const params = new URLSearchParams({
783
- grant_type: grantType,
784
- code: authorizationCode,
785
- code_verifier: codeVerifier,
786
- redirect_uri: String(redirectUri)
787
- });
788
- if (addClientAuthentication) {
789
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
790
- } else {
791
- const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
792
- const authMethod = selectClientAuthMethod(
793
- clientInformation,
794
- supportedMethods
795
- );
796
- applyClientAuthentication(authMethod, clientInformation, headers, params);
797
- }
798
- if (resource) {
799
- params.set("resource", resourceUrlStripSlash(resource));
800
- }
801
- const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
802
- method: "POST",
803
- headers,
804
- body: params
805
- });
806
- if (!response.ok) {
807
- throw await parseErrorResponse(response);
808
- }
809
- return OAuthTokensSchema.parse(await response.json());
810
- }
811
- async function refreshAuthorization(authorizationServerUrl, {
812
- metadata,
813
- clientInformation,
814
- refreshToken,
815
- resource,
816
- addClientAuthentication,
817
- fetchFn
818
- }) {
819
- var _a3;
820
- const grantType = "refresh_token";
821
- let tokenUrl;
822
- if (metadata) {
823
- tokenUrl = new URL(metadata.token_endpoint);
824
- if (metadata.grant_types_supported && !metadata.grant_types_supported.includes(grantType)) {
825
- throw new Error(
826
- `Incompatible auth server: does not support grant type ${grantType}`
827
- );
828
- }
829
- } else {
830
- tokenUrl = new URL("/token", authorizationServerUrl);
831
- }
832
- const headers = new Headers({
833
- "Content-Type": "application/x-www-form-urlencoded",
834
- Accept: "application/json"
835
- });
836
- const params = new URLSearchParams({
837
- grant_type: grantType,
838
- refresh_token: refreshToken
839
- });
840
- if (addClientAuthentication) {
841
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
842
- } else {
843
- const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
844
- const authMethod = selectClientAuthMethod(
845
- clientInformation,
846
- supportedMethods
847
- );
848
- applyClientAuthentication(authMethod, clientInformation, headers, params);
849
- }
850
- if (resource) {
851
- params.set("resource", resourceUrlStripSlash(resource));
852
- }
853
- const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
854
- method: "POST",
855
- headers,
856
- body: params
857
- });
858
- if (!response.ok) {
859
- throw await parseErrorResponse(response);
860
- }
861
- return OAuthTokensSchema.parse({
862
- refresh_token: refreshToken,
863
- ...await response.json()
864
- });
865
- }
866
- async function registerClient(authorizationServerUrl, {
867
- metadata,
868
- clientMetadata,
869
- fetchFn
870
- }) {
871
- let registrationUrl;
872
- if (metadata) {
873
- if (!metadata.registration_endpoint) {
874
- throw new Error(
875
- "Incompatible auth server: does not support dynamic client registration"
876
- );
877
- }
878
- registrationUrl = new URL(metadata.registration_endpoint);
879
- } else {
880
- registrationUrl = new URL("/register", authorizationServerUrl);
881
- }
882
- const response = await (fetchFn != null ? fetchFn : fetch)(registrationUrl, {
883
- method: "POST",
884
- headers: {
885
- "Content-Type": "application/json"
886
- },
887
- body: JSON.stringify(clientMetadata)
888
- });
889
- if (!response.ok) {
890
- throw await parseErrorResponse(response);
891
- }
892
- return OAuthClientInformationFullSchema.parse(await response.json());
893
- }
894
- async function auth(provider, options) {
895
- var _a3, _b3;
896
- try {
897
- return await authInternal(provider, options);
898
- } catch (error) {
899
- if (error instanceof InvalidClientError || error instanceof UnauthorizedClientError) {
900
- await ((_a3 = provider.invalidateCredentials) == null ? void 0 : _a3.call(provider, "all"));
901
- return await authInternal(provider, options);
902
- } else if (error instanceof InvalidGrantError) {
903
- await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "tokens"));
904
- return await authInternal(provider, options);
905
- }
906
- throw error;
907
- }
908
- }
909
- async function selectResourceURL(serverUrl, provider, resourceMetadata) {
910
- const defaultResource = resourceUrlFromServerUrl(serverUrl);
911
- if (provider.validateResourceURL) {
912
- return await provider.validateResourceURL(
913
- defaultResource,
914
- resourceMetadata == null ? void 0 : resourceMetadata.resource
915
- );
916
- }
917
- if (!resourceMetadata) {
918
- return void 0;
919
- }
920
- if (!checkResourceAllowed({
921
- requestedResource: defaultResource,
922
- configuredResource: resourceMetadata.resource
923
- })) {
924
- throw new Error(
925
- `Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`
926
- );
927
- }
928
- return new URL(resourceMetadata.resource);
929
- }
930
- async function authInternal(provider, {
931
- serverUrl,
932
- authorizationCode,
933
- callbackState,
934
- scope,
935
- resourceMetadataUrl,
936
- fetchFn
937
- }) {
938
- let resourceMetadata;
939
- let authorizationServerUrl;
940
- try {
941
- resourceMetadata = await discoverOAuthProtectedResourceMetadata(
942
- serverUrl,
943
- { resourceMetadataUrl },
944
- fetchFn
945
- );
946
- if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
947
- authorizationServerUrl = resourceMetadata.authorization_servers[0];
948
- }
949
- } catch (e) {
950
- }
951
- if (!authorizationServerUrl) {
952
- authorizationServerUrl = serverUrl;
953
- }
954
- const resource = await selectResourceURL(
955
- serverUrl,
956
- provider,
957
- resourceMetadata
958
- );
959
- const metadata = await discoverAuthorizationServerMetadata(
960
- authorizationServerUrl,
961
- {
962
- fetchFn
963
- }
964
- );
965
- let clientInformation = await Promise.resolve(provider.clientInformation());
966
- if (!clientInformation) {
967
- if (authorizationCode !== void 0) {
968
- throw new Error(
969
- "Existing OAuth client information is required when exchanging an authorization code"
970
- );
971
- }
972
- if (!provider.saveClientInformation) {
973
- throw new Error(
974
- "OAuth client information must be saveable for dynamic registration"
975
- );
976
- }
977
- const fullInformation = await registerClient(authorizationServerUrl, {
978
- metadata,
979
- clientMetadata: provider.clientMetadata,
980
- fetchFn
981
- });
982
- await provider.saveClientInformation(fullInformation);
983
- clientInformation = fullInformation;
984
- }
985
- if (authorizationCode !== void 0) {
986
- if (provider.storedState) {
987
- const expectedState = await provider.storedState();
988
- if (expectedState !== void 0 && expectedState !== callbackState) {
989
- throw new Error(
990
- "OAuth state parameter mismatch - possible CSRF attack"
991
- );
992
- }
993
- }
994
- const codeVerifier2 = await provider.codeVerifier();
995
- const tokens2 = await exchangeAuthorization(authorizationServerUrl, {
996
- metadata,
997
- clientInformation,
998
- authorizationCode,
999
- codeVerifier: codeVerifier2,
1000
- redirectUri: provider.redirectUrl,
1001
- resource,
1002
- addClientAuthentication: provider.addClientAuthentication,
1003
- fetchFn
1004
- });
1005
- await provider.saveTokens(tokens2);
1006
- return "AUTHORIZED";
1007
- }
1008
- const tokens = await provider.tokens();
1009
- if (tokens == null ? void 0 : tokens.refresh_token) {
1010
- try {
1011
- const newTokens = await refreshAuthorization(authorizationServerUrl, {
1012
- metadata,
1013
- clientInformation,
1014
- refreshToken: tokens.refresh_token,
1015
- resource,
1016
- addClientAuthentication: provider.addClientAuthentication,
1017
- fetchFn
1018
- });
1019
- await provider.saveTokens(newTokens);
1020
- return "AUTHORIZED";
1021
- } catch (error) {
1022
- if (
1023
- // If this is a ServerError, or an unknown type, log it out and try to continue. Otherwise, escalate so we can fix things and retry.
1024
- !(error instanceof MCPClientOAuthError) || error instanceof ServerError
1025
- ) {
1026
- } else {
1027
- throw error;
1028
- }
1029
- }
1030
- }
1031
- const state = provider.state ? await provider.state() : void 0;
1032
- if (state && provider.saveState) {
1033
- await provider.saveState(state);
1034
- }
1035
- const { authorizationUrl, codeVerifier } = await startAuthorization(
1036
- authorizationServerUrl,
1037
- {
1038
- metadata,
1039
- clientInformation,
1040
- state,
1041
- redirectUrl: provider.redirectUrl,
1042
- scope: scope || provider.clientMetadata.scope,
1043
- resource
1044
- }
1045
- );
1046
- await provider.saveCodeVerifier(codeVerifier);
1047
- await provider.redirectToAuthorization(authorizationUrl);
1048
- return "REDIRECT";
1049
- }
1050
-
1051
- // src/tool/mcp-sse-transport.ts
1052
- var SseMCPTransport = class {
1053
- constructor({
1054
- url,
1055
- headers,
1056
- authProvider,
1057
- redirect = "error",
1058
- fetch: fetchFn
1059
- }) {
1060
- this.connected = false;
1061
- this.url = new URL(url);
1062
- this.headers = headers;
1063
- this.authProvider = authProvider;
1064
- this.redirectMode = redirect;
1065
- this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1066
- }
1067
- async commonHeaders(base) {
1068
- const headers = {
1069
- ...this.headers,
1070
- ...base,
1071
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1072
- };
1073
- if (this.authProvider) {
1074
- const tokens = await this.authProvider.tokens();
1075
- if (tokens == null ? void 0 : tokens.access_token) {
1076
- headers["Authorization"] = `Bearer ${tokens.access_token}`;
1077
- }
1078
- }
1079
- return withUserAgentSuffix(
1080
- headers,
1081
- `ai-sdk/${VERSION}`,
1082
- getRuntimeEnvironmentUserAgent()
1083
- );
1084
- }
1085
- async start() {
1086
- return new Promise((resolve, reject) => {
1087
- if (this.connected) {
1088
- return resolve();
1089
- }
1090
- this.abortController = new AbortController();
1091
- const establishConnection = async (triedAuth = false) => {
1092
- var _a3, _b3, _c, _d, _e;
1093
- try {
1094
- const headers = await this.commonHeaders({
1095
- Accept: "text/event-stream"
1096
- });
1097
- const response = await this.fetchFn(this.url.href, {
1098
- headers,
1099
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1100
- redirect: this.redirectMode
1101
- });
1102
- if (response.status === 401 && this.authProvider && !triedAuth) {
1103
- this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1104
- try {
1105
- const result = await auth(this.authProvider, {
1106
- serverUrl: this.url,
1107
- resourceMetadataUrl: this.resourceMetadataUrl,
1108
- fetchFn: this.fetchFn
1109
- });
1110
- if (result !== "AUTHORIZED") {
1111
- const error = new UnauthorizedError();
1112
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
1113
- return reject(error);
1114
- }
1115
- } catch (error) {
1116
- (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1117
- return reject(error);
1118
- }
1119
- return establishConnection(true);
1120
- }
1121
- if (!response.ok || !response.body) {
1122
- let errorMessage = `MCP SSE Transport Error: ${response.status} ${response.statusText}`;
1123
- if (response.status === 405) {
1124
- errorMessage += ". This server does not support SSE transport. Try using `http` transport instead";
1125
- }
1126
- const error = new MCPClientError({
1127
- message: errorMessage
1128
- });
1129
- (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1130
- return reject(error);
1131
- }
1132
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream());
1133
- const reader = stream.getReader();
1134
- const processEvents = async () => {
1135
- var _a4, _b4, _c2;
1136
- try {
1137
- while (true) {
1138
- const { done, value } = await reader.read();
1139
- if (done) {
1140
- if (this.connected) {
1141
- this.connected = false;
1142
- throw new MCPClientError({
1143
- message: "MCP SSE Transport Error: Connection closed unexpectedly"
1144
- });
1145
- }
1146
- return;
1147
- }
1148
- const { event, data } = value;
1149
- if (event === "endpoint") {
1150
- this.endpoint = new URL(data, this.url);
1151
- if (this.endpoint.origin !== this.url.origin) {
1152
- throw new MCPClientError({
1153
- message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${this.endpoint.origin}`
1154
- });
1155
- }
1156
- this.connected = true;
1157
- resolve();
1158
- } else if (event === "message") {
1159
- try {
1160
- const message = JSONRPCMessageSchema.parse(
1161
- JSON.parse(data)
1162
- );
1163
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, message);
1164
- } catch (error) {
1165
- const e = new MCPClientError({
1166
- message: "MCP SSE Transport Error: Failed to parse message",
1167
- cause: error
1168
- });
1169
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1170
- }
1171
- }
1172
- }
1173
- } catch (error) {
1174
- if (error instanceof Error && error.name === "AbortError") {
1175
- return;
1176
- }
1177
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1178
- reject(error);
1179
- }
1180
- };
1181
- this.sseConnection = {
1182
- close: () => reader.cancel()
1183
- };
1184
- processEvents();
1185
- } catch (error) {
1186
- if (error instanceof Error && error.name === "AbortError") {
1187
- return;
1188
- }
1189
- (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1190
- reject(error);
1191
- }
1192
- };
1193
- void establishConnection();
1194
- });
1195
- }
1196
- async close() {
1197
- var _a3, _b3, _c;
1198
- this.connected = false;
1199
- (_a3 = this.sseConnection) == null ? void 0 : _a3.close();
1200
- (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1201
- (_c = this.onclose) == null ? void 0 : _c.call(this);
1202
- }
1203
- async send(message) {
1204
- if (!this.endpoint || !this.connected) {
1205
- throw new MCPClientError({
1206
- message: "MCP SSE Transport Error: Not connected"
1207
- });
1208
- }
1209
- const endpoint = this.endpoint;
1210
- const attempt = async (triedAuth = false) => {
1211
- var _a3, _b3, _c, _d, _e;
1212
- try {
1213
- const headers = await this.commonHeaders({
1214
- "Content-Type": "application/json"
1215
- });
1216
- const init = {
1217
- method: "POST",
1218
- headers,
1219
- body: JSON.stringify(message),
1220
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1221
- redirect: this.redirectMode
1222
- };
1223
- const response = await this.fetchFn(endpoint.href, init);
1224
- if (response.status === 401 && this.authProvider && !triedAuth) {
1225
- this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1226
- try {
1227
- const result = await auth(this.authProvider, {
1228
- serverUrl: this.url,
1229
- resourceMetadataUrl: this.resourceMetadataUrl,
1230
- fetchFn: this.fetchFn
1231
- });
1232
- if (result !== "AUTHORIZED") {
1233
- const error = new UnauthorizedError();
1234
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
1235
- return;
1236
- }
1237
- } catch (error) {
1238
- (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1239
- return;
1240
- }
1241
- return attempt(true);
1242
- }
1243
- if (!response.ok) {
1244
- const text = await response.text().catch(() => null);
1245
- const error = new MCPClientError({
1246
- message: `MCP SSE Transport Error: POSTing to endpoint (HTTP ${response.status}): ${text}`
1247
- });
1248
- (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1249
- return;
1250
- }
1251
- } catch (error) {
1252
- (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1253
- return;
1254
- }
1255
- };
1256
- await attempt();
1257
- }
1258
- };
1259
-
1260
- // src/tool/mcp-http-transport.ts
1261
- import {
1262
- EventSourceParserStream as EventSourceParserStream2,
1263
- withUserAgentSuffix as withUserAgentSuffix2,
1264
- getRuntimeEnvironmentUserAgent as getRuntimeEnvironmentUserAgent2
1265
- } from "@ai-sdk/provider-utils";
1266
- var HttpMCPTransport = class {
1267
- constructor({
1268
- url,
1269
- headers,
1270
- authProvider,
1271
- redirect = "error",
1272
- fetch: fetchFn
1273
- }) {
1274
- this.inboundReconnectAttempts = 0;
1275
- this.reconnectionOptions = {
1276
- initialReconnectionDelay: 1e3,
1277
- maxReconnectionDelay: 3e4,
1278
- reconnectionDelayGrowFactor: 1.5,
1279
- maxRetries: 2
1280
- };
1281
- this.url = new URL(url);
1282
- this.headers = headers;
1283
- this.authProvider = authProvider;
1284
- this.redirectMode = redirect;
1285
- this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1286
- }
1287
- async commonHeaders(base) {
1288
- const headers = {
1289
- ...this.headers,
1290
- ...base,
1291
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1292
- };
1293
- if (this.sessionId) {
1294
- headers["mcp-session-id"] = this.sessionId;
1295
- }
1296
- if (this.authProvider) {
1297
- const tokens = await this.authProvider.tokens();
1298
- if (tokens == null ? void 0 : tokens.access_token) {
1299
- headers["Authorization"] = `Bearer ${tokens.access_token}`;
1300
- }
1301
- }
1302
- return withUserAgentSuffix2(
1303
- headers,
1304
- `ai-sdk/${VERSION}`,
1305
- getRuntimeEnvironmentUserAgent2()
1306
- );
1307
- }
1308
- async start() {
1309
- if (this.abortController) {
1310
- throw new MCPClientError({
1311
- message: "MCP HTTP Transport Error: Transport already started. Note: client.connect() calls start() automatically."
1312
- });
1313
- }
1314
- this.abortController = new AbortController();
1315
- void this.openInboundSse();
1316
- }
1317
- async close() {
1318
- var _a3, _b3, _c;
1319
- (_a3 = this.inboundSseConnection) == null ? void 0 : _a3.close();
1320
- try {
1321
- if (this.sessionId && this.abortController && !this.abortController.signal.aborted) {
1322
- const headers = await this.commonHeaders({});
1323
- await this.fetchFn(this.url.href, {
1324
- method: "DELETE",
1325
- headers,
1326
- signal: this.abortController.signal,
1327
- redirect: this.redirectMode
1328
- }).catch(() => void 0);
1329
- }
1330
- } catch (e) {
1331
- }
1332
- (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1333
- (_c = this.onclose) == null ? void 0 : _c.call(this);
1334
- }
1335
- async send(message) {
1336
- const attempt = async (triedAuth = false) => {
1337
- var _a3, _b3, _c, _d, _e, _f, _g;
1338
- try {
1339
- const headers = await this.commonHeaders({
1340
- "Content-Type": "application/json",
1341
- Accept: "application/json, text/event-stream"
1342
- });
1343
- const init = {
1344
- method: "POST",
1345
- headers,
1346
- body: JSON.stringify(message),
1347
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1348
- redirect: this.redirectMode
1349
- };
1350
- const response = await this.fetchFn(this.url.href, init);
1351
- const sessionId = response.headers.get("mcp-session-id");
1352
- if (sessionId) {
1353
- this.sessionId = sessionId;
1354
- }
1355
- if (response.status === 401 && this.authProvider && !triedAuth) {
1356
- this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1357
- try {
1358
- const result = await auth(this.authProvider, {
1359
- serverUrl: this.url,
1360
- resourceMetadataUrl: this.resourceMetadataUrl,
1361
- fetchFn: this.fetchFn
1362
- });
1363
- if (result !== "AUTHORIZED") {
1364
- const error2 = new UnauthorizedError();
1365
- throw error2;
1366
- }
1367
- } catch (error2) {
1368
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error2);
1369
- throw error2;
1370
- }
1371
- return attempt(true);
1372
- }
1373
- if (response.status === 202) {
1374
- if (!this.inboundSseConnection) {
1375
- void this.openInboundSse();
1376
- }
1377
- return;
1378
- }
1379
- if (!response.ok) {
1380
- const text = await response.text().catch(() => null);
1381
- let errorMessage = `MCP HTTP Transport Error: POSTing to endpoint (HTTP ${response.status}): ${text}`;
1382
- if (response.status === 404) {
1383
- errorMessage += ". This server does not support HTTP transport. Try using `sse` transport instead";
1384
- }
1385
- const error2 = new MCPClientError({
1386
- message: errorMessage
1387
- });
1388
- (_c = this.onerror) == null ? void 0 : _c.call(this, error2);
1389
- throw error2;
1390
- }
1391
- const isNotification = !("id" in message);
1392
- if (isNotification) {
1393
- return;
1394
- }
1395
- const contentType = response.headers.get("content-type") || "";
1396
- if (contentType.includes("application/json")) {
1397
- const data = await response.json();
1398
- const messages = Array.isArray(data) ? data.map((m) => JSONRPCMessageSchema.parse(m)) : [JSONRPCMessageSchema.parse(data)];
1399
- for (const m of messages) (_d = this.onmessage) == null ? void 0 : _d.call(this, m);
1400
- return;
1401
- }
1402
- if (contentType.includes("text/event-stream")) {
1403
- if (!response.body) {
1404
- const error2 = new MCPClientError({
1405
- message: "MCP HTTP Transport Error: text/event-stream response without body"
1406
- });
1407
- (_e = this.onerror) == null ? void 0 : _e.call(this, error2);
1408
- throw error2;
1409
- }
1410
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1411
- const reader = stream.getReader();
1412
- const processEvents = async () => {
1413
- var _a4, _b4, _c2;
1414
- try {
1415
- while (true) {
1416
- const { done, value } = await reader.read();
1417
- if (done) return;
1418
- const { event, data } = value;
1419
- if (event === "message") {
1420
- try {
1421
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1422
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
1423
- } catch (error2) {
1424
- const e = new MCPClientError({
1425
- message: "MCP HTTP Transport Error: Failed to parse message",
1426
- cause: error2
1427
- });
1428
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1429
- }
1430
- }
1431
- }
1432
- } catch (error2) {
1433
- if (error2 instanceof Error && error2.name === "AbortError") {
1434
- return;
1435
- }
1436
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error2);
1437
- }
1438
- };
1439
- processEvents();
1440
- return;
1441
- }
1442
- const error = new MCPClientError({
1443
- message: `MCP HTTP Transport Error: Unexpected content type: ${contentType}`
1444
- });
1445
- (_f = this.onerror) == null ? void 0 : _f.call(this, error);
1446
- throw error;
1447
- } catch (error) {
1448
- (_g = this.onerror) == null ? void 0 : _g.call(this, error);
1449
- throw error;
1450
- }
1451
- };
1452
- await attempt();
1453
- }
1454
- getNextReconnectionDelay(attempt) {
1455
- const {
1456
- initialReconnectionDelay,
1457
- reconnectionDelayGrowFactor,
1458
- maxReconnectionDelay
1459
- } = this.reconnectionOptions;
1460
- return Math.min(
1461
- initialReconnectionDelay * Math.pow(reconnectionDelayGrowFactor, attempt),
1462
- maxReconnectionDelay
1463
- );
1464
- }
1465
- scheduleInboundSseReconnection() {
1466
- var _a3;
1467
- const { maxRetries } = this.reconnectionOptions;
1468
- if (maxRetries > 0 && this.inboundReconnectAttempts >= maxRetries) {
1469
- (_a3 = this.onerror) == null ? void 0 : _a3.call(
1470
- this,
1471
- new MCPClientError({
1472
- message: `MCP HTTP Transport Error: Maximum reconnection attempts (${maxRetries}) exceeded.`
1473
- })
1474
- );
1475
- return;
1476
- }
1477
- const delay = this.getNextReconnectionDelay(this.inboundReconnectAttempts);
1478
- this.inboundReconnectAttempts += 1;
1479
- setTimeout(async () => {
1480
- var _a4;
1481
- if ((_a4 = this.abortController) == null ? void 0 : _a4.signal.aborted) return;
1482
- await this.openInboundSse(false, this.lastInboundEventId);
1483
- }, delay);
1484
- }
1485
- // Open optional inbound SSE stream; best-effort and resumable
1486
- async openInboundSse(triedAuth = false, resumeToken) {
1487
- var _a3, _b3, _c, _d, _e, _f;
1488
- try {
1489
- const headers = await this.commonHeaders({
1490
- Accept: "text/event-stream"
1491
- });
1492
- if (resumeToken) {
1493
- headers["last-event-id"] = resumeToken;
1494
- }
1495
- const response = await this.fetchFn(this.url.href, {
1496
- method: "GET",
1497
- headers,
1498
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1499
- redirect: this.redirectMode
1500
- });
1501
- const sessionId = response.headers.get("mcp-session-id");
1502
- if (sessionId) {
1503
- this.sessionId = sessionId;
1504
- }
1505
- if (response.status === 401 && this.authProvider && !triedAuth) {
1506
- this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1507
- try {
1508
- const result = await auth(this.authProvider, {
1509
- serverUrl: this.url,
1510
- resourceMetadataUrl: this.resourceMetadataUrl,
1511
- fetchFn: this.fetchFn
1512
- });
1513
- if (result !== "AUTHORIZED") {
1514
- const error = new UnauthorizedError();
1515
- (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
1516
- return;
1517
- }
1518
- } catch (error) {
1519
- (_c = this.onerror) == null ? void 0 : _c.call(this, error);
1520
- return;
1521
- }
1522
- return this.openInboundSse(true, resumeToken);
1523
- }
1524
- if (response.status === 405) {
1525
- return;
1526
- }
1527
- if (!response.ok || !response.body) {
1528
- const error = new MCPClientError({
1529
- message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}`
1530
- });
1531
- (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1532
- return;
1533
- }
1534
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1535
- const reader = stream.getReader();
1536
- const processEvents = async () => {
1537
- var _a4, _b4, _c2, _d2;
1538
- try {
1539
- while (true) {
1540
- const { done, value } = await reader.read();
1541
- if (done) return;
1542
- const { event, data, id } = value;
1543
- if (id) {
1544
- this.lastInboundEventId = id;
1545
- }
1546
- if (event === "message") {
1547
- try {
1548
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1549
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
1550
- } catch (error) {
1551
- const e = new MCPClientError({
1552
- message: "MCP HTTP Transport Error: Failed to parse message",
1553
- cause: error
1554
- });
1555
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1556
- }
1557
- }
1558
- }
1559
- } catch (error) {
1560
- if (error instanceof Error && error.name === "AbortError") {
1561
- return;
1562
- }
1563
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1564
- if (!((_d2 = this.abortController) == null ? void 0 : _d2.signal.aborted)) {
1565
- this.scheduleInboundSseReconnection();
1566
- }
1567
- }
1568
- };
1569
- this.inboundSseConnection = {
1570
- close: () => reader.cancel()
1571
- };
1572
- this.inboundReconnectAttempts = 0;
1573
- processEvents();
1574
- } catch (error) {
1575
- if (error instanceof Error && error.name === "AbortError") {
1576
- return;
1577
- }
1578
- (_e = this.onerror) == null ? void 0 : _e.call(this, error);
1579
- if (!((_f = this.abortController) == null ? void 0 : _f.signal.aborted)) {
1580
- this.scheduleInboundSseReconnection();
1581
- }
1582
- }
1583
- }
1584
- };
1585
-
1586
- // src/tool/mcp-transport.ts
1587
- function createMcpTransport(config) {
1588
- switch (config.type) {
1589
- case "sse":
1590
- return new SseMCPTransport(config);
1591
- case "http":
1592
- return new HttpMCPTransport(config);
1593
- default:
1594
- throw new MCPClientError({
1595
- message: "Unsupported or invalid transport configuration. If you are using a custom transport, make sure it implements the MCPTransport interface."
1596
- });
1597
- }
1598
- }
1599
- function isCustomMcpTransport(transport) {
1600
- return "start" in transport && typeof transport.start === "function" && "send" in transport && typeof transport.send === "function" && "close" in transport && typeof transport.close === "function";
1601
- }
1602
-
1603
- // src/tool/mcp-client.ts
1604
- var CLIENT_VERSION = "1.0.0";
1605
- function mcpToModelOutput({
1606
- output
1607
- }) {
1608
- const result = output;
1609
- if (!("content" in result) || !Array.isArray(result.content)) {
1610
- return { type: "json", value: result };
1611
- }
1612
- const convertedContent = result.content.map(
1613
- (part) => {
1614
- if (part.type === "text" && "text" in part) {
1615
- return { type: "text", text: part.text };
1616
- }
1617
- if (part.type === "image" && "data" in part && "mimeType" in part) {
1618
- return {
1619
- type: "image-data",
1620
- data: part.data,
1621
- mediaType: part.mimeType
1622
- };
1623
- }
1624
- return { type: "text", text: JSON.stringify(part) };
1625
- }
1626
- );
1627
- return { type: "content", value: convertedContent };
1628
- }
1629
- async function createMCPClient(config) {
1630
- const client = new DefaultMCPClient(config);
1631
- await client.init();
1632
- return client;
1633
- }
1634
- var DefaultMCPClient = class {
1635
- constructor({
1636
- transport: transportConfig,
1637
- name: name3 = "ai-sdk-mcp-client",
1638
- version = CLIENT_VERSION,
1639
- onUncaughtError,
1640
- capabilities
1641
- }) {
1642
- this.requestMessageId = 0;
1643
- this.responseHandlers = /* @__PURE__ */ new Map();
1644
- this.serverCapabilities = {};
1645
- this._serverInfo = { name: "", version: "" };
1646
- this.isClosed = true;
1647
- this.onUncaughtError = onUncaughtError;
1648
- this.clientCapabilities = capabilities != null ? capabilities : {};
1649
- if (isCustomMcpTransport(transportConfig)) {
1650
- this.transport = transportConfig;
1651
- } else {
1652
- this.transport = createMcpTransport(transportConfig);
1653
- }
1654
- this.transport.onclose = () => this.onClose();
1655
- this.transport.onerror = (error) => this.onError(error);
1656
- this.transport.onmessage = (message) => {
1657
- if ("method" in message) {
1658
- if ("id" in message) {
1659
- this.onRequestMessage(message);
1660
- } else {
1661
- this.onError(
1662
- new MCPClientError({
1663
- message: "Unsupported message type"
1664
- })
1665
- );
1666
- }
1667
- return;
1668
- }
1669
- this.onResponse(message);
1670
- };
1671
- this.clientInfo = {
1672
- name: name3,
1673
- version
1674
- };
1675
- }
1676
- get serverInfo() {
1677
- return this._serverInfo;
1678
- }
1679
- async init() {
1680
- try {
1681
- await this.transport.start();
1682
- this.isClosed = false;
1683
- const result = await this.request({
1684
- request: {
1685
- method: "initialize",
1686
- params: {
1687
- protocolVersion: LATEST_PROTOCOL_VERSION,
1688
- capabilities: this.clientCapabilities,
1689
- clientInfo: this.clientInfo
1690
- }
1691
- },
1692
- resultSchema: InitializeResultSchema
1693
- });
1694
- if (result === void 0) {
1695
- throw new MCPClientError({
1696
- message: "Server sent invalid initialize result"
1697
- });
1698
- }
1699
- if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
1700
- throw new MCPClientError({
1701
- message: `Server's protocol version is not supported: ${result.protocolVersion}`
1702
- });
1703
- }
1704
- this.serverCapabilities = result.capabilities;
1705
- this._serverInfo = result.serverInfo;
1706
- await this.notification({
1707
- method: "notifications/initialized"
1708
- });
1709
- return this;
1710
- } catch (error) {
1711
- await this.close();
1712
- throw error;
1713
- }
1714
- }
1715
- async close() {
1716
- var _a3;
1717
- if (this.isClosed) return;
1718
- await ((_a3 = this.transport) == null ? void 0 : _a3.close());
1719
- this.onClose();
1720
- }
1721
- assertCapability(method) {
1722
- switch (method) {
1723
- case "initialize":
1724
- break;
1725
- case "tools/list":
1726
- case "tools/call":
1727
- if (!this.serverCapabilities.tools) {
1728
- throw new MCPClientError({
1729
- message: `Server does not support tools`
1730
- });
1731
- }
1732
- break;
1733
- case "resources/list":
1734
- case "resources/read":
1735
- case "resources/templates/list":
1736
- if (!this.serverCapabilities.resources) {
1737
- throw new MCPClientError({
1738
- message: `Server does not support resources`
1739
- });
1740
- }
1741
- break;
1742
- case "prompts/list":
1743
- case "prompts/get":
1744
- if (!this.serverCapabilities.prompts) {
1745
- throw new MCPClientError({
1746
- message: `Server does not support prompts`
1747
- });
1748
- }
1749
- break;
1750
- default:
1751
- throw new MCPClientError({
1752
- message: `Unsupported method: ${method}`
1753
- });
1754
- }
1755
- }
1756
- async request({
1757
- request,
1758
- resultSchema,
1759
- options
1760
- }) {
1761
- return new Promise((resolve, reject) => {
1762
- if (this.isClosed) {
1763
- return reject(
1764
- new MCPClientError({
1765
- message: "Attempted to send a request from a closed client"
1766
- })
1767
- );
1768
- }
1769
- this.assertCapability(request.method);
1770
- const signal = options == null ? void 0 : options.signal;
1771
- signal == null ? void 0 : signal.throwIfAborted();
1772
- const messageId = this.requestMessageId++;
1773
- const jsonrpcRequest = {
1774
- ...request,
1775
- jsonrpc: "2.0",
1776
- id: messageId
1777
- };
1778
- const cleanup = () => {
1779
- this.responseHandlers.delete(messageId);
1780
- };
1781
- this.responseHandlers.set(messageId, (response) => {
1782
- if (signal == null ? void 0 : signal.aborted) {
1783
- return reject(
1784
- new MCPClientError({
1785
- message: "Request was aborted",
1786
- cause: signal.reason
1787
- })
1788
- );
1789
- }
1790
- if (response instanceof Error) {
1791
- return reject(response);
1792
- }
1793
- try {
1794
- const result = resultSchema.parse(response.result);
1795
- resolve(result);
1796
- } catch (error) {
1797
- const parseError = new MCPClientError({
1798
- message: "Failed to parse server response",
1799
- cause: error
1800
- });
1801
- reject(parseError);
1802
- }
1803
- });
1804
- this.transport.send(jsonrpcRequest).catch((error) => {
1805
- cleanup();
1806
- reject(error);
1807
- });
1808
- });
1809
- }
1810
- async listTools({
1811
- params,
1812
- options
1813
- } = {}) {
1814
- return this.request({
1815
- request: { method: "tools/list", params },
1816
- resultSchema: ListToolsResultSchema,
1817
- options
1818
- });
1819
- }
1820
- async callTool({
1821
- name: name3,
1822
- args,
1823
- options
1824
- }) {
1825
- try {
1826
- return this.request({
1827
- request: { method: "tools/call", params: { name: name3, arguments: args } },
1828
- resultSchema: CallToolResultSchema,
1829
- options: {
1830
- signal: options == null ? void 0 : options.abortSignal
1831
- }
1832
- });
1833
- } catch (error) {
1834
- throw error;
1835
- }
1836
- }
1837
- async listResourcesInternal({
1838
- params,
1839
- options
1840
- } = {}) {
1841
- try {
1842
- return this.request({
1843
- request: { method: "resources/list", params },
1844
- resultSchema: ListResourcesResultSchema,
1845
- options
1846
- });
1847
- } catch (error) {
1848
- throw error;
1849
- }
1850
- }
1851
- async readResourceInternal({
1852
- uri,
1853
- options
1854
- }) {
1855
- try {
1856
- return this.request({
1857
- request: { method: "resources/read", params: { uri } },
1858
- resultSchema: ReadResourceResultSchema,
1859
- options
1860
- });
1861
- } catch (error) {
1862
- throw error;
1863
- }
1864
- }
1865
- async listResourceTemplatesInternal({
1866
- options
1867
- } = {}) {
1868
- try {
1869
- return this.request({
1870
- request: { method: "resources/templates/list" },
1871
- resultSchema: ListResourceTemplatesResultSchema,
1872
- options
1873
- });
1874
- } catch (error) {
1875
- throw error;
1876
- }
1877
- }
1878
- async listPromptsInternal({
1879
- params,
1880
- options
1881
- } = {}) {
1882
- try {
1883
- return this.request({
1884
- request: { method: "prompts/list", params },
1885
- resultSchema: ListPromptsResultSchema,
1886
- options
1887
- });
1888
- } catch (error) {
1889
- throw error;
1890
- }
1891
- }
1892
- async getPromptInternal({
1893
- name: name3,
1894
- args,
1895
- options
1896
- }) {
1897
- try {
1898
- return this.request({
1899
- request: { method: "prompts/get", params: { name: name3, arguments: args } },
1900
- resultSchema: GetPromptResultSchema,
1901
- options
1902
- });
1903
- } catch (error) {
1904
- throw error;
1905
- }
1906
- }
1907
- async notification(notification) {
1908
- const jsonrpcNotification = {
1909
- ...notification,
1910
- jsonrpc: "2.0"
1911
- };
1912
- await this.transport.send(jsonrpcNotification);
1913
- }
1914
- /**
1915
- * Returns a set of AI SDK tools from the MCP server.
1916
- * This fetches tool definitions and wraps them with execute functions.
1917
- * @returns A record of tool names to their implementations
1918
- */
1919
- async tools({
1920
- schemas = "automatic"
1921
- } = {}) {
1922
- const definitions = await this.listTools();
1923
- return this.toolsFromDefinitions(definitions, {
1924
- schemas
1925
- });
1926
- }
1927
- /**
1928
- * Creates AI SDK tools from tool definitions without fetching from the server.
1929
- */
1930
- toolsFromDefinitions(definitions, { schemas = "automatic" } = {}) {
1931
- var _a3, _b3;
1932
- const tools = {};
1933
- for (const {
1934
- name: name3,
1935
- title,
1936
- description,
1937
- inputSchema,
1938
- annotations,
1939
- _meta
1940
- } of definitions.tools) {
1941
- const resolvedTitle = title != null ? title : annotations == null ? void 0 : annotations.title;
1942
- if (schemas !== "automatic" && !(name3 in schemas)) {
1943
- continue;
1944
- }
1945
- const self = this;
1946
- const outputSchema = schemas !== "automatic" ? (_a3 = schemas[name3]) == null ? void 0 : _a3.outputSchema : void 0;
1947
- const execute = async (args, options) => {
1948
- var _a4;
1949
- (_a4 = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a4.throwIfAborted();
1950
- const result = await self.callTool({ name: name3, args, options });
1951
- if (result.isError) {
1952
- return result;
1953
- }
1954
- if (outputSchema != null) {
1955
- return self.extractStructuredContent(result, outputSchema, name3);
1956
- }
1957
- return result;
1958
- };
1959
- const toolWithExecute = schemas === "automatic" ? dynamicTool({
1960
- description,
1961
- title: resolvedTitle,
1962
- inputSchema: jsonSchema({
1963
- ...inputSchema,
1964
- properties: (_b3 = inputSchema.properties) != null ? _b3 : {},
1965
- additionalProperties: false
1966
- }),
1967
- execute,
1968
- toModelOutput: mcpToModelOutput
1969
- }) : tool({
1970
- description,
1971
- title: resolvedTitle,
1972
- inputSchema: schemas[name3].inputSchema,
1973
- ...outputSchema != null ? { outputSchema } : {},
1974
- execute,
1975
- toModelOutput: mcpToModelOutput
1976
- });
1977
- tools[name3] = { ...toolWithExecute, _meta };
1978
- }
1979
- return tools;
1980
- }
1981
- /**
1982
- * Extracts and validates structuredContent from a tool result.
1983
- */
1984
- async extractStructuredContent(result, outputSchema, toolName) {
1985
- if ("structuredContent" in result && result.structuredContent != null) {
1986
- const validationResult = await safeValidateTypes({
1987
- value: result.structuredContent,
1988
- schema: asSchema(outputSchema)
1989
- });
1990
- if (!validationResult.success) {
1991
- throw new MCPClientError({
1992
- message: `Tool "${toolName}" returned structuredContent that does not match the expected outputSchema`,
1993
- cause: validationResult.error
1994
- });
1995
- }
1996
- return validationResult.value;
1997
- }
1998
- if ("content" in result && Array.isArray(result.content)) {
1999
- const textContent = result.content.find((c) => c.type === "text");
2000
- if (textContent && "text" in textContent) {
2001
- const parseResult = await safeParseJSON({
2002
- text: textContent.text,
2003
- schema: outputSchema
2004
- });
2005
- if (!parseResult.success) {
2006
- throw new MCPClientError({
2007
- message: `Tool "${toolName}" returned content that does not match the expected outputSchema`,
2008
- cause: parseResult.error
2009
- });
2010
- }
2011
- return parseResult.value;
2012
- }
2013
- }
2014
- throw new MCPClientError({
2015
- message: `Tool "${toolName}" did not return structuredContent or parseable text content`
2016
- });
2017
- }
2018
- listResources({
2019
- params,
2020
- options
2021
- } = {}) {
2022
- return this.listResourcesInternal({ params, options });
2023
- }
2024
- readResource({
2025
- uri,
2026
- options
2027
- }) {
2028
- return this.readResourceInternal({ uri, options });
2029
- }
2030
- listResourceTemplates({
2031
- options
2032
- } = {}) {
2033
- return this.listResourceTemplatesInternal({ options });
2034
- }
2035
- experimental_listPrompts({
2036
- params,
2037
- options
2038
- } = {}) {
2039
- return this.listPromptsInternal({ params, options });
2040
- }
2041
- experimental_getPrompt({
2042
- name: name3,
2043
- arguments: args,
2044
- options
2045
- }) {
2046
- return this.getPromptInternal({ name: name3, args, options });
2047
- }
2048
- onElicitationRequest(schema, handler) {
2049
- if (schema !== ElicitationRequestSchema) {
2050
- throw new MCPClientError({
2051
- message: "Unsupported request schema. Only ElicitationRequestSchema is supported."
2052
- });
2053
- }
2054
- this.elicitationRequestHandler = handler;
2055
- }
2056
- async onRequestMessage(request) {
2057
- try {
2058
- if (request.method !== "elicitation/create") {
2059
- await this.transport.send({
2060
- jsonrpc: "2.0",
2061
- id: request.id,
2062
- error: {
2063
- code: -32601,
2064
- message: `Unsupported request method: ${request.method}`
2065
- }
2066
- });
2067
- return;
2068
- }
2069
- if (!this.elicitationRequestHandler) {
2070
- await this.transport.send({
2071
- jsonrpc: "2.0",
2072
- id: request.id,
2073
- error: {
2074
- code: -32601,
2075
- message: "No elicitation handler registered on client"
2076
- }
2077
- });
2078
- return;
2079
- }
2080
- const parsedRequest = ElicitationRequestSchema.safeParse({
2081
- method: request.method,
2082
- params: request.params
2083
- });
2084
- if (!parsedRequest.success) {
2085
- await this.transport.send({
2086
- jsonrpc: "2.0",
2087
- id: request.id,
2088
- error: {
2089
- code: -32602,
2090
- message: `Invalid elicitation request: ${parsedRequest.error.message}`,
2091
- data: parsedRequest.error.issues
2092
- }
2093
- });
2094
- return;
2095
- }
2096
- try {
2097
- const result = await this.elicitationRequestHandler(parsedRequest.data);
2098
- const validatedResult = ElicitResultSchema.parse(result);
2099
- await this.transport.send({
2100
- jsonrpc: "2.0",
2101
- id: request.id,
2102
- result: validatedResult
2103
- });
2104
- } catch (error) {
2105
- await this.transport.send({
2106
- jsonrpc: "2.0",
2107
- id: request.id,
2108
- error: {
2109
- code: -32603,
2110
- message: error instanceof Error ? error.message : "Failed to handle elicitation request"
2111
- }
2112
- });
2113
- this.onError(error);
2114
- }
2115
- } catch (error) {
2116
- this.onError(error);
2117
- }
2118
- }
2119
- onClose() {
2120
- if (this.isClosed) return;
2121
- this.isClosed = true;
2122
- const error = new MCPClientError({
2123
- message: "Connection closed"
2124
- });
2125
- for (const handler of this.responseHandlers.values()) {
2126
- handler(error);
2127
- }
2128
- this.responseHandlers.clear();
2129
- }
2130
- onError(error) {
2131
- if (this.onUncaughtError) {
2132
- this.onUncaughtError(error);
2133
- }
2134
- }
2135
- onResponse(response) {
2136
- const messageId = Number(response.id);
2137
- const handler = this.responseHandlers.get(messageId);
2138
- if (handler === void 0) {
2139
- throw new MCPClientError({
2140
- message: `Protocol error: Received a response for an unknown message ID: ${JSON.stringify(
2141
- response
2142
- )}`
2143
- });
2144
- }
2145
- this.responseHandlers.delete(messageId);
2146
- handler(
2147
- "result" in response ? response : new MCPClientError({
2148
- message: response.error.message,
2149
- code: response.error.code,
2150
- data: response.error.data,
2151
- cause: response.error
2152
- })
2153
- );
2154
- }
2155
- };
2156
- export {
2157
- ElicitResultSchema,
2158
- ElicitationRequestSchema,
2159
- UnauthorizedError,
2160
- auth,
2161
- createMCPClient,
2162
- createMCPClient as experimental_createMCPClient
2163
- };
2164
- //# sourceMappingURL=index.mjs.map