@mcpjam/inspector 0.3.5 → 0.3.6

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.
@@ -22663,7 +22663,7 @@ function createChatConfig(options = {}) {
22663
22663
  "Explain a concept to me"
22664
22664
  ];
22665
22665
  const config = {
22666
- title: `Chat`,
22666
+ title: "LLM Playground",
22667
22667
  suggestions: [...baseSuggestions, ...options.additionalSuggestions || []]
22668
22668
  };
22669
22669
  if (options.subtitle) {
@@ -26843,6 +26843,13 @@ const ChevronLeft = createLucideIcon("ChevronLeft", [
26843
26843
  const ChevronRight = createLucideIcon("ChevronRight", [
26844
26844
  ["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]
26845
26845
  ]);
26846
+ /**
26847
+ * @license lucide-react v0.447.0 - ISC
26848
+ *
26849
+ * This source code is licensed under the ISC license.
26850
+ * See the LICENSE file in the root directory of this source tree.
26851
+ */
26852
+ const ChevronUp = createLucideIcon("ChevronUp", [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]]);
26846
26853
  /**
26847
26854
  * @license lucide-react v0.447.0 - ISC
26848
26855
  *
@@ -29235,7 +29242,7 @@ const ClientLogsTab = ({
29235
29242
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
29236
29243
  "div",
29237
29244
  {
29238
- className: `flex items-start space-x-3 p-3 rounded-lg border ${config.bgColor} ${config.borderColor} hover:shadow-sm transition-all duration-200`,
29245
+ className: `group flex items-start space-x-3 p-3 rounded-lg border ${config.bgColor} ${config.borderColor} hover:shadow-sm transition-all duration-200`,
29239
29246
  children: [
29240
29247
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `flex-shrink-0 mt-0.5 ${config.iconColor}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconComponent, { className: "w-4 h-4" }) }),
29241
29248
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
@@ -29251,7 +29258,7 @@ const ClientLogsTab = ({
29251
29258
  ] }),
29252
29259
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `text-sm ${config.textColor} font-mono break-words`, children: log.message })
29253
29260
  ] }),
29254
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `flex-shrink-0 mt-0.5 ${config.iconColor}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, { value: log.message }) })
29261
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 mt-0.5 opacity-0 group-hover:opacity-100 transition-opacity duration-200", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, { value: log.message }) })
29255
29262
  ]
29256
29263
  }
29257
29264
  );
@@ -29280,11 +29287,33 @@ const TabbedHistoryPanel = ({
29280
29287
  setActiveTab
29281
29288
  }) => {
29282
29289
  const [isToolResultError, setIsToolResultError] = reactExports.useState(false);
29290
+ const { toast: toast2 } = useToast();
29283
29291
  reactExports.useEffect(() => {
29284
29292
  if (toolResult) {
29285
29293
  setIsToolResultError(toolResult.isError === true);
29286
29294
  }
29287
29295
  }, [toolResult]);
29296
+ const handleCopyLogs = async () => {
29297
+ if (clientLogs.length === 0) return;
29298
+ try {
29299
+ const logsText = clientLogs.map((log) => {
29300
+ const timestamp = new Date(log.timestamp).toISOString();
29301
+ return `[${timestamp}] ${log.level.toUpperCase()}: ${log.message}`;
29302
+ }).join("\n");
29303
+ await navigator.clipboard.writeText(logsText);
29304
+ toast2({
29305
+ title: "Logs copied to clipboard",
29306
+ description: `Successfully copied ${clientLogs.length} log entries to clipboard`
29307
+ });
29308
+ } catch (err) {
29309
+ console.error("Failed to copy logs to clipboard:", err);
29310
+ toast2({
29311
+ title: "Failed to copy logs",
29312
+ description: "Could not copy logs to clipboard. Please try again.",
29313
+ variant: "destructive"
29314
+ });
29315
+ }
29316
+ };
29288
29317
  reactExports.useEffect(() => {
29289
29318
  if (clientLogs.length > 0) {
29290
29319
  const isLastLogError = clientLogs[clientLogs.length - 1].level === "error";
@@ -29385,6 +29414,22 @@ const TabbedHistoryPanel = ({
29385
29414
  );
29386
29415
  }
29387
29416
  };
29417
+ const CopyLogsButton = ({
29418
+ onClick,
29419
+ count: count2
29420
+ }) => {
29421
+ if (count2 > 0) {
29422
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
29423
+ "button",
29424
+ {
29425
+ onClick,
29426
+ className: "p-2 rounded-lg hover:bg-accent/50 hover:text-foreground transition-all duration-200 group",
29427
+ title: "Copy all logs to clipboard",
29428
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "w-5 h-5 text-muted-foreground group-hover:text-foreground" })
29429
+ }
29430
+ );
29431
+ }
29432
+ };
29388
29433
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-transparent flex flex-col h-full", children: [
29389
29434
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-border/20 px-6 py-3", children: [
29390
29435
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-1", children: [
@@ -29392,20 +29437,30 @@ const TabbedHistoryPanel = ({
29392
29437
  renderResultsTabButton(),
29393
29438
  renderLogsTabButton()
29394
29439
  ] }),
29395
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
29396
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { children: activeTab == "activity" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
29440
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center", children: [
29441
+ activeTab === "activity" && /* @__PURE__ */ jsxRuntimeExports.jsx(
29397
29442
  ClearHistoryButton2,
29398
29443
  {
29399
29444
  onClick: onClearHistory,
29400
29445
  count: requestHistory.length
29401
29446
  }
29402
- ) : activeTab == "logs" && /* @__PURE__ */ jsxRuntimeExports.jsx(
29403
- ClearHistoryButton2,
29404
- {
29405
- onClick: onClearLogs,
29406
- count: clientLogs.length
29407
- }
29408
- ) }),
29447
+ ),
29448
+ activeTab === "logs" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
29449
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
29450
+ CopyLogsButton,
29451
+ {
29452
+ onClick: handleCopyLogs,
29453
+ count: clientLogs.length
29454
+ }
29455
+ ),
29456
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
29457
+ ClearHistoryButton2,
29458
+ {
29459
+ onClick: onClearLogs,
29460
+ count: clientLogs.length
29461
+ }
29462
+ )
29463
+ ] }),
29409
29464
  /* @__PURE__ */ jsxRuntimeExports.jsx(
29410
29465
  "button",
29411
29466
  {
@@ -29435,11 +29490,9 @@ const HistoryAndNotifications = ({
29435
29490
  const [activeTab, setActiveTab] = reactExports.useState(null);
29436
29491
  const { height, isDragging, handleDragStart, resetHeight, setCustomHeight } = useDraggablePane(500, "historyPaneHeight");
29437
29492
  const toggleCollapse = reactExports.useCallback(() => {
29438
- setIsCollapsed((c) => {
29439
- const next = !c;
29440
- if (next) {
29441
- setActiveTab(null);
29442
- }
29493
+ setIsCollapsed((collapsed) => {
29494
+ const next = !collapsed;
29495
+ if (next) setActiveTab(null);
29443
29496
  return next;
29444
29497
  });
29445
29498
  }, []);
@@ -29447,24 +29500,6 @@ const HistoryAndNotifications = ({
29447
29500
  if (!isCollapsed) resetHeight();
29448
29501
  }, [isCollapsed, resetHeight]);
29449
29502
  reactExports.useEffect(() => {
29450
- const onKey = (e) => {
29451
- var _a2;
29452
- if (isCollapsed) return;
29453
- const tag = (_a2 = e.target) == null ? void 0 : _a2.tagName.toLowerCase();
29454
- if (tag === "input" || tag === "textarea") return;
29455
- if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
29456
- e.preventDefault();
29457
- const inc = e.shiftKey ? 50 : 25;
29458
- const newH = e.key === "ArrowUp" ? height + inc : height - inc;
29459
- setCustomHeight(newH);
29460
- }
29461
- if (e.altKey && e.key === "r") {
29462
- e.preventDefault();
29463
- resetHeight();
29464
- }
29465
- };
29466
- window.addEventListener("keydown", onKey);
29467
- return () => window.removeEventListener("keydown", onKey);
29468
29503
  }, [isCollapsed, height, setCustomHeight, resetHeight]);
29469
29504
  reactExports.useEffect(() => {
29470
29505
  if (toolResult) {
@@ -29473,11 +29508,24 @@ const HistoryAndNotifications = ({
29473
29508
  }
29474
29509
  }, [toolResult]);
29475
29510
  reactExports.useEffect(() => {
29476
- if (clientLogs.length && clientLogs[clientLogs.length - 1].level === "error") {
29511
+ if (clientLogs.length > 0 && clientLogs[clientLogs.length - 1].level === "error") {
29477
29512
  setActiveTab("logs");
29478
29513
  setIsCollapsed(false);
29479
29514
  }
29480
29515
  }, [clientLogs]);
29516
+ reactExports.useEffect(() => {
29517
+ if (requestHistory.length === 0) return;
29518
+ const last = requestHistory[requestHistory.length - 1];
29519
+ if (!last.request) return;
29520
+ try {
29521
+ const parsed = JSON.parse(last.request);
29522
+ if (parsed.method === "ping") {
29523
+ setActiveTab("activity");
29524
+ setIsCollapsed(false);
29525
+ }
29526
+ } catch {
29527
+ }
29528
+ }, [requestHistory]);
29481
29529
  const counts = {
29482
29530
  activity: requestHistory.length,
29483
29531
  results: toolResult ? 1 : 0,
@@ -29505,7 +29553,7 @@ const HistoryAndNotifications = ({
29505
29553
  }
29506
29554
  ),
29507
29555
  isCollapsed ? (
29508
- // Collapsed: tab bar
29556
+ /* Collapsed: tab bar */
29509
29557
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex items-center", children: [
29510
29558
  TAB_CONFIG.map(({ key, label }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
29511
29559
  "button",
@@ -29530,7 +29578,7 @@ const HistoryAndNotifications = ({
29530
29578
  ) })
29531
29579
  ] })
29532
29580
  ) : (
29533
- // Expanded: full panel
29581
+ /* Expanded: full panel */
29534
29582
  /* @__PURE__ */ jsxRuntimeExports.jsx(
29535
29583
  TabbedHistoryPanel,
29536
29584
  {
@@ -34040,7 +34088,7 @@ const useTheme = () => {
34040
34088
  [theme, setThemeWithSideEffect]
34041
34089
  );
34042
34090
  };
34043
- const version$1 = "0.3.5";
34091
+ const version$1 = "0.3.6";
34044
34092
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
34045
34093
  createPopperScope
34046
34094
  ]);
@@ -34523,124 +34571,59 @@ const TooltipContent = reactExports.forwardRef(({ className, sideOffset = 4, ...
34523
34571
  }
34524
34572
  ));
34525
34573
  TooltipContent.displayName = Content2$1.displayName;
34526
- const Sidebar = ({
34527
- mcpAgent,
34574
+ class StringUtil {
34575
+ static shorten(str2, maxLength = 30) {
34576
+ return str2.length > maxLength ? str2.substring(0, maxLength - 3) + "..." : str2;
34577
+ }
34578
+ }
34579
+ const getConnectionStatusIcon = (status) => {
34580
+ switch (status) {
34581
+ case "connected":
34582
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Wifi, { className: "w-4 h-4 text-green-500" });
34583
+ case "disconnected":
34584
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { className: "w-4 h-4 text-gray-400" });
34585
+ case "error":
34586
+ case "error-connecting-to-proxy":
34587
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-4 h-4 text-red-500" });
34588
+ default:
34589
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { className: "w-4 h-4 text-gray-400" });
34590
+ }
34591
+ };
34592
+ const getConnectionStatusColor = (status) => {
34593
+ switch (status) {
34594
+ case "connected":
34595
+ return "text-green-600 dark:text-green-400";
34596
+ case "disconnected":
34597
+ return "text-gray-500 dark:text-gray-400";
34598
+ case "error":
34599
+ case "error-connecting-to-proxy":
34600
+ return "text-red-600 dark:text-red-400";
34601
+ default:
34602
+ return "text-gray-500 dark:text-gray-400";
34603
+ }
34604
+ };
34605
+ const getConnectionDisplayText = (connection) => {
34606
+ var _a2;
34607
+ if (connection.config.transportType === "stdio" && "command" in connection.config) {
34608
+ return `${connection.config.command} ${((_a2 = connection.config.args) == null ? void 0 : _a2.join(" ")) || ""}`;
34609
+ }
34610
+ if ("url" in connection.config && connection.config.url) {
34611
+ return StringUtil.shorten(connection.config.url.toString());
34612
+ }
34613
+ return "Unknown configuration";
34614
+ };
34615
+ const ConnectionItem = ({
34616
+ connection,
34528
34617
  selectedServerName,
34529
34618
  onServerSelect,
34619
+ onEditClient,
34530
34620
  onRemoveServer,
34531
34621
  onConnectServer,
34532
34622
  onDisconnectServer,
34533
- onCreateClient,
34534
- onEditClient,
34535
- updateTrigger,
34536
- isExpanded,
34537
- onToggleExpanded
34623
+ shouldDisableConnection,
34624
+ getConnectTooltipMessage
34538
34625
  }) => {
34539
- const [theme, setTheme] = useTheme();
34540
- const serverConnections = React.useMemo(() => {
34541
- return mcpAgent ? mcpAgent.getAllConnectionInfo() : [];
34542
- }, [mcpAgent, updateTrigger]);
34543
- const getLogoSrc = () => {
34544
- if (theme === "dark") {
34545
- return "/mcp_jam_dark.png";
34546
- } else if (theme === "light") {
34547
- return "/mcp_jam_light.png";
34548
- } else {
34549
- const isDarkMode = document.documentElement.classList.contains("dark");
34550
- return isDarkMode ? "/mcp_jam_dark.png" : "/mcp_jam_light.png";
34551
- }
34552
- };
34553
- const getConnectionStatusIcon = (status) => {
34554
- switch (status) {
34555
- case "connected":
34556
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Wifi, { className: "w-4 h-4 text-green-500" });
34557
- case "disconnected":
34558
- return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { className: "w-4 h-4 text-gray-400" });
34559
- case "error":
34560
- case "error-connecting-to-proxy":
34561
- return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-4 h-4 text-red-500" });
34562
- default:
34563
- return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { className: "w-4 h-4 text-gray-400" });
34564
- }
34565
- };
34566
- const getConnectionStatusColor = (status) => {
34567
- switch (status) {
34568
- case "connected":
34569
- return "text-green-600 dark:text-green-400";
34570
- case "disconnected":
34571
- return "text-gray-500 dark:text-gray-400";
34572
- case "error":
34573
- case "error-connecting-to-proxy":
34574
- return "text-red-600 dark:text-red-400";
34575
- default:
34576
- return "text-gray-500 dark:text-gray-400";
34577
- }
34578
- };
34579
- const shouldDisableConnection = () => {
34580
- return false;
34581
- };
34582
- const getConnectTooltipMessage = () => {
34583
- return "Connect to this server";
34584
- };
34585
- const getConnectionDisplayText = (connection) => {
34586
- var _a2;
34587
- if (connection.config.transportType === "stdio" && "command" in connection.config) {
34588
- return `${connection.config.command} ${((_a2 = connection.config.args) == null ? void 0 : _a2.join(" ")) || ""}`;
34589
- }
34590
- if ("url" in connection.config && connection.config.url) {
34591
- return connection.config.url.toString();
34592
- }
34593
- return "Unknown configuration";
34594
- };
34595
- const renderHeader = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 border-b border-gray-200 dark:border-gray-800", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center space-y-2", children: [
34596
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full flex justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
34597
- "img",
34598
- {
34599
- src: getLogoSrc(),
34600
- alt: "MCP Jam",
34601
- className: "h-6 w-auto object-contain transition-opacity duration-200",
34602
- onError: (e) => {
34603
- console.warn("Failed to load MCP Jam logo");
34604
- e.currentTarget.style.display = "none";
34605
- }
34606
- }
34607
- ) }),
34608
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground opacity-70", children: [
34609
- "v",
34610
- version$1
34611
- ] }) })
34612
- ] }) });
34613
- const renderConnectionsHeader = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 border-b border-border/50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
34614
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [
34615
- /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { className: "w-4 h-4 text-muted-foreground" }),
34616
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium text-foreground", children: "Connections" }),
34617
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground bg-muted px-1.5 py-0.5 rounded", children: serverConnections.length })
34618
- ] }),
34619
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
34620
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
34621
- Button,
34622
- {
34623
- onClick: onCreateClient,
34624
- size: "sm",
34625
- variant: "ghost",
34626
- className: "h-7 w-7 p-0 hover:bg-primary/20 hover:text-primary",
34627
- title: "Create new client",
34628
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" })
34629
- }
34630
- ) }),
34631
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: (mcpAgent == null ? void 0 : mcpAgent.hasConnectedRemoteServer()) ? "Note: Creating a remote client will disconnect the current remote connection" : "Create new client" })
34632
- ] })
34633
- ] }) });
34634
- const renderEmptyState = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-8", children: [
34635
- /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { className: "w-12 h-12 text-muted-foreground mx-auto mb-4" }),
34636
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium mb-2", children: "No connections" }),
34637
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground mb-4", children: "Create your first MCP connection to get started" }),
34638
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: onCreateClient, size: "sm", className: "w-full", children: [
34639
- /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4 mr-2" }),
34640
- "Create Connection"
34641
- ] })
34642
- ] }) });
34643
- const renderConnectionActions = (connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-1", children: [
34626
+ const renderConnectionActions = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-1", children: [
34644
34627
  /* @__PURE__ */ jsxRuntimeExports.jsx(
34645
34628
  Button,
34646
34629
  {
@@ -34668,7 +34651,7 @@ const Sidebar = ({
34668
34651
  }
34669
34652
  )
34670
34653
  ] });
