@ai-sdk/mcp 2.0.0-beta.5 → 2.0.0-beta.66

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.js CHANGED
@@ -1,79 +1,56 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name3 in all)
10
- __defProp(target, name3, { get: all[name3], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- ElicitResultSchema: () => ElicitResultSchema,
34
- ElicitationRequestSchema: () => ElicitationRequestSchema,
35
- UnauthorizedError: () => UnauthorizedError,
36
- auth: () => auth,
37
- createMCPClient: () => createMCPClient,
38
- experimental_createMCPClient: () => createMCPClient
39
- });
40
- module.exports = __toCommonJS(index_exports);
41
-
42
1
  // src/tool/mcp-client.ts
43
- var import_provider_utils3 = require("@ai-sdk/provider-utils");
2
+ import {
3
+ asSchema,
4
+ dynamicTool,
5
+ jsonSchema,
6
+ safeParseJSON,
7
+ safeValidateTypes,
8
+ tool
9
+ } from "@ai-sdk/provider-utils";
44
10
 
45
11
  // src/error/mcp-client-error.ts
46
- var import_provider = require("@ai-sdk/provider");
12
+ import { AISDKError } from "@ai-sdk/provider";
47
13
  var name = "AI_MCPClientError";
48
14
  var marker = `vercel.ai.error.${name}`;
49
15
  var symbol = Symbol.for(marker);
50
16
  var _a, _b;
