@ai-sdk/mcp 2.0.0-beta.6 → 2.0.0-beta.67

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,30 +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
1276
  authProvider,
1076
- redirect = "follow"
1277
+ redirect = "error",
1278
+ fetch: fetchFn
1077
1279
  }) {
1078
1280
  this.connected = false;
1079
1281
  this.url = new URL(url);
1080
1282
  this.headers = headers;
1081
1283
  this.authProvider = authProvider;
1082
1284
  this.redirectMode = redirect;
1285
+ this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1286
+ }
1287
+ setProtocolVersion(version) {
1288
+ this.protocolVersion = version;
1083
1289
  }
1084
1290
  async commonHeaders(base) {
1291
+ var _a3;
1085
1292
  const headers = {
1086
1293
  ...this.headers,
1087
1294
  ...base,
1088
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1295
+ "mcp-protocol-version": (_a3 = this.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION
1089
1296
  };
1090
1297
  if (this.authProvider) {
1091
1298
  const tokens = await this.authProvider.tokens();
@@ -1093,10 +1300,10 @@ var SseMCPTransport = class {
1093
1300
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
1094
1301
  }
1095
1302
  }
1096
- return (0, import_provider_utils.withUserAgentSuffix)(
1303
+ return withUserAgentSuffix(
1097
1304
  headers,
1098
1305
  `ai-sdk/${VERSION}`,
1099
- (0, import_provider_utils.getRuntimeEnvironmentUserAgent)()
1306
+ getRuntimeEnvironmentUserAgent()
1100
1307
  );
1101
1308
  }
1102
1309
  async start() {
@@ -1111,7 +1318,7 @@ var SseMCPTransport = class {
1111
1318
  const headers = await this.commonHeaders({
1112
1319
  Accept: "text/event-stream"
1113
1320
  });
1114
- const response = await fetch(this.url.href, {
1321
+ const response = await this.fetchFn(this.url.href, {
1115
1322
  headers,
1116
1323
  signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1117
1324
  redirect: this.redirectMode
@@ -1121,7 +1328,8 @@ var SseMCPTransport = class {
1121
1328
  try {
1122
1329
  const result = await auth(this.authProvider, {
1123
1330
  serverUrl: this.url,
1124
- resourceMetadataUrl: this.resourceMetadataUrl
1331
+ resourceMetadataUrl: this.resourceMetadataUrl,
1332
+ fetchFn: this.fetchFn
1125
1333
  });
1126
1334
  if (result !== "AUTHORIZED") {
1127
1335
  const error = new UnauthorizedError();
@@ -1145,10 +1353,10 @@ var SseMCPTransport = class {
1145
1353
  (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1146
1354
  return reject(error);
1147
1355
  }
1148
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils.EventSourceParserStream());
1356
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream());
1149
1357
  const reader = stream.getReader();
1150
1358
  const processEvents = async () => {
1151
- var _a4, _b4, _c2;
1359
+ var _a4, _b4, _c2, _d2, _e2;
1152
1360
  try {
1153
1361
  while (true) {
1154
1362
  const { done, value } = await reader.read();
@@ -1163,26 +1371,32 @@ var SseMCPTransport = class {
1163
1371
  }
1164
1372
  const { event, data } = value;
1165
1373
  if (event === "endpoint") {
1166
- this.endpoint = new URL(data, this.url);
1167
- 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();
1168
1383
  throw new MCPClientError({
1169
- 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}`
1170
1385
  });
1171
1386
  }
1387
+ this.endpoint = endpoint;
1172
1388
  this.connected = true;
1173
1389
  resolve();
1174
- } else if (event === "message") {
1390
+ } else if (isMessageEvent(event)) {
1175
1391
  try {
1176
- const message = JSONRPCMessageSchema.parse(
1177
- JSON.parse(data)
1178
- );
1179
- (_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);
1180
1394
  } catch (error) {
1181
1395
  const e = new MCPClientError({
1182
1396
  message: "MCP SSE Transport Error: Failed to parse message",
1183
1397
  cause: error
1184
1398
  });
1185
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1399
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, e);
1186
1400
  }
1187
1401
  }
1188
1402
  }
@@ -1190,7 +1404,7 @@ var SseMCPTransport = class {
1190
1404
  if (error instanceof Error && error.name === "AbortError") {
1191
1405
  return;
1192
1406
  }
1193
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1407
+ (_e2 = this.onerror) == null ? void 0 : _e2.call(this, error);
1194
1408
  reject(error);
1195
1409
  }
1196
1410
  };
@@ -1212,6 +1426,7 @@ var SseMCPTransport = class {
1212
1426
  async close() {
1213
1427
  var _a3, _b3, _c;
1214
1428
  this.connected = false;
1429
+ this.endpoint = void 0;
1215
1430
  (_a3 = this.sseConnection) == null ? void 0 : _a3.close();
1216
1431
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1217
1432
  (_c = this.onclose) == null ? void 0 : _c.call(this);
@@ -1236,13 +1451,14 @@ var SseMCPTransport = class {
1236
1451
  signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1237
1452
  redirect: this.redirectMode
1238
1453
  };
1239
- const response = await fetch(endpoint, init);
1454
+ const response = await this.fetchFn(endpoint.href, init);
1240
1455
  if (response.status === 401 && this.authProvider && !triedAuth) {
1241
1456
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1242
1457
  try {
1243
1458
  const result = await auth(this.authProvider, {
1244
1459
  serverUrl: this.url,
1245
- resourceMetadataUrl: this.resourceMetadataUrl
1460
+ resourceMetadataUrl: this.resourceMetadataUrl,
1461
+ fetchFn: this.fetchFn
1246
1462
  });
1247
1463
  if (result !== "AUTHORIZED") {
1248
1464
  const error = new UnauthorizedError();
@@ -1273,13 +1489,21 @@ var SseMCPTransport = class {
1273
1489
  };
1274
1490
 
1275
1491
  // src/tool/mcp-http-transport.ts
1276
- 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
+ }
1277
1500
  var HttpMCPTransport = class {
1278
1501
  constructor({
1279
1502
  url,
1280
1503
  headers,
1281
1504
  authProvider,
1282
- redirect = "follow"
1505
+ redirect = "error",
1506
+ fetch: fetchFn
1283
1507
  }) {
1284
1508
  this.inboundReconnectAttempts = 0;
1285
1509
  this.reconnectionOptions = {
@@ -1292,12 +1516,17 @@ var HttpMCPTransport = class {
1292
1516
  this.headers = headers;
1293
1517
  this.authProvider = authProvider;
1294
1518
  this.redirectMode = redirect;
1519
+ this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1520
+ }
1521
+ setProtocolVersion(version) {
1522
+ this.protocolVersion = version;
1295
1523
  }
1296
1524
  async commonHeaders(base) {
1525
+ var _a3;
1297
1526
  const headers = {
1298
1527
  ...this.headers,
1299
1528
  ...base,
1300
- "mcp-protocol-version": LATEST_PROTOCOL_VERSION
1529
+ "mcp-protocol-version": (_a3 = this.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION
1301
1530
  };
1302
1531
  if (this.sessionId) {
1303
1532
  headers["mcp-session-id"] = this.sessionId;
@@ -1308,12 +1537,30 @@ var HttpMCPTransport = class {
1308
1537
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
1309
1538
  }
1310
1539
  }
1311
- return (0, import_provider_utils2.withUserAgentSuffix)(
1540
+ return withUserAgentSuffix2(
1312
1541
  headers,
1313
1542
  `ai-sdk/${VERSION}`,
1314
- (0, import_provider_utils2.getRuntimeEnvironmentUserAgent)()
1543
+ getRuntimeEnvironmentUserAgent2()
1315
1544
  );
1316
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
+ }
1317
1564
  async start() {
1318
1565
  if (this.abortController) {
1319
1566
  throw new MCPClientError({
@@ -1329,7 +1576,7 @@ var HttpMCPTransport = class {
1329
1576
  try {
1330
1577
  if (this.sessionId && this.abortController && !this.abortController.signal.aborted) {
1331
1578
  const headers = await this.commonHeaders({});
1332
- await fetch(this.url, {
1579
+ await this.fetchFn(this.url.href, {
1333
1580
  method: "DELETE",
1334
1581
  headers,
1335
1582
  signal: this.abortController.signal,
@@ -1356,7 +1603,7 @@ var HttpMCPTransport = class {
1356
1603
  signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
1357
1604
  redirect: this.redirectMode
1358
1605
  };
1359
- const response = await fetch(this.url, init);
1606
+ const response = await this.fetchFn(this.url.href, init);
1360
1607
  const sessionId = response.headers.get("mcp-session-id");
1361
1608
  if (sessionId) {
1362
1609
  this.sessionId = sessionId;
@@ -1364,10 +1611,7 @@ var HttpMCPTransport = class {
1364
1611
  if (response.status === 401 && this.authProvider && !triedAuth) {
1365
1612
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1366
1613
  try {
1367
- const result = await auth(this.authProvider, {
1368
- serverUrl: this.url,
1369
- resourceMetadataUrl: this.resourceMetadataUrl
1370
- });
1614
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
1371
1615
  if (result !== "AUTHORIZED") {
1372
1616
  const error2 = new UnauthorizedError();
1373
1617
  throw error2;
@@ -1391,7 +1635,10 @@ var HttpMCPTransport = class {
1391
1635
  errorMessage += ". This server does not support HTTP transport. Try using `sse` transport instead";
1392
1636
  }
1393
1637
  const error2 = new MCPClientError({
1394
- message: errorMessage
1638
+ message: errorMessage,
1639
+ statusCode: response.status,
1640
+ url: this.url.href,
1641
+ responseBody: text != null ? text : void 0
1395
1642
  });
1396
1643
  (_c = this.onerror) == null ? void 0 : _c.call(this, error2);
1397
1644
  throw error2;
@@ -1403,19 +1650,25 @@ var HttpMCPTransport = class {
1403
1650
  const contentType = response.headers.get("content-type") || "";
1404
1651
  if (contentType.includes("application/json")) {
1405
1652
  const data = await response.json();
1406
- const messages = Array.isArray(data) ? data.map((m) => JSONRPCMessageSchema.parse(m)) : [JSONRPCMessageSchema.parse(data)];
1407
- 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
+ }
1408
1659
  return;
1409
1660
  }
1410
1661
  if (contentType.includes("text/event-stream")) {
1411
1662
  if (!response.body) {
1412
1663
  const error2 = new MCPClientError({
1413
- 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
1414
1667
  });
1415
1668
  (_e = this.onerror) == null ? void 0 : _e.call(this, error2);
1416
1669
  throw error2;
1417
1670
  }
1418
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils2.EventSourceParserStream());
1671
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1419
1672
  const reader = stream.getReader();
1420
1673
  const processEvents = async () => {
1421
1674
  var _a4, _b4, _c2;
@@ -1424,10 +1677,10 @@ var HttpMCPTransport = class {
1424
1677
  const { done, value } = await reader.read();
1425
1678
  if (done) return;
1426
1679
  const { event, data } = value;
1427
- if (event === "message") {
1680
+ if (isMessageEvent2(event)) {
1428
1681
  try {
1429
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1430
- (_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);
1431
1684
  } catch (error2) {
1432
1685
  const e = new MCPClientError({
1433
1686
  message: "MCP HTTP Transport Error: Failed to parse message",
@@ -1448,7 +1701,9 @@ var HttpMCPTransport = class {
1448
1701
  return;
1449
1702
  }
1450
1703
  const error = new MCPClientError({
1451
- 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
1452
1707
  });
1453
1708
  (_f = this.onerror) == null ? void 0 : _f.call(this, error);
1454
1709
  throw error;
@@ -1500,7 +1755,7 @@ var HttpMCPTransport = class {
1500
1755
  if (resumeToken) {
1501
1756
  headers["last-event-id"] = resumeToken;
1502
1757
  }
1503
- const response = await fetch(this.url.href, {
1758
+ const response = await this.fetchFn(this.url.href, {
1504
1759
  method: "GET",
1505
1760
  headers,
1506
1761
  signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
@@ -1513,10 +1768,7 @@ var HttpMCPTransport = class {
1513
1768
  if (response.status === 401 && this.authProvider && !triedAuth) {
1514
1769
  this.resourceMetadataUrl = extractResourceMetadataUrl(response);
1515
1770
  try {
1516
- const result = await auth(this.authProvider, {
1517
- serverUrl: this.url,
1518
- resourceMetadataUrl: this.resourceMetadataUrl
1519
- });
1771
+ const result = await this.authorizeOnce(this.resourceMetadataUrl);
1520
1772
  if (result !== "AUTHORIZED") {
1521
1773
  const error = new UnauthorizedError();
1522
1774
  (_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
@@ -1533,12 +1785,14 @@ var HttpMCPTransport = class {
1533
1785
  }
1534
1786
  if (!response.ok || !response.body) {
1535
1787
  const error = new MCPClientError({
1536
- 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
1537
1791
  });
1538
1792
  (_d = this.onerror) == null ? void 0 : _d.call(this, error);
1539
1793
  return;
1540
1794
  }
1541
- const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils2.EventSourceParserStream());
1795
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream2());
1542
1796
  const reader = stream.getReader();
1543
1797
  const processEvents = async () => {
1544
1798
  var _a4, _b4, _c2, _d2;
@@ -1550,10 +1804,10 @@ var HttpMCPTransport = class {
1550
1804
  if (id) {
1551
1805
  this.lastInboundEventId = id;
1552
1806
  }
1553
- if (event === "message") {
1807
+ if (isMessageEvent2(event)) {
1554
1808
  try {
1555
- const msg = JSONRPCMessageSchema.parse(JSON.parse(data));
1556
- (_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);
1557
1811
  } catch (error) {
1558
1812
  const e = new MCPClientError({
1559
1813
  message: "MCP HTTP Transport Error: Failed to parse message",
@@ -1607,6 +1861,112 @@ function isCustomMcpTransport(transport) {
1607
1861
  return "start" in transport && typeof transport.start === "function" && "send" in transport && typeof transport.send === "function" && "close" in transport && typeof transport.close === "function";
1608
1862
  }
1609
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
+
1610
1970
  // src/tool/mcp-client.ts
1611
1971
  var CLIENT_VERSION = "1.0.0";
1612
1972
  function mcpToModelOutput({
@@ -1623,9 +1983,9 @@ function mcpToModelOutput({
1623
1983
  }
1624
1984
  if (part.type === "image" && "data" in part && "mimeType" in part) {
1625
1985
  return {
1626
- type: "image-data",
1627
- data: part.data,
1628
- mediaType: part.mimeType
1986
+ type: "file",
1987
+ mediaType: part.mimeType,
1988
+ data: { type: "data", data: part.data }
1629
1989
  };
1630
1990
  }
1631
1991
  return { type: "text", text: JSON.stringify(part) };
@@ -1641,7 +2001,8 @@ async function createMCPClient(config) {
1641
2001
  var DefaultMCPClient = class {
1642
2002
  constructor({
1643
2003
  transport: transportConfig,
1644
- name: name3 = "ai-sdk-mcp-client",
2004
+ name: name3,
2005
+ clientName = name3 != null ? name3 : "ai-sdk-mcp-client",
1645
2006
  version = CLIENT_VERSION,
1646
2007
  onUncaughtError,
1647
2008
  capabilities
@@ -1649,6 +2010,7 @@ var DefaultMCPClient = class {
1649
2010
  this.requestMessageId = 0;
1650
2011
  this.responseHandlers = /* @__PURE__ */ new Map();
1651
2012
  this.serverCapabilities = {};
2013
+ this._serverInfo = { name: "", version: "" };
1652
2014
  this.isClosed = true;
1653
2015
  this.onUncaughtError = onUncaughtError;
1654
2016
  this.clientCapabilities = capabilities != null ? capabilities : {};
@@ -1675,10 +2037,16 @@ var DefaultMCPClient = class {
1675
2037
  this.onResponse(message);
1676
2038
  };
1677
2039
  this.clientInfo = {
1678
- name: name3,
2040
+ name: clientName,
1679
2041
  version
1680
2042
  };
1681
2043
  }
2044
+ get serverInfo() {
2045
+ return this._serverInfo;
2046
+ }
2047
+ get instructions() {
2048
+ return this._serverInstructions;
2049
+ }
1682
2050
  async init() {
1683
2051
  try {
1684
2052
  await this.transport.start();
@@ -1705,6 +2073,13 @@ var DefaultMCPClient = class {
1705
2073
  });
1706
2074
  }
1707
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;
1708
2083
  await this.notification({
1709
2084
  method: "notifications/initialized"
1710
2085
  });
@@ -1821,16 +2196,14 @@ var DefaultMCPClient = class {
1821
2196
  }
1822
2197
  async callTool({
1823
2198
  name: name3,
1824
- args,
2199
+ arguments: args = {},
1825
2200
  options
1826
2201
  }) {
1827
2202
  try {
1828
2203
  return this.request({
1829
2204
  request: { method: "tools/call", params: { name: name3, arguments: args } },
1830
2205
  resultSchema: CallToolResultSchema,
1831
- options: {
1832
- signal: options == null ? void 0 : options.abortSignal
1833
- }
2206
+ options
1834
2207
  });
1835
2208
  } catch (error) {
1836
2209
  throw error;
@@ -1941,33 +2314,54 @@ var DefaultMCPClient = class {
1941
2314
  _meta
1942
2315
  } of definitions.tools) {
1943
2316
  const resolvedTitle = title != null ? title : annotations == null ? void 0 : annotations.title;
1944
- if (schemas !== "automatic" && !(name3 in schemas)) {
2317
+ if (schemas !== "automatic" && !Object.prototype.hasOwnProperty.call(schemas, name3)) {
1945
2318
  continue;
1946
2319
  }
1947
2320
  const self = this;
1948
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
+ };
1949
2334
  const execute = async (args, options) => {
1950
2335
  var _a4;
1951
2336
  (_a4 = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a4.throwIfAborted();
1952
- 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
+ }
1953
2345
  if (outputSchema != null) {
1954
2346
  return self.extractStructuredContent(result, outputSchema, name3);
1955
2347
  }
1956
2348
  return result;
1957
2349
  };
1958
- const toolWithExecute = schemas === "automatic" ? (0, import_provider_utils3.dynamicTool)({
2350
+ const toolWithExecute = schemas === "automatic" ? dynamicTool({
1959
2351
  description,
1960
2352
  title: resolvedTitle,
1961
- inputSchema: (0, import_provider_utils3.jsonSchema)({
2353
+ metadata,
2354
+ inputSchema: jsonSchema({
1962
2355
  ...inputSchema,
1963
2356
  properties: (_b3 = inputSchema.properties) != null ? _b3 : {},
1964
2357
  additionalProperties: false
1965
2358
  }),
1966
2359
  execute,
1967
2360
  toModelOutput: mcpToModelOutput
1968
- }) : (0, import_provider_utils3.tool)({
2361
+ }) : tool({
1969
2362
  description,
1970
2363
  title: resolvedTitle,
2364
+ metadata,
1971
2365
  inputSchema: schemas[name3].inputSchema,
1972
2366
  ...outputSchema != null ? { outputSchema } : {},
1973
2367
  execute,
@@ -1982,9 +2376,9 @@ var DefaultMCPClient = class {
1982
2376
  */
1983
2377
  async extractStructuredContent(result, outputSchema, toolName) {
1984
2378
  if ("structuredContent" in result && result.structuredContent != null) {
1985
- const validationResult = await (0, import_provider_utils3.safeValidateTypes)({
2379
+ const validationResult = await safeValidateTypes({
1986
2380
  value: result.structuredContent,
1987
- schema: (0, import_provider_utils3.asSchema)(outputSchema)
2381
+ schema: asSchema(outputSchema)
1988
2382
  });
1989
2383
  if (!validationResult.success) {
1990
2384
  throw new MCPClientError({
@@ -1997,7 +2391,7 @@ var DefaultMCPClient = class {
1997
2391
  if ("content" in result && Array.isArray(result.content)) {
1998
2392
  const textContent = result.content.find((c) => c.type === "text");
1999
2393
  if (textContent && "text" in textContent) {
2000
- const parseResult = await (0, import_provider_utils3.safeParseJSON)({
2394
+ const parseResult = await safeParseJSON({
2001
2395
  text: textContent.text,
2002
2396
  schema: outputSchema
2003
2397
  });
@@ -2054,6 +2448,14 @@ var DefaultMCPClient = class {
2054
2448
  }
2055
2449
  async onRequestMessage(request) {
2056
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
+ }
2057
2459
  if (request.method !== "elicitation/create") {
2058
2460
  await this.transport.send({
2059
2461
  jsonrpc: "2.0",
@@ -2152,13 +2554,16 @@ var DefaultMCPClient = class {
2152
2554
  );
2153
2555
  }
2154
2556
  };
2155
- // Annotate the CommonJS export names for ESM import in node:
2156
- 0 && (module.exports = {
2557
+ export {
2157
2558
  ElicitResultSchema,
2158
2559
  ElicitationRequestSchema,
2560
+ MCP_APP_MIME_TYPE,
2159
2561
  UnauthorizedError,
2160
2562
  auth,
2161
2563
  createMCPClient,
2162
- experimental_createMCPClient
2163
- });
2564
+ createMCPClient as experimental_createMCPClient,
2565
+ mcpAppClientCapabilities,
2566
+ readMCPAppResource,
2567
+ splitMCPAppTools
2568
+ };
2164
2569
  //# sourceMappingURL=index.js.map