34671
- const renderConnectionButton = (connection) => {
34654
+ const renderConnectionButton = () => {
34672
34655
  if (connection.connectionStatus === "connected") {
34673
34656
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34674
34657
  Button,
@@ -34702,7 +34685,7 @@ const Sidebar = ({
34702
34685
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: getConnectTooltipMessage() })
34703
34686
  ] });
34704
34687
  };
34705
- const renderConnectionItem = (connection) => /* @__PURE__ */ jsxRuntimeExports.jsx(
34688
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
34706
34689
  "div",
34707
34690
  {
34708
34691
  className: `p-3 rounded-lg border cursor-pointer transition-all hover:bg-muted/50 ${selectedServerName === connection.name ? "border-primary bg-primary/10" : "border-border"}`,
@@ -34713,10 +34696,10 @@ const Sidebar = ({
34713
34696
  getConnectionStatusIcon(connection.connectionStatus),
34714
34697
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
34715
34698
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium text-sm", children: connection.name }),
34716
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: getConnectionDisplayText(connection) })
34699
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `text-xs text-muted-foreground break-all`, children: getConnectionDisplayText(connection) })
34717
34700
  ] })
34718
34701
  ] }),
34719
- renderConnectionActions(connection)
34702
+ renderConnectionActions()
34720
34703
  ] }),
34721
34704
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
34722
34705
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -34726,12 +34709,93 @@ const Sidebar = ({
34726
34709
  children: connection.connectionStatus
34727
34710
  }
34728
34711
  ),
34729
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex space-x-1", children: renderConnectionButton(connection) })
34712
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex space-x-1", children: renderConnectionButton() })
34730
34713
  ] })
34731
34714
  ] })
34732
- },
34733
- connection.name
34715
+ }
34734
34716
  );
34717
+ };
34718
+ const Sidebar = ({
34719
+ mcpAgent,
34720
+ selectedServerName,
34721
+ onServerSelect,
34722
+ onRemoveServer,
34723
+ onConnectServer,
34724
+ onDisconnectServer,
34725
+ onCreateClient,
34726
+ onEditClient,
34727
+ updateTrigger,
34728
+ isExpanded,
34729
+ onToggleExpanded
34730
+ }) => {
34731
+ const [theme, setTheme] = useTheme();
34732
+ const serverConnections = React.useMemo(() => {
34733
+ return mcpAgent ? mcpAgent.getAllConnectionInfo() : [];
34734
+ }, [mcpAgent, updateTrigger]);
34735
+ const getLogoSrc = () => {
34736
+ if (theme === "dark") {
34737
+ return "/mcp_jam_dark.png";
34738
+ } else if (theme === "light") {
34739
+ return "/mcp_jam_light.png";
34740
+ } else {
34741
+ const isDarkMode = document.documentElement.classList.contains("dark");
34742
+ return isDarkMode ? "/mcp_jam_dark.png" : "/mcp_jam_light.png";
34743
+ }
34744
+ };
34745
+ const shouldDisableConnection = () => {
34746
+ return false;
34747
+ };
34748
+ const getConnectTooltipMessage = () => {
34749
+ return "Connect to this server";
34750
+ };
34751
+ const renderHeader = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 border-b border-gray-200 dark:border-gray-800", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center space-y-2", children: [
34752
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full flex justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
34753
+ "img",
34754
+ {
34755
+ src: getLogoSrc(),
34756
+ alt: "MCP Jam",
34757
+ className: "h-6 w-auto object-contain transition-opacity duration-200",
34758
+ onError: (e) => {
34759
+ console.warn("Failed to load MCP Jam logo");
34760
+ e.currentTarget.style.display = "none";
34761
+ }
34762
+ }
34763
+ ) }),
34764
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground opacity-70", children: [
34765
+ "v",
34766
+ version$1
34767
+ ] }) })
34768
+ ] }) });
34769
+ const renderConnectionsHeader = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 border-b border-border/50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
34770
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [
34771
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { className: "w-4 h-4 text-muted-foreground" }),
34772
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium text-foreground", children: "Connections" }),
34773
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground bg-muted px-1.5 py-0.5 rounded", children: serverConnections.length })
34774
+ ] }),
34775
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
34776
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
34777
+ Button,
34778
+ {
34779
+ onClick: onCreateClient,
34780
+ size: "sm",
34781
+ variant: "ghost",
34782
+ className: "h-7 w-7 p-0 hover:bg-primary/20 hover:text-primary",
34783
+ title: "Create new connection",
34784
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" })
34785
+ }
34786
+ ) }),
34787
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: (mcpAgent == null ? void 0 : mcpAgent.hasConnectedRemoteServer()) ? "Note: Creating a remote connection will disconnect the current remote connection" : "Create new connection" })
34788
+ ] })
34789
+ ] }) });
34790
+ const renderEmptyState = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-8", children: [
34791
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { className: "w-12 h-12 text-muted-foreground mx-auto mb-4" }),
34792
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium mb-2", children: "No connections" }),
34793
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground mb-4", children: "Create your first MCP connection to get started" }),
34794
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: onCreateClient, size: "sm", className: "w-full", children: [
34795
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4 mr-2" }),
34796
+ "Create Connection"
34797
+ ] })
34798
+ ] }) });
34735
34799
  const renderThemeSelector = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 border-t", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
34736
34800
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [
34737
34801
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
@@ -34811,7 +34875,21 @@ const Sidebar = ({
34811
34875
  renderConnectionsHeader(),
34812
34876
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden flex flex-col", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
34813
34877
  shouldShowCreatePrompt && renderEmptyState(),
34814
- serverConnections.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 space-y-2", children: serverConnections.map(renderConnectionItem) })
34878
+ serverConnections.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 space-y-2", children: serverConnections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx(
34879
+ ConnectionItem,
34880
+ {
34881
+ connection,
34882
+ selectedServerName,
34883
+ onServerSelect,
34884
+ onEditClient,
34885
+ onRemoveServer,
34886
+ onConnectServer,
34887
+ onDisconnectServer,
34888
+ shouldDisableConnection,
34889
+ getConnectTooltipMessage
34890
+ },
34891
+ connection.name
34892
+ )) })
34815
34893
  ] }) }) }),
34816
34894
  renderThemeSelector()
34817
34895
  ] });
@@ -34843,7 +34921,7 @@ const Sidebar = ({
34843
34921
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" })
34844
34922
  }
34845
34923
  ) }),
34846
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "right", children: "Create new client" })
34924
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "right", children: "Create new connection" })
34847
34925
  ] })
34848
34926
  ] }) });
34849
34927
  };
@@ -34879,7 +34957,7 @@ const Tabs = ({
34879
34957
  },
34880
34958
  {
34881
34959
  id: "chat",
34882
- label: "Chat",
34960
+ label: "Playground",
34883
34961
  icon: Bot,
34884
34962
  disabled: shouldDisableAll
34885
34963
  },
@@ -36480,6 +36558,48 @@ const ConnectionSection = ({
36480
36558
  )
36481
36559
  ] });
36482
36560
  };
36561
+ function configToDisplayStrings(config) {
36562
+ var _a2, _b;
36563
+ const argsString = config.transportType === "stdio" && "args" in config ? ((_a2 = config.args) == null ? void 0 : _a2.join(" ")) || "" : "";
36564
+ const urlString = config.transportType !== "stdio" && "url" in config ? ((_b = config.url) == null ? void 0 : _b.toString()) || "" : "";
36565
+ return { argsString, urlString };
36566
+ }
36567
+ function createStdioConfig(command, args = [], env = {}) {
36568
+ return {
36569
+ transportType: "stdio",
36570
+ command,
36571
+ args,
36572
+ env
36573
+ };
36574
+ }
36575
+ function createHttpConfig(url, transportType = "sse") {
36576
+ return {
36577
+ transportType,
36578
+ url
36579
+ };
36580
+ }
36581
+ function updateConfigFromStrings(config, argsString) {
36582
+ if (config.transportType === "stdio") {
36583
+ return {
36584
+ ...config,
36585
+ args: argsString.trim() ? argsString.split(/\s+/) : []
36586
+ };
36587
+ } else {
36588
+ return config;
36589
+ }
36590
+ }
36591
+ function createDefaultStdioConfig() {
36592
+ return createStdioConfig("npx", ["@modelcontextprotocol/server-everything"]);
36593
+ }
36594
+ function createDefaultHttpConfig(transportType = "sse") {
36595
+ return createHttpConfig(new URL("https://example.com"), transportType);
36596
+ }
36597
+ function isStdioConfig(config) {
36598
+ return config.transportType === "stdio";
36599
+ }
36600
+ function isHttpConfig(config) {
36601
+ return config.transportType !== "stdio";
36602
+ }
36483
36603
  var NAME = "Label";
36484
36604
  var Label$1 = reactExports.forwardRef((props, forwardedRef) => {
36485
36605
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -36603,10 +36723,7 @@ function Badge({ className, variant, ...props }) {
36603
36723
  const ClientFormSection = ({
36604
36724
  isCreating,
36605
36725
  editingClientName,
36606
- clientFormName,
36607
- setClientFormName,
36608
- clientFormConfig,
36609
- setClientFormConfig,
36726
+ initialClient,
36610
36727
  config,
36611
36728
  setConfig,
36612
36729
  bearerToken,
@@ -36615,80 +36732,95 @@ const ClientFormSection = ({
36615
36732
  setHeaderName,
36616
36733
  onSave,
36617
36734
  onCancel,
36618
- onImportMultipleServers,
36619
- onSaveMultiple
36735
+ onImportMultipleServers
36620
36736
  }) => {
36621
- const [argsString, setArgsString] = reactExports.useState("");
36622
- const [sseUrlString, setSseUrlString] = reactExports.useState("");
36623
- const [multipleClients, setMultipleClients] = reactExports.useState([]);
36624
- const [isMultipleMode, setIsMultipleMode] = reactExports.useState(false);
36737
+ const [multipleClients, setMultipleClients] = reactExports.useState(() => {
36738
+ if (initialClient) {
36739
+ return [
36740
+ {
36741
+ id: "editing-client",
36742
+ name: initialClient.name,
36743
+ config: initialClient.config
36744
+ }
36745
+ ];
36746
+ } else {
36747
+ return [
36748
+ {
36749
+ id: "new-client",
36750
+ name: "",
36751
+ config: createDefaultStdioConfig()
36752
+ }
36753
+ ];
36754
+ }
36755
+ });
36756
+ console.log("🔧 multipleClients", multipleClients);
36625
36757
  const [isManualConfigExpanded, setIsManualConfigExpanded] = reactExports.useState(true);
36626
36758
  const { toast: toast2 } = useToast();
36627
36759
  const [showImportDialog, setShowImportDialog] = reactExports.useState(false);
36628
36760
  const [nameError, setNameError] = reactExports.useState("");
36629
36761
  const [isNameTouched, setIsNameTouched] = reactExports.useState(false);
36630
- reactExports.useEffect(() => {
36631
- var _a2, _b;
36632
- if (clientFormConfig.transportType === "stdio" && "args" in clientFormConfig) {
36633
- setArgsString(((_a2 = clientFormConfig.args) == null ? void 0 : _a2.join(" ")) || "");
36634
- setSseUrlString("");
36635
- } else if (clientFormConfig.transportType !== "stdio" && "url" in clientFormConfig) {
36636
- setArgsString("");
36637
- setSseUrlString(((_b = clientFormConfig.url) == null ? void 0 : _b.toString()) || "");
36638
- }
36639
- }, [clientFormConfig]);
36762
+ const scrollContainerRef = reactExports.useRef(null);
36763
+ const isMultipleMode = multipleClients.length > 1;
36764
+ const currentClient = multipleClients[0] || {
36765
+ id: "default",
36766
+ name: "",
36767
+ config: createDefaultStdioConfig()
36768
+ };
36769
+ const handleUpdateCurrentClient = (updates) => {
36770
+ setMultipleClients(
36771
+ (prev) => prev.map(
36772
+ (client2) => client2.id === currentClient.id ? { ...client2, ...updates } : client2
36773
+ )
36774
+ );
36775
+ };
36640
36776
  reactExports.useEffect(() => {
36641
36777
  if (!isNameTouched) return;
36642
- if (clientFormName.trim()) {
36778
+ if (currentClient.name.trim()) {
36643
36779
  setNameError("");
36644
36780
  } else {
36645
36781
  setNameError("Client name is required");
36646
36782
  }
36647
- }, [clientFormName, isNameTouched]);
36783
+ }, [currentClient.name, isNameTouched]);
36648
36784
  const handleArgsChange = (newArgsString) => {
36649
- setArgsString(newArgsString);
36650
- if (clientFormConfig.transportType === "stdio") {
36651
- setClientFormConfig({
36652
- ...clientFormConfig,
36653
- args: newArgsString.trim() ? newArgsString.split(/\s+/) : []
36654
- });
36785
+ if (isStdioConfig(currentClient.config)) {
36786
+ const updatedConfig = updateConfigFromStrings(
36787
+ currentClient.config,
36788
+ newArgsString
36789
+ );
36790
+ handleUpdateCurrentClient({ config: updatedConfig });
36655
36791
  }
36656
36792
  };
36657
36793
  const handleSseUrlChange = (newSseUrlString) => {
36658
- setSseUrlString(newSseUrlString);
36794
+ if (isHttpConfig(currentClient.config)) {
36795
+ try {
36796
+ const newUrl = new URL(newSseUrlString || "https://example.com");
36797
+ handleUpdateCurrentClient({
36798
+ config: { ...currentClient.config, url: newUrl }
36799
+ });
36800
+ } catch {
36801
+ }
36802
+ }
36659
36803
  };
36660
36804
  const handleImportServers = (servers) => {
36661
- var _a2, _b;
36662
36805
  if (servers.length > 1) {
36663
- const clients = servers.map((server, index2) => {
36664
- var _a3, _b2;
36665
- return {
36666
- id: `client-${Date.now()}-${index2}`,
36667
- name: server.name,
36668
- config: server.config,
36669
- argsString: server.config.transportType === "stdio" && "args" in server.config ? ((_a3 = server.config.args) == null ? void 0 : _a3.join(" ")) || "" : "",
36670
- sseUrlString: server.config.transportType !== "stdio" && "url" in server.config ? ((_b2 = server.config.url) == null ? void 0 : _b2.toString()) || "" : ""
36671
- };
36672
- });
36806
+ const clients = servers.map((server, index2) => ({
36807
+ id: `client-${Date.now()}-${index2}`,
36808
+ name: server.name,
36809
+ config: server.config
36810
+ }));
36673
36811
  setMultipleClients(clients);
36674
- setIsMultipleMode(true);
36675
36812
  toast2({
36676
36813
  title: "Multiple servers imported",
36677
36814
  description: `Imported ${servers.length} server configurations. Configure each client below.`
36678
36815
  });
36679
36816
  } else if (servers.length === 1) {
36680
36817
  const firstServer = servers[0];
36681
- setClientFormConfig(firstServer.config);
36682
- if (!clientFormName.trim()) {
36683
- setClientFormName(firstServer.name);
36684
- }
36685
- if (firstServer.config.transportType === "stdio" && "args" in firstServer.config) {
36686
- setArgsString(((_a2 = firstServer.config.args) == null ? void 0 : _a2.join(" ")) || "");
36687
- setSseUrlString("");
36688
- } else if (firstServer.config.transportType !== "stdio" && "url" in firstServer.config) {
36689
- setArgsString("");
36690
- setSseUrlString(((_b = firstServer.config.url) == null ? void 0 : _b.toString()) || "");
36691
- }
36818
+ const updatedClient = {
36819
+ ...currentClient,
36820
+ name: currentClient.name.trim() || firstServer.name,
36821
+ config: firstServer.config
36822
+ };
36823
+ setMultipleClients([updatedClient]);
36692
36824
  toast2({
36693
36825
  title: "Configuration imported",
36694
36826
  description: `Imported configuration for "${firstServer.name}".`
@@ -36697,6 +36829,14 @@ const ClientFormSection = ({
36697
36829
  if (onImportMultipleServers) {
36698
36830
  onImportMultipleServers(servers);
36699
36831
  }
36832
+ setTimeout(() => {
36833
+ if (scrollContainerRef.current) {
36834
+ scrollContainerRef.current.scrollTo({
36835
+ top: scrollContainerRef.current.scrollHeight,
36836
+ behavior: "smooth"
36837
+ });
36838
+ }
36839
+ }, 100);
36700
36840
  };
36701
36841
  const handleUpdateClient = (clientId, updates) => {
36702
36842
  setMultipleClients(
@@ -36714,39 +36854,12 @@ const ClientFormSection = ({
36714
36854
  const newClient = {
36715
36855
  id: `client-${Date.now()}`,
36716
36856
  name: "",
36717
- config: {
36718
- transportType: "stdio",
36719
- command: "npx",
36720
- args: ["@modelcontextprotocol/server-everything"],
36721
- env: {}
36722
- },
36723
- argsString: "@modelcontextprotocol/server-everything",
36724
- sseUrlString: ""
36857
+ config: createDefaultStdioConfig()
36725
36858
  };
36726
36859
  setMultipleClients((prev) => [...prev, newClient]);
36727
36860
  };
36728
- const handleSingleSave = () => {
36729
- let configToSave = { ...clientFormConfig };
36730
- if (configToSave.transportType !== "stdio") {
36731
- try {
36732
- const url = new URL(sseUrlString);
36733
- configToSave = {
36734
- ...configToSave,
36735
- url
36736
- };
36737
- } catch {
36738
- toast2({
36739
- title: "Invalid URL",
36740
- description: "Please enter a valid URL for the client.",
36741
- variant: "destructive"
36742
- });
36743
- return;
36744
- }
36745
- }
36746
- onSave(configToSave);
36747
- };
36748
- const handleSaveAll = async () => {
36749
- if (!onSaveMultiple) return;
36861
+ const handleSave = async () => {
36862
+ var _a2;
36750
36863
  const validClients = multipleClients.filter((c) => c.name.trim());
36751
36864
  if (validClients.length === 0) {
36752
36865
  toast2({
@@ -36756,439 +36869,478 @@ const ClientFormSection = ({
36756
36869
  });
36757
36870
  return;
36758
36871
  }
36759
- const clientsToSave = validClients.map((client2) => {
36760
- let configToSave = { ...client2.config };
36761
- if (configToSave.transportType !== "stdio") {
36872
+ const clientsToSave = [];
36873
+ const configErrors = [];
36874
+ for (const client2 of validClients) {
36875
+ if (isHttpConfig(client2.config)) {
36876
+ if (!client2.config.url) {
36877
+ configErrors.push(
36878
+ `${client2.name}: URL is required for HTTP connections`
36879
+ );
36880
+ continue;
36881
+ }
36762
36882
  try {
36763
- const url = new URL(client2.sseUrlString);
36764
- configToSave = {
36765
- ...configToSave,
36766
- url
36767
- };
36883
+ new URL(client2.config.url.toString());
36768
36884
  } catch {
36769
- throw new Error(`Invalid URL for client "${client2.name}"`);
36885
+ configErrors.push(`${client2.name}: Invalid URL format`);
36886
+ continue;
36770
36887
  }
36771
36888
  }
36772
- return {
36889
+ if (isStdioConfig(client2.config)) {
36890
+ if (!((_a2 = client2.config.command) == null ? void 0 : _a2.trim())) {
36891
+ configErrors.push(
36892
+ `${client2.name}: Command is required for stdio connections`
36893
+ );
36894
+ continue;
36895
+ }
36896
+ }
36897
+ clientsToSave.push({
36773
36898
  name: client2.name,
36774
- config: configToSave
36775
- };
36776
- });
36899
+ config: client2.config
36900
+ });
36901
+ }
36902
+ if (configErrors.length > 0) {
36903
+ toast2({
36904
+ title: "Configuration errors",
36905
+ description: `Please fix the following errors: ${configErrors.join(", ")}`,
36906
+ variant: "destructive"
36907
+ });
36908
+ return;
36909
+ }
36910
+ console.log("🔧 clientsToSave", clientsToSave);
36777
36911
  try {
36778
- const result = await onSaveMultiple(clientsToSave);
36912
+ const result = await onSave(clientsToSave);
36779
36913
  if (result.success.length > 0) {
36780
36914
  toast2({
36781
- title: "Clients created successfully",
36782
- description: `Successfully created ${result.success.length} connection(s).`
36915
+ title: "Clients saved successfully",
36916
+ description: `Successfully saved ${result.success.length} connection(s).`
36783
36917
  });
36784
36918
  }
36785
36919
  if (result.failed.length > 0) {
36786
36920
  toast2({
36787
- title: "Some clients failed to create",
36788
- description: `${result.failed.length} connection(s) failed to create. Check the console for details.`,
36921
+ title: "Some clients failed to save",
36922
+ description: `${result.failed.length} connection(s) failed to save. Check the console for details.`,
36789
36923
  variant: "destructive"
36790
36924
  });
36791
36925
  }
36792
36926
  } catch (error) {
36793
36927
  toast2({
36794
- title: "Error creating clients",
36928
+ title: "Error saving clients",
36795
36929
  description: error instanceof Error ? error.message : "An unexpected error occurred.",
36796
36930
  variant: "destructive"
36797
36931
  });
36798
36932
  }
36799
36933
  };
36800
36934
  const handleBackToSingle = () => {
36801
- setIsMultipleMode(false);
36802
- setMultipleClients([]);
36935
+ setMultipleClients([
36936
+ {
36937
+ id: "new-client",
36938
+ name: "",
36939
+ config: createDefaultStdioConfig()
36940
+ }
36941
+ ]);
36803
36942
  };
36804
36943
  if (isMultipleMode) {
36805
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-auto bg-gradient-to-br from-background to-muted/20", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-7xl mx-auto w-full p-6 space-y-6", children: [
36806
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
36807
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36808
- Button,
36809
- {
36810
- variant: "ghost",
36811
- size: "sm",
36812
- onClick: handleBackToSingle,
36813
- className: "h-8 w-8 p-0",
36814
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "h-4 w-4" })
36815
- }
36816
- ),
36817
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
36818
- /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Create Multiple Clients" }),
36819
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground mt-1", children: "Configure each imported server as a separate client" })
36820
- ] }),
36821
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "ml-auto", children: [
36822
- /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { className: "h-3 w-3 mr-1" }),
36823
- multipleClients.length,
36824
- " clients"
36825
- ] })
36826
- ] }),
36827
- /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, {}),
36828
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-6", children: [
36829
- multipleClients.map((client2, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
36830
- Card,
36831
- {
36832
- className: "border-2 border-border/50 hover:border-border transition-colors",
36833
- children: [
36834
- /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
36835
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
36836
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary font-semibold text-sm", children: index2 + 1 }),
36837
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
36838
- /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "text-lg", children: [
36839
- "Client ",
36840
- index2 + 1
36944
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
36945
+ "div",
36946
+ {
36947
+ ref: scrollContainerRef,
36948
+ className: "flex-1 flex flex-col overflow-auto bg-gradient-to-br from-background to-muted/20",
36949
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-7xl mx-auto w-full p-6 space-y-6", children: [
36950
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
36951
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
36952
+ Button,
36953
+ {
36954
+ variant: "ghost",
36955
+ size: "sm",
36956
+ onClick: handleBackToSingle,
36957
+ className: "h-8 w-8 p-0",
36958
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "h-4 w-4" })
36959
+ }
36960
+ ),
36961
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
36962
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Create Multiple Clients" }),
36963
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground mt-1", children: "Configure each imported server as a separate client" })
36964
+ ] }),
36965
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "ml-auto", children: [
36966
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { className: "h-3 w-3 mr-1" }),
36967
+ multipleClients.length,
36968
+ " clients"
36969
+ ] })
36970
+ ] }),
36971
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, {}),
36972
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-6", children: [
36973
+ multipleClients.map((client2, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
36974
+ Card,
36975
+ {
36976
+ className: "border-2 border-border/50 hover:border-border transition-colors",
36977
+ children: [
36978
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
36979
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
36980
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary font-semibold text-sm", children: index2 + 1 }),
36981
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
36982
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "text-lg", children: [
36983
+ "Client ",
36984
+ index2 + 1
36985
+ ] }),
36986
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: client2.name || "Unnamed client" })
36987
+ ] })
36841
36988
  ] }),