51
- var MCPClientError = class extends (_b = import_provider.AISDKError, _a = symbol, _b) {
17
+ var MCPClientError = class extends (_b = AISDKError, _a = symbol, _b) {
52
18
  constructor({
53
19
  name: name3 = "MCPClientError",
54
20
  message,
55
21
  cause,
56
22
  data,
57
- code
23
+ code,
24
+ statusCode,
25
+ url,
26
+ responseBody
58
27
  }) {
59
28
  super({ name: name3, message, cause });
60
29
  this[_a] = true;
61
30
  this.data = data;
62
31
  this.code = code;
32
+ this.statusCode = statusCode;
33
+ this.url = url;
34
+ this.responseBody = responseBody;
63
35
  }
64
36
  static isInstance(error) {
65
- return import_provider.AISDKError.hasMarker(error, marker);
37
+ return AISDKError.hasMarker(error, marker);
66
38
  }
67
39
  };
68
40
 
69
41
  // src/tool/mcp-sse-transport.ts
70
- var import_provider_utils = require("@ai-sdk/provider-utils");
42
+ import {
43
+ EventSourceParserStream,
44
+ withUserAgentSuffix,
45
+ getRuntimeEnvironmentUserAgent
46
+ } from "@ai-sdk/provider-utils";
71
47
 
72
48
  // src/tool/json-rpc-message.ts
73
- var import_v42 = require("zod/v4");
49
+ import { parseJSON } from "@ai-sdk/provider-utils";
50
+ import { z as z2 } from "zod/v4";
74
51
 
75
52
  // src/tool/types.ts
76
- var import_v4 = require("zod/v4");
53
+ import { z } from "zod/v4";
77
54
  var LATEST_PROTOCOL_VERSION = "2025-11-25";
78
55
  var SUPPORTED_PROTOCOL_VERSIONS = [
79
56
  LATEST_PROTOCOL_VERSION,
@@ -81,356 +58,377 @@ var SUPPORTED_PROTOCOL_VERSIONS = [
81
58
  "2025-03-26",
82
59
  "2024-11-05"
83
60
  ];
84
- var ToolMetaSchema = import_v4.z.optional(import_v4.z.record(import_v4.z.string(), import_v4.z.unknown()));
85
- var ClientOrServerImplementationSchema = import_v4.z.looseObject({
86
- name: import_v4.z.string(),
87
- version: import_v4.z.string()
61
+ var ToolMetaSchema = z.optional(z.record(z.string(), z.unknown()));
62
+ var ClientOrServerImplementationSchema = z.looseObject({
63
+ name: z.string(),
64
+ version: z.string(),
65
+ title: z.optional(z.string())
88
66
  });
89
- var BaseParamsSchema = import_v4.z.looseObject({
90
- _meta: import_v4.z.optional(import_v4.z.object({}).loose())
67
+ var BaseParamsSchema = z.looseObject({
68
+ _meta: z.optional(z.object({}).loose())
91
69
  });
92
70
  var ResultSchema = BaseParamsSchema;
93
- var RequestSchema = import_v4.z.object({
94
- method: import_v4.z.string(),
95
- params: import_v4.z.optional(BaseParamsSchema)
71
+ var RequestSchema = z.object({
72
+ method: z.string(),
73
+ params: z.optional(BaseParamsSchema)
96
74
  });
97
- var ElicitationCapabilitySchema = import_v4.z.object({
98
- applyDefaults: import_v4.z.optional(import_v4.z.boolean())
75
+ var ElicitationCapabilitySchema = z.object({
76
+ applyDefaults: z.optional(z.boolean())
99
77
  }).loose();
100
- var ServerCapabilitiesSchema = import_v4.z.looseObject({
101
- experimental: import_v4.z.optional(import_v4.z.object({}).loose()),
102
- logging: import_v4.z.optional(import_v4.z.object({}).loose()),
103
- prompts: import_v4.z.optional(
104
- import_v4.z.looseObject({
105
- listChanged: import_v4.z.optional(import_v4.z.boolean())
78
+ var ServerCapabilitiesSchema = z.looseObject({
79
+ experimental: z.optional(z.object({}).loose()),
80
+ logging: z.optional(z.object({}).loose()),
81
+ prompts: z.optional(
82
+ z.looseObject({
83
+ listChanged: z.optional(z.boolean())
106
84
  })
107
85
  ),
108
- resources: import_v4.z.optional(
109
- import_v4.z.looseObject({
110
- subscribe: import_v4.z.optional(import_v4.z.boolean()),
111
- listChanged: import_v4.z.optional(import_v4.z.boolean())
86
+ resources: z.optional(
87
+ z.looseObject({
88
+ subscribe: z.optional(z.boolean()),
89
+ listChanged: z.optional(z.boolean())
112
90
  })
113
91
  ),
114
- tools: import_v4.z.optional(
115
- import_v4.z.looseObject({
116
- listChanged: import_v4.z.optional(import_v4.z.boolean())
92
+ tools: z.optional(
93
+ z.looseObject({
94
+ listChanged: z.optional(z.boolean())
117
95
  })
118
96
  ),
119
- elicitation: import_v4.z.optional(ElicitationCapabilitySchema)
97
+ elicitation: z.optional(ElicitationCapabilitySchema)
120
98
  });
121
- var ClientCapabilitiesSchema = import_v4.z.object({
122
- elicitation: import_v4.z.optional(ElicitationCapabilitySchema)
99
+ var ClientCapabilitiesSchema = z.object({
100
+ elicitation: z.optional(ElicitationCapabilitySchema)
123
101
  }).loose();
124
102
  var InitializeResultSchema = ResultSchema.extend({
125
- protocolVersion: import_v4.z.string(),
103
+ protocolVersion: z.string(),
126
104
  capabilities: ServerCapabilitiesSchema,
127
105
  serverInfo: ClientOrServerImplementationSchema,
128
- instructions: import_v4.z.optional(import_v4.z.string())
106
+ instructions: z.optional(z.string())
129
107
  });
130
108
  var PaginatedResultSchema = ResultSchema.extend({
131
- nextCursor: import_v4.z.optional(import_v4.z.string())
109
+ nextCursor: z.optional(z.string())
132
110
  });
133
- var ToolSchema = import_v4.z.object({
134
- name: import_v4.z.string(),
111
+ var ToolSchema = z.object({
112
+ name: z.string(),
135
113
  /**
136
114
  * @see https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool
137
115
  */
138
- title: import_v4.z.optional(import_v4.z.string()),
139
- description: import_v4.z.optional(import_v4.z.string()),
140
- inputSchema: import_v4.z.object({
141
- type: import_v4.z.literal("object"),
142
- properties: import_v4.z.optional(import_v4.z.object({}).loose())
116
+ title: z.optional(z.string()),
117
+ description: z.optional(z.string()),
118
+ inputSchema: z.object({
119
+ type: z.literal("object"),
120
+ properties: z.optional(z.object({}).loose())
143
121
  }).loose(),
144
122
  /**
145
123
  * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema
146
124
  */
147
- outputSchema: import_v4.z.optional(import_v4.z.object({}).loose()),
148
- annotations: import_v4.z.optional(
149
- import_v4.z.object({
150
- title: import_v4.z.optional(import_v4.z.string())
125
+ outputSchema: z.optional(z.object({}).loose()),
126
+ annotations: z.optional(
127
+ z.object({
128
+ title: z.optional(z.string())
151
129
  }).loose()
152
130
  ),
153
131
  _meta: ToolMetaSchema
154
132
  }).loose();
155
133
  var ListToolsResultSchema = PaginatedResultSchema.extend({
156
- tools: import_v4.z.array(ToolSchema)
134
+ tools: z.array(ToolSchema)
157
135
  });
158
- var TextContentSchema = import_v4.z.object({
159
- type: import_v4.z.literal("text"),
160
- text: import_v4.z.string()
136
+ var TextContentSchema = z.object({
137
+ type: z.literal("text"),
138
+ text: z.string()
161
139
  }).loose();
162
- var ImageContentSchema = import_v4.z.object({
163
- type: import_v4.z.literal("image"),
164
- data: import_v4.z.base64(),
165
- mimeType: import_v4.z.string()
140
+ var ImageContentSchema = z.object({
141
+ type: z.literal("image"),
142
+ data: z.base64(),
143
+ mimeType: z.string()
166
144
  }).loose();
167
- var ResourceSchema = import_v4.z.object({
168
- uri: import_v4.z.string(),
169
- name: import_v4.z.string(),
170
- title: import_v4.z.optional(import_v4.z.string()),
171
- description: import_v4.z.optional(import_v4.z.string()),
172
- mimeType: import_v4.z.optional(import_v4.z.string()),
173
- size: import_v4.z.optional(import_v4.z.number())
145
+ var ResourceSchema = z.object({
146
+ uri: z.string(),
147
+ name: z.string(),
148
+ title: z.optional(z.string()),
149
+ description: z.optional(z.string()),
150
+ mimeType: z.optional(z.string()),
151
+ size: z.optional(z.number())
174
152
  }).loose();
175
153
  var ListResourcesResultSchema = PaginatedResultSchema.extend({
176
- resources: import_v4.z.array(ResourceSchema)
154
+ resources: z.array(ResourceSchema)
177
155
  });
178
- var ResourceContentsSchema = import_v4.z.object({
156
+ var ResourceContentsSchema = z.object({
179
157
  /**
180
158
  * The URI of this resource.
181
159
  */
182
- uri: import_v4.z.string(),
160
+ uri: z.string(),
183
161
  /**
184
162
  * Optional display name of the resource content.
185
163
  */
186
- name: import_v4.z.optional(import_v4.z.string()),
164
+ name: z.optional(z.string()),
187
165
  /**
188
166
  * Optional human readable title.
189
167
  */
190
- title: import_v4.z.optional(import_v4.z.string()),
168
+ title: z.optional(z.string()),
191
169
  /**
192
170
  * The MIME type of this resource, if known.
193
171
  */
194
- mimeType: import_v4.z.optional(import_v4.z.string())
172
+ mimeType: z.optional(z.string())
195
173
  }).loose();
196
174
  var TextResourceContentsSchema = ResourceContentsSchema.extend({
197
- text: import_v4.z.string()
175
+ text: z.string()
198
176
  });
199
177
  var BlobResourceContentsSchema = ResourceContentsSchema.extend({
200
- blob: import_v4.z.base64()
178
+ blob: z.base64()
201
179
  });
202
- var EmbeddedResourceSchema = import_v4.z.object({
203
- type: import_v4.z.literal("resource"),
204
- resource: import_v4.z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
180
+ var EmbeddedResourceSchema = z.object({
181
+ type: z.literal("resource"),
182
+ resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
183
+ }).loose();
184
+ var ResourceLinkContentSchema = z.object({
185
+ type: z.literal("resource_link"),
186
+ uri: z.string(),
187
+ name: z.string(),
188
+ description: z.optional(z.string()),
189
+ mimeType: z.optional(z.string())
205
190
  }).loose();
206
191
  var CallToolResultSchema = ResultSchema.extend({
207
- content: import_v4.z.array(
208
- import_v4.z.union([TextContentSchema, ImageContentSchema, EmbeddedResourceSchema])
192
+ content: z.array(
193
+ z.union([
194
+ TextContentSchema,
195
+ ImageContentSchema,
196
+ EmbeddedResourceSchema,
197
+ ResourceLinkContentSchema
198
+ ])
209
199
  ),
210
200
  /**
211
201
  * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content
212
202
  */
213
- structuredContent: import_v4.z.optional(import_v4.z.unknown()),
214
- isError: import_v4.z.boolean().default(false).optional()
203
+ structuredContent: z.optional(z.unknown()),
204
+ isError: z.boolean().default(false).optional()
215
205
  }).or(
216
206
  ResultSchema.extend({
217
- toolResult: import_v4.z.unknown()
207
+ toolResult: z.unknown()
218
208
  })
219
209
  );
220
- var ResourceTemplateSchema = import_v4.z.object({
221
- uriTemplate: import_v4.z.string(),
222
- name: import_v4.z.string(),
223
- title: import_v4.z.optional(import_v4.z.string()),
224
- description: import_v4.z.optional(import_v4.z.string()),
225
- mimeType: import_v4.z.optional(import_v4.z.string())
210
+ var ResourceTemplateSchema = z.object({
211
+ uriTemplate: z.string(),
212
+ name: z.string(),
213
+ title: z.optional(z.string()),
214
+ description: z.optional(z.string()),
215
+ mimeType: z.optional(z.string())
226
216
  }).loose();
227
217
  var ListResourceTemplatesResultSchema = ResultSchema.extend({
228
- resourceTemplates: import_v4.z.array(ResourceTemplateSchema)
218
+ resourceTemplates: z.array(ResourceTemplateSchema)
229
219
  });
230
220
  var ReadResourceResultSchema = ResultSchema.extend({
231
- contents: import_v4.z.array(
232
- import_v4.z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
221
+ contents: z.array(
222
+ z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
233
223
  )
234
224
  });
235
- var PromptArgumentSchema = import_v4.z.object({
236
- name: import_v4.z.string(),
237
- description: import_v4.z.optional(import_v4.z.string()),
238
- required: import_v4.z.optional(import_v4.z.boolean())
225
+ var PromptArgumentSchema = z.object({
226
+ name: z.string(),
227
+ description: z.optional(z.string()),
228
+ required: z.optional(z.boolean())
239
229
  }).loose();
240
- var PromptSchema = import_v4.z.object({
241
- name: import_v4.z.string(),
242
- title: import_v4.z.optional(import_v4.z.string()),
243
- description: import_v4.z.optional(import_v4.z.string()),
244
- arguments: import_v4.z.optional(import_v4.z.array(PromptArgumentSchema))
230
+ var PromptSchema = z.object({
231
+ name: z.string(),
232
+ title: z.optional(z.string()),
233
+ description: z.optional(z.string()),
234
+ arguments: z.optional(z.array(PromptArgumentSchema))
245
235
  }).loose();
246
236
  var ListPromptsResultSchema = PaginatedResultSchema.extend({
247
- prompts: import_v4.z.array(PromptSchema)
237
+ prompts: z.array(PromptSchema)
248
238
  });
249
- var PromptMessageSchema = import_v4.z.object({
250
- role: import_v4.z.union([import_v4.z.literal("user"), import_v4.z.literal("assistant")]),
251
- content: import_v4.z.union([
239
+ var PromptMessageSchema = z.object({
240
+ role: z.union([z.literal("user"), z.literal("assistant")]),
241
+ content: z.union([
252
242
  TextContentSchema,
253
243
  ImageContentSchema,
254
- EmbeddedResourceSchema
244
+ EmbeddedResourceSchema,
245
+ ResourceLinkContentSchema
255
246
  ])
256
247
  }).loose();
257
248
  var GetPromptResultSchema = ResultSchema.extend({
258
- description: import_v4.z.optional(import_v4.z.string()),
259
- messages: import_v4.z.array(PromptMessageSchema)
249
+ description: z.optional(z.string()),
250
+ messages: z.array(PromptMessageSchema)
260
251
  });
261
252
  var ElicitationRequestParamsSchema = BaseParamsSchema.extend({
262
- message: import_v4.z.string(),
263
- requestedSchema: import_v4.z.unknown()
253
+ message: z.string(),
254
+ requestedSchema: z.unknown()
264
255
  });
265
256
  var ElicitationRequestSchema = RequestSchema.extend({
266
- method: import_v4.z.literal("elicitation/create"),
257
+ method: z.literal("elicitation/create"),
267
258
  params: ElicitationRequestParamsSchema
268
259
  });
269
260
  var ElicitResultSchema = ResultSchema.extend({
270
- action: import_v4.z.union([
271
- import_v4.z.literal("accept"),
272
- import_v4.z.literal("decline"),
273
- import_v4.z.literal("cancel")
261
+ action: z.union([
262
+ z.literal("accept"),
263
+ z.literal("decline"),
264
+ z.literal("cancel")
274
265
  ]),
275
- content: import_v4.z.optional(import_v4.z.record(import_v4.z.string(), import_v4.z.unknown()))
266
+ content: z.optional(z.record(z.string(), z.unknown()))
276
267
  });
277
268
 
278
269
  // src/tool/json-rpc-message.ts
279
270
  var JSONRPC_VERSION = "2.0";
280
- var JSONRPCRequestSchema = import_v42.z.object({
281
- jsonrpc: import_v42.z.literal(JSONRPC_VERSION),
282
- id: import_v42.z.union([import_v42.z.string(), import_v42.z.number().int()])
271
+ var JSONRPCRequestSchema = z2.object({
272
+ jsonrpc: z2.literal(JSONRPC_VERSION),
273
+ id: z2.union([z2.string(), z2.number().int()])
283
274
  }).merge(RequestSchema).strict();
284
- var JSONRPCResponseSchema = import_v42.z.object({
285
- jsonrpc: import_v42.z.literal(JSONRPC_VERSION),
286
- id: import_v42.z.union([import_v42.z.string(), import_v42.z.number().int()]),
275
+ var JSONRPCResponseSchema = z2.object({
276
+ jsonrpc: z2.literal(JSONRPC_VERSION),
277
+ id: z2.union([z2.string(), z2.number().int()]),
287
278
  result: ResultSchema
288
279
  }).strict();
289
- var JSONRPCErrorSchema = import_v42.z.object({
290
- jsonrpc: import_v42.z.literal(JSONRPC_VERSION),
291
- id: import_v42.z.union([import_v42.z.string(), import_v42.z.number().int()]),
292
- error: import_v42.z.object({
293
- code: import_v42.z.number().int(),
294
- message: import_v42.z.string(),
295
- data: import_v42.z.optional(import_v42.z.unknown())
280
+ var JSONRPCErrorSchema = z2.object({
281
+ jsonrpc: z2.literal(JSONRPC_VERSION),
282
+ id: z2.union([z2.string(), z2.number().int()]),
283
+ error: z2.object({
284
+ code: z2.number().int(),
285
+ message: z2.string(),
286
+ data: z2.optional(z2.unknown())
296
287
  })
297
288
  }).strict();
298
- var JSONRPCNotificationSchema = import_v42.z.object({
299
- jsonrpc: import_v42.z.literal(JSONRPC_VERSION)
289
+ var JSONRPCNotificationSchema = z2.object({
290
+ jsonrpc: z2.literal(JSONRPC_VERSION)
300
291
  }).merge(
301
- import_v42.z.object({
302
- method: import_v42.z.string(),
303
- params: import_v42.z.optional(BaseParamsSchema)
292
+ z2.object({
293
+ method: z2.string(),
294
+ params: z2.optional(BaseParamsSchema)
304
295
  })
305
296
  ).strict();
306
- var JSONRPCMessageSchema = import_v42.z.union([
297
+ var JSONRPCMessageSchema = z2.union([
307
298
  JSONRPCRequestSchema,
308
299
  JSONRPCNotificationSchema,
309
300
  JSONRPCResponseSchema,
310
301
  JSONRPCErrorSchema
311
302
  ]);
303
+ async function parseJSONRPCMessage(text) {
304
+ return JSONRPCMessageSchema.parse(await parseJSON({ text }));
305
+ }
312
306
 
313
307
  // src/version.ts
314
308
  var VERSION = typeof __PACKAGE_VERSION__ !== "undefined" ? __PACKAGE_VERSION__ : "0.0.0-test";
315
309
 
316
310
  // src/tool/oauth.ts
317
- var import_pkce_challenge = __toESM(require("pkce-challenge"));
311
+ import pkceChallenge from "pkce-challenge";
318
312
 
319
313
  // src/tool/oauth-types.ts
320
- var import_v43 = require("zod/v4");
321
- var OAuthTokensSchema = import_v43.z.object({
322
- access_token: import_v43.z.string(),
323
- id_token: import_v43.z.string().optional(),
324
- // Optional for OAuth 2.1, but necessary in OpenID Connect
325
- token_type: import_v43.z.string(),
326
- expires_in: import_v43.z.number().optional(),
327
- scope: import_v43.z.string().optional(),
328
- refresh_token: import_v43.z.string().optional()
329
- }).strip();
330
- var SafeUrlSchema = import_v43.z.string().url().superRefine((val, ctx) => {
314
+ import { z as z3 } from "zod/v4";
315
+ var SafeUrlSchema = z3.string().url().superRefine((val, ctx) => {
331
316
  if (!URL.canParse(val)) {
332
317
  ctx.addIssue({
333
- code: import_v43.z.ZodIssueCode.custom,
318
+ code: z3.ZodIssueCode.custom,
334
319
  message: "URL must be parseable",
335
320
  fatal: true
336
321
  });
337
- return import_v43.z.NEVER;
322
+ return z3.NEVER;
338
323
  }
339
324
  }).refine(
340
325
  (url) => {
341
- const u = new URL(url);
342
- return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:";
326
+ const parsedUrl = new URL(url);
327
+ return parsedUrl.protocol !== "javascript:" && parsedUrl.protocol !== "data:" && parsedUrl.protocol !== "vbscript:";
343
328
  },
344
329
  { message: "URL cannot use javascript:, data:, or vbscript: scheme" }
345
330
  );
346
- var OAuthProtectedResourceMetadataSchema = import_v43.z.object({
347
- resource: import_v43.z.string().url(),
348
- authorization_servers: import_v43.z.array(SafeUrlSchema).optional(),
349
- jwks_uri: import_v43.z.string().url().optional(),
350
- scopes_supported: import_v43.z.array(import_v43.z.string()).optional(),
351
- bearer_methods_supported: import_v43.z.array(import_v43.z.string()).optional(),
352
- resource_signing_alg_values_supported: import_v43.z.array(import_v43.z.string()).optional(),
353
- resource_name: import_v43.z.string().optional(),
354
- resource_documentation: import_v43.z.string().optional(),
355
- resource_policy_uri: import_v43.z.string().url().optional(),
356
- resource_tos_uri: import_v43.z.string().url().optional(),
357
- tls_client_certificate_bound_access_tokens: import_v43.z.boolean().optional(),
358
- authorization_details_types_supported: import_v43.z.array(import_v43.z.string()).optional(),
359
- dpop_signing_alg_values_supported: import_v43.z.array(import_v43.z.string()).optional(),
360
- dpop_bound_access_tokens_required: import_v43.z.boolean().optional()
331
+ var OAuthTokensSchema = z3.object({
332
+ access_token: z3.string(),
333
+ id_token: z3.string().optional(),
334
+ // Optional for OAuth 2.1, but necessary in OpenID Connect
335
+ token_type: z3.string(),
336
+ expires_in: z3.number().optional(),
337
+ scope: z3.string().optional(),
338
+ refresh_token: z3.string().optional(),
339
+ authorization_server: SafeUrlSchema.optional(),
340
+ token_endpoint: SafeUrlSchema.optional()
341
+ }).strip();
342
+ var OAuthProtectedResourceMetadataSchema = z3.object({
343
+ resource: z3.string().url(),
344
+ authorization_servers: z3.array(SafeUrlSchema).optional(),
345
+ jwks_uri: z3.string().url().optional(),
346
+ scopes_supported: z3.array(z3.string()).optional(),
347
+ bearer_methods_supported: z3.array(z3.string()).optional(),
348
+ resource_signing_alg_values_supported: z3.array(z3.string()).optional(),
349
+ resource_name: z3.string().optional(),
350
+ resource_documentation: z3.string().optional(),
351
+ resource_policy_uri: z3.string().url().optional(),
352
+ resource_tos_uri: z3.string().url().optional(),
353
+ tls_client_certificate_bound_access_tokens: z3.boolean().optional(),
354
+ authorization_details_types_supported: z3.array(z3.string()).optional(),
355
+ dpop_signing_alg_values_supported: z3.array(z3.string()).optional(),
356
+ dpop_bound_access_tokens_required: z3.boolean().optional()
361
357
  }).passthrough();
362
- var OAuthMetadataSchema = import_v43.z.object({
363
- issuer: import_v43.z.string(),
358
+ var OAuthMetadataSchema = z3.object({
359
+ issuer: z3.string(),
364
360
  authorization_endpoint: SafeUrlSchema,
365
361
  token_endpoint: SafeUrlSchema,
366
362
  registration_endpoint: SafeUrlSchema.optional(),
367
- scopes_supported: import_v43.z.array(import_v43.z.string()).optional(),
368
- response_types_supported: import_v43.z.array(import_v43.z.string()),
369
- grant_types_supported: import_v43.z.array(import_v43.z.string()).optional(),
370
- code_challenge_methods_supported: import_v43.z.array(import_v43.z.string()),
371
- token_endpoint_auth_methods_supported: import_v43.z.array(import_v43.z.string()).optional(),
372
- token_endpoint_auth_signing_alg_values_supported: import_v43.z.array(import_v43.z.string()).optional()
363
+ scopes_supported: z3.array(z3.string()).optional(),
364
+ response_types_supported: z3.array(z3.string()),
365
+ grant_types_supported: z3.array(z3.string()).optional(),
366
+ code_challenge_methods_supported: z3.array(z3.string()),
367
+ token_endpoint_auth_methods_supported: z3.array(z3.string()).optional(),
368
+ token_endpoint_auth_signing_alg_values_supported: z3.array(z3.string()).optional()
373
369
  }).passthrough();
374
- var OpenIdProviderMetadataSchema = import_v43.z.object({
375
- issuer: import_v43.z.string(),
370
+ var OpenIdProviderMetadataSchema = z3.object({
371
+ issuer: z3.string(),
376
372
  authorization_endpoint: SafeUrlSchema,
377
373
  token_endpoint: SafeUrlSchema,
378
374
  userinfo_endpoint: SafeUrlSchema.optional(),
379
375
  jwks_uri: SafeUrlSchema,
380
376
  registration_endpoint: SafeUrlSchema.optional(),
381
- scopes_supported: import_v43.z.array(import_v43.z.string()).optional(),
382
- response_types_supported: import_v43.z.array(import_v43.z.string()),
383
- grant_types_supported: import_v43.z.array(import_v43.z.string()).optional(),
384
- subject_types_supported: import_v43.z.array(import_v43.z.string()),
385
- id_token_signing_alg_values_supported: import_v43.z.array(import_v43.z.string()),
386
- claims_supported: import_v43.z.array(import_v43.z.string()).optional(),
387
- token_endpoint_auth_methods_supported: import_v43.z.array(import_v43.z.string()).optional()
377
+ scopes_supported: z3.array(z3.string()).optional(),
378
+ response_types_supported: z3.array(z3.string()),
379
+ grant_types_supported: z3.array(z3.string()).optional(),
380
+ subject_types_supported: z3.array(z3.string()),
381
+ id_token_signing_alg_values_supported: z3.array(z3.string()),
382
+ claims_supported: z3.array(z3.string()).optional(),
383
+ token_endpoint_auth_methods_supported: z3.array(z3.string()).optional()
388
384
  }).passthrough();
389
385
  var OpenIdProviderDiscoveryMetadataSchema = OpenIdProviderMetadataSchema.merge(
390
386
  OAuthMetadataSchema.pick({
391
387
  code_challenge_methods_supported: true
392
388
  })
393
389
  );
394
- var OAuthClientInformationSchema = import_v43.z.object({
395
- client_id: import_v43.z.string(),
396
- client_secret: import_v43.z.string().optional(),
397
- client_id_issued_at: import_v43.z.number().optional(),
398
- client_secret_expires_at: import_v43.z.number().optional()
390
+ var OAuthClientInformationSchema = z3.object({
391
+ client_id: z3.string(),
392
+ client_secret: z3.string().optional(),
393
+ client_id_issued_at: z3.number().optional(),
394
+ client_secret_expires_at: z3.number().optional(),
395
+ authorization_server: SafeUrlSchema.optional(),
396
+ token_endpoint: SafeUrlSchema.optional()
399
397
  }).strip();
400
- var OAuthClientMetadataSchema = import_v43.z.object({
401
- redirect_uris: import_v43.z.array(SafeUrlSchema),
402
- token_endpoint_auth_method: import_v43.z.string().optional(),
403
- grant_types: import_v43.z.array(import_v43.z.string()).optional(),
404
- response_types: import_v43.z.array(import_v43.z.string()).optional(),
405
- client_name: import_v43.z.string().optional(),
398
+ var OAuthClientMetadataSchema = z3.object({
399
+ redirect_uris: z3.array(SafeUrlSchema),
400
+ token_endpoint_auth_method: z3.string().optional(),
401
+ grant_types: z3.array(z3.string()).optional(),
402
+ response_types: z3.array(z3.string()).optional(),
403
+ client_name: z3.string().optional(),
406
404
  client_uri: SafeUrlSchema.optional(),
407
405
  logo_uri: SafeUrlSchema.optional(),
408
- scope: import_v43.z.string().optional(),
409
- contacts: import_v43.z.array(import_v43.z.string()).optional(),
406
+ scope: z3.string().optional(),
407
+ contacts: z3.array(z3.string()).optional(),
410
408
  tos_uri: SafeUrlSchema.optional(),
411
- policy_uri: import_v43.z.string().optional(),
409
+ policy_uri: z3.string().optional(),
412
410
  jwks_uri: SafeUrlSchema.optional(),
413
- jwks: import_v43.z.any().optional(),
414
- software_id: import_v43.z.string().optional(),
415
- software_version: import_v43.z.string().optional(),
416
- software_statement: import_v43.z.string().optional()
411
+ jwks: z3.any().optional(),
412
+ software_id: z3.string().optional(),
413
+ software_version: z3.string().optional(),
414
+ software_statement: z3.string().optional()
417
415
  }).strip();
418
- var OAuthErrorResponseSchema = import_v43.z.object({
419
- error: import_v43.z.string(),
420
- error_description: import_v43.z.string().optional(),
421
- error_uri: import_v43.z.string().optional()
416
+ var OAuthErrorResponseSchema = z3.object({
417
+ error: z3.string(),
418
+ error_description: z3.string().optional(),
419
+ error_uri: z3.string().optional()
422
420
  });
423
421
  var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(
424
422
  OAuthClientInformationSchema
425
423
  );
426
424
 
427
425
  // src/error/oauth-error.ts
428
- var import_provider2 = require("@ai-sdk/provider");
426
+ import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
429
427
  var name2 = "AI_MCPClientOAuthError";
430
428
  var marker2 = `vercel.ai.error.${name2}`;
431
429
  var symbol2 = Symbol.for(marker2);
432
430
  var _a2, _b2;
433
- var MCPClientOAuthError = class extends (_b2 = import_provider2.AISDKError, _a2 = symbol2, _b2) {
431
+ var MCPClientOAuthError = class extends (_b2 = AISDKError2, _a2 = symbol2, _b2) {
434
432
  constructor({
435
433
  name: name3 = "MCPClientOAuthError",
436
434
  message,
@@ -440,7 +438,7 @@ var MCPClientOAuthError = class extends (_b2 = import_provider2.AISDKError, _a2
440
438
  this[_a2] = true;
441
439
  }
442
440
  static isInstance(error) {
443
- return import_provider2.AISDKError.hasMarker(error, marker2);
441
+ return AISDKError2.hasMarker(error, marker2);
444
442
  }
445
443
  };
446
444
  var ServerError = class extends MCPClientOAuthError {
@@ -468,6 +466,13 @@ function resourceUrlFromServerUrl(url) {
468
466
  resourceURL.hash = "";
469
467
  return resourceURL;
470
468
  }
469
+ function resourceUrlStripSlash(resource) {
470
+ const href = resource.href;
471
+ if (resource.pathname === "/" && href.endsWith("/")) {
472
+ return href.slice(0, -1);
473
+ }
474
+ return href;
475
+ }
471
476
  function checkResourceAllowed({
472
477
  requestedResource,
473
478
  configuredResource
@@ -486,12 +491,113 @@ function checkResourceAllowed({
486
491
  }
487
492
 
488
493
  // src/tool/oauth.ts
494
+ import { parseJSON as parseJSON2 } from "@ai-sdk/provider-utils";
489
495
  var UnauthorizedError = class extends Error {
490
496
  constructor(message = "Unauthorized") {
491
497
  super(message);
492
498
  this.name = "UnauthorizedError";
493
499
  }
494
500
  };
501
+ function normalizeUrl(url) {
502
+ return new URL(url).href;
503
+ }
504
+ function createAuthorizationServerInformation(authorizationServerUrl, metadata) {
505
+ return {
506
+ authorizationServerUrl: normalizeUrl(authorizationServerUrl),
507
+ tokenEndpoint: normalizeUrl(
508
+ (metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl)
509
+ )
510
+ };
511
+ }
512
+ function addAuthorizationServerInformationToTokens(tokens, authorizationServerInformation) {
513
+ return {
514
+ ...tokens,
515
+ authorization_server: authorizationServerInformation.authorizationServerUrl,
516
+ token_endpoint: authorizationServerInformation.tokenEndpoint
517
+ };
518
+ }
519
+ function addAuthorizationServerInformationToClientInformation(clientInformation, authorizationServerInformation) {
520
+ return {
521
+ ...clientInformation,
522
+ authorization_server: authorizationServerInformation.authorizationServerUrl,
523
+ token_endpoint: authorizationServerInformation.tokenEndpoint
524
+ };
525
+ }
526
+ function getAuthorizationServerInformationFromCredentials(credentials) {
527
+ if (!(credentials == null ? void 0 : credentials.authorization_server) || !credentials.token_endpoint) {
528
+ return void 0;
529
+ }
530
+ return {
531
+ authorizationServerUrl: normalizeUrl(credentials.authorization_server),
532
+ tokenEndpoint: normalizeUrl(credentials.token_endpoint)
533
+ };
534
+ }
535
+ async function getStoredAuthorizationServerInformation({
536
+ provider,
537
+ clientInformation,
538
+ tokens
539
+ }) {
540
+ var _a3;
541
+ const tokenAuthorizationServerInformation = getAuthorizationServerInformationFromCredentials(tokens);
542
+ if (tokenAuthorizationServerInformation) {
543
+ return tokenAuthorizationServerInformation;
544
+ }
545
+ const providerAuthorizationServerInformation = await ((_a3 = provider.authorizationServerInformation) == null ? void 0 : _a3.call(provider));
546
+ if (providerAuthorizationServerInformation) {
547
+ return {
548
+ authorizationServerUrl: normalizeUrl(
549
+ providerAuthorizationServerInformation.authorizationServerUrl
550
+ ),
551
+ tokenEndpoint: normalizeUrl(
552
+ providerAuthorizationServerInformation.tokenEndpoint
553
+ )
554
+ };
555
+ }
556
+ return getAuthorizationServerInformationFromCredentials(clientInformation);
557
+ }
558
+ async function saveAuthorizationServerInformation({
559
+ provider,
560
+ clientInformation,
561
+ authorizationServerInformation
562
+ }) {
563
+ if (provider.saveAuthorizationServerInformation) {
564
+ await provider.saveAuthorizationServerInformation(
565
+ authorizationServerInformation
566
+ );
567
+ return true;
568
+ }
569
+ if (provider.saveClientInformation) {
570
+ await provider.saveClientInformation(
571
+ addAuthorizationServerInformationToClientInformation(
572
+ clientInformation,
573
+ authorizationServerInformation
574
+ )
575
+ );
576
+ return true;
577
+ }
578
+ return false;
579
+ }
580
+ function assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl) {
581
+ if (!resourceMetadataUrl) {
582
+ return;
583
+ }
584
+ const expectedOrigin = new URL(serverUrl).origin;
585
+ if (resourceMetadataUrl.origin !== expectedOrigin) {
586
+ throw new MCPClientOAuthError({
587
+ message: `OAuth protected resource metadata URL ${resourceMetadataUrl.href} must have the same origin as the MCP server URL ${expectedOrigin}`
588
+ });
589
+ }
590
+ }
591
+ function assertAuthorizationServerInformationMatches({
592
+ storedAuthorizationServerInformation,
593
+ currentAuthorizationServerInformation
594
+ }) {
595
+ if (storedAuthorizationServerInformation.authorizationServerUrl !== currentAuthorizationServerInformation.authorizationServerUrl || storedAuthorizationServerInformation.tokenEndpoint !== currentAuthorizationServerInformation.tokenEndpoint) {
596
+ throw new MCPClientOAuthError({
597
+ message: "OAuth authorization server metadata does not match the metadata that issued the stored credentials"
598
+ });
599
+ }
600
+ }
495
601
  function extractResourceMetadataUrl(response) {
496
602
  var _a3;
497
603
  const header = (_a3 = response.headers.get("www-authenticate")) != null ? _a3 : response.headers.get("WWW-Authenticate");
@@ -586,15 +692,18 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
586
692
  function buildDiscoveryUrls(authorizationServerUrl) {
587
693
  const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
588
694
  const hasPath = url.pathname !== "/";
695
+ const rootIssuer = url.origin;
589
696
  const urlsToTry = [];
590
697
  if (!hasPath) {
591
698
  urlsToTry.push({
592
699
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
593
- type: "oauth"
700
+ type: "oauth",
701
+ expectedIssuer: rootIssuer
594
702
  });
595
703
  urlsToTry.push({
596
704
  url: new URL("/.well-known/openid-configuration", url.origin),
597
- type: "oidc"
705
+ type: "oidc",
706
+ expectedIssuer: rootIssuer
598
707
  });
599
708
  return urlsToTry;
600
709
  }
@@ -602,27 +711,39 @@ function buildDiscoveryUrls(authorizationServerUrl) {
602
711
  if (pathname.endsWith("/")) {
603
712
  pathname = pathname.slice(0, -1);
604
713
  }
714
+ const pathIssuer = `${url.origin}${pathname}`;
605
715
  urlsToTry.push({
606
716
  url: new URL(
607
717
  `/.well-known/oauth-authorization-server${pathname}`,
608
718
  url.origin
609
719
  ),
610
- type: "oauth"
720
+ type: "oauth",
721
+ expectedIssuer: pathIssuer
611
722
  });
612
723
  urlsToTry.push({
613
724
  url: new URL("/.well-known/oauth-authorization-server", url.origin),
614
- type: "oauth"
725
+ type: "oauth",
726
+ expectedIssuer: rootIssuer
615
727
  });
616
728
  urlsToTry.push({
617
729
  url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
618
- type: "oidc"
730
+ type: "oidc",
731
+ expectedIssuer: pathIssuer
619
732
  });
620
733
  urlsToTry.push({
621
734
  url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
622
- type: "oidc"
735
+ type: "oidc",
736
+ expectedIssuer: pathIssuer
623
737
  });
624
738
  return urlsToTry;
625
739
  }
740
+ function assertMetadataIssuerMatches(metadata, expectedIssuer) {
741
+ if (metadata.issuer !== expectedIssuer) {
742
+ throw new MCPClientOAuthError({
743
+ message: `OAuth authorization server metadata issuer ${metadata.issuer} does not match expected issuer ${expectedIssuer}`
744
+ });
745
+ }
746
+ }
626
747
  async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
627
748
  fetchFn = fetch,
628
749
  protocolVersion = LATEST_PROTOCOL_VERSION
@@ -630,7 +751,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
630
751
  var _a3;
631
752
  const headers = { "MCP-Protocol-Version": protocolVersion };
632
753
  const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
633
- for (const { url: endpointUrl, type } of urlsToTry) {
754
+ for (const { url: endpointUrl, type, expectedIssuer } of urlsToTry) {
634
755
  const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
635
756
  if (!response) {
636
757
  continue;
@@ -644,11 +765,14 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
644
765
  );
645
766
  }
646
767
  if (type === "oauth") {
647
- return OAuthMetadataSchema.parse(await response.json());
768
+ const metadata = OAuthMetadataSchema.parse(await response.json());
769
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
770
+ return metadata;
648
771
  } else {
649
772
  const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(
650
773
  await response.json()
651
774
  );
775
+ assertMetadataIssuerMatches(metadata, expectedIssuer);
652
776
  if (!((_a3 = metadata.code_challenge_methods_supported) == null ? void 0 : _a3.includes("S256"))) {
653
777
  throw new Error(
654
778
  `Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`
@@ -685,7 +809,7 @@ async function startAuthorization(authorizationServerUrl, {
685
809
  } else {
686
810
  authorizationUrl = new URL("/authorize", authorizationServerUrl);
687
811
  }
688
- const challenge = await (0, import_pkce_challenge.default)();
812
+ const challenge = await pkceChallenge();
689
813
  const codeVerifier = challenge.code_verifier;
690
814
  const codeChallenge = challenge.code_challenge;
691
815
  authorizationUrl.searchParams.set("response_type", responseType);
@@ -706,7 +830,10 @@ async function startAuthorization(authorizationServerUrl, {
706
830
  authorizationUrl.searchParams.append("prompt", "consent");
707
831
  }
708
832
  if (resource) {
709
- authorizationUrl.searchParams.set("resource", resource.href);
833
+ authorizationUrl.searchParams.set(
834
+ "resource",
835
+ resourceUrlStripSlash(resource)
836
+ );
710
837
  }
711
838
  return { authorizationUrl, codeVerifier };
712
839
  }
@@ -764,7 +891,9 @@ async function parseErrorResponse(input) {
764
891
  const statusCode = input instanceof Response ? input.status : void 0;
765
892
  const body = input instanceof Response ? await input.text() : input;
766
893
  try {
767
- const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
894
+ const result = OAuthErrorResponseSchema.parse(
895
+ await parseJSON2({ text: body })
896
+ );
768
897
  const { error, error_description, error_uri } = result;
769
898
  const errorClass = OAUTH_ERRORS[error] || ServerError;
770
899
  return new errorClass({
@@ -805,7 +934,12 @@ async function exchangeAuthorization(authorizationServerUrl, {
805
934
  redirect_uri: String(redirectUri)
806
935
  });
807
936
  if (addClientAuthentication) {
808
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
937
+ await addClientAuthentication(
938
+ headers,
939
+ params,
940
+ authorizationServerUrl,
941
+ metadata
942
+ );
809
943
  } else {
810
944
  const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
811
945
  const authMethod = selectClientAuthMethod(
@@ -815,7 +949,7 @@ async function exchangeAuthorization(authorizationServerUrl, {
815
949
  applyClientAuthentication(authMethod, clientInformation, headers, params);
816
950
  }
817
951
  if (resource) {
818
- params.set("resource", resource.href);
952
+ params.set("resource", resourceUrlStripSlash(resource));
819
953
  }
820
954
  const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
821
955
  method: "POST",
@@ -857,7 +991,12 @@ async function refreshAuthorization(authorizationServerUrl, {
857
991
  refresh_token: refreshToken
858
992
  });
859
993
  if (addClientAuthentication) {
860
- addClientAuthentication(headers, params, authorizationServerUrl, metadata);
994
+ await addClientAuthentication(
995
+ headers,
996
+ params,
997
+ authorizationServerUrl,
998
+ metadata
999
+ );
861
1000
  } else {
862
1001
  const supportedMethods = (_a3 = metadata == null ? void 0 : metadata.token_endpoint_auth_methods_supported) != null ? _a3 : [];
863
1002
  const authMethod = selectClientAuthMethod(
@@ -867,7 +1006,7 @@ async function refreshAuthorization(authorizationServerUrl, {
867
1006
  applyClientAuthentication(authMethod, clientInformation, headers, params);
868
1007
  }
869
1008
  if (resource) {
870
- params.set("resource", resource.href);
1009
+ params.set("resource", resourceUrlStripSlash(resource));
871
1010
  }
872
1011
  const response = await (fetchFn != null ? fetchFn : fetch)(tokenUrl, {
873
1012
  method: "POST",
@@ -954,8 +1093,10 @@ async function authInternal(provider, {
954
1093
  resourceMetadataUrl,
955
1094
  fetchFn
956
1095
  }) {
1096
+ var _a3, _b3;
957
1097
  let resourceMetadata;
958
1098
  let authorizationServerUrl;
1099
+ assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl);
959
1100
  try {
960
1101
  resourceMetadata = await discoverOAuthProtectedResourceMetadata(
961
1102
  serverUrl,
@@ -975,12 +1116,18 @@ async function authInternal(provider, {
975
1116
  provider,
976
1117
  resourceMetadata
977
1118
  );
1119
+ await ((_a3 = provider.validateAuthorizationServerURL) == null ? void 0 : _a3.call(
1120
+ provider,
1121
+ serverUrl,
1122
+ authorizationServerUrl
1123
+ ));
978
1124
  const metadata = await discoverAuthorizationServerMetadata(
979
1125
  authorizationServerUrl,
980
1126
  {
981
1127
  fetchFn
982
1128
  }
983
1129
  );
1130
+ const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
984
1131
  let clientInformation = await Promise.resolve(provider.clientInformation());
985
1132
  if (!clientInformation) {
986
1133
  if (authorizationCode !== void 0) {
@@ -998,8 +1145,11 @@ async function authInternal(provider, {
998
1145
  clientMetadata: provider.clientMetadata,
999
1146
  fetchFn
1000
1147
  });
1001
- await provider.saveClientInformation(fullInformation);
1002
- clientInformation = fullInformation;
1148
+ clientInformation = addAuthorizationServerInformationToClientInformation(
1149
+ fullInformation,
1150
+ currentAuthorizationServerInformation
1151
+ );
1152
+ await provider.saveClientInformation(clientInformation);
1003
1153
  }
1004
1154
  if (authorizationCode !== void 0) {
1005
1155
  if (provider.storedState) {
@@ -1010,6 +1160,19 @@ async function authInternal(provider, {
1010
1160
  );
1011
1161
  }
1012
1162
  }
1163
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1164
+ provider,
1165
+ clientInformation
1166
+ });
1167
+ if (!storedAuthorizationServerInformation) {
1168
+ throw new MCPClientOAuthError({
1169
+ message: "Stored OAuth authorization server metadata is required when exchanging an authorization code"
1170
+ });
1171
+ }
1172
+ assertAuthorizationServerInformationMatches({
1173
+ storedAuthorizationServerInformation,
1174
+ currentAuthorizationServerInformation
1175
+ });
1013
1176
  const codeVerifier2 = await provider.codeVerifier();
1014
1177
  const tokens2 = await exchangeAuthorization(authorizationServerUrl, {
1015
1178
  metadata,
@@ -1021,22 +1184,47 @@ async function authInternal(provider, {
1021
1184
  addClientAuthentication: provider.addClientAuthentication,
1022
1185
  fetchFn
1023
1186
  });
1024
- await provider.saveTokens(tokens2);
1187
+ await provider.saveTokens(
1188
+ addAuthorizationServerInformationToTokens(
1189
+ tokens2,
1190
+ currentAuthorizationServerInformation
1191
+ )
1192
+ );
1025
1193
  return "AUTHORIZED";
1026
1194
  }
1027
1195
  const tokens = await provider.tokens();
1028
1196
  if (tokens == null ? void 0 : tokens.refresh_token) {
1029
- try {
1030
- const newTokens = await refreshAuthorization(authorizationServerUrl, {
1031
- metadata,
1032
- clientInformation,
1033
- refreshToken: tokens.refresh_token,
1034
- resource,
1035
- addClientAuthentication: provider.addClientAuthentication,
1036
- fetchFn
1197
+ const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
1198
+ provider,
1199
+ clientInformation,
1200
+ tokens
1201
+ });
1202
+ if (storedAuthorizationServerInformation) {
1203
+ assertAuthorizationServerInformationMatches({
1204
+ storedAuthorizationServerInformation,
1205
+ currentAuthorizationServerInformation
1037
1206
  });
1038
- await provider.saveTokens(newTokens);
1039
- return "AUTHORIZED";
1207
+ } else {
1208
+ await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "tokens"));
1209
+ }
1210
+ try {
1211
+ if (storedAuthorizationServerInformation) {
1212
+ const newTokens = await refreshAuthorization(authorizationServerUrl, {
1213
+ metadata,
1214
+ clientInformation,
1215
+ refreshToken: tokens.refresh_token,
1216
+ resource,
1217
+ addClientAuthentication: provider.addClientAuthentication,
1218
+ fetchFn
1219
+ });
1220
+ await provider.saveTokens(
1221
+ addAuthorizationServerInformationToTokens(
1222
+ newTokens,
1223
+ currentAuthorizationServerInformation
1224
+ )
1225
+ );
1226
+ return "AUTHORIZED";
1227
+ }
1040
1228
  } catch (error) {
1041
1229
  if (
1042
1230
  // 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.
@@ -1062,28 +1250,49 @@ async function authInternal(provider, {
1062
1250
  resource
1063
1251
  }
1064
1252
  );
1253
+ const savedAuthorizationServerInformation = await saveAuthorizationServerInformation({
1254
+ provider,
1255
+ clientInformation,
1256
+ authorizationServerInformation: currentAuthorizationServerInformation
1257
+ });
1258
+ if (!savedAuthorizationServerInformation) {
1259
+ throw new MCPClientOAuthError({
1260
+ message: "OAuth authorization server metadata must be saveable before starting authorization"
1261
+ });
1262
+ }
1065
1263
  await provider.saveCodeVerifier(codeVerifier);
1066
1264
  await provider.redirectToAuthorization(authorizationUrl);
1067
1265
  return "REDIRECT";
1068
1266
  }
1069
1267
 
1070
1268
  // src/tool/mcp-sse-transport.ts
1269
+ function isMessageEvent(event) {
1270
+ return event === void 0 || event === "message";
1271
+ }
1071
1272
  var SseMCPTransport = class {
1072
1273
  constructor({
1073
1274
  url,
1074
1275
  headers,
1075
- authProvider
1276
+ authProvider,
1277
+ redirect = "error",
1278
+ fetch: fetchFn
1076
1279
  }) {
1077
1280
  this.connected = false;
1078
1281
  this.url = new URL(url);
1079
1282
  this.headers = headers;
1080
1283
  this.authProvider = authProvider;
1284
+ this.redirectMode = redirect;
1285
+ this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1286
+ }
1287
+ setProtocolVersion(version) {
1288
+ this.protocolVersion = version;
1081
1289
  }
1082
1290
  async commonHeaders(base) {
1291
+ var _a3;
1083
1292
  const headers = {
1084
1293
  ...this.headers,
1085
1294
  ...base,
1086
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1295
+ "mcp-protocol-version": (_a3 = this.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION
1087
1296
  };
1088
1297
  if (this.authProvider) {
1089
1298
  const tokens = await this.authProvider.tokens();
@@ -1091,10 +1300,10 @@ var SseMCPTransport = class {
1091
1300
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
1092
1301
  }
1093
1302
  }
1094
- return (0, import_provider_utils.withUserAgentSuffix)(
1303
+ return withUserAgentSuffix(
1095
1304
  headers,
1096
1305
  `ai-sdk/${VERSION}`,
1097
- (0, import_provider_utils.getRuntimeEnvironmentUserAgent)()
1306
+ getRuntimeEnvironmentUserAgent()
1098
1307
  );
1099
1308
  }
1100
1309
  async start() {
@@ -1109,16 +1318,18 @@ var SseMCPTransport = class {
1109
1318
  const headers = await this.commonHeaders({
1110
1319
  Accept: "text/event-stream"
1111
1320
  });
1112
- const response = await fetch(this.url.href, {
1321
+ const response = await this.fetchFn(this.url.href, {
1113
1322
  headers,
1114
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal
1323
+ signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1324
+ redirect: this.redirectMode
1115
1325
  });
1116
1326
  if (response.status === 401 && this.authProvider && !triedAuth) {
1117
1327
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1118
1328
  try {
1119
1329
  const result = await auth(this.authProvider, {
1120
1330
  serverUrl: this.url,
1121
- resourceMetadataUrl: this.resourceMetadataUrl
1331
+ resourceMetadataUrl: this.resourceMetadataUrl,
1332
+ fetchFn: this.fetchFn
1122
1333
  });
1123
1334
  if (result !== "AUTHORIZED") {
1124
1335
  const error = new UnauthorizedError();
@@ -1142,10 +1353,10 @@ var SseMCPTransport = class {
1142
1353
  (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1143
1354
  return reject(error);
1144
1355
  }
1145
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils.EventSourceParserStream());
1356
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream());
1146
1357
  const reader = stream.getReader();
1147
1358
  const processEvents = async () => {
1148
- var _a4, _b4, _c2;
1359
+ var _a4, _b4, _c2, _d2, _e2;
1149
1360
  try {
1150
1361
  while (true) {
1151
1362
  const { done, value } = await reader.read();
@@ -1160,26 +1371,32 @@ var SseMCPTransport = class {
1160
1371
  }
1161
1372
  const { event, data } = value;
1162
1373
  if (event === "endpoint") {
1163
- this.endpoint = new URL(data, this.url);
1164
- if (this.endpoint.origin !== this.url.origin) {
1374
+ if (this.endpoint) {
1375
+ continue;
1376
+ }
1377
+ const endpoint = new URL(data, this.url);
1378
+ if (endpoint.origin !== this.url.origin) {
1379
+ this.connected = false;
1380
+ this.endpoint = void 0;
1381
+ (_a4 = this.sseConnection) == null ? void 0 : _a4.close();
1382
+ (_b4 = this.abortController) == null ? void 0 : _b4.abort();
1165
1383
  throw new MCPClientError({
1166
- message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${this.endpoint.origin}`
1384
+ message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${endpoint.origin}`
1167
1385
  });
1168
1386
  }
1387
+ this.endpoint = endpoint;
1169
1388
  this.connected = true;
1170
1389
  resolve();
1171
- } else if (event === "message") {
1390
+ } else if (isMessageEvent(event)) {
1172
1391
  try {
1173
- const message = JSONRPCMessageSchema.parse(
1174
- JSON.parse(data)
1175
- );
1176
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, message);
1392
+ const message = await parseJSONRPCMessage(data);
1393
+ (_c2 = this.onmessage) == null ? void 0 : _c2.call(this, message);
1177
1394
  } catch (error) {
1178
1395
  const e = new MCPClientError({
1179
1396
  message: "MCP SSE Transport Error: Failed to parse message",
1180
1397
  cause: error
1181
1398
  });
1182
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1399
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, e);
1183
1400
  }
1184
1401
  }
1185
1402
  }
@@ -1187,7 +1404,7 @@ var SseMCPTransport = class {
1187
1404
  if (error instanceof Error && error.name === "AbortError") {
1188
1405
  return;
1189
1406
  }
1190
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1407
+ (_e2 = this.onerror) == null ? void 0 : _e2.call(this, error);
1191
1408
  reject(error);
1192
1409
  }
1193
1410
  };
@@ -1209,6 +1426,7 @@ var SseMCPTransport = class {
1209
1426
  async close() {
1210
1427
  var _a3, _b3, _c;
1211
1428
  this.connected = false;
1429
+ this.endpoint = void 0;
1212
1430
  (_a3 = this.sseConnection) == null ? void 0 : _a3.close();
1213
1431
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1214
1432
  (_c = this.onclose) == null ? void 0 : _c.call(this);
@@ -1230,15 +1448,17 @@ var SseMCPTransport = class {
1230
1448
  method: "POST",
1231
1449
  headers,
1232
1450
  body: JSON.stringify(message),
1233
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal
1451
+ signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1452
+ redirect: this.redirectMode
1234
1453
  };
1235
- const response = await fetch(endpoint, init);
1454
+ const response = await this.fetchFn(endpoint.href, init);
1236
1455
  if (response.status === 401 && this.authProvider && !triedAuth) {
1237
1456
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1238
1457
  try {
1239
1458
  const result = await auth(this.authProvider, {
1240
1459
  serverUrl: this.url,
1241
- resourceMetadataUrl: this.resourceMetadataUrl
1460
+ resourceMetadataUrl: this.resourceMetadataUrl,
1461
+ fetchFn: this.fetchFn
1242
1462
  });
1243
1463
  if (result !== "AUTHORIZED") {
1244
1464
  const error = new UnauthorizedError();
@@ -1269,12 +1489,21 @@ var SseMCPTransport = class {
1269
1489
  };
1270
1490
 
1271
1491
  // src/tool/mcp-http-transport.ts
1272
- var import_provider_utils2 = require("@ai-sdk/provider-utils");
1492
+ import {
1493
+ EventSourceParserStream as EventSourceParserStream2,
1494
+ withUserAgentSuffix as withUserAgentSuffix2,
1495
+ getRuntimeEnvironmentUserAgent as getRuntimeEnvironmentUserAgent2
1496
+ } from "@ai-sdk/provider-utils";
1497
+ function isMessageEvent2(event) {
1498
+ return event === void 0 || event === "message";
1499
+ }
1273
1500
  var HttpMCPTransport = class {
1274
1501
  constructor({
1275
1502
  url,
1276
1503
  headers,
1277
- authProvider
1504
+ authProvider,
1505
+ redirect = "error",
1506
+ fetch: fetchFn
1278
1507
  }) {
1279
1508
  this.inboundReconnectAttempts = 0;
1280
1509
  this.reconnectionOptions = {
@@ -1286,12 +1515,18 @@ var HttpMCPTransport = class {
1286
1515
  this.url = new URL(url);
1287
1516
  this.headers = headers;
1288
1517
  this.authProvider = authProvider;
1518
+ this.redirectMode = redirect;
1519
+ this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1520
+ }
1521
+ setProtocolVersion(version) {
1522
+ this.protocolVersion = version;
1289
1523
  }
1290
1524
  async commonHeaders(base) {
1525
+ var _a3;
1291
1526
  const headers = {
1292
1527
  ...this.headers,
1293
1528
  ...base,
1294
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1529
+ "mcp-protocol-version": (_a3 = this.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION
1295
1530
  };
1296
1531
  if (this.sessionId) {
1297
1532
  headers["mcp-session-id"] = this.sessionId;
@@ -1302,12 +1537,30 @@ var HttpMCPTransport = class {
1302
1537
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
1303
1538
  }
1304
1539
  }
1305
- return (0, import_provider_utils2.withUserAgentSuffix)(
1540
+ return withUserAgentSuffix2(
1306
1541
  headers,
1307
1542
  `ai-sdk/${VERSION}`,
1308
- (0, import_provider_utils2.getRuntimeEnvironmentUserAgent)()
1543
+ getRuntimeEnvironmentUserAgent2()
1309
1544
  );
1310
1545
  }
1546
+ /**
1547
+ * Runs a single OAuth recovery flow for concurrent 401 responses.
1548
+ */
1549
+ authorizeOnce(resourceMetadataUrl) {
1550
+ if (!this.authProvider) {
1551
+ return Promise.resolve("REDIRECT");
1552
+ }
1553
+ if (!this.authPromise) {
1554
+ this.authPromise = auth(this.authProvider, {
1555
+ serverUrl: this.url,
1556
+ resourceMetadataUrl,
1557
+ fetchFn: this.fetchFn
1558
+ }).finally(() => {
1559
+ this.authPromise = void 0;
1560
+ });
1561
+ }
1562
+ return this.authPromise;
1563
+ }
1311
1564
  async start() {
1312
1565
  if (this.abortController) {
1313
1566
  throw new MCPClientError({
@@ -1323,10 +1576,11 @@ var HttpMCPTransport = class {
1323
1576
  try {
1324
1577
  if (this.sessionId && this.abortController && !this.abortController.signal.aborted) {
1325
1578
  const headers = await this.commonHeaders({});
1326
- await fetch(this.url, {
1579
+ await this.fetchFn(this.url.href, {
1327
1580
  method: "DELETE",
1328
1581
  headers,
1329
- signal: this.abortController.signal
1582
+ signal: this.abortController.signal,
1583
+ redirect: this.redirectMode
1330
1584
  }).catch(() => void 0);
1331
1585
  }
1332
1586
  } catch (e) {
@@ -1346,9 +1600,10 @@ var HttpMCPTransport = class {
1346
1600
  method: "POST",
1347
1601
  headers,
1348
1602
  body: JSON.stringify(message),
1349
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal
1603
+ signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1604
+ redirect: this.redirectMode
1350
1605
  };
1351
- const response = await fetch(this.url, init);
1606
+ const response = await this.fetchFn(this.url.href, init);
1352
1607
  const sessionId = response.headers.get("mcp-session-id");
1353
1608
  if (sessionId) {
1354
1609
  this.sessionId = sessionId;
@@ -1356,10 +1611,7 @@ var HttpMCPTransport = class {
1356
1611
  if (response.status === 401 && this.authProvider && !triedAuth) {
1357
1612
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1358
1613
  try {
1359
- const result = await auth(this.authProvider, {
1360
- serverUrl: this.url,
1361
- resourceMetadataUrl: this.resourceMetadataUrl
1362
- });
1614
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
1363
1615
  if (result !== "AUTHORIZED") {
1364
1616
  const error2 = new UnauthorizedError();
1365
1617
  throw error2;
@@ -1383,7 +1635,10 @@ var HttpMCPTransport = class {
1383
1635
  errorMessage += ". This server does not support HTTP transport. Try using `sse` transport instead";
1384
1636
  }
1385
1637
  const error2 = new MCPClientError({
1386
- message: errorMessage
1638
+ message: errorMessage,
1639
+ statusCode: response.status,
1640
+ url: this.url.href,
1641
+ responseBody: text != null ? text : void 0
1387
1642
  });
1388
1643
  (_c = this.onerror) == null ? void 0 : _c.call(this, error2);
1389
1644
  throw error2;
@@ -1395,19 +1650,25 @@ var HttpMCPTransport = class {
1395
1650
  const contentType = response.headers.get("content-type") || "";
1396
1651
  if (contentType.includes("application/json")) {
1397
1652
  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);
1653
+ const messages = Array.isArray(data) ? data.map(
1654
+ (message2) => JSONRPCMessageSchema.parse(message2)
1655
+ ) : [JSONRPCMessageSchema.parse(data)];
1656
+ for (const jsonRpcMessage of messages) {
1657
+ (_d = this.onmessage) == null ? void 0 : _d.call(this, jsonRpcMessage);
1658
+ }
1400
1659
  return;
1401
1660
  }
1402
1661
  if (contentType.includes("text/event-stream")) {
1403
1662
  if (!response.body) {
1404
1663
  const error2 = new MCPClientError({
1405
- message: "MCP HTTP Transport Error: text/event-stream response without body"
1664
+ message: "MCP HTTP Transport Error: text/event-stream response without body",
1665
+ statusCode: response.status,
1666
+ url: this.url.href
1406
1667
  });
1407
1668
  (_e = this.onerror) == null ? void 0 : _e.call(this, error2);
1408
1669
  throw error2;
1409
1670
  }
1410
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils2.EventSourceParserStream());
1671
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1411
1672
  const reader = stream.getReader();
1412
1673
  const processEvents = async () => {
1413
1674
  var _a4, _b4, _c2;
@@ -1416,10 +1677,10 @@ var HttpMCPTransport = class {
1416
1677
  const { done, value } = await reader.read();
1417
1678
  if (done) return;
1418
1679
  const { event, data } = value;
1419
- if (event === "message") {
1680
+ if (isMessageEvent2(event)) {
1420
1681
  try {
1421
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1422
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
1682
+ const jsonRpcMessage = await parseJSONRPCMessage(data);
1683
+ (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, jsonRpcMessage);
1423
1684
  } catch (error2) {
1424
1685
  const e = new MCPClientError({
1425
1686
  message: "MCP HTTP Transport Error: Failed to parse message",
@@ -1440,7 +1701,9 @@ var HttpMCPTransport = class {
1440
1701
  return;
1441
1702
  }
1442
1703
  const error = new MCPClientError({
1443
- message: `MCP HTTP Transport Error: Unexpected content type: ${contentType}`
1704
+ message: `MCP HTTP Transport Error: Unexpected content type: ${contentType}`,
1705
+ statusCode: response.status,
1706
+ url: this.url.href
1444
1707
  });
1445
1708
  (_f = this.onerror) == null ? void 0 : _f.call(this, error);
1446
1709
  throw error;
@@ -1492,10 +1755,11 @@ var HttpMCPTransport = class {
1492
1755
  if (resumeToken) {
1493
1756
  headers["last-event-id"] = resumeToken;
1494
1757
  }
1495
- const response = await fetch(this.url.href, {
1758
+ const response = await this.fetchFn(this.url.href, {
1496
1759
  method: "GET",
1497
1760
  headers,
1498
- signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal
1761
+ signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1762
+ redirect: this.redirectMode
1499
1763
  });
1500
1764
  const sessionId = response.headers.get("mcp-session-id");
1501
1765
  if (sessionId) {
@@ -1504,10 +1768,7 @@ var HttpMCPTransport = class {
1504
1768
  if (response.status === 401 && this.authProvider && !triedAuth) {
1505
1769
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1506
1770
  try {
1507
- const result = await auth(this.authProvider, {
1508
- serverUrl: this.url,
1509
- resourceMetadataUrl: this.resourceMetadataUrl
1510
- });
1771
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
1511
1772
  if (result !== "AUTHORIZED") {
1512
1773
  const error = new UnauthorizedError();
1513
1774
  (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
@@ -1524,12 +1785,14 @@ var HttpMCPTransport = class {
1524
1785
  }
1525
1786
  if (!response.ok || !response.body) {
1526
1787
  const error = new MCPClientError({
1527
- message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}`
1788
+ message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}`,
1789
+ statusCode: response.status,
1790
+ url: this.url.href
1528
1791
  });
1529
1792
  (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1530
1793
  return;
1531
1794
  }
1532
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils2.EventSourceParserStream());
1795
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1533
1796
  const reader = stream.getReader();
1534
1797
  const processEvents = async () => {
1535
1798
  var _a4, _b4, _c2, _d2;
@@ -1541,10 +1804,10 @@ var HttpMCPTransport = class {
1541
1804
  if (id) {
1542
1805
  this.lastInboundEventId = id;
1543
1806
  }
1544
- if (event === "message") {
1807
+ if (isMessageEvent2(event)) {
1545
1808
  try {
1546
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1547
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, msg);
1809
+ const jsonRpcMessage = await parseJSONRPCMessage(data);
1810
+ (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, jsonRpcMessage);
1548
1811
  } catch (error) {
1549
1812
  const e = new MCPClientError({
1550
1813
  message: "MCP HTTP Transport Error: Failed to parse message",
@@ -1598,6 +1861,112 @@ function isCustomMcpTransport(transport) {
1598
1861
  return "start" in transport && typeof transport.start === "function" && "send" in transport && typeof transport.send === "function" && "close" in transport && typeof transport.close === "function";
1599
1862
  }
1600
1863
 
1864
+ // src/tool/mcp-apps.ts
1865
+ import { isJSONObject } from "@ai-sdk/provider";
1866
+ import { convertBase64ToUint8Array } from "@ai-sdk/provider-utils";
1867
+ var MCP_APP_EXTENSION_NAME = "io.modelcontextprotocol/ui";
1868
+ var MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
1869
+ var MCP_APP_LEGACY_RESOURCE_URI_META_KEY = "ui/resourceUri";
1870
+ var mcpAppClientCapabilities = {
1871
+ extensions: {
1872
+ [MCP_APP_EXTENSION_NAME]: {
1873
+ mimeTypes: [MCP_APP_MIME_TYPE]
1874
+ }
1875
+ }
1876
+ };
1877
+ function getToolUiMeta(meta) {
1878
+ const uiMeta = meta == null ? void 0 : meta.ui;
1879
+ return isJSONObject(uiMeta) ? uiMeta : void 0;
1880
+ }
1881
+ function getResourceUiMeta(meta) {
1882
+ const resourceMeta = isJSONObject(meta) ? meta : void 0;
1883
+ const rawUiMeta = resourceMeta == null ? void 0 : resourceMeta.ui;
1884
+ const uiMeta = isJSONObject(rawUiMeta) ? rawUiMeta : void 0;
1885
+ return uiMeta;
1886
+ }
1887
+ function parseVisibility(value) {
1888
+ return Array.isArray(value) ? value.filter(
1889
+ (v) => v === "model" || v === "app"
1890
+ ) : void 0;
1891
+ }
1892
+ function getMCPAppToolMeta(tool2) {
1893
+ var _a3, _b3;
1894
+ const uiMeta = getToolUiMeta(tool2._meta);
1895
+ const resourceUri = (_b3 = uiMeta == null ? void 0 : uiMeta.resourceUri) != null ? _b3 : (_a3 = tool2._meta) == null ? void 0 : _a3[MCP_APP_LEGACY_RESOURCE_URI_META_KEY];
1896
+ const visibility = parseVisibility(uiMeta == null ? void 0 : uiMeta.visibility);
1897
+ if (resourceUri !== void 0) {
1898
+ if (typeof resourceUri !== "string" || !resourceUri.startsWith("ui://")) {
1899
+ throw new Error(
1900
+ `Invalid MCP App resource URI: ${JSON.stringify(resourceUri)}`
1901
+ );
1902
+ }
1903
+ } else if (uiMeta == null) {
1904
+ return void 0;
1905
+ }
1906
+ return {
1907
+ ...uiMeta,
1908
+ ...resourceUri != null ? { resourceUri } : {},
1909
+ ...visibility != null ? { visibility } : {}
1910
+ };
1911
+ }
1912
+ function splitMCPAppTools(definitions) {
1913
+ var _a3;
1914
+ const modelVisibleTools = [];
1915
+ const appVisibleTools = [];
1916
+ for (const tool2 of definitions.tools) {
1917
+ const visibility = (_a3 = getMCPAppToolMeta(tool2)) == null ? void 0 : _a3.visibility;
1918
+ if (visibility == null || visibility.includes("model")) {
1919
+ modelVisibleTools.push(tool2);
1920
+ }
1921
+ if ((visibility == null ? void 0 : visibility.includes("app")) === true) {
1922
+ appVisibleTools.push(tool2);
1923
+ }
1924
+ }
1925
+ return {
1926
+ modelVisible: {
1927
+ ...definitions,
1928
+ tools: modelVisibleTools
1929
+ },
1930
+ appVisible: {
1931
+ ...definitions,
1932
+ tools: appVisibleTools
1933
+ }
1934
+ };
1935
+ }
1936
+ function getMCPAppResourceFromReadResult({
1937
+ uri,
1938
+ resource
1939
+ }) {
1940
+ const content = resource.contents.find((content2) => content2.uri === uri);
1941
+ if (content == null) {
1942
+ throw new Error(`MCP App resource not found in read result: ${uri}`);
1943
+ }
1944
+ if (content.mimeType !== MCP_APP_MIME_TYPE) {
1945
+ throw new Error(
1946
+ `Unsupported MCP App resource MIME type: ${content.mimeType}`
1947
+ );
1948
+ }
1949
+ const html = "text" in content && typeof content.text === "string" ? content.text : "blob" in content && typeof content.blob === "string" ? new TextDecoder().decode(convertBase64ToUint8Array(content.blob)) : void 0;
1950
+ if (html == null) {
1951
+ throw new Error(`Unsupported MCP App resource content format: ${uri}`);
1952
+ }
1953
+ const meta = getResourceUiMeta(content._meta);
1954
+ return { uri, mimeType: MCP_APP_MIME_TYPE, html, meta };
1955
+ }
1956
+ async function readMCPAppResource({
1957
+ client,
1958
+ uri,
1959
+ options
1960
+ }) {
1961
+ if (!uri.startsWith("ui://")) {
1962
+ throw new Error(`Unsupported MCP App resource URI: ${uri}`);
1963
+ }
1964
+ return getMCPAppResourceFromReadResult({
1965
+ uri,
1966
+ resource: await client.readResource({ uri, options })
1967
+ });
1968
+ }
1969
+
1601
1970
  // src/tool/mcp-client.ts
1602
1971
  var CLIENT_VERSION = "1.0.0";
1603
1972
  function mcpToModelOutput({
@@ -1614,9 +1983,9 @@ function mcpToModelOutput({
1614
1983
  }
1615
1984
  if (part.type === "image" && "data" in part && "mimeType" in part) {
1616
1985
  return {
1617
- type: "image-data",
1618
- data: part.data,
1619
- mediaType: part.mimeType
1986
+ type: "file",
1987
+ mediaType: part.mimeType,
1988
+ data: { type: "data", data: part.data }
1620
1989
  };
1621
1990
  }
1622
1991
  return { type: "text", text: JSON.stringify(part) };
@@ -1632,7 +2001,8 @@ async function createMCPClient(config) {
1632
2001
  var DefaultMCPClient = class {
1633
2002
  constructor({
1634
2003
  transport: transportConfig,
1635
- name: name3 = "ai-sdk-mcp-client",
2004
+ name: name3,
2005
+ clientName = name3 != null ? name3 : "ai-sdk-mcp-client",
1636
2006
  version = CLIENT_VERSION,
1637
2007
  onUncaughtError,
1638
2008
  capabilities
@@ -1640,6 +2010,7 @@ var DefaultMCPClient = class {
1640
2010
  this.requestMessageId = 0;
1641
2011
  this.responseHandlers = /* @__PURE__ */ new Map();
1642
2012
  this.serverCapabilities = {};
2013
+ this._serverInfo = { name: "", version: "" };
1643
2014
  this.isClosed = true;
1644
2015
  this.onUncaughtError = onUncaughtError;
1645
2016
  this.clientCapabilities = capabilities != null ? capabilities : {};
@@ -1666,10 +2037,16 @@ var DefaultMCPClient = class {
1666
2037
  this.onResponse(message);
1667
2038
  };
1668
2039
  this.clientInfo = {
1669
- name: name3,
2040
+ name: clientName,
1670
2041
  version
1671
2042
  };
1672
2043
  }
2044
+ get serverInfo() {
2045
+ return this._serverInfo;
2046
+ }
2047
+ get instructions() {
2048
+ return this._serverInstructions;
2049
+ }
1673
2050
  async init() {
1674
2051
  try {
1675
2052
  await this.transport.start();
@@ -1696,6 +2073,13 @@ var DefaultMCPClient = class {
1696
2073
  });
1697
2074
  }
1698
2075
  this.serverCapabilities = result.capabilities;
2076
+ this._serverInfo = result.serverInfo;
2077
+ if (this.transport.setProtocolVersion) {
2078
+ this.transport.setProtocolVersion(result.protocolVersion);
2079
+ } else {
2080
+ this.transport.protocolVersion = result.protocolVersion;
2081
+ }
2082
+ this._serverInstructions = result.instructions;
1699
2083
  await this.notification({
1700
2084
  method: "notifications/initialized"
1701
2085
  });
@@ -1812,16 +2196,14 @@ var DefaultMCPClient = class {
1812
2196
  }
1813
2197
  async callTool({
1814
2198
  name: name3,
1815
- args,
2199
+ arguments: args = {},
1816
2200
  options
1817
2201
  }) {
1818
2202
  try {
1819
2203
  return this.request({
1820
2204
  request: { method: "tools/call", params: { name: name3, arguments: args } },
1821
2205
  resultSchema: CallToolResultSchema,
1822
- options: {
1823
- signal: options == null ? void 0 : options.abortSignal
1824
- }
2206
+ options
1825
2207
  });
1826
2208
  } catch (error) {
1827
2209
  throw error;
@@ -1932,33 +2314,54 @@ var DefaultMCPClient = class {
1932
2314
  _meta
1933
2315
  } of definitions.tools) {
1934
2316
  const resolvedTitle = title != null ? title : annotations == null ? void 0 : annotations.title;
1935
- if (schemas !== "automatic" && !(name3 in schemas)) {
2317
+ if (schemas !== "automatic" && !Object.prototype.hasOwnProperty.call(schemas, name3)) {
1936
2318
  continue;
1937
2319
  }
1938
2320
  const self = this;
1939
2321
  const outputSchema = schemas !== "automatic" ? (_a3 = schemas[name3]) == null ? void 0 : _a3.outputSchema : void 0;
2322
+ const appMeta = getMCPAppToolMeta({ _meta });
2323
+ const metadata = {
2324
+ clientName: this.clientInfo.name,
2325
+ toolName: name3,
2326
+ ...resolvedTitle != null ? { title: resolvedTitle } : {},
2327
+ ...(appMeta == null ? void 0 : appMeta.resourceUri) != null ? {
2328
+ app: {
2329
+ ...appMeta,
2330
+ mimeType: MCP_APP_MIME_TYPE
2331
+ }
2332
+ } : {}
2333
+ };
1940
2334
  const execute = async (args, options) => {
1941
2335
  var _a4;
1942
2336
  (_a4 = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a4.throwIfAborted();
1943
- const result = await self.callTool({ name: name3, args, options });
2337
+ const result = await self.callTool({
2338
+ name: name3,
2339
+ arguments: args,
2340
+ options: { signal: options == null ? void 0 : options.abortSignal }
2341
+ });
2342
+ if (result.isError) {
2343
+ return result;
2344
+ }
1944
2345
  if (outputSchema != null) {
1945
2346
  return self.extractStructuredContent(result, outputSchema, name3);
1946
2347
  }
1947
2348
  return result;
1948
2349
  };
1949
- const toolWithExecute = schemas === "automatic" ? (0, import_provider_utils3.dynamicTool)({
2350
+ const toolWithExecute = schemas === "automatic" ? dynamicTool({
1950
2351
  description,
1951
2352
  title: resolvedTitle,
1952
- inputSchema: (0, import_provider_utils3.jsonSchema)({
2353
+ metadata,
2354
+ inputSchema: jsonSchema({
1953
2355
  ...inputSchema,
1954
2356
  properties: (_b3 = inputSchema.properties) != null ? _b3 : {},
1955
2357
  additionalProperties: false
1956
2358
  }),
1957
2359
  execute,
1958
2360
  toModelOutput: mcpToModelOutput
1959
- }) : (0, import_provider_utils3.tool)({
2361
+ }) : tool({
1960
2362
  description,
1961
2363
  title: resolvedTitle,
2364
+ metadata,
1962
2365
  inputSchema: schemas[name3].inputSchema,
1963
2366
  ...outputSchema != null ? { outputSchema } : {},
1964
2367
  execute,
@@ -1973,9 +2376,9 @@ var DefaultMCPClient = class {
1973
2376
  */
1974
2377
  async extractStructuredContent(result, outputSchema, toolName) {
1975
2378
  if ("structuredContent" in result && result.structuredContent != null) {
1976
- const validationResult = await (0, import_provider_utils3.safeValidateTypes)({
2379
+ const validationResult = await safeValidateTypes({
1977
2380
  value: result.structuredContent,
1978
- schema: (0, import_provider_utils3.asSchema)(outputSchema)
2381
+ schema: asSchema(outputSchema)
1979
2382
  });
1980
2383
  if (!validationResult.success) {
1981
2384
  throw new MCPClientError({
@@ -1988,7 +2391,7 @@ var DefaultMCPClient = class {
1988
2391
  if ("content" in result && Array.isArray(result.content)) {
1989
2392
  const textContent = result.content.find((c) => c.type === "text");
1990
2393
  if (textContent && "text" in textContent) {
1991
- const parseResult = await (0, import_provider_utils3.safeParseJSON)({
2394
+ const parseResult = await safeParseJSON({
1992
2395
  text: textContent.text,
1993
2396
  schema: outputSchema
1994
2397
  });
@@ -2045,6 +2448,14 @@ var DefaultMCPClient = class {
2045
2448
  }
2046
2449
  async onRequestMessage(request) {
2047
2450
  try {
2451
+ if (request.method === "ping") {
2452
+ await this.transport.send({
2453
+ jsonrpc: "2.0",
2454
+ id: request.id,
2455
+ result: {}
2456
+ });
2457
+ return;
2458
+ }
2048
2459
  if (request.method !== "elicitation/create") {
2049
2460
  await this.transport.send({
2050
2461
  jsonrpc: "2.0",
@@ -2143,13 +2554,16 @@ var DefaultMCPClient = class {
2143
2554
  );
2144
2555
  }
2145
2556
  };
2146
- // Annotate the CommonJS export names for ESM import in node:
2147
- 0 && (module.exports = {
2557
+ export {
2148
2558
  ElicitResultSchema,
2149
2559
  ElicitationRequestSchema,
2560
+ MCP_APP_MIME_TYPE,
2150
2561
  UnauthorizedError,
2151
2562
  auth,
2152
2563
  createMCPClient,
2153
- experimental_createMCPClient
2154
- });
2564
+ createMCPClient as experimental_createMCPClient,
2565
+ mcpAppClientCapabilities,
2566
+ readMCPAppResource,
2567
+ splitMCPAppTools
2568
+ };
2155
2569
  //# sourceMappingURL=index.js.map