@mcp-use/inspector 0.7.0 → 0.7.1-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/cli.js +2 -1
  2. package/dist/client/assets/{browser-BdCJ_qyB.js → browser-8hDgrmFA.js} +5 -5
  3. package/dist/client/assets/{chunk-VL2OQCWN-CxD8xDNw.js → chunk-VL2OQCWN-BF4Vlh6u.js} +1 -1
  4. package/dist/client/assets/{display-YIYC6WJE-B6ZSv77R.js → display-YIYC6WJE-CTiX0vGg.js} +1 -1
  5. package/dist/client/assets/{embeddings-DlCMB9po.js → embeddings-BBixu_w5.js} +1 -1
  6. package/dist/client/assets/{index-Q_pqNaNk.js → index-Bk_3A_7h.js} +4 -4
  7. package/dist/client/assets/{index-kVFYovMy.css → index-C2qHJtN-.css} +19 -0
  8. package/dist/client/assets/{index-CKXUnlZB.js → index-C6-RG1Zg.js} +1239 -372
  9. package/dist/client/assets/{index-Cb09SlUY.js → index-DXRtNbHK.js} +2 -2
  10. package/dist/client/assets/{index-CsP5AdwX.js → index-LnKUeTzV.js} +4 -4
  11. package/dist/client/assets/{index-B0NYybvW.js → index-XmiNerc_.js} +3 -3
  12. package/dist/client/assets/{winston-qgF6niUt.js → winston-DEk87ZzD.js} +1 -1
  13. package/dist/client/index.html +3 -3
  14. package/dist/server/{chunk-RRPLH7DL.js → chunk-26WTIZ4S.js} +1 -1
  15. package/dist/server/{chunk-S7NOZBMG.js → chunk-6ZFXPXO4.js} +6 -6
  16. package/dist/server/{chunk-ZONLXYBO.js → chunk-KW44WB52.js} +2 -1
  17. package/dist/server/{chunk-3T2VCYG6.js → chunk-V5FEV5SU.js} +2 -1
  18. package/dist/server/{chunk-FS77NTZN.js → chunk-XU7SXB3C.js} +1 -1
  19. package/dist/server/cli.js +4 -4
  20. package/dist/server/index.js +5 -5
  21. package/dist/server/middleware.d.ts +5 -1
  22. package/dist/server/middleware.d.ts.map +1 -1
  23. package/dist/server/middleware.js +5 -5
  24. package/dist/server/server.js +4 -4
  25. package/dist/server/shared-routes.js +2 -2
  26. package/dist/server/shared-static.js +2 -2
  27. package/dist/server/shared-utils-browser.d.ts.map +1 -1
  28. package/dist/server/shared-utils-browser.js +1 -1
  29. package/dist/server/shared-utils.d.ts.map +1 -1
  30. package/dist/server/shared-utils.js +1 -1
  31. package/package.json +2 -2