36842
- /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: client2.name || "Unnamed client" })
36989
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
36990
+ Button,
36991
+ {
36992
+ variant: "ghost",
36993
+ size: "sm",
36994
+ onClick: () => handleRemoveClient(client2.id),
36995
+ className: "h-8 w-8 p-0 text-muted-foreground hover:text-destructive",
36996
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "h-4 w-4" })
36997
+ }
36998
+ )
36999
+ ] }) }),
37000
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
37001
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37002
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37003
+ Label,
37004
+ {
37005
+ htmlFor: `client-name-${client2.id}`,
37006
+ className: "text-sm font-medium",
37007
+ children: "Client Name"
37008
+ }
37009
+ ),
37010
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37011
+ Input,
37012
+ {
37013
+ id: `client-name-${client2.id}`,
37014
+ value: client2.name,
37015
+ onChange: (e) => handleUpdateClient(client2.id, { name: e.target.value }),
37016
+ placeholder: "Enter a descriptive name for this client",
37017
+ className: "max-w-md"
37018
+ }
37019
+ )
37020
+ ] }),
37021
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
37022
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
37023
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-4 w-4 text-muted-foreground" }),
37024
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { className: "text-sm font-medium", children: "Connection Settings" })
37025
+ ] }),
37026
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border/50 rounded-lg p-4 bg-muted/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
37027
+ ConnectionSection,
37028
+ {
37029
+ connectionStatus: "disconnected",
37030
+ transportType: client2.config.transportType,
37031
+ setTransportType: (type2) => {
37032
+ const newConfig = type2 === "stdio" ? createDefaultStdioConfig() : createDefaultHttpConfig(type2);
37033
+ handleUpdateClient(client2.id, {
37034
+ config: newConfig
37035
+ });
37036
+ },
37037
+ command: isStdioConfig(client2.config) ? client2.config.command || "" : "",
37038
+ setCommand: (command) => {
37039
+ if (isStdioConfig(client2.config)) {
37040
+ handleUpdateClient(client2.id, {
37041
+ config: {
37042
+ ...client2.config,
37043
+ command
37044
+ }
37045
+ });
37046
+ }
37047
+ },
37048
+ args: configToDisplayStrings(client2.config).argsString,
37049
+ setArgs: (newArgsString) => {
37050
+ if (isStdioConfig(client2.config)) {
37051
+ const updatedConfig = updateConfigFromStrings(
37052
+ client2.config,
37053
+ newArgsString
37054
+ );
37055
+ handleUpdateClient(client2.id, {
37056
+ config: updatedConfig
37057
+ });
37058
+ }
37059
+ },
37060
+ sseUrl: configToDisplayStrings(client2.config).urlString,
37061
+ setSseUrl: (url) => {
37062
+ if (isHttpConfig(client2.config)) {
37063
+ try {
37064
+ const newUrl = new URL(
37065
+ url || "https://example.com"
37066
+ );
37067
+ handleUpdateClient(client2.id, {
37068
+ config: {
37069
+ ...client2.config,
37070
+ url: newUrl
37071
+ }
37072
+ });
37073
+ } catch {
37074
+ }
37075
+ }
37076
+ },
37077
+ env: isStdioConfig(client2.config) ? client2.config.env || {} : {},
37078
+ setEnv: (env) => {
37079
+ if (isStdioConfig(client2.config)) {
37080
+ handleUpdateClient(client2.id, {
37081
+ config: {
37082
+ ...client2.config,
37083
+ env
37084
+ }
37085
+ });
37086
+ }
37087
+ },
37088
+ config,
37089
+ setConfig,
37090
+ bearerToken,
37091
+ setBearerToken,
37092
+ headerName,
37093
+ setHeaderName,
37094
+ onConnect: () => {
37095
+ },
37096
+ onDisconnect: () => {
37097
+ },
37098
+ stdErrNotifications: [],
37099
+ clearStdErrNotifications: () => {
37100
+ },
37101
+ logLevel: "debug",
37102
+ sendLogLevelRequest: async () => {
37103
+ },
37104
+ loggingSupported: false,
37105
+ hideActionButtons: true
37106
+ }
37107
+ ) })
37108
+ ] })
36843
37109
  ] })
37110
+ ]
37111
+ },
37112
+ client2.id
37113
+ )),
37114
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { className: "border-2 border-dashed border-border/50 hover:border-border transition-colors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
37115
+ Button,
37116
+ {
37117
+ variant: "ghost",
37118
+ onClick: handleAddClient,
37119
+ className: "w-full h-16 text-muted-foreground hover:text-foreground",
37120
+ children: [
37121
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "h-5 w-5 mr-2" }),
37122
+ "Add Another Client"
37123
+ ]
37124
+ }
37125
+ ) }) })
37126
+ ] }),
37127
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sticky bottom-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-t pt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
37128
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: multipleClients.some((c) => !c.name.trim()) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-amber-600", children: [
37129
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
37130
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Some clients need names" })
37131
+ ] }) }),
37132
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
37133
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", onClick: onCancel, children: "Cancel" }),
37134
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
37135
+ Button,
37136
+ {
37137
+ onClick: handleSave,
37138
+ disabled: multipleClients.filter((c) => c.name.trim()).length === 0,
37139
+ className: "min-w-[200px]",
37140
+ children: [
37141
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { className: "h-4 w-4 mr-2" }),
37142
+ isCreating ? "Create" : "Update",
37143
+ " ",
37144
+ multipleClients.filter((c) => c.name.trim()).length,
37145
+ " ",
37146
+ "Connection(s)"
37147
+ ]
37148
+ }
37149
+ )
37150
+ ] })
37151
+ ] }) })
37152
+ ] })
37153
+ }
37154
+ );
37155
+ }
37156
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
37157
+ "div",
37158
+ {
37159
+ ref: scrollContainerRef,
37160
+ className: "flex-1 flex flex-col overflow-auto bg-gradient-to-br from-background to-muted/20",
37161
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-5xl mx-auto w-full p-6 space-y-8", children: [
37162
+ isCreating && /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "border-2 border-primary/20 bg-gradient-to-r from-primary/5 to-primary/10", children: [
37163
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
37164
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-primary/10 rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-5 w-5 text-primary" }) }),
37165
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-lg", children: "Quick Import" }) }),
37166
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "ml-auto", children: [
37167
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-3 w-3 mr-1" }),
37168
+ "Recommended"
37169
+ ] })
37170
+ ] }) }),
37171
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
37172
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Supports the same format used by Claude Desktop and Cursor." }),
37173
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
37174
+ Button,
37175
+ {
37176
+ onClick: () => setShowImportDialog(true),
37177
+ className: "w-full sm:w-auto",
37178
+ children: [
37179
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-4 h-4 mr-2" }),
37180
+ "Import from Configuration File"
37181
+ ]
37182
+ }
37183
+ )
37184
+ ] })
37185
+ ] }),
37186
+ isCreating && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
37187
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, { className: "w-16" }),
37188
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-muted-foreground", children: "or" }),
37189
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, { className: "w-16" })
37190
+ ] }) }),
37191
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "border-2 border-border/50", children: [
37192
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37193
+ CardHeader,
37194
+ {
37195
+ className: "cursor-pointer",
37196
+ onClick: () => setIsManualConfigExpanded(!isManualConfigExpanded),
37197
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
37198
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
37199
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-muted rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-5 w-5 text-muted-foreground" }) }),
37200
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-lg", children: isCreating ? "Manual Setup" : `Edit: ${editingClientName}` }) })
36844
37201
  ] }),
36845
37202
  /* @__PURE__ */ jsxRuntimeExports.jsx(
36846
37203
  Button,
36847
37204
  {
36848
37205
  variant: "ghost",
36849
37206
  size: "sm",
36850
- onClick: () => handleRemoveClient(client2.id),
36851
- className: "h-8 w-8 p-0 text-muted-foreground hover:text-destructive",
36852
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "h-4 w-4" })
37207
+ className: "h-8 w-8 p-0",
37208
+ onClick: (e) => {
37209
+ e.stopPropagation();
37210
+ setIsManualConfigExpanded(!isManualConfigExpanded);
37211
+ },
37212
+ children: isManualConfigExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "h-4 w-4" })
36853
37213
  }
36854
37214
  )
36855
- ] }) }),
36856
- /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
36857
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36858
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36859
- Label,
36860
- {
36861
- htmlFor: `client-name-${client2.id}`,
36862
- className: "text-sm font-medium",
36863
- children: "Client Name"
36864
- }
36865
- ),
36866
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36867
- Input,
37215
+ ] })
37216
+ }
37217
+ ),
37218
+ isManualConfigExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
37219
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37220
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "client-name", className: "text-sm font-medium", children: "Name*" }),
37221
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37222
+ Input,
37223
+ {
37224
+ id: "client-name",
37225
+ value: currentClient.name,
37226
+ onChange: (e) => handleUpdateCurrentClient({ name: e.target.value }),
37227
+ onBlur: () => setIsNameTouched(true),
37228
+ placeholder: "Enter client name",
37229
+ className: `max-w-md ${nameError ? "border-red-500 focus:border-red-500 focus:ring-red-500" : ""}`
37230
+ }
37231
+ ),
37232
+ nameError && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-red-500 flex items-center gap-1", children: [
37233
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
37234
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 cursor-help" }) }),
37235
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
37236
+ TooltipContent,
36868
37237
  {
36869
- id: `client-name-${client2.id}`,
36870
- value: client2.name,
36871
- onChange: (e) => handleUpdateClient(client2.id, { name: e.target.value }),
36872
- placeholder: "Enter a descriptive name for this client",
36873
- className: "max-w-md"
37238
+ side: "top",
37239
+ className: "max-w-sm p-2 text-xs leading-relaxed",
37240
+ children: [
37241
+ "A client name is required to help you identify and manage your MCP connections.",
37242
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
37243
+ "It ensures clarity when debugging or switching between multiple clients. Leaving it blank makes the connection untraceable within the tool."
37244
+ ]
36874
37245
  }
36875
37246
  )
