@ai-sdk/mcp 1.0.47 → 1.0.49

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/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.49
4
+
5
+ ### Patch Changes
6
+
7
+ - 3e8d9ba: fix(mcp): lock first sse endpoint received via event
8
+ - 4fa7354: fix(mcp): prevent prototype-named tools from bypassing the `schemas` allowlist
9
+
10
+ When using `client.tools({ schemas })` to expose only an explicitly allowed
11
+ subset of an MCP server's tools, the allowlist check used the `in` operator,
12
+ which also matches inherited `Object.prototype` properties. A server-advertised
13
+ tool named `constructor`, `toString`, `__proto__`, etc. would pass the check
14
+ even though the developer never defined it in `schemas`, and was then exposed to
15
+ the model and executable. The check now uses `Object.hasOwn`, so only
16
+ explicitly defined tools are returned.
17
+
18
+ - Updated dependencies [bfa5864]
19
+ - Updated dependencies [f42aa79]
20
+ - @ai-sdk/provider-utils@4.0.29
21
+
22
+ ## 1.0.48
23
+
24
+ ### Patch Changes
25
+
26
+ - 26d93a4: fix(mcp): add optional hook to validate authorization servers
27
+ - 3c9ad04: fix(mcp): support official sdk protocol version negotiation
28
+ - Updated dependencies [942f2f8]
29
+ - @ai-sdk/provider-utils@4.0.28
30
+
3
31
  ## 1.0.47
4
32
 