@@ -1,8 +1,8 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/winston-qgF6niUt.js","assets/__vite-browser-external-CHS79mP1.js","assets/index-DX0TIfSM.js","assets/path-QsnVvLoj.js","assets/index-CsP5AdwX.js","assets/index-Cb09SlUY.js","assets/chunk-VL2OQCWN-CxD8xDNw.js","assets/embeddings-DlCMB9po.js","assets/index-B0NYybvW.js","assets/index-Q_pqNaNk.js","assets/browser-BdCJ_qyB.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/winston-DEk87ZzD.js","assets/__vite-browser-external-CHS79mP1.js","assets/index-DX0TIfSM.js","assets/path-QsnVvLoj.js","assets/index-LnKUeTzV.js","assets/index-DXRtNbHK.js","assets/chunk-VL2OQCWN-BF4Vlh6u.js","assets/embeddings-BBixu_w5.js","assets/index-XmiNerc_.js","assets/index-Bk_3A_7h.js","assets/browser-8hDgrmFA.js"])))=>i.map(i=>d[i]);
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- var _a, _b, _c, _d, _e2, _f, _g, _h, _i, _j, _k, _l, _m, _n;
5
+ var _a, _b, _c, _d, _e2, _f, _g, _h, _i, _j, _k, _l, _m;
6
6
  function _mergeNamespaces(n2, m2) {
7
7
  for (var i2 = 0; i2 < m2.length; i2++) {
8
8
  const e = m2[i2];
@@ -211,7 +211,7 @@ function loadWinstonSync() {
211
211
  __name(loadWinstonSync, "loadWinstonSync");
212
212
  async function getWinston() {
213
213
  if (!winston) {
214
- winston = await __vitePreload(() => import("./winston-qgF6niUt.js").then((n2) => n2.w), true ? __vite__mapDeps([0,1,2,3]) : void 0);
214
+ winston = await __vitePreload(() => import("./winston-DEk87ZzD.js").then((n2) => n2.w), true ? __vite__mapDeps([0,1,2,3]) : void 0);
215
215
  }
216
216
  return winston;
217
217
  }
@@ -446,254 +446,6 @@ if (isNodeJSEnvironment()) {
446
446
  }
447
447
  }
448
448
  var logger = Logger.get();
449
- var BaseConnector = (_c = class {
450
- client = null;
451
- connectionManager = null;
452
- toolsCache = null;
453
- capabilitiesCache = null;
454
- serverInfoCache = null;
455
- connected = false;
456
- opts;
457
- constructor(opts = {}) {
458
- this.opts = opts;
459
- }
460
- /** Disconnect and release resources. */
461
- async disconnect() {
462
- if (!this.connected) {
463
- logger.debug("Not connected to MCP implementation");
464
- return;
465
- }
466
- logger.debug("Disconnecting from MCP implementation");
467
- await this.cleanupResources();
468
- this.connected = false;
469
- logger.debug("Disconnected from MCP implementation");
470
- }
471
- /** Check if the client is connected */
472
- get isClientConnected() {
473
- return this.client != null;
474
- }
475
- /**
476
- * Initialise the MCP session **after** `connect()` has succeeded.
477
- *
478
- * In the SDK, `Client.connect(transport)` automatically performs the
479
- * protocol‑level `initialize` handshake, so we only need to cache the list of
480
- * tools and expose some server info.
481
- */
482
- async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
483
- if (!this.client) {
484
- throw new Error("MCP client is not connected");
485
- }
486
- logger.debug("Caching server capabilities & tools");
487
- const capabilities = this.client.getServerCapabilities();
488
- this.capabilitiesCache = capabilities;
489
- const serverInfo = this.client.getServerVersion();
490
- this.serverInfoCache = serverInfo || null;
491
- const listToolsRes = await this.client.listTools(
492
- void 0,
493
- defaultRequestOptions
494
- );
495
- this.toolsCache = listToolsRes.tools ?? [];
496
- logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
497
- logger.debug("Server capabilities:", capabilities);
498
- logger.debug("Server info:", serverInfo);
499
- return capabilities;
500
- }
501
- /** Lazily expose the cached tools list. */
502
- get tools() {
503
- if (!this.toolsCache) {
504
- throw new Error("MCP client is not initialized; call initialize() first");
505
- }
506
- return this.toolsCache;
507
- }
508
- /** Expose cached server capabilities. */
509
- get serverCapabilities() {
510
- return this.capabilitiesCache;
511
- }
512
- /** Expose cached server info. */
513
- get serverInfo() {
514
- return this.serverInfoCache;
515
- }
516
- /** Call a tool on the server. */
517
- async callTool(name, args, options) {
518
- if (!this.client) {
519
- throw new Error("MCP client is not connected");
520
- }
521
- logger.debug(`Calling tool '${name}' with args`, args);
522
- const res = await this.client.callTool(
523
- { name, arguments: args },
524
- void 0,
525
- options
526
- );
527
- logger.debug(`Tool '${name}' returned`, res);
528
- return res;
529
- }
530
- /**
531
- * List resources from the server with optional pagination
532
- *
533
- * @param cursor - Optional cursor for pagination
534
- * @param options - Request options
535
- * @returns Resource list with optional nextCursor for pagination
536
- */
537
- async listResources(cursor, options) {
538
- if (!this.client) {
539
- throw new Error("MCP client is not connected");
540
- }
541
- logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
542
- return await this.client.listResources({ cursor }, options);
543
- }
544
- /**
545
- * List all resources from the server, automatically handling pagination
546
- *
547
- * @param options - Request options
548
- * @returns Complete list of all resources
549
- */
550
- async listAllResources(options) {
551
- if (!this.client) {
552
- throw new Error("MCP client is not connected");
553
- }
554
- if (!this.capabilitiesCache?.resources) {
555
- logger.debug("Server does not advertise resources capability, skipping");
556
- return { resources: [] };
557
- }
558
- try {
559
- logger.debug("Listing all resources (with auto-pagination)");
560
- const allResources = [];
561
- let cursor = void 0;
562
- do {
563
- const result = await this.client.listResources({ cursor }, options);
564
- allResources.push(...result.resources || []);
565
- cursor = result.nextCursor;
566
- } while (cursor);
567
- return { resources: allResources };
568
- } catch (err) {
569
- if (err.code === -32601) {
570
- logger.debug("Server advertised resources but method not found");
571
- return { resources: [] };
572
- }
573
- throw err;
574
- }
575
- }
576
- /**
577
- * List resource templates from the server
578
- *
579
- * @param options - Request options
580
- * @returns List of available resource templates
581
- */
582
- async listResourceTemplates(options) {
583
- if (!this.client) {
584
- throw new Error("MCP client is not connected");
585
- }
586
- logger.debug("Listing resource templates");
587
- return await this.client.listResourceTemplates(void 0, options);
588
- }
589
- /** Read a resource by URI. */
590
- async readResource(uri, options) {
591
- if (!this.client) {
592
- throw new Error("MCP client is not connected");
593
- }
594
- logger.debug(`Reading resource ${uri}`);
595
- const res = await this.client.readResource({ uri }, options);
596
- return res;
597
- }
598
- /**
599
- * Subscribe to resource updates
600
- *
601
- * @param uri - URI of the resource to subscribe to
602
- * @param options - Request options
603
- */
604
- async subscribeToResource(uri, options) {
605
- if (!this.client) {
606
- throw new Error("MCP client is not connected");
607
- }
608
- logger.debug(`Subscribing to resource: ${uri}`);
609
- return await this.client.subscribeResource({ uri }, options);
610
- }
611
- /**
612
- * Unsubscribe from resource updates
613
- *
614
- * @param uri - URI of the resource to unsubscribe from
615
- * @param options - Request options
616
- */
617
- async unsubscribeFromResource(uri, options) {
618
- if (!this.client) {
619
- throw new Error("MCP client is not connected");
620
- }
621
- logger.debug(`Unsubscribing from resource: ${uri}`);
622
- return await this.client.unsubscribeResource({ uri }, options);
623
- }
624
- async listPrompts() {
625
- if (!this.client) {
626
- throw new Error("MCP client is not connected");
627
- }
628
- if (!this.capabilitiesCache?.prompts) {
629
- logger.debug("Server does not advertise prompts capability, skipping");
630
- return { prompts: [] };
631
- }
632
- try {
633
- logger.debug("Listing prompts");
634
- return await this.client.listPrompts();
635
- } catch (err) {
636
- if (err.code === -32601) {
637
- logger.debug("Server advertised prompts but method not found");
638
- return { prompts: [] };
639
- }
640
- throw err;
641
- }
642
- }
643
- async getPrompt(name, args) {
644
- if (!this.client) {
645
- throw new Error("MCP client is not connected");
646
- }
647
- logger.debug(`Getting prompt ${name}`);
648
- return await this.client.getPrompt({ name, arguments: args });
649
- }
650
- /** Send a raw request through the client. */
651
- async request(method, params = null, options) {
652
- if (!this.client) {
653
- throw new Error("MCP client is not connected");
654
- }
655
- logger.debug(`Sending raw request '${method}' with params`, params);
656
- return await this.client.request(
657
- { method, params: params ?? {} },
658
- void 0,
659
- options
660
- );
661
- }
662
- /**
663
- * Helper to tear down the client & connection manager safely.
664
- */
665
- async cleanupResources() {
666
- const issues = [];
667
- if (this.client) {
668
- try {
669
- if (typeof this.client.close === "function") {
670
- await this.client.close();
671
- }
672
- } catch (e) {
673
- const msg = `Error closing client: ${e}`;
674
- logger.warn(msg);
675
- issues.push(msg);
676
- } finally {
677
- this.client = null;
678
- }
679
- }
680
- if (this.connectionManager) {
681
- try {
682
- await this.connectionManager.stop();
683
- } catch (e) {
684
- const msg = `Error stopping connection manager: ${e}`;
685
- logger.warn(msg);
686
- issues.push(msg);
687
- } finally {
688
- this.connectionManager = null;
689
- }
690
- }
691
- this.toolsCache = null;
692
- if (issues.length) {
693
- logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
694
- }
695
- }
696
- }, __name(_c, "BaseConnector"), _c);
697
449
  var util$1;
698
450
  (function(util2) {
699
451
  util2.assertEqual = (_2) => {
@@ -5516,6 +5268,400 @@ class McpError extends Error {
5516
5268
  this.name = "McpError";
5517
5269
  }
5518
5270
  }
5271
+ var BaseConnector = (_c = class {
5272
+ client = null;
5273
+ connectionManager = null;
5274
+ toolsCache = null;
5275
+ capabilitiesCache = null;
5276
+ serverInfoCache = null;
5277
+ connected = false;
5278
+ opts;
5279
+ notificationHandlers = [];
5280
+ rootsCache = [];
5281
+ constructor(opts = {}) {
5282
+ this.opts = opts;
5283
+ if (opts.roots) {
5284
+ this.rootsCache = [...opts.roots];
5285
+ }
5286
+ }
5287
+ /**
5288
+ * Register a handler for server notifications
5289
+ *
5290
+ * @param handler - Function to call when a notification is received
5291
+ *
5292
+ * @example
5293
+ * ```typescript
5294
+ * connector.onNotification((notification) => {
5295
+ * console.log(`Received: ${notification.method}`, notification.params);
5296
+ * });
5297
+ * ```
5298
+ */
5299
+ onNotification(handler) {
5300
+ this.notificationHandlers.push(handler);
5301
+ if (this.client) {
5302
+ this.setupNotificationHandler();
5303
+ }
5304
+ }
5305
+ /**
5306
+ * Internal: wire notification handlers to the SDK client
5307
+ * Includes automatic handling for list_changed notifications per MCP spec
5308
+ */
5309
+ setupNotificationHandler() {
5310
+ if (!this.client) return;
5311
+ this.client.fallbackNotificationHandler = async (notification) => {
5312
+ switch (notification.method) {
5313
+ case "notifications/tools/list_changed":
5314
+ await this.refreshToolsCache();
5315
+ break;
5316
+ case "notifications/resources/list_changed":
5317
+ await this.onResourcesListChanged();
5318
+ break;
5319
+ case "notifications/prompts/list_changed":
5320
+ await this.onPromptsListChanged();
5321
+ break;
5322
+ }
5323
+ for (const handler of this.notificationHandlers) {
5324
+ try {
5325
+ await handler(notification);
5326
+ } catch (err) {
5327
+ logger.error("Error in notification handler:", err);
5328
+ }
5329
+ }
5330
+ };
5331
+ }
5332
+ /**
5333
+ * Auto-refresh tools cache when server sends tools/list_changed notification
5334
+ */
5335
+ async refreshToolsCache() {
5336
+ if (!this.client) return;
5337
+ try {
5338
+ logger.debug(
5339
+ "[Auto] Refreshing tools cache due to list_changed notification"
5340
+ );
5341
+ const result = await this.client.listTools();
5342
+ this.toolsCache = result.tools ?? [];
5343
+ logger.debug(
5344
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
5345
+ );
5346
+ } catch (err) {
5347
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
5348
+ }
5349
+ }
5350
+ /**
5351
+ * Called when server sends resources/list_changed notification
5352
+ * Resources aren't cached by default, but we log for user awareness
5353
+ */
5354
+ async onResourcesListChanged() {
5355
+ logger.debug(
5356
+ "[Auto] Resources list changed - clients should re-fetch if needed"
5357
+ );
5358
+ }
5359
+ /**
5360
+ * Called when server sends prompts/list_changed notification
5361
+ * Prompts aren't cached by default, but we log for user awareness
5362
+ */
5363
+ async onPromptsListChanged() {
5364
+ logger.debug(
5365
+ "[Auto] Prompts list changed - clients should re-fetch if needed"
5366
+ );
5367
+ }
5368
+ /**
5369
+ * Set roots and notify the server.
5370
+ * Roots represent directories or files that the client has access to.
5371
+ *
5372
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
5373
+ *
5374
+ * @example
5375
+ * ```typescript
5376
+ * await connector.setRoots([
5377
+ * { uri: "file:///home/user/project", name: "My Project" },
5378
+ * { uri: "file:///home/user/data" }
5379
+ * ]);
5380
+ * ```
5381
+ */
5382
+ async setRoots(roots) {
5383
+ this.rootsCache = [...roots];
5384
+ if (this.client) {
5385
+ logger.debug(
5386
+ `Sending roots/list_changed notification with ${roots.length} root(s)`
5387
+ );
5388
+ await this.client.sendRootsListChanged();
5389
+ }
5390
+ }
5391
+ /**
5392
+ * Get the current roots.
5393
+ */
5394
+ getRoots() {
5395
+ return [...this.rootsCache];
5396
+ }
5397
+ /**
5398
+ * Internal: set up roots/list request handler.
5399
+ * This is called after the client connects to register the handler for server requests.
5400
+ */
5401
+ setupRootsHandler() {
5402
+ if (!this.client) return;
5403
+ this.client.setRequestHandler(
5404
+ ListRootsRequestSchema,
5405
+ async (_request, _extra) => {
5406
+ logger.debug(
5407
+ `Server requested roots list, returning ${this.rootsCache.length} root(s)`
5408
+ );
5409
+ return { roots: this.rootsCache };
5410
+ }
5411
+ );
5412
+ }
5413
+ /**
5414
+ * Internal: set up sampling/createMessage request handler.
5415
+ * This is called after the client connects to register the handler for sampling requests.
5416
+ */
5417
+ setupSamplingHandler() {
5418
+ if (!this.client) return;
5419
+ if (!this.opts.samplingCallback) return;
5420
+ this.client.setRequestHandler(
5421
+ CreateMessageRequestSchema,
5422
+ async (request, _extra) => {
5423
+ logger.debug("Server requested sampling, forwarding to callback");
5424
+ return await this.opts.samplingCallback(request.params);
5425
+ }
5426
+ );
5427
+ }
5428
+ /** Disconnect and release resources. */
5429
+ async disconnect() {
5430
+ if (!this.connected) {
5431
+ logger.debug("Not connected to MCP implementation");
5432
+ return;
5433
+ }
5434
+ logger.debug("Disconnecting from MCP implementation");
5435
+ await this.cleanupResources();
5436
+ this.connected = false;
5437
+ logger.debug("Disconnected from MCP implementation");
5438
+ }
5439
+ /** Check if the client is connected */
5440
+ get isClientConnected() {
5441
+ return this.client != null;
5442
+ }
5443
+ /**
5444
+ * Initialise the MCP session **after** `connect()` has succeeded.
5445
+ *
5446
+ * In the SDK, `Client.connect(transport)` automatically performs the
5447
+ * protocol‑level `initialize` handshake, so we only need to cache the list of
5448
+ * tools and expose some server info.
5449
+ */
5450
+ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
5451
+ if (!this.client) {
5452
+ throw new Error("MCP client is not connected");
5453
+ }
5454
+ logger.debug("Caching server capabilities & tools");
5455
+ const capabilities = this.client.getServerCapabilities();
5456
+ this.capabilitiesCache = capabilities;
5457
+ const serverInfo = this.client.getServerVersion();
5458
+ this.serverInfoCache = serverInfo || null;
5459
+ const listToolsRes = await this.client.listTools(
5460
+ void 0,
5461
+ defaultRequestOptions
5462
+ );
5463
+ this.toolsCache = listToolsRes.tools ?? [];
5464
+ logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
5465
+ logger.debug("Server capabilities:", capabilities);
5466
+ logger.debug("Server info:", serverInfo);
5467
+ return capabilities;
5468
+ }
5469
+ /** Lazily expose the cached tools list. */
5470
+ get tools() {
5471
+ if (!this.toolsCache) {
5472
+ throw new Error("MCP client is not initialized; call initialize() first");
5473
+ }
5474
+ return this.toolsCache;
5475
+ }
5476
+ /** Expose cached server capabilities. */
5477
+ get serverCapabilities() {
5478
+ return this.capabilitiesCache;
5479
+ }
5480
+ /** Expose cached server info. */
5481
+ get serverInfo() {
5482
+ return this.serverInfoCache;
5483
+ }
5484
+ /** Call a tool on the server. */
5485
+ async callTool(name, args, options) {
5486
+ if (!this.client) {
5487
+ throw new Error("MCP client is not connected");
5488
+ }
5489
+ logger.debug(`Calling tool '${name}' with args`, args);
5490
+ const res = await this.client.callTool(
5491
+ { name, arguments: args },
5492
+ void 0,
5493
+ options
5494
+ );
5495
+ logger.debug(`Tool '${name}' returned`, res);
5496
+ return res;
5497
+ }
5498
+ /**
5499
+ * List resources from the server with optional pagination
5500
+ *
5501
+ * @param cursor - Optional cursor for pagination
5502
+ * @param options - Request options
5503
+ * @returns Resource list with optional nextCursor for pagination
5504
+ */
5505
+ async listResources(cursor, options) {
5506
+ if (!this.client) {
5507
+ throw new Error("MCP client is not connected");
5508
+ }
5509
+ logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
5510
+ return await this.client.listResources({ cursor }, options);
5511
+ }
5512
+ /**
5513
+ * List all resources from the server, automatically handling pagination
5514
+ *
5515
+ * @param options - Request options
5516
+ * @returns Complete list of all resources
5517
+ */
5518
+ async listAllResources(options) {
5519
+ if (!this.client) {
5520
+ throw new Error("MCP client is not connected");
5521
+ }
5522
+ if (!this.capabilitiesCache?.resources) {
5523
+ logger.debug("Server does not advertise resources capability, skipping");
5524
+ return { resources: [] };
5525
+ }
5526
+ try {
5527
+ logger.debug("Listing all resources (with auto-pagination)");
5528
+ const allResources = [];
5529
+ let cursor = void 0;
5530
+ do {
5531
+ const result = await this.client.listResources({ cursor }, options);
5532
+ allResources.push(...result.resources || []);
5533
+ cursor = result.nextCursor;
5534
+ } while (cursor);
5535
+ return { resources: allResources };
5536
+ } catch (err) {
5537
+ if (err.code === -32601) {
5538
+ logger.debug("Server advertised resources but method not found");
5539
+ return { resources: [] };
5540
+ }
5541
+ throw err;
5542
+ }
5543
+ }
5544
+ /**
5545
+ * List resource templates from the server
5546
+ *
5547
+ * @param options - Request options
5548
+ * @returns List of available resource templates
5549
+ */
5550
+ async listResourceTemplates(options) {
5551
+ if (!this.client) {
5552
+ throw new Error("MCP client is not connected");
5553
+ }
5554
+ logger.debug("Listing resource templates");
5555
+ return await this.client.listResourceTemplates(void 0, options);
5556
+ }
5557
+ /** Read a resource by URI. */
5558
+ async readResource(uri, options) {
5559
+ if (!this.client) {
5560
+ throw new Error("MCP client is not connected");
5561
+ }
5562
+ logger.debug(`Reading resource ${uri}`);
5563
+ const res = await this.client.readResource({ uri }, options);
5564
+ return res;
5565
+ }
5566
+ /**
5567
+ * Subscribe to resource updates
5568
+ *
5569
+ * @param uri - URI of the resource to subscribe to
5570
+ * @param options - Request options
5571
+ */
5572
+ async subscribeToResource(uri, options) {
5573
+ if (!this.client) {
5574
+ throw new Error("MCP client is not connected");
5575
+ }
5576
+ logger.debug(`Subscribing to resource: ${uri}`);
5577
+ return await this.client.subscribeResource({ uri }, options);
5578
+ }
5579
+ /**
5580
+ * Unsubscribe from resource updates
5581
+ *
5582
+ * @param uri - URI of the resource to unsubscribe from
5583
+ * @param options - Request options
5584
+ */
5585
+ async unsubscribeFromResource(uri, options) {
5586
+ if (!this.client) {
5587
+ throw new Error("MCP client is not connected");
5588
+ }
5589
+ logger.debug(`Unsubscribing from resource: ${uri}`);
5590
+ return await this.client.unsubscribeResource({ uri }, options);
5591
+ }
5592
+ async listPrompts() {
5593
+ if (!this.client) {
5594
+ throw new Error("MCP client is not connected");
5595
+ }
5596
+ if (!this.capabilitiesCache?.prompts) {
5597
+ logger.debug("Server does not advertise prompts capability, skipping");
5598
+ return { prompts: [] };
5599
+ }
5600
+ try {
5601
+ logger.debug("Listing prompts");
5602
+ return await this.client.listPrompts();
5603
+ } catch (err) {
5604
+ if (err.code === -32601) {
5605
+ logger.debug("Server advertised prompts but method not found");
5606
+ return { prompts: [] };
5607
+ }
5608
+ throw err;
5609
+ }
5610
+ }
5611
+ async getPrompt(name, args) {
5612
+ if (!this.client) {
5613
+ throw new Error("MCP client is not connected");
5614
+ }
5615
+ logger.debug(`Getting prompt ${name}`);
5616
+ return await this.client.getPrompt({ name, arguments: args });
5617
+ }
5618
+ /** Send a raw request through the client. */
5619
+ async request(method, params = null, options) {
5620
+ if (!this.client) {
5621
+ throw new Error("MCP client is not connected");
5622
+ }
5623
+ logger.debug(`Sending raw request '${method}' with params`, params);
5624
+ return await this.client.request(
5625
+ { method, params: params ?? {} },
5626
+ void 0,
5627
+ options
5628
+ );
5629
+ }
5630
+ /**
5631
+ * Helper to tear down the client & connection manager safely.
5632
+ */
5633
+ async cleanupResources() {
5634
+ const issues = [];
5635
+ if (this.client) {
5636
+ try {
5637
+ if (typeof this.client.close === "function") {
5638
+ await this.client.close();
5639
+ }
5640
+ } catch (e) {
5641
+ const msg = `Error closing client: ${e}`;
5642
+ logger.warn(msg);
5643
+ issues.push(msg);
5644
+ } finally {
5645
+ this.client = null;
5646
+ }
5647
+ }
5648
+ if (this.connectionManager) {
5649
+ try {
5650
+ await this.connectionManager.stop();
5651
+ } catch (e) {
5652
+ const msg = `Error stopping connection manager: ${e}`;
5653
+ logger.warn(msg);
5654
+ issues.push(msg);
5655
+ } finally {
5656
+ this.connectionManager = null;
5657
+ }
5658
+ }
5659
+ this.toolsCache = null;
5660
+ if (issues.length) {
5661
+ logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
5662
+ }
5663
+ }
5664
+ }, __name(_c, "BaseConnector"), _c);
5519
5665
  const DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
5520
5666
  class Protocol {
5521
5667
  constructor(_options) {
@@ -5974,11 +6120,11 @@ function requireUri_all() {
5974
6120
  var slicedToArray = /* @__PURE__ */ (function() {
5975
6121
  function sliceIterator(arr, i2) {
5976
6122
  var _arr = [];
5977
- var _n2 = true;
6123
+ var _n = true;
5978
6124
  var _d2 = false;
5979
6125
  var _e3 = void 0;
5980
6126
  try {
5981
- for (var _i2 = arr[Symbol.iterator](), _s; !(_n2 = (_s = _i2.next()).done); _n2 = true) {
6127
+ for (var _i2 = arr[Symbol.iterator](), _s; !(_n = (_s = _i2.next()).done); _n = true) {
5982
6128
  _arr.push(_s.value);
5983
6129
  if (i2 && _arr.length === i2) break;
5984
6130
  }
@@ -5987,7 +6133,7 @@ function requireUri_all() {
5987
6133
  _e3 = err;
5988
6134
  } finally {
5989
6135
  try {
5990
- if (!_n2 && _i2["return"]) _i2["return"]();
6136
+ if (!_n && _i2["return"]) _i2["return"]();
5991
6137
  } finally {
5992
6138
  if (_d2) throw _e3;
5993
6139
  }
@@ -13887,6 +14033,51 @@ var MCPSession = (_d = class {
13887
14033
  get isConnected() {
13888
14034
  return this.connector && this.connector.isClientConnected;
13889
14035
  }
14036
+ /**
14037
+ * Register an event handler for session events
14038
+ *
14039
+ * @param event - The event type to listen for
14040
+ * @param handler - The handler function to call when the event occurs
14041
+ *
14042
+ * @example
14043
+ * ```typescript
14044
+ * session.on("notification", async (notification) => {
14045
+ * console.log(`Received: ${notification.method}`, notification.params);
14046
+ *
14047
+ * if (notification.method === "notifications/tools/list_changed") {
14048
+ * // Refresh tools list
14049
+ * }
14050
+ * });
14051
+ * ```
14052
+ */
14053
+ on(event, handler) {
14054
+ if (event === "notification") {
14055
+ this.connector.onNotification(handler);
14056
+ }
14057
+ }
14058
+ /**
14059
+ * Set roots and notify the server.
14060
+ * Roots represent directories or files that the client has access to.
14061
+ *
14062
+ * @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
14063
+ *
14064
+ * @example
14065
+ * ```typescript
14066
+ * await session.setRoots([
14067
+ * { uri: "file:///home/user/project", name: "My Project" },
14068
+ * { uri: "file:///home/user/data" }
14069
+ * ]);
14070
+ * ```
14071
+ */
14072
+ async setRoots(roots) {
14073
+ return this.connector.setRoots(roots);
14074
+ }
14075
+ /**
14076
+ * Get the current roots.
14077
+ */
14078
+ getRoots() {
14079
+ return this.connector.getRoots();
14080
+ }
13890
14081
  }, __name(_d, "MCPSession"), _d);
13891
14082
  var ConnectionManager = (_e2 = class {
13892
14083
  _readyPromise;
@@ -14038,52 +14229,7 @@ var SseConnectionManager = (_f = class extends ConnectionManager {
14038
14229
  }
14039
14230
  }
14040
14231
  }, __name(_f, "SseConnectionManager"), _f);
14041
- var StreamableHttpConnectionManager = (_g = class extends ConnectionManager {
14042
- url;
14043
- opts;
14044
- _transport = null;
14045
- /**
14046
- * Create a Streamable HTTP connection manager.
14047
- *
14048
- * @param url The HTTP endpoint URL.
14049
- * @param opts Optional transport options (auth, headers, etc.).
14050
- */
14051
- constructor(url, opts) {
14052
- super();
14053
- this.url = typeof url === "string" ? new URL(url) : url;
14054
- this.opts = opts;
14055
- }
14056
- /**
14057
- * Spawn a new `StreamableHTTPClientTransport` and return it.
14058
- * The Client.connect() method will handle starting the transport.
14059
- */
14060
- async establishConnection() {
14061
- this._transport = new StreamableHTTPClientTransport(this.url, this.opts);
14062
- logger.debug(`${this.constructor.name} created successfully`);
14063
- return this._transport;
14064
- }
14065
- /**
14066
- * Close the underlying transport and clean up resources.
14067
- */
14068
- async closeConnection(_connection) {
14069
- if (this._transport) {
14070
- try {
14071
- await this._transport.close();
14072
- } catch (e) {
14073
- logger.warn(`Error closing Streamable HTTP transport: ${e}`);
14074
- } finally {
14075
- this._transport = null;
14076
- }
14077
- }
14078
- }
14079
- /**
14080
- * Get the session ID from the transport if available.
14081
- */
14082
- get sessionId() {
14083
- return this._transport?.sessionId;
14084
- }
14085
- }, __name(_g, "StreamableHttpConnectionManager"), _g);
14086
- var HttpConnector = (_h = class extends BaseConnector {
14232
+ var HttpConnector = (_g = class extends BaseConnector {
14087
14233
  baseUrl;
14088
14234
  headers;
14089
14235
  timeout;
@@ -14091,6 +14237,7 @@ var HttpConnector = (_h = class extends BaseConnector {
14091
14237
  clientInfo;
14092
14238
  preferSse;
14093
14239
  transportType = null;
14240
+ streamableTransport = null;
14094
14241
  constructor(baseUrl, opts = {}) {
14095
14242
  super(opts);
14096
14243
  this.baseUrl = baseUrl.replace(/\/$/, "");
@@ -14182,34 +14329,67 @@ var HttpConnector = (_h = class extends BaseConnector {
14182
14329
  }
14183
14330
  async connectWithStreamableHttp(baseUrl) {
14184
14331
  try {
14185
- this.connectionManager = new StreamableHttpConnectionManager(baseUrl, {
14186
- authProvider: this.opts.authProvider,
14187
- // ← Pass OAuth provider to SDK
14188
- requestInit: {
14189
- headers: this.headers
14190
- },
14191
- // Pass through timeout and other options
14192
- reconnectionOptions: {
14193
- maxReconnectionDelay: 3e4,
14194
- initialReconnectionDelay: 1e3,
14195
- reconnectionDelayGrowFactor: 1.5,
14196
- maxRetries: 2
14332
+ const streamableTransport = new StreamableHTTPClientTransport(
14333
+ new URL(baseUrl),
14334
+ {
14335
+ authProvider: this.opts.authProvider,
14336
+ // ← Pass OAuth provider to SDK
14337
+ requestInit: {
14338
+ headers: this.headers
14339
+ },
14340
+ // Pass through reconnection options
14341
+ reconnectionOptions: {
14342
+ maxReconnectionDelay: 3e4,
14343
+ initialReconnectionDelay: 1e3,
14344
+ reconnectionDelayGrowFactor: 1.5,
14345
+ maxRetries: 2
14346
+ }
14347
+ // Don't pass sessionId - let the SDK generate it automatically during connect()
14197
14348
  }
14198
- });
14199
- let transport = await this.connectionManager.start();
14349
+ );
14350
+ let transport = streamableTransport;
14200
14351
  if (this.opts.wrapTransport) {
14201
14352
  const serverId = this.baseUrl;
14202
- transport = this.opts.wrapTransport(transport, serverId);
14353
+ transport = this.opts.wrapTransport(
14354
+ transport,
14355
+ serverId
14356
+ );
14203
14357
  }
14204
- this.client = new Client(this.clientInfo, this.opts.clientOptions);
14358
+ const clientOptions = {
14359
+ ...this.opts.clientOptions || {},
14360
+ capabilities: {
14361
+ ...this.opts.clientOptions?.capabilities || {},
14362
+ roots: { listChanged: true },
14363
+ // Always advertise roots capability
14364
+ // Add sampling capability if callback is provided
14365
+ ...this.opts.samplingCallback ? { sampling: {} } : {}
14366
+ }
14367
+ };
14368
+ logger.debug(
14369
+ `Creating Client with capabilities:`,
14370
+ JSON.stringify(clientOptions.capabilities, null, 2)
14371
+ );
14372
+ this.client = new Client(this.clientInfo, clientOptions);
14373
+ this.setupRootsHandler();
14374
+ logger.debug("Roots handler registered before connect");
14205
14375
  try {
14206
- await this.client.connect(transport);
14376
+ await this.client.connect(transport, {
14377
+ timeout: Math.min(this.timeout, 3e3)
14378
+ });
14379
+ const sessionId = streamableTransport.sessionId;
14380
+ if (sessionId) {
14381
+ logger.debug(`Session ID obtained: ${sessionId}`);
14382
+ } else {
14383
+ logger.warn(
14384
+ "Session ID not available after connect - this may cause issues with SSE stream"
14385
+ );
14386
+ }
14207
14387
  } catch (connectErr) {
14208
14388
  if (connectErr instanceof Error) {
14209
14389
  const errMsg = connectErr.message || connectErr.toString();
14210
- if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID")) {
14390
+ if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
14211
14391
  const wrappedError = new Error(
14212
- `FastMCP session ID error: ${errMsg}`
14392
+ `Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
14213
14393
  );
14214
14394
  wrappedError.cause = connectErr;
14215
14395
  throw wrappedError;
@@ -14217,8 +14397,24 @@ var HttpConnector = (_h = class extends BaseConnector {
14217
14397
  }
14218
14398
  throw connectErr;
14219
14399
  }
14400
+ this.streamableTransport = streamableTransport;
14401
+ this.connectionManager = {
14402
+ stop: /* @__PURE__ */ __name(async () => {
14403
+ if (this.streamableTransport) {
14404
+ try {
14405
+ await this.streamableTransport.close();
14406
+ } catch (e) {
14407
+ logger.warn(`Error closing Streamable HTTP transport: ${e}`);
14408
+ } finally {
14409
+ this.streamableTransport = null;
14410
+ }
14411
+ }
14412
+ }, "stop")
14413
+ };
14220
14414
  this.connected = true;
14221
14415
  this.transportType = "streamable-http";
14416
+ this.setupNotificationHandler();
14417
+ this.setupSamplingHandler();
14222
14418
  logger.debug(
14223
14419
  `Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
14224
14420
  );
@@ -14239,10 +14435,28 @@ var HttpConnector = (_h = class extends BaseConnector {
14239
14435
  const serverId = this.baseUrl;
14240
14436
  transport = this.opts.wrapTransport(transport, serverId);
14241
14437
  }
14242
- this.client = new Client(this.clientInfo, this.opts.clientOptions);
14438
+ const clientOptions = {
14439
+ ...this.opts.clientOptions || {},
14440
+ capabilities: {
14441
+ ...this.opts.clientOptions?.capabilities || {},
14442
+ roots: { listChanged: true },
14443
+ // Always advertise roots capability
14444
+ // Add sampling capability if callback is provided
14445
+ ...this.opts.samplingCallback ? { sampling: {} } : {}
14446
+ }
14447
+ };
14448
+ logger.debug(
14449
+ `Creating Client with capabilities (SSE):`,
14450
+ JSON.stringify(clientOptions.capabilities, null, 2)
14451
+ );
14452
+ this.client = new Client(this.clientInfo, clientOptions);
14453
+ this.setupRootsHandler();
14454
+ logger.debug("Roots handler registered before connect (SSE)");
14243
14455
  await this.client.connect(transport);
14244
14456
  this.connected = true;
14245
14457
  this.transportType = "sse";
14458
+ this.setupNotificationHandler();
14459
+ this.setupSamplingHandler();
14246
14460
  logger.debug(
14247
14461
  `Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
14248
14462
  );
@@ -14264,8 +14478,8 @@ var HttpConnector = (_h = class extends BaseConnector {
14264
14478
  getTransportType() {
14265
14479
  return this.transportType;
14266
14480
  }
14267
- }, __name(_h, "HttpConnector"), _h);
14268
- var WebSocketConnectionManager = (_i = class extends ConnectionManager {
14481
+ }, __name(_g, "HttpConnector"), _g);
14482
+ var WebSocketConnectionManager = (_h = class extends ConnectionManager {
14269
14483
  url;
14270
14484
  headers;
14271
14485
  _ws = null;
@@ -14326,8 +14540,8 @@ var WebSocketConnectionManager = (_i = class extends ConnectionManager {
14326
14540
  }
14327
14541
  });
14328
14542
  }
14329
- }, __name(_i, "WebSocketConnectionManager"), _i);
14330
- var WebSocketConnector = (_j = class extends BaseConnector {
14543
+ }, __name(_h, "WebSocketConnectionManager"), _h);
14544
+ var WebSocketConnector = (_i = class extends BaseConnector {
14331
14545
  url;
14332
14546
  headers;
14333
14547
  connectionManager = null;
@@ -14402,6 +14616,9 @@ var WebSocketConnector = (_j = class extends BaseConnector {
14402
14616
  this.pending.delete(id2);
14403
14617
  if ("result" in data2) resolve(data2.result);
14404
14618
  else if ("error" in data2) reject(data2.error);
14619
+ } else if (data2.method && !data2.id) {
14620
+ logger.debug("Received notification", data2.method, data2.params);
14621
+ this.handleNotification(data2);
14405
14622
  } else {
14406
14623
  logger.debug("Received unsolicited message", data2);
14407
14624
  }
@@ -14432,6 +14649,47 @@ var WebSocketConnector = (_j = class extends BaseConnector {
14432
14649
  for (const { reject } of this.pending.values()) reject(err);
14433
14650
  this.pending.clear();
14434
14651
  }
14652
+ async handleNotification(data2) {
14653
+ switch (data2.method) {
14654
+ case "notifications/tools/list_changed":
14655
+ await this.refreshToolsCache();
14656
+ break;
14657
+ case "notifications/resources/list_changed":
14658
+ await this.onResourcesListChanged();
14659
+ break;
14660
+ case "notifications/prompts/list_changed":
14661
+ await this.onPromptsListChanged();
14662
+ break;
14663
+ }
14664
+ for (const handler of this.notificationHandlers) {
14665
+ try {
14666
+ await handler({
14667
+ method: data2.method,
14668
+ params: data2.params
14669
+ });
14670
+ } catch (err) {
14671
+ logger.error("Error in notification handler:", err);
14672
+ }
14673
+ }
14674
+ }
14675
+ /**
14676
+ * Auto-refresh tools cache when server sends tools/list_changed notification
14677
+ * Override to use WebSocket-specific listTools method
14678
+ */
14679
+ async refreshToolsCache() {
14680
+ try {
14681
+ logger.debug(
14682
+ "[Auto] Refreshing tools cache due to list_changed notification"
14683
+ );
14684
+ const tools = await this.listTools();
14685
+ this.toolsCache = tools.map((t) => t);
14686
+ logger.debug(
14687
+ `[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
14688
+ );
14689
+ } catch (err) {
14690
+ logger.warn("[Auto] Failed to refresh tools cache:", err);
14691
+ }
14692
+ }
14435
14693
  async initialize() {
14436
14694
  logger.debug("Initializing MCP session over WebSocket");
14437
14695
  const result = await this.sendRequest("initialize");
@@ -14480,8 +14738,8 @@ var WebSocketConnector = (_j = class extends BaseConnector {
14480
14738
  url: this.url
14481
14739
  };
14482
14740
  }
14483
- }, __name(_j, "WebSocketConnector"), _j);
14484
- var BrowserOAuthClientProvider = (_k = class {
14741
+ }, __name(_i, "WebSocketConnector"), _i);
14742
+ var BrowserOAuthClientProvider = (_j = class {
14485
14743
  serverUrl;
14486
14744
  storageKeyPrefix;
14487
14745
  serverUrlHash;
@@ -14689,7 +14947,7 @@ var BrowserOAuthClientProvider = (_k = class {
14689
14947
  getKey(keySuffix) {
14690
14948
  return `${this.storageKeyPrefix}_${this.serverUrlHash}_${keySuffix}`;
14691
14949
  }
14692
- }, __name(_k, "BrowserOAuthClientProvider"), _k);
14950
+ }, __name(_j, "BrowserOAuthClientProvider"), _j);
14693
14951
  async function onMcpAuthorization() {
14694
14952
  const queryParams = new URLSearchParams(window.location.search);
14695
14953
  const code = queryParams.get("code");
@@ -14816,7 +15074,7 @@ async function onMcpAuthorization() {
14816
15074
  }
14817
15075
  }
14818
15076
  __name(onMcpAuthorization, "onMcpAuthorization");
14819
- var BaseMCPClient = (_l = class {
15077
+ var BaseMCPClient = (_k = class {
14820
15078
  config = {};
14821
15079
  sessions = {};
14822
15080
  activeSessions = [];
@@ -14927,20 +15185,29 @@ var BaseMCPClient = (_l = class {
14927
15185
  logger.debug("All sessions closed successfully");
14928
15186
  }
14929
15187
  }
14930
- }, __name(_l, "BaseMCPClient"), _l);
14931
- var BrowserMCPClient = (_m = class extends BaseMCPClient {
15188
+ }, __name(_k, "BaseMCPClient"), _k);
15189
+ var BrowserMCPClient = (_l = class extends BaseMCPClient {
14932
15190
  constructor(config) {
14933
15191
  super(config);
14934
15192
  }
14935
15193
  static fromDict(cfg) {
14936
- return new _m(cfg);
15194
+ return new _l(cfg);
14937
15195
  }
14938
15196
  /**
14939
15197
  * Create a connector from server configuration (Browser version)
14940
15198
  * Supports HTTP and WebSocket connectors only
14941
15199
  */
14942
15200
  createConnectorFromConfig(serverConfig) {
14943
- const { url, transport, headers, authToken, authProvider, wrapTransport } = serverConfig;
15201
+ const {
15202
+ url,
15203
+ transport,
15204
+ headers,
15205
+ authToken,
15206
+ authProvider,
15207
+ wrapTransport,
15208
+ clientOptions,
15209
+ samplingCallback
15210
+ } = serverConfig;
14944
15211
  if (!url) {
14945
15212
  throw new Error("Server URL is required");
14946
15213
  }
@@ -14949,9 +15216,23 @@ var BrowserMCPClient = (_m = class extends BaseMCPClient {
14949
15216
  authToken,
14950
15217
  authProvider,
14951
15218
  // ← Pass OAuth provider to connector
14952
- wrapTransport
15219
+ wrapTransport,
14953
15220
  // ← Pass transport wrapper if provided
15221
+ clientOptions,
15222
+ // ← Pass client options (capabilities, etc.) to connector
15223
+ samplingCallback
15224
+ // ← Pass sampling callback to connector
14954
15225
  };
15226
+ if (clientOptions) {
15227
+ console.log(
15228
+ "[BrowserMCPClient] Passing clientOptions to connector:",
15229
+ JSON.stringify(clientOptions, null, 2)
15230
+ );
15231
+ } else {
15232
+ console.warn(
15233
+ "[BrowserMCPClient] No clientOptions provided to connector!"
15234
+ );
15235
+ }
14955
15236
  if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
14956
15237
  return new WebSocketConnector(url, connectorOptions);
14957
15238
  } else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
@@ -14960,7 +15241,7 @@ var BrowserMCPClient = (_m = class extends BaseMCPClient {
14960
15241
  return new HttpConnector(url, connectorOptions);
14961
15242
  }
14962
15243
  }
14963
- }, __name(_m, "BrowserMCPClient"), _m);
15244
+ }, __name(_l, "BrowserMCPClient"), _l);
14964
15245
  var react = { exports: {} };
14965
15246
  var react_production = {};
14966
15247
  var hasRequiredReact_production;
@@ -17675,7 +17956,9 @@ function useMcp(options) {
17675
17956
  // 30 seconds default for connection timeout
17676
17957
  sseReadTimeout = 3e5,
17677
17958
  // 5 minutes default for SSE read timeout
17678
- wrapTransport
17959
+ wrapTransport,
17960
+ onNotification,
17961
+ samplingCallback
17679
17962
  } = options;
17680
17963
  const [state, setState] = reactExports.useState("discovering");
17681
17964
  const [tools, setTools] = reactExports.useState([]);
@@ -17828,6 +18111,10 @@ function useMcp(options) {
17828
18111
  ...serverConfig,
17829
18112
  authProvider: authProviderRef.current,
17830
18113
  // ← SDK handles OAuth automatically!
18114
+ clientOptions: clientConfig,
18115
+ // ← Pass client config to connector
18116
+ samplingCallback,
18117
+ // ← Pass sampling callback to connector
17831
18118
  wrapTransport: wrapTransport ? (transport) => {
17832
18119
  console.log(
17833
18120
  "[useMcp] Applying transport wrapper for server:",
@@ -17838,7 +18125,13 @@ function useMcp(options) {
17838
18125
  return wrapTransport(transport, url);
17839
18126
  } : void 0
17840
18127
  });
17841
- const session = await clientRef.current.createSession(serverName);
18128
+ const session = await clientRef.current.createSession(
18129
+ serverName,
18130
+ false
18131
+ );
18132
+ if (onNotification) {
18133
+ session.on("notification", onNotification);
18134
+ }
17842
18135
  await session.initialize();
17843
18136
  addLog("info", "✅ Successfully connected to MCP server");
17844
18137
  addLog("info", "Server info:", session.connector.serverInfo);
@@ -18249,7 +18542,7 @@ function useMcp(options) {
18249
18542
  };
18250
18543
  }
18251
18544
  __name(useMcp, "useMcp");
18252
- var ErrorBoundary = (_n = class extends re$1.Component {
18545
+ var ErrorBoundary = (_m = class extends re$1.Component {
18253
18546
  constructor(props2) {
18254
18547
  super(props2);
18255
18548
  this.state = { hasError: false, error: null };
@@ -18266,7 +18559,7 @@ var ErrorBoundary = (_n = class extends re$1.Component {
18266
18559
  }
18267
18560
  return this.props.children;
18268
18561
  }
18269
- }, __name(_n, "ErrorBoundary"), _n);
18562
+ }, __name(_m, "ErrorBoundary"), _m);
18270
18563
  var SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
18271
18564
  function useOpenAiGlobal(key) {
18272
18565
  return reactExports.useSyncExternalStore(
@@ -40376,7 +40669,7 @@ class MCPToolSavedEvent {
40376
40669
  function getPackageVersion() {
40377
40670
  try {
40378
40671
  if (true) {
40379
- return "0.7.0";
40672
+ return "0.7.1-canary.1";
40380
40673
  }
40381
40674
  return "0.0.0";
40382
40675
  } catch {
@@ -40667,6 +40960,55 @@ function McpConnectionWrapper({
40667
40960
  return wrapTransportRef.current(transport, actualServerId);
40668
40961
  };
40669
40962
  }, [wrapTransportReady, url]);
40963
+ const NOTIFICATIONS_STORAGE_KEY = `mcp-inspector-notifications-${url}`;
40964
+ const MAX_NOTIFICATIONS = 500;
40965
+ const [notifications, setNotifications] = reactExports.useState([]);
40966
+ reactExports.useEffect(() => {
40967
+ try {
40968
+ const saved = localStorage.getItem(NOTIFICATIONS_STORAGE_KEY);
40969
+ if (saved) {
40970
+ const parsed = JSON.parse(saved);
40971
+ if (Array.isArray(parsed)) {
40972
+ setNotifications(parsed);
40973
+ }
40974
+ }
40975
+ } catch (e) {
40976
+ console.error("Failed to load notifications from localStorage:", e);
40977
+ }
40978
+ }, [NOTIFICATIONS_STORAGE_KEY]);
40979
+ reactExports.useEffect(() => {
40980
+ try {
40981
+ localStorage.setItem(
40982
+ NOTIFICATIONS_STORAGE_KEY,
40983
+ JSON.stringify(notifications)
40984
+ );
40985
+ } catch (e) {
40986
+ console.error("Failed to save notifications to localStorage:", e);
40987
+ }
40988
+ }, [notifications, NOTIFICATIONS_STORAGE_KEY]);
40989
+ const markNotificationRead = reactExports.useCallback((id2) => {
40990
+ setNotifications(
40991
+ (prev) => prev.map((n2) => n2.id === id2 ? { ...n2, read: true } : n2)
40992
+ );
40993
+ }, []);
40994
+ const markAllNotificationsRead = reactExports.useCallback(() => {
40995
+ setNotifications((prev) => prev.map((n2) => ({ ...n2, read: true })));
40996
+ }, []);
40997
+ const clearNotifications = reactExports.useCallback(() => {
40998
+ setNotifications([]);
40999
+ }, []);
41000
+ const onNotificationReceived = reactExports.useCallback(
41001
+ (notification) => {
41002
+ setNotifications((prev) => {
41003
+ const updated = [notification, ...prev];
41004
+ if (updated.length > MAX_NOTIFICATIONS) {
41005
+ return updated.slice(0, MAX_NOTIFICATIONS);
41006
+ }
41007
+ return updated;
41008
+ });
41009
+ },
41010
+ []
41011
+ );
40670
41012
  const mcpHook = useMcp({
40671
41013
  url: finalUrl,
40672
41014
  callbackUrl,
@@ -40675,7 +41017,16 @@ function McpConnectionWrapper({
40675
41017
  // Default to 'http' for Streamable HTTP
40676
41018
  enabled: wrapTransportReady,
40677
41019
  // Only connect when wrapper is ready
40678
- wrapTransport: wrapTransportFn
41020
+ wrapTransport: wrapTransportFn,
41021
+ onNotification: (notification) => {
41022
+ onNotificationReceived({
41023
+ id: globalThis.crypto.randomUUID(),
41024
+ method: notification.method,
41025
+ params: notification.params,
41026
+ timestamp: Date.now(),
41027
+ read: false
41028
+ });
41029
+ }
40679
41030
  });
40680
41031
  const onUpdateRef = reactExports.useRef(onUpdate);
40681
41032
  const prevConnectionRef = reactExports.useRef(null);
@@ -40691,6 +41042,7 @@ function McpConnectionWrapper({
40691
41042
  mcpHook.serverInfo
40692
41043
  );
40693
41044
  }
41045
+ const unreadCount = notifications.filter((n2) => !n2.read).length;
40694
41046
  const connection = {
40695
41047
  id: url,
40696
41048
  url,
@@ -40707,6 +41059,11 @@ function McpConnectionWrapper({
40707
41059
  proxyConfig,
40708
41060
  serverInfo: mcpHook.serverInfo,
40709
41061
  capabilities: mcpHook.capabilities,
41062
+ notifications,
41063
+ unreadNotificationCount: unreadCount,
41064
+ markNotificationRead,
41065
+ markAllNotificationsRead,
41066
+ clearNotifications,
40710
41067
  callTool: mcpHook.callTool,
40711
41068
  readResource: mcpHook.readResource,
40712
41069
  listPrompts: mcpHook.listPrompts,
@@ -40717,12 +41074,13 @@ function McpConnectionWrapper({
40717
41074
  client: mcpHook.client
40718
41075
  };
40719
41076
  const prev = prevConnectionRef.current;
40720
- if (!prev || prev.state !== connection.state || prev.error !== connection.error || prev.authUrl !== connection.authUrl || prev.name !== connection.name || prev.tools.length !== connection.tools.length || prev.resources.length !== connection.resources.length || prev.prompts.length !== connection.prompts.length || prev.serverInfo !== connection.serverInfo || prev.capabilities !== connection.capabilities || !prev.client) {
41077
+ if (!prev || prev.state !== connection.state || prev.error !== connection.error || prev.authUrl !== connection.authUrl || prev.name !== connection.name || prev.tools.length !== connection.tools.length || prev.resources.length !== connection.resources.length || prev.prompts.length !== connection.prompts.length || prev.serverInfo !== connection.serverInfo || prev.capabilities !== connection.capabilities || prev.notifications.length !== connection.notifications.length || prev.unreadNotificationCount !== connection.unreadNotificationCount || !prev.client) {
40721
41078
  prevConnectionRef.current = connection;
40722
41079
  onUpdateRef.current(connection);
40723
41080
  }
40724
41081
  });
40725
41082
  } else {
41083
+ const unreadCount = notifications.filter((n2) => !n2.read).length;
40726
41084
  const connection = {
40727
41085
  id: url,
40728
41086
  url,
@@ -40739,6 +41097,11 @@ function McpConnectionWrapper({
40739
41097
  proxyConfig,
40740
41098
  serverInfo: mcpHook.serverInfo,
40741
41099
  capabilities: mcpHook.capabilities,
41100
+ notifications,
41101
+ unreadNotificationCount: unreadCount,
41102
+ markNotificationRead,
41103
+ markAllNotificationsRead,
41104
+ clearNotifications,
40742
41105
  callTool: mcpHook.callTool,
40743
41106
  readResource: mcpHook.readResource,
40744
41107
  listPrompts: mcpHook.listPrompts,
@@ -40749,7 +41112,7 @@ function McpConnectionWrapper({
40749
41112
  client: mcpHook.client
40750
41113
  };
40751
41114
  const prev = prevConnectionRef.current;
40752
- if (!prev || prev.state !== connection.state || prev.error !== connection.error || prev.authUrl !== connection.authUrl || prev.name !== connection.name || prev.tools.length !== connection.tools.length || prev.resources.length !== connection.resources.length || prev.prompts.length !== connection.prompts.length || prev.serverInfo !== connection.serverInfo || prev.capabilities !== connection.capabilities || !prev.client) {
41115
+ if (!prev || prev.state !== connection.state || prev.error !== connection.error || prev.authUrl !== connection.authUrl || prev.name !== connection.name || prev.tools.length !== connection.tools.length || prev.resources.length !== connection.resources.length || prev.prompts.length !== connection.prompts.length || prev.serverInfo !== connection.serverInfo || prev.capabilities !== connection.capabilities || prev.notifications.length !== connection.notifications.length || prev.unreadNotificationCount !== connection.unreadNotificationCount || !prev.client) {
40753
41116
  prevConnectionRef.current = connection;
40754
41117
  onUpdateRef.current(connection);
40755
41118
  }
@@ -40770,6 +41133,10 @@ function McpConnectionWrapper({
40770
41133
  mcpHook.serverInfo,
40771
41134
  mcpHook.capabilities,
40772
41135
  mcpHook.client,
41136
+ notifications,
41137
+ markNotificationRead,
41138
+ markAllNotificationsRead,
41139
+ clearNotifications,
40773
41140
  // Stable functions don't strictly need to be here but good practice
40774
41141
  mcpHook.callTool,
40775
41142
  mcpHook.readResource,
@@ -40807,6 +41174,14 @@ function McpProvider({ children }) {
40807
41174
  customHeaders: config.proxyConfig?.customHeaders,
40808
41175
  transportType: config.transportType,
40809
41176
  proxyConfig: config.proxyConfig,
41177
+ notifications: [],
41178
+ unreadNotificationCount: 0,
41179
+ markNotificationRead: () => {
41180
+ },
41181
+ markAllNotificationsRead: () => {
41182
+ },
41183
+ clearNotifications: () => {
41184
+ },
40810
41185
  callTool: async () => {
40811
41186
  },
40812
41187
  readResource: async () => {
@@ -40877,6 +41252,14 @@ function McpProvider({ children }) {
40877
41252
  customHeaders: proxyConfig?.customHeaders,
40878
41253
  transportType,
40879
41254
  proxyConfig,
41255
+ notifications: [],
41256
+ unreadNotificationCount: 0,
41257
+ markNotificationRead: () => {
41258
+ },
41259
+ markAllNotificationsRead: () => {
41260
+ },
41261
+ clearNotifications: () => {
41262
+ },
40880
41263
  callTool: async () => {
40881
41264
  },
40882
41265
  readResource: async () => {
@@ -40947,7 +41330,7 @@ function McpProvider({ children }) {
40947
41330
  const index2 = prev.findIndex((c2) => c2.id === updatedConnection.id);
40948
41331
  if (index2 === -1) return prev;
40949
41332
  const current = prev[index2];
40950
- if (current.state === updatedConnection.state && current.tools === updatedConnection.tools && current.resources === updatedConnection.resources && current.prompts === updatedConnection.prompts && current.error === updatedConnection.error && current.serverInfo === updatedConnection.serverInfo && current.client === updatedConnection.client) {
41333
+ if (current.state === updatedConnection.state && current.tools === updatedConnection.tools && current.resources === updatedConnection.resources && current.prompts === updatedConnection.prompts && current.error === updatedConnection.error && current.serverInfo === updatedConnection.serverInfo && current.client === updatedConnection.client && current.notifications === updatedConnection.notifications && current.unreadNotificationCount === updatedConnection.unreadNotificationCount) {
40951
41334
  return prev;
40952
41335
  }
40953
41336
  const newConnections = [...prev];
@@ -41075,23 +41458,34 @@ const createLucideIcon = (iconName, iconNode) => {
41075
41458
  Component.displayName = toPascalCase(iconName);
41076
41459
  return Component;
41077
41460
  };
41078
- const __iconNode$U = [
41461
+ const __iconNode$V = [
41079
41462
  ["path", { d: "M12 17V3", key: "1cwfxf" }],
41080
41463
  ["path", { d: "m6 11 6 6 6-6", key: "12ii2o" }],
41081
41464
  ["path", { d: "M19 21H5", key: "150jfl" }]
41082
41465
  ];
41083
- const ArrowDownToLine = createLucideIcon("arrow-down-to-line", __iconNode$U);
41084
- const __iconNode$T = [
41466
+ const ArrowDownToLine = createLucideIcon("arrow-down-to-line", __iconNode$V);
41467
+ const __iconNode$U = [
41085
41468
  ["path", { d: "m18 9-6-6-6 6", key: "kcunyi" }],
41086
41469
  ["path", { d: "M12 3v14", key: "7cf3v8" }],
41087
41470
  ["path", { d: "M5 21h14", key: "11awu3" }]
41088
41471
  ];
41089
- const ArrowUpFromLine = createLucideIcon("arrow-up-from-line", __iconNode$T);
41090
- const __iconNode$S = [
41472
+ const ArrowUpFromLine = createLucideIcon("arrow-up-from-line", __iconNode$U);
41473
+ const __iconNode$T = [
41091
41474
  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
41092
41475
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
41093
41476
  ];
41094
- const ArrowUp = createLucideIcon("arrow-up", __iconNode$S);
41477
+ const ArrowUp = createLucideIcon("arrow-up", __iconNode$T);
41478
+ const __iconNode$S = [
41479
+ ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
41480
+ [
41481
+ "path",
41482
+ {
41483
+ d: "M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326",
41484
+ key: "11g9vi"
41485
+ }
41486
+ ]
41487
+ ];
41488
+ const Bell = createLucideIcon("bell", __iconNode$S);
41095
41489
  const __iconNode$R = [
41096
41490
  ["path", { d: "m11 10 3 3", key: "fzmg1i" }],
41097
41491
  [
@@ -82563,6 +82957,12 @@ function OpenAIComponentRendererBase({
82563
82957
  if (iframeRef.current?.contentWindow) {
82564
82958
  try {
82565
82959
  const iframeWindow = iframeRef.current.contentWindow;
82960
+ const iframeDocument = iframeRef.current.contentDocument;
82961
+ if (updates.theme !== void 0 && iframeDocument) {
82962
+ const htmlElement = iframeDocument.documentElement;
82963
+ htmlElement.setAttribute("data-theme", updates.theme);
82964
+ htmlElement.style.colorScheme = updates.theme;
82965
+ }
82566
82966
  if (iframeWindow.openai) {
82567
82967
  if (updates.displayMode !== void 0) {
82568
82968
  iframeWindow.openai.displayMode = updates.displayMode;
@@ -82869,6 +83269,14 @@ function OpenAIComponentRendererBase({
82869
83269
  updateIframeGlobals,
82870
83270
  useDevMode
82871
83271
  ]);
83272
+ reactExports.useEffect(() => {
83273
+ if (!iframeRef.current?.contentDocument || !isReady) return;
83274
+ const iframeDoc = iframeRef.current.contentDocument;
83275
+ const htmlElement = iframeDoc.documentElement;
83276
+ htmlElement.setAttribute("data-theme", resolvedTheme);
83277
+ htmlElement.style.colorScheme = resolvedTheme;
83278
+ updateIframeGlobals({ theme: resolvedTheme });
83279
+ }, [resolvedTheme, isReady, updateIframeGlobals]);
82872
83280
  reactExports.useEffect(() => {
82873
83281
  if (!widgetUrl) return;
82874
83282
  const measure = () => {
@@ -86425,7 +86833,7 @@ function useChatMessagesClientSide({
86425
86833
  let llm;
86426
86834
  if (llmConfig.provider === "openai") {
86427
86835
  const { ChatOpenAI } = await __vitePreload(async () => {
86428
- const { ChatOpenAI: ChatOpenAI2 } = await import("./index-CsP5AdwX.js");
86836
+ const { ChatOpenAI: ChatOpenAI2 } = await import("./index-LnKUeTzV.js");
86429
86837
  return { ChatOpenAI: ChatOpenAI2 };
86430
86838
  }, true ? __vite__mapDeps([4,5,6,2,7]) : void 0);
86431
86839
  llm = new ChatOpenAI({
@@ -86434,7 +86842,7 @@ function useChatMessagesClientSide({
86434
86842
  });
86435
86843
  } else if (llmConfig.provider === "anthropic") {
86436
86844
  const { ChatAnthropic } = await __vitePreload(async () => {
86437
- const { ChatAnthropic: ChatAnthropic2 } = await import("./index-B0NYybvW.js");
86845
+ const { ChatAnthropic: ChatAnthropic2 } = await import("./index-XmiNerc_.js");
86438
86846
  return { ChatAnthropic: ChatAnthropic2 };
86439
86847
  }, true ? __vite__mapDeps([8,5,6,2]) : void 0);
86440
86848
  llm = new ChatAnthropic({
@@ -86443,7 +86851,7 @@ function useChatMessagesClientSide({
86443
86851
  });
86444
86852
  } else if (llmConfig.provider === "google") {
86445
86853
  const { ChatGoogleGenerativeAI } = await __vitePreload(async () => {
86446
- const { ChatGoogleGenerativeAI: ChatGoogleGenerativeAI2 } = await import("./index-Q_pqNaNk.js");
86854
+ const { ChatGoogleGenerativeAI: ChatGoogleGenerativeAI2 } = await import("./index-Bk_3A_7h.js");
86447
86855
  return { ChatGoogleGenerativeAI: ChatGoogleGenerativeAI2 };
86448
86856
  }, true ? __vite__mapDeps([9,5,6,2,7]) : void 0);
86449
86857
  llm = new ChatGoogleGenerativeAI({
@@ -86462,7 +86870,7 @@ function useChatMessagesClientSide({
86462
86870
  }
86463
86871
  if (!agentRef.current || agentRef.current.llm !== llmRef.current.instance) {
86464
86872
  const { MCPAgent } = await __vitePreload(async () => {
86465
- const { MCPAgent: MCPAgent2 } = await import("./browser-BdCJ_qyB.js");
86873
+ const { MCPAgent: MCPAgent2 } = await import("./browser-8hDgrmFA.js");
86466
86874
  return { MCPAgent: MCPAgent2 };
86467
86875
  }, true ? __vite__mapDeps([10,6,2,1,3]) : void 0);
86468
86876
  agentRef.current = new MCPAgent({
@@ -89165,6 +89573,86 @@ function ResizableHandle({
89165
89573
  }
89166
89574
  );
89167
89575
  }
89576
+ function Kbd({ className, ...props2 }) {
89577
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
89578
+ "kbd",
89579
+ {
89580
+ "data-slot": "kbd",
89581
+ className: cn$1(
89582
+ "bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium select-none",
89583
+ "[&_svg:not([class*='size-'])]:size-3",
89584
+ "[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
89585
+ className
89586
+ ),
89587
+ ...props2
89588
+ }
89589
+ );
89590
+ }
89591
+ function NotificationsTabHeader({
89592
+ isSearchExpanded,
89593
+ searchQuery,
89594
+ filteredNotificationsCount,
89595
+ notificationsCount,
89596
+ onSearchExpand,
89597
+ onSearchChange,
89598
+ onSearchBlur,
89599
+ onClearAll,
89600
+ searchInputRef
89601
+ }) {
89602
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-4 py-3", children: [
89603
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 flex-1", children: !isSearchExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
89604
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-lg font-medium text-gray-900 dark:text-gray-100", children: "Notifications" }),
89605
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
89606
+ Badge,
89607
+ {
89608
+ className: "bg-zinc-500/20 text-zinc-600 dark:text-zinc-400 border-transparent",
89609
+ variant: "outline",
89610
+ children: filteredNotificationsCount
89611
+ }
89612
+ ),
89613
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
89614
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
89615
+ Button,
89616
+ {
89617
+ variant: "ghost",
89618
+ size: "sm",
89619
+ onClick: onSearchExpand,
89620
+ className: "h-8 w-8 p-0",
89621
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "h-4 w-4" })
89622
+ }
89623
+ ) }),
89624
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContent, { side: "bottom", className: "flex gap-2", children: [
89625
+ "Search",
89626
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Kbd, { children: "F" })
89627
+ ] })
89628
+ ] })
89629
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
89630
+ Input,
89631
+ {
89632
+ ref: searchInputRef,
89633
+ placeholder: "Search notifications...",
89634
+ value: searchQuery,
89635
+ onChange: (e) => onSearchChange(e.target.value),
89636
+ onBlur: onSearchBlur,
89637
+ className: "h-8 border-gray-300 dark:border-zinc-600"
89638
+ }
89639
+ ) }),
89640
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
89641
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
89642
+ Button,
89643
+ {
89644
+ variant: "ghost",
89645
+ size: "sm",
89646
+ onClick: onClearAll,
89647
+ disabled: notificationsCount === 0,
89648
+ className: "h-8 w-8 p-0",
89649
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "h-4 w-4" })
89650
+ }
89651
+ ) }),
89652
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "bottom", children: "Clear all" })
89653
+ ] }) })
89654
+ ] });
89655
+ }
89168
89656
  function ListItem({
89169
89657
  id: id2,
89170
89658
  isSelected,
@@ -89189,7 +89677,7 @@ function ListItem({
89189
89677
  className
89190
89678
  ),
89191
89679
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 sm:gap-3", children: [
89192
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 mt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
89680
+ icon && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 mt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
89193
89681
  "div",
89194
89682
  {
89195
89683
  className: cn$1(
@@ -89207,20 +89695,381 @@ function ListItem({
89207
89695
  }
89208
89696
  );
89209
89697
  }
89210
- function Kbd({ className, ...props2 }) {
89211
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
89212
- "kbd",
89213
- {
89214
- "data-slot": "kbd",
89215
- className: cn$1(
89216
- "bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium select-none",
89217
- "[&_svg:not([class*='size-'])]:size-3",
89218
- "[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
89219
- className
89220
- ),
89221
- ...props2
89698
+ function NotificationsList({
89699
+ notifications,
89700
+ selectedNotification,
89701
+ onNotificationSelect,
89702
+ focusedIndex,
89703
+ formatRelativeTime: formatRelativeTime2,
89704
+ listRef
89705
+ }) {
89706
+ if (notifications.length === 0) {
89707
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [
89708
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bell, { className: "h-12 w-12 text-gray-400 dark:text-gray-600 mb-3" }),
89709
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "No notifications yet" })
89710
+ ] });
89711
+ }
89712
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: listRef, className: "overflow-y-auto flex-1 overscroll-contain", children: notifications.map((notification, index2) => {
89713
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
89714
+ ListItem,
89715
+ {
89716
+ id: `notification-${notification.id}`,
89717
+ isSelected: selectedNotification?.id === notification.id,
89718
+ isFocused: focusedIndex === index2,
89719
+ title: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-3", children: [
89720
+ notification.method,
89721
+ !notification.read && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 block rounded-full bg-orange-500" })
89722
+ ] }),
89723
+ description: (() => {
89724
+ const timeStr = formatRelativeTime2(notification.timestamp);
89725
+ const paramCount = notification.params && Object.keys(notification.params).length > 0 ? Object.keys(notification.params).length : 0;
89726
+ const paramStr = paramCount > 0 ? ` | ${paramCount} param${paramCount > 1 ? "s" : ""}` : "";
89727
+ return timeStr + paramStr;
89728
+ })(),
89729
+ onClick: () => onNotificationSelect(notification)
89730
+ },
89731
+ notification.id
89732
+ );
89733
+ }) });
89734
+ }
89735
+ function NotificationResultDisplay({
89736
+ notification,
89737
+ previewMode,
89738
+ onTogglePreview,
89739
+ onCopy,
89740
+ onDownload,
89741
+ onFullscreen,
89742
+ isCopied = false,
89743
+ onClose
89744
+ }) {
89745
+ if (!notification) {
89746
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [
89747
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bell, { className: "h-12 w-12 text-gray-400 dark:text-gray-600 mb-3" }),
89748
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "Select a notification to view details" })
89749
+ ] });
89750
+ }
89751
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full", children: [
89752
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-shrink-0 px-4 py-3 border-b border-gray-200 dark:border-zinc-700 flex items-center justify-between", children: [
89753
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
89754
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
89755
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "h-3 w-3 text-gray-400" }),
89756
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: new Date(notification.timestamp).toLocaleTimeString() })
89757
+ ] }),
89758
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: notification.formatRelativeTime(notification.timestamp) })
89759
+ ] }),
89760
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
89761
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
89762
+ Button,
89763
+ {
89764
+ variant: "ghost",
89765
+ size: "sm",
89766
+ onClick: onTogglePreview,
89767
+ className: !previewMode ? "text-purple-600 dark:text-purple-400" : "",
89768
+ children: [
89769
+ previewMode ? /* @__PURE__ */ jsxRuntimeExports.jsx(Code, { className: "h-4 w-4 mr-1" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Brush, { className: "h-4 w-4 mr-1" }),
89770
+ previewMode ? "JSON" : "Formatted"
89771
+ ]
89772
+ }
89773
+ ),
89774
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", size: "sm", onClick: onCopy, children: isCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-4 w-4" }) }),
89775
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", size: "sm", onClick: onDownload, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "h-4 w-4" }) }),
89776
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", size: "sm", onClick: onFullscreen, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Maximize, { className: "h-4 w-4" }) }),
89777
+ onClose && /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$3, { className: "h-4 w-4" }) })
89778
+ ] })
89779
+ ] }),
89780
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
89781
+ JSONDisplay,
89782
+ {
89783
+ data: {
89784
+ method: notification.method,
89785
+ timestamp: notification.timestamp,
89786
+ read: notification.read,
89787
+ params: notification.params
89788
+ },
89789
+ filename: `notification-${notification.method.replace(/[^a-zA-Z0-9]/g, "-")}-${Date.now()}.json`
89790
+ }
89791
+ ) }) })
89792
+ ] });
89793
+ }
89794
+ function formatRelativeTime(timestamp) {
89795
+ const now2 = Date.now();
89796
+ const diff = now2 - timestamp;
89797
+ const seconds = Math.floor(diff / 1e3);
89798
+ const minutes = Math.floor(seconds / 60);
89799
+ const hours = Math.floor(minutes / 60);
89800
+ const days = Math.floor(hours / 24);
89801
+ if (seconds < 60) {
89802
+ return "just now";
89803
+ } else if (minutes < 60) {
89804
+ return `${minutes}m ago`;
89805
+ } else if (hours < 24) {
89806
+ return `${hours}h ago`;
89807
+ } else if (days < 7) {
89808
+ return `${days}d ago`;
89809
+ } else {
89810
+ return new Date(timestamp).toLocaleDateString();
89811
+ }
89812
+ }
89813
+ function NotificationsTab({
89814
+ notifications,
89815
+ unreadCount: _unreadCount,
89816
+ markNotificationRead,
89817
+ markAllNotificationsRead: _markAllNotificationsRead,
89818
+ clearNotifications,
89819
+ serverId: _serverId,
89820
+ isConnected
89821
+ }) {
89822
+ const [selectedNotification, setSelectedNotification] = reactExports.useState(null);
89823
+ const [searchQuery, setSearchQuery] = reactExports.useState("");
89824
+ const [focusedIndex, setFocusedIndex] = reactExports.useState(-1);
89825
+ const [autoScroll, setAutoScroll] = reactExports.useState(true);
89826
+ const [isSearchExpanded, setIsSearchExpanded] = reactExports.useState(false);
89827
+ const [previewMode, setPreviewMode] = reactExports.useState(true);
89828
+ const [isCopied, setIsCopied] = reactExports.useState(false);
89829
+ const listRef = reactExports.useRef(null);
89830
+ const notificationDisplayRef = reactExports.useRef(null);
89831
+ const searchInputRef = reactExports.useRef(null);
89832
+ const userHasScrolledRef = reactExports.useRef(false);
89833
+ reactExports.useEffect(() => {
89834
+ if (autoScroll && notifications.length > 0 && listRef.current && !userHasScrolledRef.current) {
89835
+ listRef.current.scrollTop = 0;
89222
89836
  }
89837
+ }, [notifications.length, autoScroll]);
89838
+ reactExports.useEffect(() => {
89839
+ const listElement = listRef.current;
89840
+ if (!listElement) return;
89841
+ const handleScroll2 = () => {
89842
+ if (listElement.scrollTop > 0) {
89843
+ userHasScrolledRef.current = true;
89844
+ setAutoScroll(false);
89845
+ }
89846
+ };
89847
+ listElement.addEventListener("scroll", handleScroll2);
89848
+ return () => listElement.removeEventListener("scroll", handleScroll2);
89849
+ }, []);
89850
+ reactExports.useEffect(() => {
89851
+ if (notifications.length === 0) {
89852
+ userHasScrolledRef.current = false;
89853
+ setAutoScroll(true);
89854
+ }
89855
+ }, [notifications.length]);
89856
+ reactExports.useEffect(() => {
89857
+ if (selectedNotification && !selectedNotification.read) {
89858
+ markNotificationRead(selectedNotification.id);
89859
+ }
89860
+ }, [selectedNotification, markNotificationRead]);
89861
+ reactExports.useEffect(() => {
89862
+ if (isSearchExpanded && searchInputRef.current) {
89863
+ searchInputRef.current.focus();
89864
+ }
89865
+ }, [isSearchExpanded]);
89866
+ const handleSearchBlur = reactExports.useCallback(() => {
89867
+ if (!searchQuery.trim()) {
89868
+ setIsSearchExpanded(false);
89869
+ }
89870
+ }, [searchQuery]);
89871
+ const filteredNotifications = reactExports.useMemo(() => {
89872
+ if (!searchQuery.trim()) return notifications;
89873
+ const query = searchQuery.toLowerCase();
89874
+ return notifications.filter(
89875
+ (notification) => notification.method.toLowerCase().includes(query) || JSON.stringify(notification.params || {}).toLowerCase().includes(query)
89876
+ );
89877
+ }, [notifications, searchQuery]);
89878
+ reactExports.useEffect(() => {
89879
+ setFocusedIndex(-1);
89880
+ }, [searchQuery]);
89881
+ reactExports.useEffect(() => {
89882
+ const handleKeyDown = (e) => {
89883
+ const target = e.target;
89884
+ const isInputFocused = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.contentEditable === "true";
89885
+ if (isInputFocused || e.metaKey || e.ctrlKey || e.altKey) {
89886
+ return;
89887
+ }
89888
+ const items2 = filteredNotifications;
89889
+ if (e.key === "ArrowDown") {
89890
+ e.preventDefault();
89891
+ setFocusedIndex((prev) => {
89892
+ const next = prev + 1;
89893
+ return next >= items2.length ? 0 : next;
89894
+ });
89895
+ } else if (e.key === "ArrowUp") {
89896
+ e.preventDefault();
89897
+ setFocusedIndex((prev) => {
89898
+ const next = prev - 1;
89899
+ return next < 0 ? items2.length - 1 : next;
89900
+ });
89901
+ } else if (e.key === "Enter" && focusedIndex >= 0) {
89902
+ e.preventDefault();
89903
+ const notification = filteredNotifications[focusedIndex];
89904
+ if (notification) {
89905
+ handleNotificationSelect(notification);
89906
+ }
89907
+ }
89908
+ };
89909
+ document.addEventListener("keydown", handleKeyDown);
89910
+ return () => document.removeEventListener("keydown", handleKeyDown);
89911
+ }, [focusedIndex, filteredNotifications]);
89912
+ reactExports.useEffect(() => {
89913
+ if (focusedIndex >= 0) {
89914
+ const itemId = `notification-${filteredNotifications[focusedIndex]?.id}`;
89915
+ const element = document.getElementById(itemId);
89916
+ if (element) {
89917
+ element.scrollIntoView({ behavior: "smooth", block: "nearest" });
89918
+ }
89919
+ }
89920
+ }, [focusedIndex, filteredNotifications]);
89921
+ const handleNotificationSelect = reactExports.useCallback(
89922
+ (notification) => {
89923
+ setSelectedNotification(notification);
89924
+ },
89925
+ []
89223
89926
  );
89927
+ const handleClearAll = reactExports.useCallback(() => {
89928
+ if (window.confirm(
89929
+ "Are you sure you want to clear all notifications? This cannot be undone."
89930
+ )) {
89931
+ clearNotifications();
89932
+ setSelectedNotification(null);
89933
+ }
89934
+ }, [clearNotifications]);
89935
+ const handleCopy = reactExports.useCallback(async () => {
89936
+ if (!selectedNotification) return;
89937
+ try {
89938
+ await navigator.clipboard.writeText(
89939
+ JSON.stringify(
89940
+ {
89941
+ method: selectedNotification.method,
89942
+ timestamp: selectedNotification.timestamp,
89943
+ read: selectedNotification.read,
89944
+ params: selectedNotification.params
89945
+ },
89946
+ null,
89947
+ 2
89948
+ )
89949
+ );
89950
+ setIsCopied(true);
89951
+ setTimeout(() => setIsCopied(false), 2e3);
89952
+ } catch (error) {
89953
+ console.error("[NotificationsTab] Failed to copy notification:", error);
89954
+ }
89955
+ }, [selectedNotification]);
89956
+ const handleDownload = reactExports.useCallback(() => {
89957
+ if (!selectedNotification) return;
89958
+ try {
89959
+ const blob = new globalThis.Blob(
89960
+ [
89961
+ JSON.stringify(
89962
+ {
89963
+ method: selectedNotification.method,
89964
+ timestamp: selectedNotification.timestamp,
89965
+ read: selectedNotification.read,
89966
+ params: selectedNotification.params
89967
+ },
89968
+ null,
89969
+ 2
89970
+ )
89971
+ ],
89972
+ {
89973
+ type: "application/json"
89974
+ }
89975
+ );
89976
+ const url = URL.createObjectURL(blob);
89977
+ const a2 = document.createElement("a");
89978
+ a2.href = url;
89979
+ a2.download = `notification-${Date.now()}.json`;
89980
+ document.body.appendChild(a2);
89981
+ a2.click();
89982
+ document.body.removeChild(a2);
89983
+ URL.revokeObjectURL(url);
89984
+ } catch (error) {
89985
+ console.error(
89986
+ "[NotificationsTab] Failed to download notification:",
89987
+ error
89988
+ );
89989
+ }
89990
+ }, [selectedNotification]);
89991
+ const handleFullscreen = reactExports.useCallback(async () => {
89992
+ if (!notificationDisplayRef.current) return;
89993
+ try {
89994
+ if (!document.fullscreenElement) {
89995
+ await notificationDisplayRef.current.requestFullscreen();
89996
+ } else {
89997
+ await document.exitFullscreen();
89998
+ }
89999
+ } catch (error) {
90000
+ console.error("[NotificationsTab] Failed to toggle fullscreen:", error);
90001
+ }
90002
+ }, []);
90003
+ const notificationResult = selectedNotification ? {
90004
+ method: selectedNotification.method,
90005
+ params: selectedNotification.params,
90006
+ timestamp: selectedNotification.timestamp,
90007
+ read: selectedNotification.read,
90008
+ formatRelativeTime
90009
+ } : null;
90010
+ if (!isConnected) {
90011
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full p-4 text-center", children: [
90012
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bell, { className: "h-12 w-12 text-gray-400 dark:text-gray-600 mb-3" }),
90013
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "Not connected to server" })
90014
+ ] });
90015
+ }
90016
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(ResizablePanelGroup, { direction: "horizontal", className: "h-full", children: [
90017
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ResizablePanel, { defaultSize: 40, minSize: 30, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
90018
+ ResizablePanelGroup,
90019
+ {
90020
+ direction: "vertical",
90021
+ className: "h-full border-r dark:border-zinc-700",
90022
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(ResizablePanel, { defaultSize: 75, minSize: 30, children: [
90023
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
90024
+ NotificationsTabHeader,
90025
+ {
90026
+ isSearchExpanded,
90027
+ searchQuery,
90028
+ filteredNotificationsCount: filteredNotifications.length,
90029
+ notificationsCount: notifications.length,
90030
+ onSearchExpand: () => setIsSearchExpanded(true),
90031
+ onSearchChange: setSearchQuery,
90032
+ onSearchBlur: handleSearchBlur,
90033
+ onClearAll: handleClearAll,
90034
+ searchInputRef
90035
+ }
90036
+ ),
90037
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col h-full", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
90038
+ NotificationsList,
90039
+ {
90040
+ notifications: filteredNotifications,
90041
+ selectedNotification,
90042
+ onNotificationSelect: handleNotificationSelect,
90043
+ focusedIndex,
90044
+ formatRelativeTime,
90045
+ listRef
90046
+ }
90047
+ ) })
90048
+ ] })
90049
+ }
90050
+ ) }),
90051
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ResizableHandle, {}),
90052
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ResizablePanel, { defaultSize: 60, minSize: 40, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
90053
+ "div",
90054
+ {
90055
+ ref: notificationDisplayRef,
90056
+ className: "h-full bg-white dark:bg-zinc-900",
90057
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
90058
+ NotificationResultDisplay,
90059
+ {
90060
+ notification: notificationResult,
90061
+ previewMode,
90062
+ onTogglePreview: () => setPreviewMode(!previewMode),
90063
+ onCopy: handleCopy,
90064
+ onDownload: handleDownload,
90065
+ onFullscreen: handleFullscreen,
90066
+ onClose: () => setSelectedNotification(null),
90067
+ isCopied
90068
+ }
90069
+ )
90070
+ }
90071
+ ) })
90072
+ ] });
89224
90073
  }