36876
- ] }),
36877
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
36878
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
36879
- /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-4 w-4 text-muted-foreground" }),
36880
- /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { className: "text-sm font-medium", children: "Connection Settings" })
36881
- ] }),
36882
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border/50 rounded-lg p-4 bg-muted/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36883
- ConnectionSection,
36884
- {
36885
- connectionStatus: "disconnected",
36886
- transportType: client2.config.transportType,
36887
- setTransportType: (type2) => {
36888
- let newConfig;
36889
- let newArgsString = "";
36890
- if (type2 === "stdio") {
36891
- newConfig = {
36892
- transportType: type2,
36893
- command: "npx",
36894
- args: ["@modelcontextprotocol/server-everything"],
36895
- env: {}
36896
- };
36897
- newArgsString = "@modelcontextprotocol/server-everything";
36898
- } else {
36899
- newConfig = {
36900
- transportType: type2,
36901
- url: new URL("https://example.com")
36902
- };
36903
- }
36904
- handleUpdateClient(client2.id, {
36905
- config: newConfig,
36906
- argsString: newArgsString,
36907
- sseUrlString: newConfig.transportType !== "stdio" && "url" in newConfig && newConfig.url ? newConfig.url.toString() : ""
36908
- });
36909
- },
36910
- command: client2.config.transportType === "stdio" && "command" in client2.config ? client2.config.command || "" : "",
36911
- setCommand: (command) => {
36912
- if (client2.config.transportType === "stdio") {
36913
- handleUpdateClient(client2.id, {
36914
- config: {
36915
- ...client2.config,
36916
- command
36917
- }
36918
- });
36919
- }
36920
- },
36921
- args: client2.argsString,
36922
- setArgs: (newArgsString) => {
36923
- if (client2.config.transportType === "stdio") {
36924
- handleUpdateClient(client2.id, {
36925
- argsString: newArgsString,
36926
- config: {
36927
- ...client2.config,
36928
- args: newArgsString.trim() ? newArgsString.split(/\s+/) : []
36929
- }
36930
- });
37247
+ ] }) }),
37248
+ nameError
37249
+ ] })
37250
+ ] }),
37251
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
37252
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { className: "text-sm font-medium", children: "Connection" }),
37253
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border/50 rounded-lg p-4 bg-muted/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
37254
+ ConnectionSection,
37255
+ {
37256
+ connectionStatus: "disconnected",
37257
+ transportType: currentClient.config.transportType,
37258
+ setTransportType: (type2) => {
37259
+ const newConfig = type2 === "stdio" ? createDefaultStdioConfig() : createDefaultHttpConfig(type2);
37260
+ handleUpdateCurrentClient({ config: newConfig });
37261
+ },
37262
+ command: isStdioConfig(currentClient.config) ? currentClient.config.command || "" : "",
37263
+ setCommand: (command) => {
37264
+ if (isStdioConfig(currentClient.config)) {
37265
+ handleUpdateCurrentClient({
37266
+ config: {
37267
+ ...currentClient.config,
37268
+ command
36931
37269
  }
36932
- },
36933
- sseUrl: client2.sseUrlString,
36934
- setSseUrl: (url) => {
36935
- handleUpdateClient(client2.id, { sseUrlString: url });
36936
- },
36937
- env: client2.config.transportType === "stdio" && "env" in client2.config ? client2.config.env || {} : {},
36938
- setEnv: (env) => {
36939
- if (client2.config.transportType === "stdio") {
36940
- handleUpdateClient(client2.id, {
36941
- config: {
36942
- ...client2.config,
36943
- env
36944
- }
36945
- });
37270
+ });
37271
+ }
37272
+ },
37273
+ args: configToDisplayStrings(currentClient.config).argsString,
37274
+ setArgs: handleArgsChange,
37275
+ sseUrl: configToDisplayStrings(currentClient.config).urlString,
37276
+ setSseUrl: handleSseUrlChange,
37277
+ env: isStdioConfig(currentClient.config) ? currentClient.config.env || {} : {},
37278
+ setEnv: (env) => {
37279
+ if (isStdioConfig(currentClient.config)) {
37280
+ handleUpdateCurrentClient({
37281
+ config: {
37282
+ ...currentClient.config,
37283
+ env
36946
37284
  }
36947
- },
36948
- config,
36949
- setConfig,
36950
- bearerToken,
36951
- setBearerToken,
36952
- headerName,
36953
- setHeaderName,
36954
- onConnect: () => {
36955
- },
36956
- onDisconnect: () => {
36957
- },
36958
- stdErrNotifications: [],
36959
- clearStdErrNotifications: () => {
36960
- },
36961
- logLevel: "debug",
36962
- sendLogLevelRequest: async () => {
36963
- },
36964
- loggingSupported: false,
36965
- hideActionButtons: true
37285
+ });
36966
37286
  }
36967
- ) })
36968
- ] })
36969
- ] })
36970
- ]
36971
- },
36972
- client2.id
36973
- )),
36974
- /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { className: "border-2 border-dashed border-border/50 hover:border-border transition-colors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
36975
- Button,
36976
- {
36977
- variant: "ghost",
36978
- onClick: handleAddClient,
36979
- className: "w-full h-16 text-muted-foreground hover:text-foreground",
36980
- children: [
36981
- /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "h-5 w-5 mr-2" }),
36982
- "Add Another Client"
36983
- ]
36984
- }
36985
- ) }) })
36986
- ] }),
36987
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sticky bottom-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-t pt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
36988
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: multipleClients.some((c) => !c.name.trim()) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-amber-600", children: [
36989
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
36990
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Some clients need names" })
36991
- ] }) }),
36992
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
36993
- /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", onClick: onCancel, children: "Cancel" }),
37287
+ },
37288
+ config,
37289
+ setConfig,
37290
+ bearerToken,
37291
+ setBearerToken,
37292
+ headerName,
37293
+ setHeaderName,
37294
+ onConnect: () => {
37295
+ },
37296
+ onDisconnect: () => {
37297
+ },
37298
+ stdErrNotifications: [],
37299
+ clearStdErrNotifications: () => {
37300
+ },
37301
+ logLevel: "debug",
37302
+ sendLogLevelRequest: async () => {
37303
+ },
37304
+ loggingSupported: false,
37305
+ hideActionButtons: true
37306
+ }
37307
+ ) })
37308
+ ] })
37309
+ ] })
37310
+ ] }),
37311
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 pt-4", children: [
36994
37312
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36995
37313
  Button,
36996
37314
  {
36997
- onClick: handleSaveAll,
36998
- disabled: multipleClients.filter((c) => c.name.trim()).length === 0,
36999
- className: "min-w-[200px]",
37315
+ onClick: handleSave,
37316
+ disabled: !currentClient.name.trim(),
37317
+ className: "min-w-[180px] h-12 text-base font-semibold bg-primary hover:bg-primary/90 shadow-lg hover:shadow-xl transition-all duration-200 border-2 border-primary/20",
37000
37318
  children: [
37001
- /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { className: "h-4 w-4 mr-2" }),
37002
- "Create ",
37003
- multipleClients.filter((c) => c.name.trim()).length,
37004
- " ",
37005
- "Connection(s)"
37319
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { className: "h-5 w-5 mr-2" }),
37320
+ isCreating ? "Create Connection" : "Update Connection"
37006
37321
  ]
37007
37322
  }
37008
- )
37009
- ] })
37010
- ] }) })
37011
- ] }) });
37012
- }
37013
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-auto bg-gradient-to-br from-background to-muted/20", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-5xl mx-auto w-full p-6 space-y-8", children: [
37014
- isCreating && /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "border-2 border-primary/20 bg-gradient-to-r from-primary/5 to-primary/10", children: [
37015
- /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
37016
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-primary/10 rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-5 w-5 text-primary" }) }),
37017
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-lg", children: "Quick Import" }) }),
37018
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "ml-auto", children: [
37019
- /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-3 w-3 mr-1" }),
37020
- "Recommended"
37021
- ] })
37022
- ] }) }),
37023
- /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
37024
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Supports the same format used by Claude Desktop and Cursor." }),
37025
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
37026
- Button,
37027
- {
37028
- onClick: () => setShowImportDialog(true),
37029
- className: "w-full sm:w-auto",
37030
- children: [
37031
- /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-4 h-4 mr-2" }),
37032
- "Import from Configuration File"
37033
- ]
37034
- }
37035
- )
37036
- ] })
37037
- ] }),
37038
- isCreating && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
37039
- /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, { className: "w-16" }),
37040
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-muted-foreground", children: "or" }),
37041
- /* @__PURE__ */ jsxRuntimeExports.jsx(Separator, { className: "w-16" })
37042
- ] }) }),
37043
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "border-2 border-border/50", children: [
37044
- /* @__PURE__ */ jsxRuntimeExports.jsx(
37045
- CardHeader,
37046
- {
37047
- className: "cursor-pointer",
37048
- onClick: () => setIsManualConfigExpanded(!isManualConfigExpanded),
37049
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
37050
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
37051
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-muted rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-5 w-5 text-muted-foreground" }) }),
37052
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-lg", children: isCreating ? "Manual Setup" : `Edit: ${editingClientName}` }) })
37053
- ] }),
37054
- /* @__PURE__ */ jsxRuntimeExports.jsx(
37055
- Button,
37056
- {
37057
- variant: "ghost",
37058
- size: "sm",
37059
- className: "h-8 w-8 p-0",
37060
- onClick: (e) => {
37061
- e.stopPropagation();
37062
- setIsManualConfigExpanded(!isManualConfigExpanded);
37063
- },
37064
- children: isManualConfigExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "h-4 w-4" })
37065
- }
37066
- )
37067
- ] })
37068
- }
37069
- ),
37070
- isManualConfigExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
37071
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37072
- /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "client-name", className: "text-sm font-medium", children: "Name*" }),
37323
+ ),
37073
37324
  /* @__PURE__ */ jsxRuntimeExports.jsx(
37074
- Input,
37325
+ "button",
37075
37326
  {
37076
- id: "client-name",
37077
- value: clientFormName,
37078
- onChange: (e) => setClientFormName(e.target.value),
37079
- onBlur: () => setIsNameTouched(true),
37080
- placeholder: "Enter client name",
37081
- className: `max-w-md ${nameError ? "border-red-500 focus:border-red-500 focus:ring-red-500" : ""}`
37327
+ onClick: onCancel,
37328
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors underline-offset-4 hover:underline",
37329
+ children: "Cancel"
37082
37330
  }
37083
- ),
37084
- nameError && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-red-500 flex items-center gap-1", children: [
37085
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-3 w-3" }),
37086
- nameError
37087
- ] })
37331
+ )
37088
37332
  ] }),
37089
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
37090
- /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { className: "text-sm font-medium", children: "Connection" }),
37091
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border/50 rounded-lg p-4 bg-muted/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
37092
- ConnectionSection,
37093
- {
37094
- connectionStatus: "disconnected",
37095
- transportType: clientFormConfig.transportType,
37096
- setTransportType: (type2) => {
37097
- if (type2 === "stdio") {
37098
- const newConfig = {
37099
- transportType: type2,
37100
- command: "npx",
37101
- args: ["@modelcontextprotocol/server-everything"],
37102
- env: {}
37103
- };
37104
- setClientFormConfig(newConfig);
37105
- setArgsString(
37106
- "@modelcontextprotocol/server-everything"
37107
- );
37108
- } else {
37109
- setClientFormConfig({
37110
- transportType: type2,
37111
- url: new URL("https://example.com")
37112
- });
37113
- setArgsString("");
37114
- }
37115
- },
37116
- command: clientFormConfig.transportType === "stdio" && "command" in clientFormConfig ? clientFormConfig.command || "" : "",
37117
- setCommand: (command) => {
37118
- if (clientFormConfig.transportType === "stdio") {
37119
- setClientFormConfig({
37120
- ...clientFormConfig,
37121
- command
37122
- });
37123
- }
37124
- },
37125
- args: argsString,
37126
- setArgs: handleArgsChange,
37127
- sseUrl: sseUrlString,
37128
- setSseUrl: handleSseUrlChange,
37129
- env: clientFormConfig.transportType === "stdio" && "env" in clientFormConfig ? clientFormConfig.env || {} : {},
37130
- setEnv: (env) => {
37131
- if (clientFormConfig.transportType === "stdio") {
37132
- setClientFormConfig({
37133
- ...clientFormConfig,
37134
- env
37135
- });
37136
- }
37137
- },
37138
- config,
37139
- setConfig,
37140
- bearerToken,
37141
- setBearerToken,
37142
- headerName,
37143
- setHeaderName,
37144
- onConnect: () => {
37145
- },
37146
- onDisconnect: () => {
37147
- },
37148
- stdErrNotifications: [],
37149
- clearStdErrNotifications: () => {
37150
- },
37151
- logLevel: "debug",
37152
- sendLogLevelRequest: async () => {
37153
- },
37154
- loggingSupported: false,
37155
- hideActionButtons: true
37156
- }
37157
- ) })
37158
- ] })
37333
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37334
+ ConfigImportDialog,
37335
+ {
37336
+ open: showImportDialog,
37337
+ onOpenChange: setShowImportDialog,
37338
+ onImportServers: handleImportServers
37339
+ }
37340
+ )
37159
37341
  ] })
37160
- ] }),
37161
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 pt-4", children: [
37162
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
37163
- Button,
37164
- {
37165
- onClick: handleSingleSave,
37166
- disabled: !clientFormName.trim(),
37167
- className: "min-w-[180px] h-12 text-base font-semibold bg-primary hover:bg-primary/90 shadow-lg hover:shadow-xl transition-all duration-200 border-2 border-primary/20",
37168
- children: [
37169
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { className: "h-5 w-5 mr-2" }),
37170
- isCreating ? "Create Connection" : "Update Connection"
37171
- ]
37172
- }
37173
- ),
37174
- /* @__PURE__ */ jsxRuntimeExports.jsx(
37175
- "button",
37176
- {
37177
- onClick: onCancel,
37178
- className: "text-sm text-muted-foreground hover:text-foreground transition-colors underline-offset-4 hover:underline",
37179
- children: "Cancel"
37180
- }
37181
- )
37182
- ] }),
37183
- /* @__PURE__ */ jsxRuntimeExports.jsx(
37184
- ConfigImportDialog,
37185
- {
37186
- open: showImportDialog,
37187
- onOpenChange: setShowImportDialog,
37188
- onImportServers: handleImportServers
37189
- }
37190
- )
37191
- ] }) });
37342
+ }
37343
+ );
37192
37344
  };
37193
37345
  const StarGitHubModal = ({
37194
37346
  isOpen,
@@ -37328,6 +37480,7 @@ objectType({
37328
37480
  const SESSION_KEYS = {
37329
37481
  CODE_VERIFIER: "mcp_code_verifier",
37330
37482
  SERVER_URL: "mcp_server_url",
37483
+ TRANSPORT_TYPE: "mcp_transport_type",
37331
37484
  TOKENS: "mcp_tokens",
37332
37485
  CLIENT_INFORMATION: "mcp_client_information",
37333
37486
  SERVER_METADATA: "mcp_server_metadata"
@@ -37360,9 +37513,17 @@ const DEFAULT_INSPECTOR_CONFIG = {
37360
37513
  }
37361
37514
  };
37362
37515
  class InspectorOAuthClientProvider {
37363
- constructor(serverUrl) {
37516
+ constructor(serverUrl, transportType) {
37364
37517
  this.serverUrl = serverUrl;
37518
+ this.transportType = transportType;
37365
37519
  sessionStorage.setItem(SESSION_KEYS.SERVER_URL, serverUrl);
37520
+ if (transportType) {
37521
+ const transportKey = getServerSpecificKey(
37522
+ SESSION_KEYS.TRANSPORT_TYPE,
37523
+ serverUrl
37524
+ );
37525
+ sessionStorage.setItem(transportKey, transportType);
37526
+ }
37366
37527
  }
37367
37528
  get redirectUrl() {
37368
37529
  return window.location.origin + "/oauth/callback";
@@ -37438,6 +37599,9 @@ class InspectorOAuthClientProvider {
37438
37599
  sessionStorage.removeItem(
37439
37600
  getServerSpecificKey(SESSION_KEYS.CODE_VERIFIER, this.serverUrl)
37440
37601
  );
37602
+ sessionStorage.removeItem(
37603
+ getServerSpecificKey(SESSION_KEYS.TRANSPORT_TYPE, this.serverUrl)
37604
+ );
37441
37605
  }
37442
37606
  }
37443
37607
  class DebugInspectorOAuthClientProvider extends InspectorOAuthClientProvider {
@@ -43492,6 +43656,12 @@ const ToolCallMessage = ({
43492
43656
  toolCall
43493
43657
  }) => {
43494
43658
  const { type: type2, toolName, args, error, message, result } = toolCall;
43659
+ const [isCollapsed, setIsCollapsed] = reactExports.useState(true);
43660
+ const shouldBeCollapsible = reactExports.useMemo(() => {
43661
+ if (type2 !== "tool_result" || !result) return false;
43662
+ return result.length > 200;
43663
+ }, [result, type2]);
43664
+ const toggleCollapse = () => setIsCollapsed((prev) => !prev);
43495
43665
  const getIcon = () => {
43496
43666
  switch (type2) {
43497
43667
  case "tool_call":
@@ -43555,9 +43725,10 @@ const ToolCallMessage = ({
43555
43725
  /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs bg-black/10 dark:bg-white/10 rounded p-2 overflow-x-auto whitespace-pre-wrap", children: error })
43556
43726
  ] }),
43557
43727
  type2 === "tool_warning" && message && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs bg-black/10 dark:bg-white/10 rounded p-2", children: message }) }),
43558
- type2 === "tool_result" && result && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
43728
+ type2 === "tool_result" && result && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 relative", children: [
43559
43729
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs opacity-75 mb-1", children: "Result:" }),
43560
- /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs bg-black/10 dark:bg-white/10 rounded p-2 overflow-x-auto whitespace-pre-wrap", children: result })
43730
+ /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs bg-black/10 dark:bg-white/10 rounded p-2 overflow-x-auto whitespace-pre-wrap", children: shouldBeCollapsible && isCollapsed ? result.slice(0, 200) + "..." : result }),
43731
+ shouldBeCollapsible && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center mt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: toggleCollapse, className: "p-1", children: isCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) })
43561
43732
  ] })
43562
43733
  ]
43563
43734
  }
@@ -43895,11 +44066,15 @@ const ToolSelector = ({
43895
44066
  loading = false
43896
44067
  }) => {
43897
44068
  const [showSelector, setShowSelector] = reactExports.useState(false);
44069
+ const [expandedServers, setExpandedServers] = reactExports.useState(
44070
+ /* @__PURE__ */ new Set()
44071
+ );
43898
44072
  const selectorRef = reactExports.useRef(null);
43899
- const totalTools = tools.length;
44073
+ const availableTools = serverInfo.filter((server) => toolSelection.enabledServers.has(server.name)).flatMap((server) => server.tools);
44074
+ const totalAvailableTools = availableTools.length;
43900
44075
  const enabledToolCount = toolSelection.enabledTools.size;
43901
- const allToolsEnabled = enabledToolCount === totalTools;
43902
- const someToolsDisabled = enabledToolCount < totalTools;
44076
+ const allAvailableToolsEnabled = enabledToolCount === totalAvailableTools && totalAvailableTools > 0;
44077
+ const someToolsDisabled = enabledToolCount < totalAvailableTools;
43903
44078
  const toggleServer = (serverName, enabled) => {
43904
44079
  var _a2;
43905
44080
  const newEnabledServers = new Set(toolSelection.enabledServers);
@@ -43930,6 +44105,17 @@ const ToolSelector = ({
43930
44105
  enabledServers: toolSelection.enabledServers
43931
44106
  });
43932
44107
  };
44108
+ const toggleExpandedServer = (serverName) => {
44109
+ setExpandedServers((prev) => {
44110
+ const newSet = new Set(prev);
44111
+ if (newSet.has(serverName)) {
44112
+ newSet.delete(serverName);
44113
+ } else {
44114
+ newSet.add(serverName);
44115
+ }
44116
+ return newSet;
44117
+ });
44118
+ };
43933
44119
  const toggleAllServers = (enabled) => {
43934
44120
  const newEnabledServers = new Set(serverInfo.map((s) => s.name));
43935
44121
  const newEnabledTools = new Set(tools.map((t) => t.name));
@@ -43965,7 +44151,7 @@ const ToolSelector = ({
43965
44151
  someToolsDisabled && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs px-1.5 py-0.5 bg-amber-100 dark:bg-amber-900/50 text-amber-600 dark:text-amber-400 rounded", children: [
43966
44152
  enabledToolCount,
43967
44153
  "/",
43968
- totalTools
44154
+ totalAvailableTools
43969
44155
  ] }),
43970
44156
  /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-3 h-3 text-slate-400" })
43971
44157
  ]
@@ -43979,7 +44165,7 @@ const ToolSelector = ({
43979
44165
  {
43980
44166
  onClick: () => toggleAllServers(),
43981
44167
  className: "text-xs px-2 py-1 bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700 rounded text-slate-600 dark:text-slate-300",
43982
- disabled: allToolsEnabled,
44168
+ disabled: allAvailableToolsEnabled,
43983
44169
  children: "All"
43984
44170
  }
43985
44171
  ) })
