mcp-use 1.5.0 → 1.5.1-canary.0

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.
Files changed (47) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/{chunk-WERYJ6PF.js → chunk-2AOGMX4T.js} +1 -1
  3. package/dist/{chunk-DSBKVAWD.js → chunk-2JBWOW4S.js} +152 -0
  4. package/dist/{chunk-UT7O4SIJ.js → chunk-BWOTID2D.js} +209 -75
  5. package/dist/{chunk-GPAOZN2F.js → chunk-QRABML5H.js} +15 -3
  6. package/dist/index.cjs +395 -84
  7. package/dist/index.d.ts +4 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +30 -10
  10. package/dist/src/agents/index.cjs +1 -0
  11. package/dist/src/agents/index.js +2 -2
  12. package/dist/src/browser.cjs +351 -72
  13. package/dist/src/browser.d.ts +2 -0
  14. package/dist/src/browser.d.ts.map +1 -1
  15. package/dist/src/browser.js +2 -2
  16. package/dist/src/client/browser.d.ts.map +1 -1
  17. package/dist/src/client/prompts.cjs +3 -0
  18. package/dist/src/client/prompts.js +2 -2
  19. package/dist/src/client.d.ts +8 -0
  20. package/dist/src/client.d.ts.map +1 -1
  21. package/dist/src/config.d.ts +2 -1
  22. package/dist/src/config.d.ts.map +1 -1
  23. package/dist/src/connectors/base.d.ts +79 -1
  24. package/dist/src/connectors/base.d.ts.map +1 -1
  25. package/dist/src/connectors/http.d.ts +1 -0
  26. package/dist/src/connectors/http.d.ts.map +1 -1
  27. package/dist/src/connectors/stdio.d.ts.map +1 -1
  28. package/dist/src/connectors/websocket.d.ts +6 -0
  29. package/dist/src/connectors/websocket.d.ts.map +1 -1
  30. package/dist/src/react/index.cjs +365 -73
  31. package/dist/src/react/index.d.ts +1 -0
  32. package/dist/src/react/index.d.ts.map +1 -1
  33. package/dist/src/react/index.js +3 -3
  34. package/dist/src/react/types.d.ts +9 -1
  35. package/dist/src/react/types.d.ts.map +1 -1
  36. package/dist/src/react/useMcp.d.ts.map +1 -1
  37. package/dist/src/server/adapters/mcp-ui-adapter.d.ts +1 -0
  38. package/dist/src/server/adapters/mcp-ui-adapter.d.ts.map +1 -1
  39. package/dist/src/server/index.cjs +605 -168
  40. package/dist/src/server/index.js +605 -168
  41. package/dist/src/server/mcp-server.d.ts +201 -10
  42. package/dist/src/server/mcp-server.d.ts.map +1 -1
  43. package/dist/src/server/types/common.d.ts +28 -0
  44. package/dist/src/server/types/common.d.ts.map +1 -1
  45. package/dist/src/session.d.ts +40 -1
  46. package/dist/src/session.d.ts.map +1 -1
  47. package/package.json +10 -4
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  import {
23
23
  CodeModeConnector,
24
24
  PROMPTS
25
- } from "./chunk-WERYJ6PF.js";
25
+ } from "./chunk-2AOGMX4T.js";
26
26
  import {
27
27
  ErrorBoundary,
28
28
  Image,
@@ -34,7 +34,7 @@ import {
34
34
  useWidgetProps,
35
35
  useWidgetState,
36
36
  useWidgetTheme
37
- } from "./chunk-GPAOZN2F.js";
37
+ } from "./chunk-QRABML5H.js";
38
38
  import {
39
39
  BaseMCPClient,
40
40
  BrowserOAuthClientProvider,
@@ -43,10 +43,10 @@ import {
43
43
  MCPSession,
44
44
  WebSocketConnector,
45
45
  onMcpAuthorization
46
- } from "./chunk-UT7O4SIJ.js";
46
+ } from "./chunk-BWOTID2D.js";
47
47
  import {
48
48
  BaseConnector
49
- } from "./chunk-DSBKVAWD.js";
49
+ } from "./chunk-2JBWOW4S.js";
50
50
  import "./chunk-YURRUCIM.js";
