@ai-sdk/mcp 0.0.1

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