@@ -43988,44 +44174,55 @@ const ToolSelector = ({
43988
44174
  const serverEnabled = toolSelection.enabledServers.has(
43989
44175
  server.name
43990
44176
  );
44177
+ const serverExpanded = expandedServers.has(server.name);
43991
44178
  const serverTools = server.tools;
43992
44179
  const enabledServerToolCount = serverTools.filter(
43993
44180
  (tool) => toolSelection.enabledTools.has(tool.name)
43994
44181
  ).length;
43995
44182
  const allServerToolsEnabled = enabledServerToolCount === serverTools.length;
43996
44183
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
43997
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-2 hover:bg-slate-50 dark:hover:bg-slate-800/50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-3 cursor-pointer", children: [
43998
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
43999
- /* @__PURE__ */ jsxRuntimeExports.jsx(
44000
- "input",
44001
- {
44002
- type: "checkbox",
44003
- checked: serverEnabled,
44004
- onChange: (e) => toggleServer(server.name, e.target.checked),
44005
- className: "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
44006
- }
44007
- ),
44008
- serverEnabled && allServerToolsEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "w-3 h-3 text-blue-600 absolute top-0.5 left-0.5 pointer-events-none" })
44009
- ] }),
44010
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
44011
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: server.name }),
44012
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
44013
- enabledServerToolCount,
44014
- "/",
44015
- serverTools.length,
44016
- " tools"
44184
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
44185
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-3 pl-4 pr-12 py-2 min-w-0 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800/50", children: [
44186
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
44187
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
44188
+ "input",
44189
+ {
44190
+ type: "checkbox",
44191
+ checked: serverEnabled,
44192
+ onChange: (e) => toggleServer(server.name, e.target.checked),
44193
+ className: "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
44194
+ }
44195
+ ),
44196
+ serverEnabled && allServerToolsEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "w-3 h-3 text-blue-600 absolute top-0.5 left-0.5 pointer-events-none" })
44197
+ ] }),
44198
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
44199
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium break-words text-slate-900 dark:text-slate-100", children: server.name }),
44200
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
44201
+ enabledServerToolCount,
44202
+ "/",
44203
+ serverTools.length,
44204
+ " tools"
44205
+ ] })
44017
44206
  ] })
44018
- ] })
44019
- ] }) }),
44020
- serverEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-8 space-y-1", children: serverTools.map((tool) => {
44207
+ ] }),
44208
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
44209
+ "button",
44210
+ {
44211
+ onClick: () => toggleExpandedServer(server.name),
44212
+ className: "absolute top-1/2 right-3 -translate-y-1/2 text-xs p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded text-slate-600 dark:text-slate-300",
44213
+ children: serverExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-3 h-3 text-slate-400" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-3 h-3 text-slate-400" })
44214
+ }
44215
+ )
44216
+ ] }),
44217
+ serverExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: serverTools.map((tool) => {
44021
44218
  const toolEnabled = toolSelection.enabledTools.has(
44022
44219
  tool.name
44023
44220
  );
44024
44221
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
44025
44222
  "div",
44026
44223
  {
44027
- className: "px-4 py-1.5 hover:bg-slate-50 dark:hover:bg-slate-800/50",
44028
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-3 cursor-pointer", children: [
44224
+ className: "hover:bg-slate-50 dark:hover:bg-slate-800/50",
44225
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "pl-12 pr-4 py-1.5 flex items-center gap-3 cursor-pointer", children: [
44029
44226
  /* @__PURE__ */ jsxRuntimeExports.jsx(
44030
44227
  "input",
44031
44228
  {
@@ -44055,6 +44252,365 @@ const ToolSelector = ({
44055
44252
  ] })
44056
44253
  ] });
44057
44254
  };
44255
+ function commonjsRequire(path2) {
44256
+ throw new Error('Could not dynamically require "' + path2 + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
44257
+ }
44258
+ var pluralize$2 = { exports: {} };
44259
+ var pluralize$1 = pluralize$2.exports;
44260
+ var hasRequiredPluralize;
44261
+ function requirePluralize() {
44262
+ if (hasRequiredPluralize) return pluralize$2.exports;
44263
+ hasRequiredPluralize = 1;
44264
+ (function(module, exports) {
44265
+ (function(root, pluralize2) {
44266
+ if (typeof commonjsRequire === "function" && true && true) {
44267
+ module.exports = pluralize2();
44268
+ } else {
44269
+ root.pluralize = pluralize2();
44270
+ }
44271
+ })(pluralize$1, function() {
44272
+ var pluralRules = [];
44273
+ var singularRules = [];
44274
+ var uncountables = {};
44275
+ var irregularPlurals = {};
44276
+ var irregularSingles = {};
44277
+ function sanitizeRule(rule) {
44278
+ if (typeof rule === "string") {
44279
+ return new RegExp("^" + rule + "$", "i");
44280
+ }
44281
+ return rule;
44282
+ }
44283
+ function restoreCase(word, token) {
44284
+ if (word === token) return token;
44285
+ if (word === word.toLowerCase()) return token.toLowerCase();
44286
+ if (word === word.toUpperCase()) return token.toUpperCase();
44287
+ if (word[0] === word[0].toUpperCase()) {
44288
+ return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
44289
+ }
44290
+ return token.toLowerCase();
44291
+ }
44292
+ function interpolate(str2, args) {
44293
+ return str2.replace(/\$(\d{1,2})/g, function(match, index2) {
44294
+ return args[index2] || "";
44295
+ });
44296
+ }
44297
+ function replace(word, rule) {
44298
+ return word.replace(rule[0], function(match, index2) {
44299
+ var result = interpolate(rule[1], arguments);
44300
+ if (match === "") {
44301
+ return restoreCase(word[index2 - 1], result);
44302
+ }
44303
+ return restoreCase(match, result);
44304
+ });
44305
+ }
44306
+ function sanitizeWord(token, word, rules2) {
44307
+ if (!token.length || uncountables.hasOwnProperty(token)) {
44308
+ return word;
44309
+ }
44310
+ var len = rules2.length;
44311
+ while (len--) {
44312
+ var rule = rules2[len];
44313
+ if (rule[0].test(word)) return replace(word, rule);
44314
+ }
44315
+ return word;
44316
+ }
44317
+ function replaceWord(replaceMap, keepMap, rules2) {
44318
+ return function(word) {
44319
+ var token = word.toLowerCase();
44320
+ if (keepMap.hasOwnProperty(token)) {
44321
+ return restoreCase(word, token);
44322
+ }
44323
+ if (replaceMap.hasOwnProperty(token)) {
44324
+ return restoreCase(word, replaceMap[token]);
44325
+ }
44326
+ return sanitizeWord(token, word, rules2);
44327
+ };
44328
+ }
44329
+ function checkWord(replaceMap, keepMap, rules2, bool) {
44330
+ return function(word) {
44331
+ var token = word.toLowerCase();
44332
+ if (keepMap.hasOwnProperty(token)) return true;
44333
+ if (replaceMap.hasOwnProperty(token)) return false;
44334
+ return sanitizeWord(token, token, rules2) === token;
44335
+ };
44336
+ }
44337
+ function pluralize2(word, count2, inclusive) {
44338
+ var pluralized = count2 === 1 ? pluralize2.singular(word) : pluralize2.plural(word);
44339
+ return (inclusive ? count2 + " " : "") + pluralized;
44340
+ }
44341
+ pluralize2.plural = replaceWord(
44342
+ irregularSingles,
44343
+ irregularPlurals,
44344
+ pluralRules
44345
+ );
44346
+ pluralize2.isPlural = checkWord(
44347
+ irregularSingles,
44348
+ irregularPlurals,
44349
+ pluralRules
44350
+ );
44351
+ pluralize2.singular = replaceWord(
44352
+ irregularPlurals,
44353
+ irregularSingles,
44354
+ singularRules
44355
+ );
44356
+ pluralize2.isSingular = checkWord(
44357
+ irregularPlurals,
44358
+ irregularSingles,
44359
+ singularRules
44360
+ );
44361
+ pluralize2.addPluralRule = function(rule, replacement) {
44362
+ pluralRules.push([sanitizeRule(rule), replacement]);
44363
+ };
44364
+ pluralize2.addSingularRule = function(rule, replacement) {
44365
+ singularRules.push([sanitizeRule(rule), replacement]);
44366
+ };
44367
+ pluralize2.addUncountableRule = function(word) {
44368
+ if (typeof word === "string") {
44369
+ uncountables[word.toLowerCase()] = true;
44370
+ return;
44371
+ }
44372
+ pluralize2.addPluralRule(word, "$0");
44373
+ pluralize2.addSingularRule(word, "$0");
44374
+ };
44375
+ pluralize2.addIrregularRule = function(single, plural) {
44376
+ plural = plural.toLowerCase();
44377
+ single = single.toLowerCase();
44378
+ irregularSingles[single] = plural;
44379
+ irregularPlurals[plural] = single;
44380
+ };
44381
+ [
44382
+ // Pronouns.
44383
+ ["I", "we"],
44384
+ ["me", "us"],
44385
+ ["he", "they"],
44386
+ ["she", "they"],
44387
+ ["them", "them"],
44388
+ ["myself", "ourselves"],
44389
+ ["yourself", "yourselves"],
44390
+ ["itself", "themselves"],
44391
+ ["herself", "themselves"],
44392
+ ["himself", "themselves"],
44393
+ ["themself", "themselves"],
44394
+ ["is", "are"],
44395
+ ["was", "were"],
44396
+ ["has", "have"],
44397
+ ["this", "these"],
44398
+ ["that", "those"],
44399
+ // Words ending in with a consonant and `o`.
44400
+ ["echo", "echoes"],
44401
+ ["dingo", "dingoes"],
44402
+ ["volcano", "volcanoes"],
44403
+ ["tornado", "tornadoes"],
44404
+ ["torpedo", "torpedoes"],
44405
+ // Ends with `us`.
44406
+ ["genus", "genera"],
44407
+ ["viscus", "viscera"],
44408
+ // Ends with `ma`.
44409
+ ["stigma", "stigmata"],
44410
+ ["stoma", "stomata"],
44411
+ ["dogma", "dogmata"],
44412
+ ["lemma", "lemmata"],
44413
+ ["schema", "schemata"],
44414
+ ["anathema", "anathemata"],
44415
+ // Other irregular rules.
44416
+ ["ox", "oxen"],
44417
+ ["axe", "axes"],
44418
+ ["die", "dice"],
44419
+ ["yes", "yeses"],
44420
+ ["foot", "feet"],
44421
+ ["eave", "eaves"],
44422
+ ["goose", "geese"],
44423
+ ["tooth", "teeth"],
44424
+ ["quiz", "quizzes"],
44425
+ ["human", "humans"],
44426
+ ["proof", "proofs"],
44427
+ ["carve", "carves"],
44428
+ ["valve", "valves"],
44429
+ ["looey", "looies"],
44430
+ ["thief", "thieves"],
44431
+ ["groove", "grooves"],
44432
+ ["pickaxe", "pickaxes"],
44433
+ ["passerby", "passersby"]
44434
+ ].forEach(function(rule) {
44435
+ return pluralize2.addIrregularRule(rule[0], rule[1]);
44436
+ });
44437
+ [
44438
+ [/s?$/i, "s"],
44439
+ [/[^\u0000-\u007F]$/i, "$0"],
44440
+ [/([^aeiou]ese)$/i, "$1"],
44441
+ [/(ax|test)is$/i, "$1es"],
44442
+ [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, "$1es"],
44443
+ [/(e[mn]u)s?$/i, "$1s"],
44444
+ [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, "$1"],
44445
+ [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1i"],
44446
+ [/(alumn|alg|vertebr)(?:a|ae)$/i, "$1ae"],
44447
+ [/(seraph|cherub)(?:im)?$/i, "$1im"],
44448
+ [/(her|at|gr)o$/i, "$1oes"],
44449
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, "$1a"],
44450
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, "$1a"],
44451
+ [/sis$/i, "ses"],
44452
+ [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, "$1$2ves"],
44453
+ [/([^aeiouy]|qu)y$/i, "$1ies"],
44454
+ [/([^ch][ieo][ln])ey$/i, "$1ies"],
44455
+ [/(x|ch|ss|sh|zz)$/i, "$1es"],
44456
+ [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, "$1ices"],
44457
+ [/\b((?:tit)?m|l)(?:ice|ouse)$/i, "$1ice"],
44458
+ [/(pe)(?:rson|ople)$/i, "$1ople"],
44459
+ [/(child)(?:ren)?$/i, "$1ren"],
44460
+ [/eaux$/i, "$0"],
44461
+ [/m[ae]n$/i, "men"],
44462
+ ["thou", "you"]
44463
+ ].forEach(function(rule) {
44464
+ return pluralize2.addPluralRule(rule[0], rule[1]);
44465
+ });
44466
+ [
44467
+ [/s$/i, ""],
44468
+ [/(ss)$/i, "$1"],
44469
+ [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, "$1fe"],
44470
+ [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, "$1f"],
44471
+ [/ies$/i, "y"],
44472
+ [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, "$1ie"],
44473
+ [/\b(mon|smil)ies$/i, "$1ey"],
44474
+ [/\b((?:tit)?m|l)ice$/i, "$1ouse"],
44475
+ [/(seraph|cherub)im$/i, "$1"],
44476
+ [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, "$1"],
44477
+ [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, "$1sis"],
44478
+ [/(movie|twelve|abuse|e[mn]u)s$/i, "$1"],
44479
+ [/(test)(?:is|es)$/i, "$1is"],
44480
+ [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1us"],
44481
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, "$1um"],
44482
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, "$1on"],
44483
+ [/(alumn|alg|vertebr)ae$/i, "$1a"],
44484
+ [/(cod|mur|sil|vert|ind)ices$/i, "$1ex"],
44485
+ [/(matr|append)ices$/i, "$1ix"],
44486
+ [/(pe)(rson|ople)$/i, "$1rson"],
44487
+ [/(child)ren$/i, "$1"],
44488
+ [/(eau)x?$/i, "$1"],
44489
+ [/men$/i, "man"]
44490
+ ].forEach(function(rule) {
44491
+ return pluralize2.addSingularRule(rule[0], rule[1]);
44492
+ });
44493
+ [
44494
+ // Singular words with no plurals.
44495
+ "adulthood",
44496
+ "advice",
44497
+ "agenda",
44498
+ "aid",
44499
+ "aircraft",
44500
+ "alcohol",
44501
+ "ammo",
44502
+ "analytics",
44503
+ "anime",
44504
+ "athletics",
44505
+ "audio",
44506
+ "bison",
44507
+ "blood",
44508
+ "bream",
44509
+ "buffalo",
44510
+ "butter",
44511
+ "carp",
44512
+ "cash",
44513
+ "chassis",
44514
+ "chess",
44515
+ "clothing",
44516
+ "cod",
44517
+ "commerce",
44518
+ "cooperation",
44519
+ "corps",
44520
+ "debris",
44521
+ "diabetes",
44522
+ "digestion",
44523
+ "elk",
44524
+ "energy",
44525
+ "equipment",
44526
+ "excretion",
44527
+ "expertise",
44528
+ "firmware",
44529
+ "flounder",
44530
+ "fun",
44531
+ "gallows",
44532
+ "garbage",
44533
+ "graffiti",
44534
+ "hardware",
44535
+ "headquarters",
44536
+ "health",
44537
+ "herpes",
44538
+ "highjinks",
44539
+ "homework",
44540
+ "housework",
44541
+ "information",
44542
+ "jeans",
44543
+ "justice",
44544
+ "kudos",
44545
+ "labour",
44546
+ "literature",
44547
+ "machinery",
44548
+ "mackerel",
44549
+ "mail",
44550
+ "media",
44551
+ "mews",
44552
+ "moose",
44553
+ "music",
44554
+ "mud",
44555
+ "manga",
44556
+ "news",
44557
+ "only",
44558
+ "personnel",
44559
+ "pike",
44560
+ "plankton",
44561
+ "pliers",
44562
+ "police",
44563
+ "pollution",
44564
+ "premises",
44565
+ "rain",
44566
+ "research",
44567
+ "rice",
44568
+ "salmon",
44569
+ "scissors",
44570
+ "series",
44571
+ "sewage",
44572
+ "shambles",
44573
+ "shrimp",
44574
+ "software",
44575
+ "species",
44576
+ "staff",
44577
+ "swine",
44578
+ "tennis",
44579
+ "traffic",
44580
+ "transportation",
44581
+ "trout",
44582
+ "tuna",
44583
+ "wealth",
44584
+ "welfare",
44585
+ "whiting",
44586
+ "wildebeest",
44587
+ "wildlife",
44588
+ "you",
44589
+ /pok[eé]mon$/i,
44590
+ // Regexes.
44591
+ /[^aeiou]ese$/i,
44592
+ // "chinese", "japanese"
44593
+ /deer$/i,
44594
+ // "deer", "reindeer"
44595
+ /fish$/i,
44596
+ // "fish", "blowfish", "angelfish"
44597
+ /measles$/i,
44598
+ /o[iu]s$/i,
44599
+ // "carnivorous"
44600
+ /pox$/i,
44601
+ // "chickpox", "smallpox"
44602
+ /sheep$/i
44603
+ ].forEach(pluralize2.addUncountableRule);
44604
+ return pluralize2;
44605
+ });
44606
+ })(pluralize$2);
44607
+ return pluralize$2.exports;
44608
+ }
44609
+ var pluralizeExports = requirePluralize();
44610
+ const pluralize = /* @__PURE__ */ getDefaultExportFromCjs(pluralizeExports);
44611
+ function formatPlural(count2, word) {
44612
+ return `${count2} ${pluralize(word, count2)}`;
44613
+ }
44058
44614
  const Chat2 = ({
44059
44615
  provider,
44060
44616
  config,
@@ -44407,7 +44963,7 @@ const Chat2 = ({
44407
44963
  ) }),
44408
44964
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
44409
44965
  /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-base font-semibold text-slate-900 dark:text-slate-100", children: config.title }),
44410
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: hasApiKey ? `${serversCount} servers • ${toolSelection.enabledTools.size}/${toolsCount} tools` : "API key required" })
44966
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: hasApiKey ? `${formatPlural(serversCount, "server")} • ${toolSelection.enabledTools.size}/${formatPlural(toolsCount, "tool")}` : "API key required" })
44411
44967
  ] })