51
51
  import {
52
52
  Logger,
@@ -808,9 +808,22 @@ var StdioConnector = class extends BaseConnector {
808
808
  this.errlog
809
809
  );
810
810
  const transport = await this.connectionManager.start();
811
- this.client = new Client(this.clientInfo, this.opts.clientOptions);
811
+ const clientOptions = {
812
+ ...this.opts.clientOptions || {},
813
+ capabilities: {
814
+ ...this.opts.clientOptions?.capabilities || {},
815
+ roots: { listChanged: true },
816
+ // Always advertise roots capability
817
+ // Add sampling capability if callback is provided
818
+ ...this.opts.samplingCallback ? { sampling: {} } : {}
819
+ }
820
+ };
821
+ this.client = new Client(this.clientInfo, clientOptions);
812
822
  await this.client.connect(transport);
813
823
  this.connected = true;
824
+ this.setupNotificationHandler();
825
+ this.setupRootsHandler();
826
+ this.setupSamplingHandler();
814
827
  logger.debug(
815
828
  `Successfully connected to MCP implementation: ${this.command}`
816
829
  );
@@ -834,12 +847,13 @@ function loadConfigFile(filepath) {
834
847
  return JSON.parse(raw);
835
848
  }
836
849
  __name(loadConfigFile, "loadConfigFile");
837
- function createConnectorFromConfig(serverConfig) {
850
+ function createConnectorFromConfig(serverConfig, connectorOptions) {
838
851
  if ("command" in serverConfig && "args" in serverConfig) {
839
852
  return new StdioConnector({
840
853
  command: serverConfig.command,
841
854
  args: serverConfig.args,
842
- env: serverConfig.env
855
+ env: serverConfig.env,
856
+ ...connectorOptions
843
857
  });
844
858
  }
845
859
  if ("url" in serverConfig) {
@@ -848,13 +862,15 @@ function createConnectorFromConfig(serverConfig) {
848
862
  headers: serverConfig.headers,
849
863
  authToken: serverConfig.auth_token || serverConfig.authToken,
850
864
  // Only force SSE if explicitly requested
851
- preferSse: serverConfig.preferSse || transport === "sse"
865
+ preferSse: serverConfig.preferSse || transport === "sse",
866
+ ...connectorOptions
852
867
  });
853
868
  }
854
869
  if ("ws_url" in serverConfig) {
855
870
  return new WebSocketConnector(serverConfig.ws_url, {
856
871
  headers: serverConfig.headers,
857
- authToken: serverConfig.auth_token
872
+ authToken: serverConfig.auth_token,
873
+ ...connectorOptions
858
874
  });
859
875
  }
860
876
  throw new Error("Cannot determine connector type from config");
@@ -871,6 +887,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
871
887
  _customCodeExecutor = null;
872
888
  _codeExecutorConfig = "vm";
873
889
  _executorOptions;
890
+ _samplingCallback;
874
891
  constructor(config, options) {
875
892
  if (config) {
876
893
  if (typeof config === "string") {
@@ -896,6 +913,7 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
896
913
  this.codeMode = codeModeEnabled;
897
914
  this._codeExecutorConfig = executorConfig;
898
915
  this._executorOptions = executorOptions;
916
+ this._samplingCallback = options?.samplingCallback;
899
917
  if (this.codeMode) {
900
918
  this._setupCodeModeConnector();
901
919
  }
@@ -921,7 +939,9 @@ var MCPClient = class _MCPClient extends BaseMCPClient {
921
939
  * Supports all connector types including StdioConnector
922
940
  */
923
941
  createConnectorFromConfig(serverConfig) {
924
- return createConnectorFromConfig(serverConfig);
942
+ return createConnectorFromConfig(serverConfig, {
943
+ samplingCallback: this._samplingCallback
944
+ });
925
945
  }
926
946
  _setupCodeModeConnector() {
927
947
  logger.debug("Code mode connector initialized as internal meta server");
@@ -995,6 +995,7 @@ __export(agents_exports, {
995
995
  module.exports = __toCommonJS(agents_exports);
996
996
 
997
997
  // src/connectors/base.ts
998
+ var import_types = require("@modelcontextprotocol/sdk/types.js");
998
999
  init_logging();
999
1000
 
1000
1001
  // src/client/connectors/codeMode.ts
@@ -7,8 +7,8 @@ import {
7
7
  } from "../../chunk-MCF5P6GJ.js";
8
8
  import {
9
9
  PROMPTS
10
- } from "../../chunk-WERYJ6PF.js";
11
- import "../../chunk-DSBKVAWD.js";
10
+ } from "../../chunk-2AOGMX4T.js";
11
+ import "../../chunk-2JBWOW4S.js";
12
12
  import "../../chunk-YURRUCIM.js";
13
13
  import "../../chunk-34R6SIER.js";
14
14
  import "../../chunk-3GQAWCBQ.js";
@@ -1009,7 +1009,7 @@ module.exports = __toCommonJS(browser_exports);
1009
1009
 
1010
1010
  // src/connectors/http.ts
1011
1011
  var import_client = require("@modelcontextprotocol/sdk/client/index.js");
1012
- var import_streamableHttp2 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
1012
+ var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
1013
1013
  init_logging();
1014
1014
 
1015
1015
  // src/task_managers/sse.ts
@@ -1177,73 +1177,170 @@ var SseConnectionManager = class extends ConnectionManager {
1177
1177
  }
1178
1178
  };
1179
1179
 
1180
- // src/task_managers/streamable_http.ts
1181
- var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
1180
+ // src/connectors/base.ts
1181
+ var import_types = require("@modelcontextprotocol/sdk/types.js");
1182
1182
  init_logging();
1183
- var StreamableHttpConnectionManager = class extends ConnectionManager {
1183
+ var BaseConnector = class {
1184
1184
  static {
1185
- __name(this, "StreamableHttpConnectionManager");
1185
+ __name(this, "BaseConnector");
1186
1186
  }
1187
- url;
1187
+ client = null;
1188
+ connectionManager = null;
1189
+ toolsCache = null;
1190
+ capabilitiesCache = null;
1191
+ serverInfoCache = null;
1192
+ connected = false;
1188
1193
  opts;
1189
- _transport = null;
1194
+ notificationHandlers = [];
1195
+ rootsCache = [];
1196
+ constructor(opts = {}) {
1197
+ this.opts = opts;
1198
+ if (opts.roots) {
1199
+ this.rootsCache = [...opts.roots];
1200
+ }
1201
+ }
1190
1202
  /**
1191
- * Create a Streamable HTTP connection manager.
1203
+ * Register a handler for server notifications
1192
1204
  *
1193
- * @param url The HTTP endpoint URL.
1194
- * @param opts Optional transport options (auth, headers, etc.).
1205
+ * @param handler - Function to call when a notification is received
1206
+ *
1207
+ * @example
1208
+ * ```typescript
1209
+ * connector.onNotification((notification) => {
1210
+ * console.log(`Received: ${notification.method}`, notification.params);
1211
+ * });
1212
+ * ```
1195
1213
  */
1196
- constructor(url, opts) {
1197
- super();
1198
- this.url = typeof url === "string" ? new URL(url) : url;
1199
- this.opts = opts;
1214
+ onNotification(handler) {
1215
+ this.notificationHandlers.push(handler);
1216
+ if (this.client) {
1217
+ this.setupNotificationHandler();
1218
+ }
1200
1219
  }
1201
1220
  /**
1202
- * Spawn a new `StreamableHTTPClientTransport` and return it.
1203
- * The Client.connect() method will handle starting the transport.
1221
+ * Internal: wire notification handlers to the SDK client
1222
+ * Includes automatic handling for list_changed notifications per MCP spec
1204
1223
  */
1205
- async establishConnection() {
1206
- this._transport = new import_streamableHttp.StreamableHTTPClientTransport(this.url, this.opts);
1207
- logger.debug(`${this.constructor.name} created successfully`);
1208
- return this._transport;
1224
+ setupNotificationHandler() {
1225
+ if (!this.client) return;
1226
+ this.client.fallbackNotificationHandler = async (notification) => {
1227
+ switch (notification.method) {
1228
+ case "notifications/tools/list_changed":
1229
+ await this.refreshToolsCache();
1230
+ break;
1231
+ case "notifications/resources/list_changed":
1232
+ await this.onResourcesListChanged();
1233
+ break;
1234
+ case "notifications/prompts/list_changed":
1235
+ await this.onPromptsListChanged();
1236
+ break;
1237
+ default:
1238
+ break;
1239
+ }
1240
+ for (const handler of this.notificationHandlers) {
1241
+ try {
1242
+ await handler(notification);
1243
+ } catch (err) {
1244
+ logger.error("Error in notification handler:", err);
1245
+ }
1246
+ }
1247
+ };
1209
1248
  }
1210
1249
  /**
1211
- * Close the underlying transport and clean up resources.
1250
+ * Auto-refresh tools cache when server sends tools/list_changed notification
1212
1251
  */
1213
- async closeConnection(_connection) {
1214
- if (this._transport) {
1215
- try {
1216
- await this._transport.close();
1217
- } catch (e) {
1218
- logger.warn(`Error closing Streamable HTTP transport: ${e}`);
1219
- } finally {
1220
- this._transport = null;
1221
- }
1252
+ async refreshToolsCache() {
1253
+ if (!this.client) return;
1254
+ try {
1255
+ logger.debug(
1256
+ "[Auto] Refreshing tools cache due to list_changed notification"
1257
+ );
1258
+ const result = await this.client.listTools();
1259
+ this.toolsCache = result.tools ?? [];
1260
+ logger.debug(
1261
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
1262
+ );
1263
+ } catch (err) {
1264
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
1222
1265
  }
1223
1266
  }
1224
1267
  /**
1225
- * Get the session ID from the transport if available.
1268
+ * Called when server sends resources/list_changed notification
1269
+ * Resources aren't cached by default, but we log for user awareness
1226
1270
  */
1227
- get sessionId() {
1228
- return this._transport?.sessionId;
1271
+ async onResourcesListChanged() {
1272
+ logger.debug(
1273
+ "[Auto] Resources list changed - clients should re-fetch if needed"
1274
+ );
1229
1275
  }
1230
- };
1231
-
1232
- // src/connectors/base.ts
1233
- init_logging();
1234
- var BaseConnector = class {
1235
- static {
1236
- __name(this, "BaseConnector");
1276
+ /**
1277
+ * Called when server sends prompts/list_changed notification
1278
+ * Prompts aren't cached by default, but we log for user awareness
1279
+ */
1280
+ async onPromptsListChanged() {
1281
+ logger.debug(
1282
+ "[Auto] Prompts list changed - clients should re-fetch if needed"
1283
+ );
1237
1284
  }
1238
- client = null;
1239
- connectionManager = null;
1240
- toolsCache = null;
1241
- capabilitiesCache = null;
1242
- serverInfoCache = null;
1243
- connected = false;
1244
- opts;
1245
- constructor(opts = {}) {
1246
- this.opts = opts;
1285
+ /**
1286
+ * Set roots and notify the server.
1287
+ * Roots represent directories or files that the client has access to.
1288
+ *
1289
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
1290
+ *
1291
+ * @example
1292
+ * ```typescript
1293
+ * await connector.setRoots([
1294
+ * { uri: "file:///home/user/project", name: "My Project" },
1295
+ * { uri: "file:///home/user/data" }
1296
+ * ]);
1297
+ * ```
1298
+ */
1299
+ async setRoots(roots) {
1300
+ this.rootsCache = [...roots];
1301
+ if (this.client) {
1302
+ logger.debug(
1303
+ `Sending roots/list_changed notification with ${roots.length} root(s)`
1304
+ );
1305
+ await this.client.sendRootsListChanged();
1306
+ }
1307
+ }
1308
+ /**
1309
+ * Get the current roots.
1310
+ */
1311
+ getRoots() {
1312
+ return [...this.rootsCache];
1313
+ }
1314
+ /**
1315
+ * Internal: set up roots/list request handler.
1316
+ * This is called after the client connects to register the handler for server requests.
1317
+ */
1318
+ setupRootsHandler() {
1319
+ if (!this.client) return;
1320
+ this.client.setRequestHandler(
1321
+ import_types.ListRootsRequestSchema,
1322
+ async (_request, _extra) => {
1323
+ logger.debug(
1324
+ `Server requested roots list, returning ${this.rootsCache.length} root(s)`
1325
+ );
1326
+ return { roots: this.rootsCache };
1327
+ }
1328
+ );
1329
+ }
1330
+ /**
1331
+ * Internal: set up sampling/createMessage request handler.
1332
+ * This is called after the client connects to register the handler for sampling requests.
1333
+ */
1334
+ setupSamplingHandler() {
1335
+ if (!this.client) return;
1336
+ if (!this.opts.samplingCallback) return;
1337
+ this.client.setRequestHandler(
1338
+ import_types.CreateMessageRequestSchema,
1339
+ async (request, _extra) => {
1340
+ logger.debug("Server requested sampling, forwarding to callback");
1341
+ return await this.opts.samplingCallback(request.params);
1342
+ }
1343
+ );
1247
1344
  }
1248
1345
  /** Disconnect and release resources. */
1249
1346
  async disconnect() {
@@ -1495,6 +1592,7 @@ var HttpConnector = class extends BaseConnector {
1495
1592
  clientInfo;
1496
1593
  preferSse;
1497
1594
  transportType = null;
1595
+ streamableTransport = null;
1498
1596
  constructor(baseUrl, opts = {}) {
1499
1597
  super(opts);
1500
1598
  this.baseUrl = baseUrl.replace(/\/$/, "");
@@ -1530,7 +1628,7 @@ var HttpConnector = class extends BaseConnector {
1530
1628
  } catch (err) {
1531
1629
  let fallbackReason = "Unknown error";
1532
1630
  let is401Error = false;
1533
- if (err instanceof import_streamableHttp2.StreamableHTTPError) {
1631
+ if (err instanceof import_streamableHttp.StreamableHTTPError) {
1534
1632
  is401Error = err.code === 401;
1535
1633
  if (err.code === 400 && err.message.includes("Missing session ID")) {
1536
1634
  fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
@@ -1586,34 +1684,67 @@ var HttpConnector = class extends BaseConnector {
1586
1684
  }
1587
1685
  async connectWithStreamableHttp(baseUrl) {
1588
1686
  try {
1589
- this.connectionManager = new StreamableHttpConnectionManager(baseUrl, {
1590
- authProvider: this.opts.authProvider,
1591
- // ← Pass OAuth provider to SDK
1592
- requestInit: {
1593
- headers: this.headers
1594
- },
1595
- // Pass through timeout and other options
1596
- reconnectionOptions: {
1597
- maxReconnectionDelay: 3e4,
1598
- initialReconnectionDelay: 1e3,
1599
- reconnectionDelayGrowFactor: 1.5,
1600
- maxRetries: 2
1687
+ const streamableTransport = new import_streamableHttp.StreamableHTTPClientTransport(
1688
+ new URL(baseUrl),
1689
+ {
1690
+ authProvider: this.opts.authProvider,
1691
+ // ← Pass OAuth provider to SDK
1692
+ requestInit: {
1693
+ headers: this.headers
1694
+ },
1695
+ // Pass through reconnection options
1696
+ reconnectionOptions: {
1697
+ maxReconnectionDelay: 3e4,
1698
+ initialReconnectionDelay: 1e3,
1699
+ reconnectionDelayGrowFactor: 1.5,
1700
+ maxRetries: 2
1701
+ }
1702
+ // Don't pass sessionId - let the SDK generate it automatically during connect()
1601
1703
  }
1602
- });
1603
- let transport = await this.connectionManager.start();
1704
+ );
1705
+ let transport = streamableTransport;
1604
1706
  if (this.opts.wrapTransport) {
1605
1707
  const serverId = this.baseUrl;
1606
- transport = this.opts.wrapTransport(transport, serverId);
1708
+ transport = this.opts.wrapTransport(
1709
+ transport,
1710
+ serverId
1711
+ );
1607
1712
  }
1608
- this.client = new import_client.Client(this.clientInfo, this.opts.clientOptions);
1713
+ const clientOptions = {
1714
+ ...this.opts.clientOptions || {},
1715
+ capabilities: {
1716
+ ...this.opts.clientOptions?.capabilities || {},
1717
+ roots: { listChanged: true },
1718
+ // Always advertise roots capability
1719
+ // Add sampling capability if callback is provided
1720
+ ...this.opts.samplingCallback ? { sampling: {} } : {}
1721
+ }
1722
+ };
1723
+ logger.debug(
1724
+ `Creating Client with capabilities:`,
1725
+ JSON.stringify(clientOptions.capabilities, null, 2)
1726
+ );
1727
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
1728
+ this.setupRootsHandler();
1729
+ logger.debug("Roots handler registered before connect");
1609
1730
  try {
1610
- await this.client.connect(transport);
1731
+ await this.client.connect(transport, {
1732
+ timeout: Math.min(this.timeout, 3e3)
1733
+ });
1734
+ const sessionId = streamableTransport.sessionId;
1735
+ if (sessionId) {
1736
+ logger.debug(`Session ID obtained: ${sessionId}`);
1737
+ } else {
1738
+ logger.warn(
1739
+ "Session ID not available after connect - this may cause issues with SSE stream"
1740
+ );
1741
+ }
1611
1742
  } catch (connectErr) {
1612
1743
  if (connectErr instanceof Error) {
1613
1744
  const errMsg = connectErr.message || connectErr.toString();
1614
- if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID")) {
1745
+ if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
1615
1746
  const wrappedError = new Error(
1616
- `FastMCP session ID error: ${errMsg}`
1747
+ `Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
1617
1748
  );
1618
1749
  wrappedError.cause = connectErr;
1619
1750
  throw wrappedError;
@@ -1621,8 +1752,24 @@ var HttpConnector = class extends BaseConnector {
1621
1752
  }
1622
1753
  throw connectErr;
1623
1754
  }
1755
+ this.streamableTransport = streamableTransport;
1756
+ this.connectionManager = {
1757
+ stop: /* @__PURE__ */ __name(async () => {
1758
+ if (this.streamableTransport) {
1759
+ try {
1760
+ await this.streamableTransport.close();
1761
+ } catch (e) {
1762
+ logger.warn(`Error closing Streamable HTTP transport: ${e}`);
1763
+ } finally {
1764
+ this.streamableTransport = null;
1765
+ }
1766
+ }
1767
+ }, "stop")
1768
+ };
1624
1769
  this.connected = true;
1625
1770
  this.transportType = "streamable-http";
1771
+ this.setupNotificationHandler();
1772
+ this.setupSamplingHandler();
1626
1773
  logger.debug(
1627
1774
  `Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
1628
1775
  );
@@ -1643,10 +1790,28 @@ var HttpConnector = class extends BaseConnector {
1643
1790
  const serverId = this.baseUrl;
1644
1791
  transport = this.opts.wrapTransport(transport, serverId);
1645
1792
  }
1646
- this.client = new import_client.Client(this.clientInfo, this.opts.clientOptions);
1793
+ const clientOptions = {
1794
+ ...this.opts.clientOptions || {},
1795
+ capabilities: {
1796
+ ...this.opts.clientOptions?.capabilities || {},
1797
+ roots: { listChanged: true },
1798
+ // Always advertise roots capability
1799
+ // Add sampling capability if callback is provided
1800
+ ...this.opts.samplingCallback ? { sampling: {} } : {}
1801
+ }
1802
+ };
1803
+ logger.debug(
1804
+ `Creating Client with capabilities (SSE):`,
1805
+ JSON.stringify(clientOptions.capabilities, null, 2)
1806
+ );
1807
+ this.client = new import_client.Client(this.clientInfo, clientOptions);
1808
+ this.setupRootsHandler();
1809
+ logger.debug("Roots handler registered before connect (SSE)");
1647
1810
  await this.client.connect(transport);
1648
1811
  this.connected = true;
1649
1812
  this.transportType = "sse";
1813
+ this.setupNotificationHandler();
1814
+ this.setupSamplingHandler();
1650
1815
  logger.debug(
1651
1816
  `Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
1652
1817
  );
@@ -1822,6 +1987,9 @@ var WebSocketConnector = class extends BaseConnector {
1822
1987
  this.pending.delete(id);
1823
1988
  if ("result" in data) resolve(data.result);
1824
1989
  else if ("error" in data) reject(data.error);
1990
+ } else if (data.method && !data.id) {
1991
+ logger.debug("Received notification", data.method, data.params);
1992
+ this.handleNotification(data);
1825
1993
  } else {
1826
1994
  logger.debug("Received unsolicited message", data);
1827
1995
  }
@@ -1852,6 +2020,49 @@ var WebSocketConnector = class extends BaseConnector {
1852
2020
  for (const { reject } of this.pending.values()) reject(err);
1853
2021
  this.pending.clear();
1854
2022
  }
2023
+ async handleNotification(data) {
2024
+ switch (data.method) {
2025
+ case "notifications/tools/list_changed":
2026
+ await this.refreshToolsCache();
2027
+ break;
2028
+ case "notifications/resources/list_changed":
2029
+ await this.onResourcesListChanged();
2030
+ break;
2031
+ case "notifications/prompts/list_changed":
2032
+ await this.onPromptsListChanged();
2033
+ break;
2034
+ default:
2035
+ break;
2036
+ }
2037
+ for (const handler of this.notificationHandlers) {
2038
+ try {
2039
+ await handler({
2040
+ method: data.method,
2041
+ params: data.params
2042
+ });
2043
+ } catch (err) {
2044
+ logger.error("Error in notification handler:", err);
2045
+ }
2046
+ }
2047
+ }
2048
+ /**
2049
+ * Auto-refresh tools cache when server sends tools/list_changed notification
2050
+ * Override to use WebSocket-specific listTools method
2051
+ */
2052
+ async refreshToolsCache() {
2053
+ try {
2054
+ logger.debug(
2055
+ "[Auto] Refreshing tools cache due to list_changed notification"
2056
+ );
2057
+ const tools = await this.listTools();
2058
+ this.toolsCache = tools.map((t) => t);
2059
+ logger.debug(
2060
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
2061
+ );
2062
+ } catch (err) {
2063
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
2064
+ }
2065
+ }
1855
2066
  async initialize() {
1856
2067
  logger.debug("Initializing MCP session over WebSocket");
1857
2068
  const result = await this.sendRequest("initialize");
@@ -1931,6 +2142,51 @@ var MCPSession = class {
1931
2142
  get isConnected() {
1932
2143
  return this.connector && this.connector.isClientConnected;
1933
2144
  }
2145
+ /**
2146
+ * Register an event handler for session events
2147
+ *
2148
+ * @param event - The event type to listen for
2149
+ * @param handler - The handler function to call when the event occurs
2150
+ *
2151
+ * @example
2152
+ * ```typescript
2153
+ * session.on("notification", async (notification) => {
2154
+ * console.log(`Received: ${notification.method}`, notification.params);
2155
+ *
2156
+ * if (notification.method === "notifications/tools/list_changed") {
2157
+ * // Refresh tools list
2158
+ * }
2159
+ * });
2160
+ * ```
2161
+ */
2162
+ on(event, handler) {
2163
+ if (event === "notification") {
2164
+ this.connector.onNotification(handler);
2165
+ }
2166
+ }
2167
+ /**
2168
+ * Set roots and notify the server.
2169
+ * Roots represent directories or files that the client has access to.
2170
+ *
2171
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
2172
+ *
2173
+ * @example
2174
+ * ```typescript
2175
+ * await session.setRoots([
2176
+ * { uri: "file:///home/user/project", name: "My Project" },
2177
+ * { uri: "file:///home/user/data" }
2178
+ * ]);
2179
+ * ```
2180
+ */
2181
+ async setRoots(roots) {
2182
+ return this.connector.setRoots(roots);
2183
+ }
2184
+ /**
2185
+ * Get the current roots.
2186
+ */
2187
+ getRoots() {
2188
+ return this.connector.getRoots();
2189
+ }
1934
2190
  };
1935
2191
 
1936
2192
  // src/client/base.ts
@@ -2066,7 +2322,16 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
2066
2322
  * Supports HTTP and WebSocket connectors only
2067
2323
  */
2068
2324
  createConnectorFromConfig(serverConfig) {
2069
- const { url, transport, headers, authToken, authProvider, wrapTransport } = serverConfig;
2325
+ const {
2326
+ url,
2327
+ transport,
2328
+ headers,
2329
+ authToken,
2330
+ authProvider,
2331
+ wrapTransport,
2332
+ clientOptions,
2333
+ samplingCallback
2334
+ } = serverConfig;
2070
2335
  if (!url) {
2071
2336
  throw new Error("Server URL is required");
2072
2337
  }
@@ -2075,9 +2340,23 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
2075
2340
  authToken,
2076
2341
  authProvider,
2077
2342
  // ← Pass OAuth provider to connector
2078
- wrapTransport
2343
+ wrapTransport,
2079
2344
  // ← Pass transport wrapper if provided
2345
+ clientOptions,
2346
+ // ← Pass client options (capabilities, etc.) to connector
2347
+ samplingCallback
2348
+ // ← Pass sampling callback to connector
2080
2349
  };
2350
+ if (clientOptions) {
2351
+ console.log(
2352
+ "[BrowserMCPClient] Passing clientOptions to connector:",
2353
+ JSON.stringify(clientOptions, null, 2)
2354
+ );
2355
+ } else {
2356
+ console.warn(
2357
+ "[BrowserMCPClient] No clientOptions provided to connector!"
2358
+ );
2359
+ }
2081
2360
  if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
2082
2361
  return new WebSocketConnector(url, connectorOptions);
2083
2362
  } else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
@@ -6,9 +6,11 @@ export { MCPAgent } from "./agents/mcp_agent.js";
6
6
  export { RemoteAgent } from "./agents/remote.js";
7
7
  export { BaseAdapter, LangChainAdapter } from "./adapters/index.js";
8
8
  export { BaseConnector } from "./connectors/base.js";
9
+ export type { NotificationHandler } from "./connectors/base.js";
9
10
  export { HttpConnector } from "./connectors/http.js";
10
11
  export { WebSocketConnector } from "./connectors/websocket.js";
11
12
  export { MCPSession } from "./session.js";
13
+ export type { Notification, Root } from "./session.js";
12
14
  export { BrowserOAuthClientProvider } from "./auth/browser-provider.js";
13
15
  export { onMcpAuthorization } from "./auth/callback.js";
14
16
  export type { StoredState } from "./auth/types.js";