89225
90074
  function ListTabHeader({
89226
90075
  activeTab,
@@ -90300,7 +91149,7 @@ function PromptsTab({
90300
91149
  defaultSize: 0,
90301
91150
  collapsible: true,
90302
91151
  minSize: 5,
90303
- collapsedSize: 5,
91152
+ collapsedSize: 6,
90304
91153
  onCollapse: () => setRpcPanelCollapsed(true),
90305
91154
  onExpand: () => setRpcPanelCollapsed(false),
90306
91155
  className: "flex flex-col border-t dark:border-zinc-700",
@@ -91116,7 +91965,7 @@ function ResourcesTab({
91116
91965
  defaultSize: 0,
91117
91966
  collapsible: true,
91118
91967
  minSize: 5,
91119
- collapsedSize: 5,
91968
+ collapsedSize: 6,
91120
91969
  onCollapse: () => setRpcPanelCollapsed(true),
91121
91970
  onExpand: () => setRpcPanelCollapsed(false),
91122
91971
  className: "flex flex-col border-t dark:border-zinc-700",
@@ -92694,7 +93543,7 @@ function ToolsTab({
92694
93543
  defaultSize: 0,
92695
93544
  collapsible: true,
92696
93545
  minSize: 5,
92697
- collapsedSize: 5,
93546
+ collapsedSize: 6,
92698
93547
  onCollapse: () => {
92699
93548
  setRpcPanelCollapsed(true);
92700
93549
  },
@@ -92872,6 +93721,19 @@ function LayoutContent({
92872
93721
  },
92873
93722
  selectedServer.id
92874
93723
  );
93724
+ case "notifications":
93725
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
93726
+ NotificationsTab,
93727
+ {
93728
+ notifications: selectedServer.notifications,
93729
+ unreadCount: selectedServer.unreadNotificationCount,
93730
+ markNotificationRead: selectedServer.markNotificationRead,
93731
+ markAllNotificationsRead: selectedServer.markAllNotificationsRead,
93732
+ clearNotifications: selectedServer.clearNotifications,
93733
+ serverId: selectedServer.id,
93734
+ isConnected: selectedServer.state === "ready"
93735
+ }
93736
+ );
92875
93737
  default:
92876
93738
  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children });
92877
93739
  }
@@ -93968,7 +94830,8 @@ const tabs = [
93968
94830
  { id: "tools", label: "Tools", icon: Wrench },
93969
94831
  { id: "prompts", label: "Prompts", icon: MessageSquare },
93970
94832
  { id: "resources", label: "Resources", icon: FolderOpen },
93971
- { id: "chat", label: "Chat", icon: MessageCircle }
94833
+ { id: "chat", label: "Chat", icon: MessageCircle },
94834
+ { id: "notifications", label: "Notifications", icon: Bell }
93972
94835
  ];
93973
94836
  function LayoutHeader({
93974
94837
  connections,
@@ -94038,13 +94901,15 @@ function LayoutHeader({
94038
94901
  count2 = selectedServer.prompts.length;
94039
94902
  } else if (tab.id === "resources") {
94040
94903
  count2 = selectedServer.resources.length;
94904
+ } else if (tab.id === "notifications") {
94905
+ count2 = selectedServer.unreadNotificationCount;
94041
94906
  }
94042
94907
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
94043
94908
  TabsTrigger,
94044
94909
  {
94045
94910
  value: tab.id,
94046
94911
  icon: tab.icon,
94047
- className: "[&>svg]:mr-0 flex-1 flex-row gap-2",
94912
+ className: "[&>svg]:mr-0 flex-1 flex-row gap-2 relative",
94048
94913
  children: [
94049
94914
  count2 > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
94050
94915
  "span",
@@ -94089,13 +94954,15 @@ function LayoutHeader({
94089
94954
  count2 = selectedServer.prompts.length;
94090
94955
  } else if (tab.id === "resources") {
94091
94956
  count2 = selectedServer.resources.length;
94957
+ } else if (tab.id === "notifications") {
94958
+ count2 = selectedServer.unreadNotificationCount;
94092
94959
  }
94093
94960
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
94094
94961
  TabsTrigger,
94095
94962
  {
94096
94963
  value: tab.id,
94097
94964
  icon: tab.icon,
94098
- className: "[&>svg]:mr-0 lg:[&>svg]:mr-2",
94965
+ className: "[&>svg]:mr-0 lg:[&>svg]:mr-2 relative",
94099
94966
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "items-center gap-2 hidden lg:flex", children: [
94100
94967
  tab.label,
94101
94968
  count2 > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(