44412
44968
  ] }),
44413
44969
  hasApiKey && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
@@ -44605,7 +45161,7 @@ const Chat2 = ({
44605
45161
  };
44606
45162
  const ChatTab = ({ mcpAgent, updateTrigger }) => {
44607
45163
  const config = createChatConfig({
44608
- subtitle: "Chat with access to tools from all connected servers",
45164
+ subtitle: "LLM Playground with access to tools from all connected servers",
44609
45165
  additionalSuggestions: ["What tools do you have access to?"]
44610
45166
  });
44611
45167
  const getServersCount = () => {
@@ -44635,245 +45191,167 @@ const ChatTab = ({ mcpAgent, updateTrigger }) => {
44635
45191
  }
44636
45192
  );
44637
45193
  };
44638
- const ProviderSection = ({
44639
- providerName,
45194
+ const ProviderCard = ({
45195
+ provider,
44640
45196
  config,
44641
- keyData,
44642
- isCollapsed,
45197
+ data: data2,
44643
45198
  disabled = false,
44644
- onApiKeyChange,
44645
- onClearApiKey,
44646
- onToggleShowKey,
44647
- onToggleCollapse
45199
+ onChange,
45200
+ onClear,
45201
+ onToggleShow
44648
45202
  }) => {
44649
- console.log("providerName", providerName);
44650
- console.log("keyData", keyData);
44651
- const renderCollapsedView = () => {
44652
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
44653
- "div",
44654
- {
44655
- className: "p-3 bg-green-50/80 dark:bg-green-900/20 backdrop-blur-sm rounded-lg border border-green-200/60 dark:border-green-700/60 shadow-sm",
44656
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
44657
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
44658
- /* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "w-4 h-4 text-green-600 dark:text-green-400" }),
44659
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "w-4 h-4 text-green-600 dark:text-green-400" }),
44660
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm font-medium text-green-700 dark:text-green-300", children: [
44661
- config.displayName,
44662
- " API Key Configured"
44663
- ] })
44664
- ] }),
44665
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
44666
- Button,
44667
- {
44668
- variant: "ghost",
44669
- size: "sm",
44670
- onClick: () => onToggleCollapse(providerName),
44671
- disabled,
44672
- className: "h-7 px-2 text-green-700 dark:text-green-300 hover:bg-green-100/50 dark:hover:bg-green-800/30",
44673
- children: [
44674
- /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4" }),
44675
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1 text-xs", children: "Manage" })
44676
- ]
44677
- }
44678
- ) })
44679
- ] })
44680
- },
44681
- providerName
44682
- );
44683
- };
44684
- const renderExpandedView = () => {
44685
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
44686
- "div",
44687
- {
44688
- className: "p-4 bg-white/60 dark:bg-slate-800/60 backdrop-blur-sm rounded-xl border border-slate-200/60 dark:border-slate-700/60 shadow-lg",
44689
- children: [
44690
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
44691
- /* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "w-5 h-5 text-blue-600 dark:text-blue-400" }),
44692
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold text-slate-800 dark:text-slate-200", children: config.displayName }),
44693
- keyData.isValid && /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "w-5 h-5 text-green-600 dark:text-green-400" }),
44694
- keyData.key.length > 0 && !keyData.isValid && /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-5 h-5 text-red-600 dark:text-red-400" })
44695
- ] }) }),
44696
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-4", children: config.description }),
44697
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
44698
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
44699
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 relative", children: [
44700
- /* @__PURE__ */ jsxRuntimeExports.jsx(
44701
- Input,
44702
- {
44703
- type: keyData.showKey ? "text" : "password",
44704
- placeholder: config.placeholder,
44705
- value: keyData.key,
44706
- onChange: (e) => onApiKeyChange(providerName, e.target.value),
44707
- disabled,
44708
- className: `font-mono pr-10 ${keyData.key.length > 0 ? keyData.isValid ? "border-green-500 dark:border-green-400" : "border-red-500 dark:border-red-400" : ""}`
44709
- }
44710
- ),
44711
- /* @__PURE__ */ jsxRuntimeExports.jsx(
44712
- Button,
44713
- {
44714
- type: "button",
44715
- variant: "ghost",
44716
- size: "icon",
44717
- className: "absolute right-1 top-1/2 transform -translate-y-1/2 h-8 w-8",
44718
- onClick: () => onToggleShowKey(providerName),
44719
- disabled,
44720
- children: keyData.showKey ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "h-4 w-4" })
44721
- }
44722
- )
44723
- ] }),
44724
- keyData.key.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
44725
- Button,
44726
- {
44727
- variant: "outline",
44728
- onClick: () => onClearApiKey(providerName),
44729
- disabled,
44730
- className: "bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm border-slate-300/60 dark:border-slate-600/60 hover:border-red-400/60 dark:hover:border-red-500/60 hover:bg-red-50/80 dark:hover:bg-red-900/20",
44731
- children: "Clear"
44732
- }
44733
- )
44734
- ] }),
44735
- keyData.key.length > 0 && !keyData.isValid && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-red-600 dark:text-red-400", children: [
44736
- "Please enter a valid ",
44737
- config.displayName,
44738
- " API key with the correct format"
44739
- ] }),
44740
- !keyData.key.length && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: [
44741
- "Enter your ",
44742
- config.displayName,
44743
- " API key to enable related functionality. Your key will be securely stored in your browser's local storage."
44744
- ] }),
44745
- keyData.isValid && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-green-600 dark:text-green-400", children: [
44746
- "✓ Valid ",
44747
- config.displayName,
44748
- " API key configured."
44749
- ] })
44750
- ] })
44751
- ]
44752
- },
44753
- providerName
44754
- );
44755
- };
44756
- return isCollapsed ? renderCollapsedView() : renderExpandedView();
45203
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-gray-800 rounded-xl shadow hover:shadow-lg transition p-6 flex flex-col", children: [
45204
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center mb-4 -ml-1", children: [
45205
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 flex items-center justify-center bg-white rounded-md", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
45206
+ "img",
45207
+ {
45208
+ src: config.logo,
45209
+ alt: `${config.displayName} logo`,
45210
+ className: "w-5 h-5"
45211
+ }
45212
+ ) }),
45213
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-xl font-semibold text-gray-900 dark:text-gray-100", children: config.displayName })
45214
+ ] }),
45215
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-600 dark:text-gray-400 mb-4 text-sm", children: config.description }),
45216
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
45217
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
45218
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45219
+ "input",
45220
+ {
45221
+ type: data2.showKey ? "text" : "password",
45222
+ value: data2.key,
45223
+ placeholder: config.placeholder,
45224
+ disabled,
45225
+ onChange: (e) => onChange(provider, e.target.value),
45226
+ className: "w-full pr-10 p-2 text-sm border rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-400"
45227
+ }
45228
+ ),
45229
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45230
+ "button",
45231
+ {
45232
+ onClick: () => onToggleShow(provider),
45233
+ className: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300",
45234
+ disabled: disabled || !data2.key,
45235
+ children: data2.showKey ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { size: 16 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { size: 16 })
45236
+ }
45237
+ )
45238
+ ] }),
45239
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-2", children: [
45240
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45241
+ "button",
45242
+ {
45243
+ onClick: () => onChange(provider, data2.key),
45244
+ disabled: disabled || !data2.key,
45245
+ className: "flex-1 bg-gray-600 hover:bg-gray-700 text-white text-sm py-1 rounded transition disabled:opacity-50",
45246
+ children: "Save"
45247
+ }
45248
+ ),
45249
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45250
+ "button",
45251
+ {
45252
+ onClick: () => onClear(provider),
45253
+ disabled: disabled || !data2.key,
45254
+ className: "flex-1 border border-gray-400 hover:border-gray-500 text-gray-400 hover:text-gray-600 text-sm py-1 rounded transition disabled:opacity-50",
45255
+ children: "Clear"
45256
+ }
45257
+ )
45258
+ ] })
45259
+ ] })
45260
+ ] });
44757
45261
  };
45262
+ const ClaudeLogo = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20shape-rendering='geometricPrecision'%20text-rendering='geometricPrecision'%20image-rendering='optimizeQuality'%20fill-rule='evenodd'%20clip-rule='evenodd'%20viewBox='0%200%20512%20509.64'%3e%3cpath%20fill='%23D77655'%20d='M115.612%200h280.775C459.974%200%20512%2052.026%20512%20115.612v278.415c0%2063.587-52.026%20115.612-115.613%20115.612H115.612C52.026%20509.639%200%20457.614%200%20394.027V115.612C0%2052.026%2052.026%200%20115.612%200z'/%3e%3cpath%20fill='%23FCF2EE'%20fill-rule='nonzero'%20d='M142.27%20316.619l73.655-41.326%201.238-3.589-1.238-1.996-3.589-.001-12.31-.759-42.084-1.138-36.498-1.516-35.361-1.896-8.897-1.895-8.34-10.995.859-5.484%207.482-5.03%2010.717.935%2023.683%201.617%2035.537%202.452%2025.782%201.517%2038.193%203.968h6.064l.86-2.451-2.073-1.517-1.618-1.517-36.776-24.922-39.81-26.338-20.852-15.166-11.273-7.683-5.687-7.204-2.451-15.721%2010.237-11.273%2013.75.935%203.513.936%2013.928%2010.716%2029.749%2023.027%2038.848%2028.612%205.687%204.727%202.275-1.617.278-1.138-2.553-4.271-21.13-38.193-22.546-38.848-10.035-16.101-2.654-9.655c-.935-3.968-1.617-7.304-1.617-11.374l11.652-15.823%206.445-2.073%2015.545%202.073%206.547%205.687%209.655%2022.092%2015.646%2034.78%2024.265%2047.291%207.103%2014.028%203.791%2012.992%201.416%203.968%202.449-.001v-2.275l1.997-26.641%203.69-32.707%203.589-42.084%201.239-11.854%205.863-14.206%2011.652-7.683%209.099%204.348%207.482%2010.716-1.036%206.926-4.449%2028.915-8.72%2045.294-5.687%2030.331h3.313l3.792-3.791%2015.342-20.372%2025.782-32.227%2011.374-12.789%2013.27-14.129%208.517-6.724%2016.1-.001%2011.854%2017.617-5.307%2018.199-16.581%2021.029-13.75%2017.819-19.716%2026.54-12.309%2021.231%201.138%201.694%202.932-.278%2044.536-9.479%2024.062-4.347%2028.714-4.928%2012.992%206.066%201.416%206.167-5.106%2012.613-30.71%207.583-36.018%207.204-53.636%2012.689-.657.48.758.935%2024.164%202.275%2010.337.556h25.301l47.114%203.514%2012.309%208.139%207.381%209.959-1.238%207.583-18.957%209.655-25.579-6.066-59.702-14.205-20.474-5.106-2.83-.001v1.694l17.061%2016.682%2031.266%2028.233%2039.152%2036.397%201.997%208.999-5.03%207.102-5.307-.758-34.401-25.883-13.27-11.651-30.053-25.302-1.996-.001v2.654l6.926%2010.136%2036.574%2054.975%201.895%2016.859-2.653%205.485-9.479%203.311-10.414-1.895-21.408-30.054-22.092-33.844-17.819-30.331-2.173%201.238-10.515%20113.261-4.929%205.788-11.374%204.348-9.478-7.204-5.03-11.652%205.03-23.027%206.066-30.052%204.928-23.886%204.449-29.674%202.654-9.858-.177-.657-2.173.278-22.37%2030.71-34.021%2045.977-26.919%2028.815-6.445%202.553-11.173-5.789%201.037-10.337%206.243-9.2%2037.257-47.392%2022.47-29.371%2014.508-16.961-.101-2.451h-.859l-98.954%2064.251-17.618%202.275-7.583-7.103.936-11.652%203.589-3.791%2029.749-20.474-.101.102.024.101z'/%3e%3c/svg%3e";
45263
+ const OpenAILogo = "data:image/svg+xml,%3csvg%20viewBox='0%200%20512%20512'%20xmlns='http://www.w3.org/2000/svg'%20fill-rule='evenodd'%20clip-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%3e%3cpath%20d='M474.123%20209.81c11.525-34.577%207.569-72.423-10.838-103.904-27.696-48.168-83.433-72.94-137.794-61.414a127.14%20127.14%200%2000-95.475-42.49c-55.564%200-104.936%2035.781-122.139%2088.593-35.781%207.397-66.574%2029.76-84.637%2061.414-27.868%2048.167-21.503%20108.72%2015.826%20150.007-11.525%2034.578-7.569%2072.424%2010.838%20103.733%2027.696%2048.34%2083.433%2073.111%20137.966%2061.585%2024.084%2027.18%2058.833%2042.835%2095.303%2042.663%2055.564%200%20104.936-35.782%20122.139-88.594%2035.782-7.397%2066.574-29.76%2084.465-61.413%2028.04-48.168%2021.676-108.722-15.654-150.008v-.172zm-39.567-87.218c11.01%2019.267%2015.139%2041.803%2011.354%2063.65-.688-.516-2.064-1.204-2.924-1.72l-101.152-58.49a16.965%2016.965%200%2000-16.687%200L206.621%20194.5v-50.232l97.883-56.597c45.587-26.32%20103.732-10.666%20130.052%2034.921zm-227.935%20104.42l49.888-28.9%2049.887%2028.9v57.63l-49.887%2028.9-49.888-28.9v-57.63zm23.223-191.81c22.364%200%2043.867%207.742%2061.07%2022.02-.688.344-2.064%201.204-3.097%201.72L186.666%20117.26c-5.161%202.925-8.258%208.43-8.258%2014.45v136.934l-43.523-25.116V130.333c0-52.64%2042.491-95.13%2095.131-95.302l-.172.172zM52.14%20168.697c11.182-19.268%2028.557-34.062%2049.544-41.803V247.14c0%206.02%203.097%2011.354%208.258%2014.45l118.354%2068.295-43.695%2025.288-97.711-56.425c-45.415-26.32-61.07-84.465-34.75-130.052zm26.665%20220.71c-11.182-19.095-15.139-41.802-11.354-63.65.688.516%202.064%201.204%202.924%201.72l101.152%2058.49a16.965%2016.965%200%200016.687%200l118.354-68.467v50.232l-97.883%2056.425c-45.587%2026.148-103.732%2010.665-130.052-34.75h.172zm204.54%2087.39c-22.192%200-43.867-7.741-60.898-22.02a62.439%2062.439%200%20003.097-1.72l101.152-58.317c5.16-2.924%208.429-8.43%208.257-14.45V243.527l43.523%2025.116v113.022c0%2052.64-42.663%2095.303-95.131%2095.303v-.172zM461.22%20343.303c-11.182%2019.267-28.729%2034.061-49.544%2041.63V264.687c0-6.021-3.097-11.526-8.257-14.45L284.893%20181.77l43.523-25.116%2097.883%2056.424c45.587%2026.32%2061.07%2084.466%2034.75%20130.053l.172.172z'%20fill-rule='nonzero'/%3e%3c/svg%3e";
45264
+ const OllamaLogo = "data:image/svg+xml,%3csvg%20fill='currentColor'%20fill-rule='evenodd'%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eOllama%3c/title%3e%3cpath%20d='M7.905%201.09c.216.085.411.225.588.41.295.306.544.744.734%201.263.191.522.315%201.1.362%201.68a5.054%205.054%200%20012.049-.636l.051-.004c.87-.07%201.73.087%202.48.474.101.053.2.11.297.17.05-.569.172-1.134.36-1.644.19-.52.439-.957.733-1.264a1.67%201.67%200%2001.589-.41c.257-.1.53-.118.796-.042.401.114.745.368%201.016.737.248.337.434.769.561%201.287.23.934.27%202.163.115%203.645l.053.04.026.019c.757.576%201.284%201.397%201.563%202.35.435%201.487.216%203.155-.534%204.088l-.018.021.002.003c.417.762.67%201.567.724%202.4l.002.03c.064%201.065-.2%202.137-.814%203.19l-.007.01.01.024c.472%201.157.62%202.322.438%203.486l-.006.039a.651.651%200%2001-.747.536.648.648%200%2001-.54-.742c.167-1.033.01-2.069-.48-3.123a.643.643%200%2001.04-.617l.004-.006c.604-.924.854-1.83.8-2.72-.046-.779-.325-1.544-.8-2.273a.644.644%200%2001.18-.886l.009-.006c.243-.159.467-.565.58-1.12a4.229%204.229%200%2000-.095-1.974c-.205-.7-.58-1.284-1.105-1.683-.595-.454-1.383-.673-2.38-.61a.653.653%200%2001-.632-.371c-.314-.665-.772-1.141-1.343-1.436a3.288%203.288%200%2000-1.772-.332c-1.245.099-2.343.801-2.67%201.686a.652.652%200%2001-.61.425c-1.067.002-1.893.252-2.497.703-.522.39-.878.935-1.066%201.588a4.07%204.07%200%2000-.068%201.886c.112.558.331%201.02.582%201.269l.008.007c.212.207.257.53.109.785-.36.622-.629%201.549-.673%202.44-.05%201.018.186%201.902.719%202.536l.016.019a.643.643%200%2001.095.69c-.576%201.236-.753%202.252-.562%203.052a.652.652%200%2001-1.269.298c-.243-1.018-.078-2.184.473-3.498l.014-.035-.008-.012a4.339%204.339%200%2001-.598-1.309l-.005-.019a5.764%205.764%200%2001-.177-1.785c.044-.91.278-1.842.622-2.59l.012-.026-.002-.002c-.293-.418-.51-.953-.63-1.545l-.005-.024a5.352%205.352%200%2001.093-2.49c.262-.915.777-1.701%201.536-2.269.06-.045.123-.09.186-.132-.159-1.493-.119-2.73.112-3.67.127-.518.314-.95.562-1.287.27-.368.614-.622%201.015-.737.266-.076.54-.059.797.042zm4.116%209.09c.936%200%201.8.313%202.446.855.63.527%201.005%201.235%201.005%201.94%200%20.888-.406%201.58-1.133%202.022-.62.375-1.451.557-2.403.557-1.009%200-1.871-.259-2.493-.734-.617-.47-.963-1.13-.963-1.845%200-.707.398-1.417%201.056-1.946.668-.537%201.55-.849%202.485-.849zm0%20.896a3.07%203.07%200%2000-1.916.65c-.461.37-.722.835-.722%201.25%200%20.428.21.829.61%201.134.455.347%201.124.548%201.943.548.799%200%201.473-.147%201.932-.426.463-.28.7-.686.7-1.257%200-.423-.246-.89-.683-1.256-.484-.405-1.14-.643-1.864-.643zm.662%201.21l.004.004c.12.151.095.37-.056.49l-.292.23v.446a.375.375%200%2001-.376.373.375.375%200%2001-.376-.373v-.46l-.271-.218a.347.347%200%2001-.052-.49.353.353%200%2001.494-.051l.215.172.22-.174a.353.353%200%2001.49.051zm-5.04-1.919c.478%200%20.867.39.867.871a.87.87%200%2001-.868.871.87.87%200%2001-.867-.87.87.87%200%2001.867-.872zm8.706%200c.48%200%20.868.39.868.871a.87.87%200%2001-.868.871.87.87%200%2001-.867-.87.87.87%200%2001.867-.872zM7.44%202.3l-.003.002a.659.659%200%2000-.285.238l-.005.006c-.138.189-.258.467-.348.832-.17.692-.216%201.631-.124%202.782.43-.128.899-.208%201.404-.237l.01-.001.019-.034c.046-.082.095-.161.148-.239.123-.771.022-1.692-.253-2.444-.134-.364-.297-.65-.453-.813a.628.628%200%2000-.107-.09L7.44%202.3zm9.174.04l-.002.001a.628.628%200%2000-.107.09c-.156.163-.32.45-.453.814-.29.794-.387%201.776-.23%202.572l.058.097.008.014h.03a5.184%205.184%200%20011.466.212c.086-1.124.038-2.043-.128-2.722-.09-.365-.21-.643-.349-.832l-.004-.006a.659.659%200%2000-.285-.239h-.004z'%3e%3c/path%3e%3c/svg%3e";
44758
45265
  const PROVIDERS = {
44759
45266
  anthropic: {
44760
45267
  name: "anthropic",
44761
45268
  displayName: "Anthropic (Claude)",
44762
- placeholder: "Enter your Claude API key (sk-ant-api03-...)",
44763
- description: "Required for Claude AI chat functionality"
45269
+ placeholder: "sk-ant-…",
45270
+ description: "Enable Claude AI chat functionality",
45271
+ logo: ClaudeLogo
44764
45272
  },
44765
45273
  openai: {
44766
45274
  name: "openai",
44767
45275
  displayName: "OpenAI",
44768
- placeholder: "Enter your OpenAI API key (sk-...)",
44769
- description: "Required for GPT models and OpenAI features"
45276
+ placeholder: "sk-…",
45277
+ description: "Enable GPT models & OpenAI features",
45278
+ logo: OpenAILogo
44770
45279
  },
44771
45280
  ollama: {
44772
45281
  name: "ollama",
44773
45282
  displayName: "Ollama",
44774
- placeholder: "Enter Ollama host URL (optional, defaults to http://127.0.0.1:11434)",
44775
- description: "Local Ollama installation - requires Ollama to be running. 📥 Download from https://ollama.com/download • 🔧 Pull tool-calling models from https://ollama.com/search?c=tools • 🔄 Models appear dynamically in chat"
45283
+ placeholder: "http://127.0.0.1:11434",
45284
+ description: "Local Ollamarequires Ollama running. Models load dynamically.",
45285
+ logo: OllamaLogo
44776
45286
  }
44777
45287
  };