5
33
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -191,6 +191,11 @@ interface OAuthClientProvider {
191
191
  saveClientInformation?(clientInformation: OAuthClientInformation): void | Promise<void>;
192
192
  authorizationServerInformation?(): OAuthAuthorizationServerInformation | undefined | Promise<OAuthAuthorizationServerInformation | undefined>;
193
193
  saveAuthorizationServerInformation?(authorizationServerInformation: OAuthAuthorizationServerInformation): void | Promise<void>;
194
+ /**
195
+ * Validates an authorization server URL discovered from MCP protected resource
196
+ * metadata before the client fetches its OAuth metadata.
197
+ */
198
+ validateAuthorizationServerURL?(serverUrl: string | URL, authorizationServerUrl: string | URL): void | Promise<void>;
194
199
  state?(): string | Promise<string>;
195
200
  saveState?(state: string): void | Promise<void>;
196
201
  storedState?(): string | undefined | Promise<string | undefined>;
@@ -242,6 +247,10 @@ interface MCPTransport {
242
247
  * The protocol version negotiated during initialization.
243
248
  */
244
249
  protocolVersion?: string;
250
+ /**
251
+ * Set the protocol version negotiated during initialization.
252
+ */
253
+ setProtocolVersion?(version: string): void;
245
254
  }
246
255
  type MCPTransportConfig = {
247
256
  type: 'sse' | 'http';
package/dist/index.d.ts CHANGED
@@ -191,6 +191,11 @@ interface OAuthClientProvider {
191
191
  saveClientInformation?(clientInformation: OAuthClientInformation): void | Promise<void>;
192
192
  authorizationServerInformation?(): OAuthAuthorizationServerInformation | undefined | Promise<OAuthAuthorizationServerInformation | undefined>;
193
193
  saveAuthorizationServerInformation?(authorizationServerInformation: OAuthAuthorizationServerInformation): void | Promise<void>;
194
+ /**
195
+ * Validates an authorization server URL discovered from MCP protected resource
196
+ * metadata before the client fetches its OAuth metadata.
197
+ */
198
+ validateAuthorizationServerURL?(serverUrl: string | URL, authorizationServerUrl: string | URL): void | Promise<void>;
194
199
  state?(): string | Promise<string>;
195
200
  saveState?(state: string): void | Promise<void>;
196
201
  storedState?(): string | undefined | Promise<string | undefined>;
@@ -242,6 +247,10 @@ interface MCPTransport {
242
247
  * The protocol version negotiated during initialization.
243
248
  */
244
249
  protocolVersion?: string;
250
+ /**
251
+ * Set the protocol version negotiated during initialization.
252
+ */
253
+ setProtocolVersion?(version: string): void;
245
254
  }
246
255
  type MCPTransportConfig = {
247
256
  type: 'sse' | 'http';
package/dist/index.js CHANGED
@@ -1105,7 +1105,7 @@ async function authInternal(provider, {
1105
1105
  resourceMetadataUrl,
1106
1106
  fetchFn
1107
1107
  }) {
1108
- var _a3;
1108
+ var _a3, _b3;
1109
1109
  let resourceMetadata;
1110
1110
  let authorizationServerUrl;
1111
1111
  assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl);
@@ -1128,6 +1128,11 @@ async function authInternal(provider, {
1128
1128
  provider,
1129
1129
  resourceMetadata
1130
1130
  );
1131
+ await ((_a3 = provider.validateAuthorizationServerURL) == null ? void 0 : _a3.call(
1132
+ provider,
1133
+ serverUrl,
1134
+ authorizationServerUrl
1135
+ ));
1131
1136
  const metadata = await discoverAuthorizationServerMetadata(
1132
1137
  authorizationServerUrl,
1133
1138
  {
@@ -1212,7 +1217,7 @@ async function authInternal(provider, {
1212
1217
  currentAuthorizationServerInformation
1213
1218
  });
1214
1219
  } else {
1215
- await ((_a3 = provider.invalidateCredentials) == null ? void 0 : _a3.call(provider, "tokens"));
1220
+ await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "tokens"));
1216
1221
  }
1217
1222
  try {
1218
1223
  if (storedAuthorizationServerInformation) {
@@ -1288,6 +1293,9 @@ var SseMCPTransport = class {
1288
1293
  this.redirectMode = redirect;
1289
1294
  this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1290
1295
  }
1296
+ setProtocolVersion(version) {
1297
+ this.protocolVersion = version;
1298
+ }
1291
1299
  async commonHeaders(base) {
1292
1300
  var _a3;
1293
1301
  const headers = {
@@ -1357,7 +1365,7 @@ var SseMCPTransport = class {
1357
1365
  const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new import_provider_utils3.EventSourceParserStream());
1358
1366
  const reader = stream.getReader();
1359
1367
  const processEvents = async () => {
1360
- var _a4, _b4, _c2;
1368
+ var _a4, _b4, _c2, _d2, _e2;
1361
1369
  try {
1362
1370
  while (true) {
1363
1371
  const { done, value } = await reader.read();
@@ -1372,24 +1380,32 @@ var SseMCPTransport = class {
1372
1380
  }
1373
1381
  const { event, data } = value;
1374
1382
  if (event === "endpoint") {
1375
- this.endpoint = new URL(data, this.url);
1376
- if (this.endpoint.origin !== this.url.origin) {
1383
+ if (this.endpoint) {
1384
+ continue;
1385
+ }
1386
+ const endpoint = new URL(data, this.url);
1387
+ if (endpoint.origin !== this.url.origin) {
1388
+ this.connected = false;
1389
+ this.endpoint = void 0;
1390
+ (_a4 = this.sseConnection) == null ? void 0 : _a4.close();
1391
+ (_b4 = this.abortController) == null ? void 0 : _b4.abort();
1377
1392
  throw new MCPClientError({
1378
- message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${this.endpoint.origin}`
1393
+ message: `MCP SSE Transport Error: Endpoint origin does not match connection origin: ${endpoint.origin}`
1379
1394
  });
1380
1395
  }
1396
+ this.endpoint = endpoint;
1381
1397
  this.connected = true;
1382
1398
  resolve();
1383
1399
  } else if (event === "message") {
1384
1400
  try {
1385
1401
  const message = await parseJSONRPCMessage(data);
1386
- (_a4 = this.onmessage) == null ? void 0 : _a4.call(this, message);
1402
+ (_c2 = this.onmessage) == null ? void 0 : _c2.call(this, message);
1387
1403
  } catch (error) {
1388
1404
  const e = new MCPClientError({
1389
1405
  message: "MCP SSE Transport Error: Failed to parse message",
1390
1406
  cause: error
1391
1407
  });
1392
- (_b4 = this.onerror) == null ? void 0 : _b4.call(this, e);
1408
+ (_d2 = this.onerror) == null ? void 0 : _d2.call(this, e);
1393
1409
  }
1394
1410
  }
1395
1411
  }
@@ -1397,7 +1413,7 @@ var SseMCPTransport = class {
1397
1413
  if (error instanceof Error && error.name === "AbortError") {
1398
1414
  return;
1399
1415
  }
1400
- (_c2 = this.onerror) == null ? void 0 : _c2.call(this, error);
1416
+ (_e2 = this.onerror) == null ? void 0 : _e2.call(this, error);
1401
1417
  reject(error);
1402
1418
  }
1403
1419
  };
@@ -1419,6 +1435,7 @@ var SseMCPTransport = class {
1419
1435
  async close() {
1420
1436
  var _a3, _b3, _c;
1421
1437
  this.connected = false;
1438
+ this.endpoint = void 0;
1422
1439
  (_a3 = this.sseConnection) == null ? void 0 : _a3.close();
1423
1440
  (_b3 = this.abortController) == null ? void 0 : _b3.abort();
1424
1441
  (_c = this.onclose) == null ? void 0 : _c.call(this);
@@ -1503,6 +1520,9 @@ var HttpMCPTransport = class {
1503
1520
  this.redirectMode = redirect;
1504
1521
  this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
1505
1522
  }
1523
+ setProtocolVersion(version) {
1524
+ this.protocolVersion = version;
1525
+ }
1506
1526
  async commonHeaders(base) {
1507
1527
  var _a3;
1508
1528
  const headers = {
@@ -1946,8 +1966,12 @@ var DefaultMCPClient = class {
1946
1966
  }
1947
1967
  this.serverCapabilities = result.capabilities;
1948
1968
  this._serverInfo = result.serverInfo;
1969
+ if (this.transport.setProtocolVersion) {
1970
+ this.transport.setProtocolVersion(result.protocolVersion);
1971
+ } else {
1972
+ this.transport.protocolVersion = result.protocolVersion;
1973
+ }
1949
1974
  this._serverInstructions = result.instructions;
1950
- this.transport.protocolVersion = result.protocolVersion;
1951
1975
  await this.notification({
1952
1976
  method: "notifications/initialized"
1953
1977
  });
@@ -2184,7 +2208,7 @@ var DefaultMCPClient = class {
2184
2208
  _meta
2185
2209
  } of definitions.tools) {
2186
2210
  const resolvedTitle = title != null ? title : annotations == null ? void 0 : annotations.title;
2187
- if (schemas !== "automatic" && !(name3 in schemas)) {
2211
+ if (schemas !== "automatic" && !Object.prototype.hasOwnProperty.call(schemas, name3)) {
2188
2212
  continue;
2189
2213
  }
2190
2214
  const self = this;