44778
45288
  const SettingsTab = ({ disabled = false }) => {
44779
- const [apiKeys, setApiKeys] = reactExports.useState({
44780
- anthropic: { key: "", isValid: false, showKey: false },
44781
- openai: { key: "", isValid: false, showKey: false },
44782
- ollama: { key: "", isValid: false, showKey: false }
44783
- });
44784
- const [collapsedSections, setCollapsedSections] = reactExports.useState({});
44785
- const { toast: toast2 } = useToast();
44786
- reactExports.useEffect(() => {
44787
- const newApiKeys = { ...apiKeys };
44788
- Object.keys(PROVIDERS).forEach((providerName) => {
44789
- const provider = providerName;
44790
- const apiKey = providerManager.getApiKey(provider);
44791
- const isValid2 = providerManager.isProviderReady(provider);
44792
- newApiKeys[provider] = {
44793
- key: apiKey,
44794
- isValid: isValid2,
45289
+ const [apiKeys, setApiKeys] = reactExports.useState(
45290
+ () => Object.keys(PROVIDERS).reduce((acc, p2) => {
45291
+ acc[p2] = {
45292
+ key: "",
45293
+ isValid: false,
44795
45294
  showKey: false
44796
45295
  };
44797
- if (isValid2) {
44798
- setCollapsedSections((prev) => ({ ...prev, [providerName]: true }));
44799
- }
45296
+ return acc;
45297
+ }, {})
45298
+ );
45299
+ const { toast: toast2 } = useToast();
45300
+ reactExports.useEffect(() => {
45301
+ Object.keys(PROVIDERS).forEach((prov) => {
45302
+ const provider = prov;
45303
+ const key = providerManager.getApiKey(provider);
45304
+ const valid = providerManager.isProviderReady(provider);
45305
+ setApiKeys((prev) => ({
45306
+ ...prev,
45307
+ [provider]: { key, isValid: valid, showKey: false }
45308
+ }));
44800
45309
  });
44801
- setApiKeys(newApiKeys);
44802
45310
  }, []);
44803
- const handleApiKeyChange = (providerName, value) => {
44804
- const config = PROVIDERS[providerName];
44805
- const isValid2 = providerManager.setApiKey(providerName, value);
45311
+ const handleApiKeyChange = (provider, value) => {
45312
+ const cfg = PROVIDERS[provider];
45313
+ const valid = providerManager.setApiKey(provider, value);
44806
45314
  setApiKeys((prev) => ({
44807
45315
  ...prev,
44808
- [providerName]: {
44809
- ...prev[providerName],
44810
- key: value,
44811
- isValid: isValid2
44812
- }
45316
+ [provider]: { ...prev[provider], key: value, isValid: valid }
44813
45317
  }));
44814
- if (isValid2) {
44815
- setCollapsedSections((prev) => ({ ...prev, [providerName]: true }));
44816
- toast2({
44817
- title: "API Key Set",
44818
- description: `Your ${config.displayName} API key has been saved and configured successfully.`,
44819
- variant: "default"
44820
- });
44821
- } else {
44822
- setCollapsedSections((prev) => ({ ...prev, [providerName]: false }));
44823
- }
44824
- };
44825
- const clearApiKey = (providerName) => {
44826
- const config = PROVIDERS[providerName];
44827
- providerManager.clearApiKey(providerName);
44828
- setApiKeys((prev) => ({
44829
- ...prev,
44830
- [providerName]: {
44831
- ...prev[providerName],
44832
- key: "",
44833
- isValid: false
44834
- }
44835
- }));
44836
- setCollapsedSections((prev) => ({ ...prev, [providerName]: false }));
44837
45318
  toast2({
44838
- title: "API Key Cleared",
44839
- description: `Your ${config.displayName} API key has been removed from storage.`,
44840
- variant: "default"
45319
+ title: valid ? `${cfg.displayName} key saved` : `${cfg.displayName} key invalid`,
45320
+ description: valid ? `Your ${cfg.displayName} API key was saved successfully.` : `Unable to validate your ${cfg.displayName} key.`
44841
45321
  });
44842
45322
  };
44843
- const toggleShowKey = (providerName) => {
44844
- setApiKeys((prev) => ({
44845
- ...prev,
44846
- [providerName]: {
44847
- ...prev[providerName],
44848
- showKey: !prev[providerName].showKey
44849
- }
45323
+ const handleClear = (provider) => {
45324
+ const cfg = PROVIDERS[provider];
45325
+ providerManager.clearApiKey(provider);
45326
+ setApiKeys((p2) => ({
45327
+ ...p2,
45328
+ [provider]: { ...p2[provider], key: "", isValid: false }
44850
45329
  }));
45330
+ toast2({ title: `${cfg.displayName} key cleared` });
44851
45331
  };
44852
- const toggleCollapse = (providerName) => {
44853
- setCollapsedSections((prev) => ({
44854
- ...prev,
44855
- [providerName]: !prev[providerName]
45332
+ const toggleShow = (provider) => {
45333
+ setApiKeys((p2) => ({
45334
+ ...p2,
45335
+ [provider]: { ...p2[provider], showKey: !p2[provider].showKey }
44856
45336
  }));
44857
45337
  };
44858
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-6 p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
44859
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold text-slate-800 dark:text-slate-200 mb-6", children: "API Key Management" }),
44860
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-slate-600 dark:text-slate-400 mb-6", children: "Configure your API keys for different AI providers. Keys are stored securely in your browser's local storage." }),
44861
- Object.entries(PROVIDERS).map(([providerName, config]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
44862
- ProviderSection,
45338
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-8 p-8", children: [
45339
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-3xl font-bold text-gray-900 dark:text-gray-100", children: "API Key Management" }),
45340
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-600 dark:text-gray-400 max-w-2xl", children: "Enter your API keys below. They’re stored securely in local storage." }),
45341
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-6 md:grid-cols-2 lg:grid-cols-3", children: Object.entries(PROVIDERS).map(([prov, cfg]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
45342
+ ProviderCard,
44863
45343
  {
44864
- providerName,
44865
- config,
44866
- keyData: apiKeys[providerName],
44867
- isCollapsed: collapsedSections[providerName] && apiKeys[providerName].isValid,
45344
+ provider: prov,
45345
+ config: cfg,
45346
+ data: apiKeys[prov],
44868
45347
  disabled,
44869
- onApiKeyChange: handleApiKeyChange,
44870
- onClearApiKey: clearApiKey,
44871
- onToggleShowKey: toggleShowKey,
44872
- onToggleCollapse: toggleCollapse
45348
+ onChange: handleApiKeyChange,
45349
+ onClear: handleClear,
45350
+ onToggleShow: toggleShow
44873
45351
  },
44874
- providerName
44875
- ))
44876
- ] }) });
45352
+ prov
45353
+ )) })
45354
+ ] });
44877
45355
  };
44878
45356
  const McpClientContext = reactExports.createContext(null);
44879
45357
  const SERVER_CONFIGS_STORAGE_KEY = "mcpServerConfigs_v1";
@@ -44954,13 +45432,6 @@ const useServerState = () => {
44954
45432
  const [editingClientName, setEditingClientName] = reactExports.useState(
44955
45433
  null
44956
45434
  );
44957
- const [clientFormConfig, setClientFormConfig] = reactExports.useState({
44958
- transportType: "stdio",
44959
- command: "npx",
44960
- args: ["@modelcontextprotocol/server-everything"],
44961
- env: {}
44962
- });
44963
- const [clientFormName, setClientFormName] = reactExports.useState("");
44964
45435
  reactExports.useEffect(() => {
44965
45436
  try {
44966
45437
  if (Object.keys(serverConfigs).length > 0) {
@@ -44999,27 +45470,14 @@ const useServerState = () => {
44999
45470
  const handleCreateClient = reactExports.useCallback(() => {
45000
45471
  setIsCreatingClient(true);
45001
45472
  setEditingClientName(null);
45002
- setClientFormName("");
45003
- setClientFormConfig({
45004
- transportType: "stdio",
45005
- command: "npx",
45006
- args: ["@modelcontextprotocol/server-everything"],
45007
- env: {}
45008
- });
45009
45473
  }, []);
45010
- const handleEditClient = reactExports.useCallback(
45011
- (serverName, config) => {
45012
- setIsCreatingClient(false);
45013
- setEditingClientName(serverName);
45014
- setClientFormName(serverName);
45015
- setClientFormConfig(config);
45016
- },
45017
- []
45018
- );
45474
+ const handleEditClient = reactExports.useCallback((serverName) => {
45475
+ setIsCreatingClient(false);
45476
+ setEditingClientName(serverName);
45477
+ }, []);
45019
45478
  const handleCancelClientForm = reactExports.useCallback(() => {
45020
45479
  setIsCreatingClient(false);
45021
45480
  setEditingClientName(null);
45022
- setClientFormName("");
45023
45481
  }, []);
45024
45482
  return {
45025
45483
  serverConfigs,
@@ -45028,10 +45486,6 @@ const useServerState = () => {
45028
45486
  setSelectedServerName,
45029
45487
  isCreatingClient,
45030
45488
  editingClientName,
45031
- clientFormConfig,
45032
- setClientFormConfig,
45033
- clientFormName,
45034
- setClientFormName,
45035
45489
  updateServerConfig,
45036
45490
  removeServerConfig,
45037
45491
  handleCreateClient,
@@ -51647,7 +52101,7 @@ class Client extends Protocol {
51647
52101
  return this.notification({ method: "notifications/roots/list_changed" });
51648
52102
  }
51649
52103
  }
51650
- const version = "0.3.5";
52104
+ const version = "0.3.6";
51651
52105
  const packageJson = {
51652
52106
  version
51653
52107
  };
@@ -52969,7 +53423,10 @@ class MCPJamClient extends Client {
52969
53423
  */
52970
53424
  createAuthProvider() {
52971
53425
  if (this.serverConfig.transportType !== "stdio" && "url" in this.serverConfig && this.serverConfig.url) {
52972
- return new InspectorOAuthClientProvider(this.serverConfig.url.toString());
53426
+ return new InspectorOAuthClientProvider(
53427
+ this.serverConfig.url.toString(),
53428
+ this.serverConfig.transportType
53429
+ );
52973
53430
  }
52974
53431
  return null;
52975
53432
  }
@@ -53052,7 +53509,8 @@ class MCPJamClient extends Client {
53052
53509
  "debug"
53053
53510
  );
53054
53511
  const serverAuthProvider = new InspectorOAuthClientProvider(
53055
- this.serverConfig.url.toString()
53512
+ this.serverConfig.url.toString(),
53513
+ this.serverConfig.transportType
53056
53514
  );
53057
53515
  const token = this.bearerToken || ((_a2 = await serverAuthProvider.tokens()) == null ? void 0 : _a2.access_token);
53058
53516
  if (token) {
@@ -53308,7 +53766,8 @@ class MCPJamClient extends Client {
53308
53766
  this.connectionStatus = "disconnected";
53309
53767
  if (this.serverConfig.transportType !== "stdio") {
53310
53768
  const authProvider = new InspectorOAuthClientProvider(
53311
- this.serverConfig.url.toString()
53769
+ this.serverConfig.url.toString(),
53770
+ this.serverConfig.transportType
53312
53771
  );
53313
53772
  authProvider.clear();
53314
53773
  this.addClientLog("OAuth tokens cleared", "debug");
@@ -54701,7 +55160,7 @@ const useConnectionState = (addRequestHistory, addClientLog) => {
54701
55160
  const updateServer = reactExports.useCallback(
54702
55161
  async (serverName, config) => {
54703
55162
  if (!mcpAgent) return;
54704
- await mcpAgent.disconnectFromServer(serverName);
55163
+ await mcpAgent.removeServer(serverName);
54705
55164
  mcpAgent.addServer(serverName, config);
54706
55165
  try {
54707
55166
  await mcpAgent.connectToServer(serverName);
@@ -61655,6 +62114,24 @@ function requireAjv() {
61655
62114
  }
61656
62115
  var ajvExports = requireAjv();
61657
62116
  const Ajv = /* @__PURE__ */ getDefaultExportFromCjs(ajvExports);
62117
+ function stripEnumNames(schema) {
62118
+ if (Array.isArray(schema)) {
62119
+ return schema.map(stripEnumNames);
62120
+ }
62121
+ if (typeof schema !== "object" || schema === null) return schema;
62122
+ const { properties: properties2, items: items2, ...rest } = schema;
62123
+ const cleaned = { ...rest };
62124
+ if (properties2) {
62125
+ cleaned.properties = {};
62126
+ for (const key in properties2) {
62127
+ cleaned.properties[key] = stripEnumNames(properties2[key]);
62128
+ }
62129
+ }
62130
+ if (items2) {
62131
+ cleaned.items = stripEnumNames(items2);
62132
+ }
62133
+ return cleaned;
62134
+ }
61658
62135
  const ElicitationModal = ({ request, onClose }) => {
61659
62136
  const [formData, setFormData] = reactExports.useState({});
61660
62137
  const [validationError, setValidationError] = reactExports.useState(null);
@@ -61700,7 +62177,8 @@ const ElicitationModal = ({ request, onClose }) => {
61700
62177
  return;
61701
62178
  }
61702
62179
  const ajv2 = new Ajv();
61703
- const validate2 = ajv2.compile(request.requestedSchema);
62180
+ const cleanedSchema = stripEnumNames(request.requestedSchema);
62181
+ const validate2 = ajv2.compile(cleanedSchema);
61704
62182
  const isValid2 = validate2(formData);
61705
62183
  if (!isValid2) {
61706
62184
  const errorMessage = ajv2.errorsText(validate2.errors);
@@ -61719,7 +62197,7 @@ const ElicitationModal = ({ request, onClose }) => {
61719
62197
  }
61720
62198
  };
61721
62199
  const handleReject = () => {
61722
- request.resolve({ action: "reject" });
62200
+ request.resolve({ action: "decline" });
61723
62201
  onClose();
61724
62202
  };
61725
62203
  const handleCancel = () => {
@@ -61862,14 +62340,9 @@ const useServerManagement = (serverState, connectionState, configState, mcpOpera
61862
62340
  );
61863
62341
  const handleEditClient = reactExports.useCallback(
61864
62342
  (serverName) => {
61865
- const serverConnections = connectionState.mcpAgent ? connectionState.mcpAgent.getAllConnectionInfo() : [];
61866
- const connection = serverConnections.find(
61867
- (conn) => conn.name === serverName
61868
- );
61869
- if (!connection) return;
61870
- serverState.handleEditClient(serverName, connection.config);
62343
+ serverState.handleEditClient(serverName);
61871
62344
  },
61872
- [connectionState.mcpAgent, serverState]
62345
+ [serverState]
61873
62346
  );
61874
62347
  const handleConnectServer = reactExports.useCallback(
61875
62348
  async (serverName) => {
@@ -61877,47 +62350,7 @@ const useServerManagement = (serverState, connectionState, configState, mcpOpera
61877
62350
  },
61878
62351
  [connectionState]
61879
62352
  );
61880
- const handleSaveClient = reactExports.useCallback(
61881
- async (config) => {
61882
- if (!serverState.clientFormName.trim()) return;
61883
- try {
61884
- if (serverState.isCreatingClient) {
61885
- await handleAddServer(serverState.clientFormName, config, {
61886
- autoConnect: true
61887
- });
61888
- } else if (serverState.editingClientName) {
61889
- const oldServerName = serverState.editingClientName;
61890
- const newServerName = serverState.clientFormName.trim();
61891
- if (oldServerName !== newServerName) {
61892
- addClientLog(
61893
- `🔄 Server name changed from "${oldServerName}" to "${newServerName}"`,
61894
- "info"
61895
- );
61896
- await handleRemoveServer(oldServerName);
61897
- await handleAddServer(newServerName, config, {
61898
- autoConnect: true
61899
- });
61900
- if (serverState.selectedServerName === oldServerName) {
61901
- serverState.setSelectedServerName(newServerName);
61902
- }
61903
- } else {
61904
- await handleUpdateServer(serverState.editingClientName, config);
61905
- }
61906
- }
61907
- serverState.handleCancelClientForm();
61908
- } catch (error) {
61909
- console.error("Failed to save client:", error);
61910
- }
61911
- },
61912
- [
61913
- serverState,
61914
- handleAddServer,
61915
- handleUpdateServer,
61916
- handleRemoveServer,
61917
- addClientLog
61918
- ]
61919
- );
61920
- const handleSaveMultiple = reactExports.useCallback(
62353
+ const saveClients = reactExports.useCallback(
61921
62354
  async (clients) => {
61922
62355
  const results = {
61923
62356
  success: [],
@@ -61925,19 +62358,43 @@ const useServerManagement = (serverState, connectionState, configState, mcpOpera
61925
62358
  };
61926
62359
  for (const client2 of clients) {
61927
62360
  try {
61928
- console.log(`🔧 Creating client: "${client2.name}"`);
61929
- await handleAddServer(client2.name, client2.config, {
61930
- autoConnect: false
61931
- });
62361
+ if (serverState.editingClientName && clients.length === 1) {
62362
+ const oldServerName = serverState.editingClientName;
62363
+ const newServerName = client2.name.trim();
62364
+ if (oldServerName !== newServerName) {
62365
+ addClientLog(
62366
+ `🔄 Server name changed from "${oldServerName}" to "${newServerName}"`,
62367
+ "info"
62368
+ );
62369
+ await handleRemoveServer(oldServerName);
62370
+ await handleAddServer(newServerName, client2.config, {
62371
+ autoConnect: true
62372
+ });
62373
+ if (serverState.selectedServerName === oldServerName) {
62374
+ serverState.setSelectedServerName(newServerName);
62375
+ }
62376
+ } else {
62377
+ await handleUpdateServer(
62378
+ serverState.editingClientName,
62379
+ client2.config
62380
+ );
62381
+ }
62382
+ } else {
62383
+ console.log(`🔧 Creating client: "${client2.name}"`);
62384
+ await handleAddServer(client2.name, client2.config, {
62385
+ autoConnect: clients.length === 1
62386
+ // Auto-connect only for single client
62387
+ });
62388
+ }
61932
62389
  results.success.push(client2.name);
61933
62390
  addClientLog(
61934
- `✅ Successfully created client: "${client2.name}"`,
62391
+ `✅ Successfully ${serverState.editingClientName ? "updated" : "created"} client: "${client2.name}"`,
61935
62392
  "info"
61936
62393
  );
61937
62394
  } catch (error) {
61938
62395
  const errorMessage = error instanceof Error ? error.message : String(error);
61939
62396
  addClientLog(
61940
- `❌ Failed to create client "${client2.name}": ${errorMessage}`,
62397
+ `❌ Failed to ${serverState.editingClientName ? "update" : "create"} client "${client2.name}": ${errorMessage}`,
61941
62398
  "error"
61942
62399
  );
61943
62400
  results.failed.push({ name: client2.name, error: errorMessage });
@@ -61946,19 +62403,25 @@ const useServerManagement = (serverState, connectionState, configState, mcpOpera
61946
62403
  serverState.handleCancelClientForm();
61947
62404
  if (results.success.length > 0) {
61948
62405
  addClientLog(
61949
- `✅ Successfully created ${results.success.length} client(s): ${results.success.join(", ")}`,
62406
+ `✅ Successfully ${serverState.editingClientName ? "updated" : "created"} ${results.success.length} client(s): ${results.success.join(", ")}`,
61950
62407
  "info"
61951
62408
  );
61952
62409
  }
61953
62410
  if (results.failed.length > 0) {
61954
62411
  addClientLog(
61955
- `❌ Failed to create ${results.failed.length} client(s): ${results.failed.map(({ name, error }) => `${name}: ${error}`).join(", ")}`,
62412
+ `❌ Failed to ${serverState.editingClientName ? "update" : "create"} ${results.failed.length} client(s): ${results.failed.map(({ name, error }) => `${name}: ${error}`).join(", ")}`,
61956
62413
  "error"
61957
62414
  );
61958
62415
  }
61959
62416
  return results;
61960
62417
  },
61961
- [handleAddServer, serverState, addClientLog]
62418
+ [
62419
+ handleAddServer,
62420
+ handleUpdateServer,
62421
+ handleRemoveServer,
62422
+ serverState,
62423
+ addClientLog
62424
+ ]
61962
62425
  );
61963
62426
  return {
61964
62427
  handleAddServer,
@@ -61966,8 +62429,7 @@ const useServerManagement = (serverState, connectionState, configState, mcpOpera
61966
62429
  handleUpdateServer,
61967
62430
  handleEditClient,
61968
62431
  handleConnectServer,
61969
- handleSaveClient,
61970
- handleSaveMultiple
62432
+ saveClients
61971
62433
  };
61972
62434
  };
61973
62435
  const loadOAuthTokens = async (serverUrl, updateAuthState) => {
@@ -62029,8 +62491,14 @@ const useOAuthHandlers = (serverState, configState, handleAddServer) => {
62029
62491
  }
62030
62492
  }
62031
62493
  const finalServerName = existingServerName || serverName;
62494
+ const transportKey = getServerSpecificKey(
62495
+ SESSION_KEYS.TRANSPORT_TYPE,
62496
+ serverUrl
62497
+ );
62498
+ const storedTransportType = sessionStorage.getItem(transportKey);
62499
+ const transportType = storedTransportType || "sse";
62032
62500
  const serverConfig = {
62033
- transportType: "sse",
62501
+ transportType,
62034
62502
  url: new URL(serverUrl)
62035
62503
  };
62036
62504
  try {
@@ -62152,15 +62620,73 @@ const useAppEffects = (serverState, connectionState, configState, mcpOperations,
62152
62620
  const proxyAddress = await getMCPProxyAddressAsync(configState.config);
62153
62621
  const response = await fetch(`${proxyAddress}/config`);
62154
62622
  const data2 = await response.json();
62155
- const currentConfig = serverState.serverConfigs[serverState.selectedServerName];
62156
- if ((currentConfig == null ? void 0 : currentConfig.transportType) === "stdio") {
62157
- serverState.setServerConfigs((prev) => ({
62158
- ...prev,
62159
- [serverState.selectedServerName]: {
62160
- ...prev[serverState.selectedServerName],
62161
- env: data2.defaultEnvironment || {}
62623
+ if (data2.serverConfigs && Object.keys(data2.serverConfigs).length > 0) {
62624
+ console.log("📡 Found CLI server configurations, loading...");
62625
+ const convertedConfigs = {};
62626
+ for (const [serverName, cliConfig] of Object.entries(
62627
+ data2.serverConfigs
62628
+ )) {
62629
+ const config = cliConfig;
62630
+ if (config.type === "sse" && config.url) {
62631
+ convertedConfigs[serverName] = {
62632
+ transportType: "sse",
62633
+ url: new URL(config.url),
62634
+ name: serverName
62635
+ };
62636
+ } else if (config.command) {
62637
+ convertedConfigs[serverName] = {
62638
+ transportType: "stdio",
62639
+ command: config.command,
62640
+ args: config.args || [],
62641
+ env: {
62642
+ ...data2.defaultEnvironment || {},
62643
+ ...config.env || {}
62644
+ },
62645
+ name: serverName
62646
+ };
62647
+ } else if (config.url) {
62648
+ convertedConfigs[serverName] = {
62649
+ transportType: "sse",
62650
+ url: new URL(config.url),
62651
+ name: serverName
62652
+ };
62653
+ }
62654
+ }
62655
+ if (Object.keys(convertedConfigs).length > 0) {
62656
+ const existingConfigs = serverState.serverConfigs;
62657
+ const hasExistingConfigs = Object.keys(existingConfigs).length > 0;
62658
+ const mergedConfigs = { ...convertedConfigs, ...existingConfigs };
62659
+ console.log(
62660
+ `✅ Loading ${Object.keys(convertedConfigs).length} servers from CLI config`
62661
+ );
62662
+ if (hasExistingConfigs) {
62663
+ console.log(
62664
+ `📦 Merging with ${Object.keys(existingConfigs).length} existing localStorage servers`
62665
+ );
62162
62666
  }
62163
- }));
62667
+ serverState.setServerConfigs(mergedConfigs);
62668
+ if (!serverState.selectedServerName || !mergedConfigs[serverState.selectedServerName]) {
62669
+ const firstServerName = Object.keys(convertedConfigs)[0];
62670
+ serverState.setSelectedServerName(firstServerName);
62671
+ }
62672
+ const totalServers = Object.keys(mergedConfigs).length;
62673
+ const cliServers = Object.keys(convertedConfigs).length;
62674
+ addClientLog(
62675
+ `Loaded ${cliServers} servers from CLI configuration (${totalServers} total)`,
62676
+ "info"
62677
+ );
62678
+ }
62679
+ } else {
62680
+ const currentConfig = serverState.serverConfigs[serverState.selectedServerName];
62681
+ if ((currentConfig == null ? void 0 : currentConfig.transportType) === "stdio") {
62682
+ serverState.setServerConfigs((prev) => ({
62683
+ ...prev,
62684
+ [serverState.selectedServerName]: {
62685
+ ...prev[serverState.selectedServerName],
62686
+ env: data2.defaultEnvironment || {}
62687
+ }
62688
+ }));
62689
+ }
62164
62690
  }
62165
62691
  } catch (error) {
62166
62692
  console.error("Error fetching default environment:", error);
@@ -62263,7 +62789,7 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
62263
62789
  });
62264
62790
  };
62265
62791
  const renderOAuthCallback = (onOAuthConnect) => {
62266
- const OAuthCallback = React.lazy(() => __vitePreload(() => import("./OAuthCallback-CaYMoLGO.js"), true ? [] : void 0));
62792
+ const OAuthCallback = React.lazy(() => __vitePreload(() => import("./OAuthCallback-Bgz6lAmx.js"), true ? [] : void 0));
62267
62793
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
62268
62794
  reactExports.Suspense,
62269
62795
  {
@@ -62277,7 +62803,7 @@ const renderOAuthCallback = (onOAuthConnect) => {
62277
62803
  };
62278
62804
  const renderOAuthDebugCallback = (onOAuthDebugConnect) => {
62279
62805
  const OAuthDebugCallback = React.lazy(
62280
- () => __vitePreload(() => import("./OAuthDebugCallback-CBFeYzo9.js"), true ? [] : void 0)
62806
+ () => __vitePreload(() => import("./OAuthDebugCallback-Gd08QO37.js"), true ? [] : void 0)
62281
62807
  );
62282
62808
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-900 dark:to-slate-800 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
62283
62809
  reactExports.Suspense,
@@ -62326,6 +62852,7 @@ const App = () => {
62326
62852
  mcpOperations.addClientLog
62327
62853
  );
62328
62854
  const configState = useConfigState();
62855
+ console.log("🔧 serverState", serverState);
62329
62856
  const rootsRef = reactExports.useRef(mcpOperations.roots);
62330
62857
  const nextRequestId = reactExports.useRef(0);
62331
62858
  const [currentPage, setCurrentPage] = reactExports.useState(() => {
@@ -62390,8 +62917,7 @@ const App = () => {
62390
62917
  handleRemoveServer,
62391
62918
  handleEditClient,
62392
62919
  handleConnectServer,
62393
- handleSaveClient,
62394
- handleSaveMultiple,
62920
+ saveClients,
62395
62921
  handleAddServer
62396
62922
  } = useServerManagement(
62397
62923
  serverState,
@@ -62685,23 +63211,23 @@ const App = () => {
62685
63211
  }
62686
63212
  const renderTabs = () => {
62687
63213
  if (serverState.isCreatingClient || serverState.editingClientName) {
63214
+ const initialClient = serverState.editingClientName ? {
63215
+ name: serverState.editingClientName,
63216
+ config: serverState.serverConfigs[serverState.editingClientName]
63217
+ } : void 0;
62688
63218
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
62689
63219
  ClientFormSection,
62690
63220
  {
62691
63221
  isCreating: serverState.isCreatingClient,
62692
63222
  editingClientName: serverState.editingClientName,
62693
- clientFormName: serverState.clientFormName,
62694
- setClientFormName: serverState.setClientFormName,
62695
- clientFormConfig: serverState.clientFormConfig,
62696
- setClientFormConfig: serverState.setClientFormConfig,
63223
+ initialClient,
62697
63224
  config: configState.config,
62698
63225
  setConfig: configState.setConfig,
62699
63226
  bearerToken: configState.bearerToken,
62700
63227
  setBearerToken: configState.setBearerToken,
62701
63228
  headerName: configState.headerName,
62702
63229
  setHeaderName: configState.setHeaderName,
62703
- onSave: handleSaveClient,
62704
- onSaveMultiple: handleSaveMultiple,
63230
+ onSave: saveClients,
62705
63231
  onCancel: serverState.handleCancelClientForm
62706
63232
  }
62707
63233
  );
@@ -62733,7 +63259,10 @@ const App = () => {
62733
63259
  Tabs,
62734
63260
  {
62735
63261
  currentPage,
62736
- onPageChange: setCurrentPage,
63262
+ onPageChange: (page) => {
63263
+ setCurrentPage(page);
63264
+ serverState.handleCancelClientForm();
63265
+ },
62737
63266
  serverCapabilities,
62738
63267
  pendingSampleRequests: mcpOperations.pendingSampleRequests,
62739
63268
  shouldDisableAll: !connectionState.mcpAgent