@mcpjam/inspector 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/build/cli.js CHANGED
@@ -73,15 +73,13 @@ async function runWebClient(args) {
73
73
  if (serverOk) {
74
74
  try {
75
75
  console.log("\x1b[32m%s\x1b[0m", "✅ Server initialized successfully"); // Green color
76
- console.log("\x1b[36m%s\x1b[0m", `🌐 Opening browser at http://127.0.0.1:${CLIENT_PORT}`);
77
- if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
78
- // Note: We need to import 'open' if we want to auto-open browser
79
- // import open from "open";
80
- // open(`http://127.0.0.1:${CLIENT_PORT}`);
81
- }
82
76
  console.log("\x1b[33m%s\x1b[0m", "🖥️ Starting client interface...");
83
77
  await spawnPromise("node", [inspectorClientPath], {
84
- env: { ...process.env, PORT: CLIENT_PORT },
78
+ env: {
79
+ ...process.env,
80
+ PORT: CLIENT_PORT,
81
+ MCP_AUTO_OPEN_ENABLED: process.env.MCP_AUTO_OPEN_ENABLED ?? "true",
82
+ },
85
83
  signal: abort.signal,
86
84
  echoOutput: true,
87
85
  });
@@ -4,6 +4,7 @@ import { join, dirname } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import handler from "serve-handler";
6
6
  import http from "http";
7
+ import open from "open";
7
8
 
8
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
10
  const distPath = join(__dirname, "../dist");
@@ -39,19 +40,32 @@ const server = http.createServer((request, response) => {
39
40
  return handler(request, response, handlerOptions);
40
41
  });
41
42
 
42
- const port = process.env.PORT || 6274;
43
+ const defaultPort = process.env.PORT || 6274;
44
+ let port = Number(defaultPort);
45
+
46
+ // Try ports sequentially until one works
47
+ server.on("error", (err) => {
48
+ if (err.code === "EADDRINUSE") {
49
+ console.log(`⚠️ Port ${port} was in use, trying ${port + 1}`);
50
+ port++;
51
+ server.listen(port);
52
+ } else {
53
+ console.error(`❌ MCPJam Inspector failed to start: ${err.message}`);
54
+ }
55
+ });
56
+
43
57
  server.on("listening", () => {
58
+ const url = `http://127.0.0.1:${port}`;
44
59
  console.log(
45
- `🔍 MCPJam Inspector is up and running at http://127.0.0.1:${port} 🚀`,
60
+ `🔍 MCPJam Inspector is up and running at \u001B]8;;${url}\u0007${url}\u001B]8;;\u0007 🚀`,
46
61
  );
47
- });
48
- server.on("error", (err) => {
49
- if (err.message.includes(`EADDRINUSE`)) {
50
- console.error(
51
- `❌ MCPJam Inspector PORT IS IN USE at http://127.0.0.1:${port} ❌ `,
62
+
63
+ if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
64
+ console.log(
65
+ `🌐 Opening browser at \u001B]8;;${url}\u0007${url}\u001B]8;;\u0007`,
52
66
  );
53
- } else {
54
- throw err;
67
+ open(url);
55
68
  }
56
69
  });
70
+
57
71
  server.listen(port);
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import open from "open";
4
3
  import { resolve, dirname } from "path";
5
4
  import { spawnPromise } from "spawn-rx";
6
5
  import { fileURLToPath } from "url";
@@ -87,6 +86,7 @@ async function main() {
87
86
  abort.abort();
88
87
  console.log("\n\x1b[31m%s\x1b[0m", "⚠️ Shutting down MCP Inspector..."); // Red color
89
88
  });
89
+
90
90
  let server, serverOk;
91
91
  try {
92
92
  server = spawnPromise(
@@ -116,19 +116,14 @@ async function main() {
116
116
  if (serverOk) {
117
117
  try {
118
118
  console.log("\x1b[32m%s\x1b[0m", "✅ Server initialized successfully"); // Green color
119
- console.log(
120
- "\x1b[36m%s\x1b[0m",
121
- `🌐 Opening browser at http://127.0.0.1:${CLIENT_PORT}`,
122
- );
123
-
124
- if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
125
- open(`http://127.0.0.1:${CLIENT_PORT}`);
126
- }
127
-
128
119
  console.log("\x1b[33m%s\x1b[0m", "🖥️ Starting client interface...");
129
120
 
130
121
  await spawnPromise("node", [inspectorClientPath], {
131
- env: { ...process.env, PORT: CLIENT_PORT },
122
+ env: {
123
+ ...process.env,
124
+ PORT: CLIENT_PORT,
125
+ MCP_AUTO_OPEN_ENABLED: process.env.MCP_AUTO_OPEN_ENABLED ?? "true",
126
+ },
132
127
  signal: abort.signal,
133
128
  echoOutput: true,
134
129
  });
@@ -1,4 +1,4 @@
1
- import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-B_8Xm9gw.js";
1
+ import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-DQYTYcqe.js";
2
2
  const OAuthCallback = ({ onConnect }) => {
3
3
  const { toast } = useToast();
4
4
  const hasProcessedRef = reactExports.useRef(false);
@@ -1,4 +1,4 @@
1
- import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-B_8Xm9gw.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-DQYTYcqe.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -27125,17 +27125,6 @@ const Hash = createLucideIcon("Hash", [
27125
27125
  ["line", { x1: "10", x2: "8", y1: "3", y2: "21", key: "1ggp8o" }],
27126
27126
  ["line", { x1: "16", x2: "14", y1: "3", y2: "21", key: "weycgp" }]
27127
27127
  ]);
27128
- /**
27129
- * @license lucide-react v0.447.0 - ISC
27130
- *
27131
- * This source code is licensed under the ISC license.
27132
- * See the LICENSE file in the root directory of this source tree.
27133
- */
27134
- const History = createLucideIcon("History", [
27135
- ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
27136
- ["path", { d: "M3 3v5h5", key: "1xhq8a" }],
27137
- ["path", { d: "M12 7v5l4 2", key: "1fdv2h" }]
27138
- ]);
27139
27128
  /**
27140
27129
  * @license lucide-react v0.447.0 - ISC
27141
27130
  *
@@ -28099,12 +28088,8 @@ const ActivityHeader = ({
28099
28088
  ] })
28100
28089
  ] });
28101
28090
  const CompactHeader = ({
28102
- requestHistory,
28103
- onClearHistory
28104
- }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
28105
- /* @__PURE__ */ jsxRuntimeExports.jsx(RequestCountBadge, { count: requestHistory.length }),
28106
- /* @__PURE__ */ jsxRuntimeExports.jsx(ClearHistoryButton, { onClick: onClearHistory })
28107
- ] });
28091
+ requestHistory
28092
+ }) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between mb-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(RequestCountBadge, { count: requestHistory.length }) });
28108
28093
  const EmptyState$1 = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
28109
28094
  /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-12 h-12 text-muted-foreground/40 mb-4" }),
28110
28095
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No activity yet" }),
@@ -28141,13 +28126,7 @@ const ActivityTab = ({
28141
28126
  }
28142
28127
  ),
28143
28128
  requestHistory.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState$1, {}) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
28144
- !showHeader && requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
28145
- CompactHeader,
28146
- {
28147
- requestHistory,
28148
- onClearHistory
28149
- }
28150
- ),
28129
+ !showHeader && requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(CompactHeader, { requestHistory }),
28151
28130
  /* @__PURE__ */ jsxRuntimeExports.jsx(RequestHistoryList, { requestHistory })
28152
28131
  ] })
28153
28132
  ]
@@ -29174,9 +29153,29 @@ const ResultsTab = ({
29174
29153
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-gradient-to-br from-background/80 to-background/60 backdrop-blur-sm p-4 rounded-xl border border-border/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ToolResult, { toolResult }) })
29175
29154
  ] });
29176
29155
  };
29156
+ function CopyIcon({ value }) {
29157
+ const [copied, setCopied] = reactExports.useState(false);
29158
+ const handleCopy = async () => {
29159
+ await navigator.clipboard.writeText(value);
29160
+ setCopied(true);
29161
+ };
29162
+ reactExports.useEffect(() => {
29163
+ let timeoutId;
29164
+ if (copied) {
29165
+ timeoutId = setTimeout(() => {
29166
+ setCopied(false);
29167
+ }, 500);
29168
+ }
29169
+ return () => {
29170
+ if (timeoutId) {
29171
+ clearTimeout(timeoutId);
29172
+ }
29173
+ };
29174
+ }, [copied]);
29175
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", className: "size-4", onClick: handleCopy, children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(CheckCheck, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, {}) });
29176
+ }
29177
29177
  const ClientLogsTab = ({
29178
29178
  clientLogs,
29179
- onClearLogs,
29180
29179
  showHeader = true
29181
29180
  }) => {
29182
29181
  const reversedClientLogs = [...clientLogs].reverse();
@@ -29240,7 +29239,7 @@ const ClientLogsTab = ({
29240
29239
  children: [
29241
29240
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `flex-shrink-0 mt-0.5 ${config.iconColor}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconComponent, { className: "w-4 h-4" }) }),
29242
29241
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
29243
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2 mb-1", children: [
29242
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center mb-1 space-x-2", children: [
29244
29243
  /* @__PURE__ */ jsxRuntimeExports.jsx(
29245
29244
  "span",
29246
29245
  {
@@ -29248,36 +29247,26 @@ const ClientLogsTab = ({
29248
29247
  children: config.label
29249
29248
  }
29250
29249
  ),
29251
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground font-mono", children: formatTimestamp(log.timestamp) })
29250
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs text-muted-foreground", children: formatTimestamp(log.timestamp) })
29252
29251
  ] }),
29253
29252
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `text-sm ${config.textColor} font-mono break-words`, children: log.message })
29254
- ] })
29253
+ ] }),
29254
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `flex-shrink-0 mt-0.5 ${config.iconColor}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, { value: log.message }) })
29255
29255
  ]
29256
29256
  }
29257
29257
  );
29258
29258
  };
29259
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col", children: [
29260
- !showHeader && clientLogs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
29261
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-muted-foreground bg-muted/50 px-3 py-1 rounded-full", children: [
29262
- clientLogs.length,
29263
- " log",
29264
- clientLogs.length !== 1 ? "s" : ""
29265
- ] }),
29266
- /* @__PURE__ */ jsxRuntimeExports.jsx(
29267
- "button",
29268
- {
29269
- onClick: onClearLogs,
29270
- className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
29271
- title: "Clear all activity",
29272
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-4 h-4 text-muted-foreground group-hover:text-destructive" })
29273
- }
29274
- )
29275
- ] }),
29276
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: clientLogs.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center p-8", children: [
29277
- /* @__PURE__ */ jsxRuntimeExports.jsx(Bug, { className: "w-12 h-12 text-muted-foreground/50 mb-4" }),
29278
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium text-muted-foreground mb-2", children: "No logs yet" }),
29279
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground/70 max-w-sm", children: "Client logs will appear here when you perform operations. Logs include info, warnings, errors, and debug messages." })
29280
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-4 space-y-2", children: reversedClientLogs.map((log, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(LogEntry, { log }, `${log.timestamp}-${index2}`)) }) })
29259
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full", children: [
29260
+ !showHeader && clientLogs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between mb-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-3 py-1 text-sm rounded-full text-muted-foreground bg-muted/50", children: [
29261
+ clientLogs.length,
29262
+ " log",
29263
+ clientLogs.length !== 1 ? "s" : ""
29264
+ ] }) }),
29265
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: clientLogs.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center", children: [
29266
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bug, { className: "w-12 h-12 mb-4 text-muted-foreground/50" }),
29267
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mb-2 text-lg font-medium text-muted-foreground", children: "No logs yet" }),
29268
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "max-w-sm text-sm text-muted-foreground/70", children: "Client logs will appear here when you perform operations. Logs include info, warnings, errors, and debug messages." })
29269
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full p-4 space-y-2 overflow-y-auto", children: reversedClientLogs.map((log, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(LogEntry, { log }, `${log.timestamp}-${index2}`)) }) })
29281
29270
  ] });
29282
29271
  };
29283
29272
  const TabbedHistoryPanel = ({
@@ -29286,14 +29275,14 @@ const TabbedHistoryPanel = ({
29286
29275
  clientLogs,
29287
29276
  onClearHistory,
29288
29277
  onClearLogs,
29289
- onToggleCollapse
29278
+ onToggleCollapse,
29279
+ activeTab,
29280
+ setActiveTab
29290
29281
  }) => {
29291
- const [activeTab, setActiveTab] = reactExports.useState("activity");
29292
29282
  const [isToolResultError, setIsToolResultError] = reactExports.useState(false);
29293
29283
  reactExports.useEffect(() => {
29294
29284
  if (toolResult) {
29295
29285
  setIsToolResultError(toolResult.isError === true);
29296
- setActiveTab("results");
29297
29286
  }
29298
29287
  }, [toolResult]);
29299
29288
  reactExports.useEffect(() => {
@@ -29306,7 +29295,7 @@ const TabbedHistoryPanel = ({
29306
29295
  setActiveTab("logs");
29307
29296
  }
29308
29297
  }
29309
- }, [clientLogs]);
29298
+ }, [clientLogs, setActiveTab]);
29310
29299
  const renderActivityTabButton = () => {
29311
29300
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
29312
29301
  "button",
@@ -29375,18 +29364,27 @@ const TabbedHistoryPanel = ({
29375
29364
  case "results":
29376
29365
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ResultsTab, { toolResult, showHeader: false }) });
29377
29366
  case "logs":
29378
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
29379
- ClientLogsTab,
29380
- {
29381
- clientLogs,
29382
- onClearLogs,
29383
- showHeader: false
29384
- }
29385
- ) });
29367
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogsTab, { clientLogs, showHeader: false }) });
29386
29368
  default:
29387
29369
  return null;
29388
29370
  }
29389
29371
  };
29372
+ const ClearHistoryButton2 = ({
29373
+ onClick,
29374
+ count: count2
29375
+ }) => {
29376
+ if (count2 > 0) {
29377
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
29378
+ "button",
29379
+ {
29380
+ onClick,
29381
+ className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
29382
+ title: "Clear all activity",
29383
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-5 h-5 text-muted-foreground group-hover:text-destructive" })
29384
+ }
29385
+ );
29386
+ }
29387
+ };
29390
29388
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-transparent flex flex-col h-full", children: [
29391
29389
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-border/20 px-6 py-3", children: [
29392
29390
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-1", children: [
@@ -29394,18 +29392,38 @@ const TabbedHistoryPanel = ({
29394
29392
  renderResultsTabButton(),
29395
29393
  renderLogsTabButton()
29396
29394
  ] }),
29397
- /* @__PURE__ */ jsxRuntimeExports.jsx(
29398
- "button",
29399
- {
29400
- onClick: onToggleCollapse,
29401
- className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
29402
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
29403
- }
29404
- )
29395
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
29396
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { children: activeTab == "activity" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
29397
+ ClearHistoryButton2,
29398
+ {
29399
+ onClick: onClearHistory,
29400
+ count: requestHistory.length
29401
+ }
29402
+ ) : activeTab == "logs" && /* @__PURE__ */ jsxRuntimeExports.jsx(
29403
+ ClearHistoryButton2,
29404
+ {
29405
+ onClick: onClearLogs,
29406
+ count: clientLogs.length
29407
+ }
29408
+ ) }),
29409
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
29410
+ "button",
29411
+ {
29412
+ onClick: onToggleCollapse,
29413
+ className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
29414
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
29415
+ }
29416
+ )
29417
+ ] })
29405
29418
  ] }),
29406
29419
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: renderTabContent() })
29407
29420
  ] });
29408
29421
  };
29422
+ const TAB_CONFIG = [
29423
+ { key: "activity", label: "History" },
29424
+ { key: "results", label: "Results" },
29425
+ { key: "logs", label: "Logs" }
29426
+ ];
29409
29427
  const HistoryAndNotifications = ({
29410
29428
  requestHistory,
29411
29429
  toolResult,
@@ -29413,109 +29431,120 @@ const HistoryAndNotifications = ({
29413
29431
  onClearHistory,
29414
29432
  onClearLogs
29415
29433
  }) => {
29416
- const [isHistoryCollapsed, setIsHistoryCollapsed] = reactExports.useState(true);
29417
- const {
29418
- height: historyPaneHeight,
29419
- isDragging,
29420
- handleDragStart,
29421
- resetHeight,
29422
- setCustomHeight
29423
- } = useDraggablePane(500, "historyPaneHeight");
29434
+ const [isCollapsed, setIsCollapsed] = reactExports.useState(true);
29435
+ const [activeTab, setActiveTab] = reactExports.useState(null);
29436
+ const { height, isDragging, handleDragStart, resetHeight, setCustomHeight } = useDraggablePane(500, "historyPaneHeight");
29424
29437
  const toggleCollapse = reactExports.useCallback(() => {
29425
- setIsHistoryCollapsed(!isHistoryCollapsed);
29426
- }, [isHistoryCollapsed]);
29438
+ setIsCollapsed((c) => {
29439
+ const next = !c;
29440
+ if (next) {
29441
+ setActiveTab(null);
29442
+ }
29443
+ return next;
29444
+ });
29445
+ }, []);
29427
29446
  const handleDoubleClick = reactExports.useCallback(() => {
29428
- if (!isHistoryCollapsed) {
29429
- resetHeight();
29430
- }
29431
- }, [isHistoryCollapsed, resetHeight]);
29447
+ if (!isCollapsed) resetHeight();
29448
+ }, [isCollapsed, resetHeight]);
29432
29449
  reactExports.useEffect(() => {
29433
- const handleKeyDown = (e) => {
29434
- var _a2, _b, _c, _d;
29435
- if (isHistoryCollapsed || ((_b = (_a2 = e.target) == null ? void 0 : _a2.tagName) == null ? void 0 : _b.toLowerCase()) === "input" || ((_d = (_c = e.target) == null ? void 0 : _c.tagName) == null ? void 0 : _d.toLowerCase()) === "textarea") {
29436
- return;
29437
- }
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;
29438
29455
  if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
29439
29456
  e.preventDefault();
29440
- const increment = e.shiftKey ? 50 : 25;
29441
- const newHeight = e.key === "ArrowUp" ? historyPaneHeight + increment : historyPaneHeight - increment;
29442
- setCustomHeight(newHeight);
29457
+ const inc = e.shiftKey ? 50 : 25;
29458
+ const newH = e.key === "ArrowUp" ? height + inc : height - inc;
29459
+ setCustomHeight(newH);
29443
29460
  }
29444
29461
  if (e.altKey && e.key === "r") {
29445
29462
  e.preventDefault();
29446
29463
  resetHeight();
29447
29464
  }
29448
29465
  };
29449
- window.addEventListener("keydown", handleKeyDown);
29450
- return () => window.removeEventListener("keydown", handleKeyDown);
29451
- }, [isHistoryCollapsed, historyPaneHeight, setCustomHeight, resetHeight]);
29466
+ window.addEventListener("keydown", onKey);
29467
+ return () => window.removeEventListener("keydown", onKey);
29468
+ }, [isCollapsed, height, setCustomHeight, resetHeight]);
29452
29469
  reactExports.useEffect(() => {
29453
29470
  if (toolResult) {
29454
- setIsHistoryCollapsed(false);
29471
+ setActiveTab("results");
29472
+ setIsCollapsed(false);
29455
29473
  }
29456
29474
  }, [toolResult]);
29457
29475
  reactExports.useEffect(() => {
29458
- if (clientLogs.length > 0) {
29459
- const isLastError = clientLogs[clientLogs.length - 1].level === "error";
29460
- if (isLastError) {
29461
- setIsHistoryCollapsed(false);
29462
- }
29476
+ if (clientLogs.length && clientLogs[clientLogs.length - 1].level === "error") {
29477
+ setActiveTab("logs");
29478
+ setIsCollapsed(false);
29463
29479
  }
29464
29480
  }, [clientLogs]);
29481
+ const counts = {
29482
+ activity: requestHistory.length,
29483
+ results: toolResult ? 1 : 0,
29484
+ logs: clientLogs.length
29485
+ };
29465
29486
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
29466
29487
  "div",
29467
29488
  {
29468
- className: `relative bg-gradient-to-r from-card/95 via-card to-card/95 backdrop-blur-md border-t border-border/30 transition-all duration-500 ease-out ${isHistoryCollapsed ? "shadow-lg shadow-black/5" : "shadow-2xl shadow-black/10"}`,
29469
- style: {
29470
- height: `${isHistoryCollapsed ? 60 : historyPaneHeight}px`
29471
- },
29489
+ className: `relative bg-card backdrop-blur-md border-t border-border/30 transition-shadow duration-300 ${isCollapsed ? "shadow-md" : "shadow-xl"}`,
29490
+ style: { height: isCollapsed ? 40 : height },
29472
29491
  children: [
29473
29492
  /* @__PURE__ */ jsxRuntimeExports.jsx(
29474
29493
  "div",
29475
29494
  {
29476
- className: `absolute w-full h-3 -top-1.5 cursor-row-resize group flex items-center justify-center ${isDragging ? "bg-primary/20" : "hover:bg-border/20"} transition-all duration-200`,
29495
+ className: `absolute w-full h-3 -top-1.5 cursor-row-resize flex items-center justify-center ${isDragging ? "bg-primary/20" : "hover:bg-border/20"} transition-all duration-200`,
29477
29496
  onMouseDown: handleDragStart,
29478
29497
  onDoubleClick: handleDoubleClick,
29479
- title: "Drag to resize • Double-click to reset • Alt+↑/↓ to adjust • Alt+R to reset",
29498
+ title: "Drag to resize • Doubleclick to reset • Alt+↑↓ to adjust • Alt+R to reset",
29480
29499
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
29481
- "div",
29500
+ GripHorizontal,
29482
29501
  {
29483
- className: `flex items-center space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200 ${isDragging ? "opacity-100" : ""}`,
29484
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(GripHorizontal, { className: "w-4 h-4 text-muted-foreground" })
29502
+ className: `w-4 h-4 text-muted-foreground transition-opacity duration-200 ${isDragging ? "opacity-100" : "opacity-0 group-hover:opacity-100"}`
29485
29503
  }
29486
29504
  )
29487
29505
  }
29488
29506
  ),
29489
- /* @__PURE__ */ jsxRuntimeExports.jsx(
29490
- "div",
29491
- {
29492
- className: `absolute w-full h-0.5 -top-0.5 transition-all duration-200 ${isDragging ? "bg-primary" : "bg-border/50"}`
29493
- }
29494
- ),
29495
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-hidden", children: !isHistoryCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(
29496
- TabbedHistoryPanel,
29497
- {
29498
- requestHistory,
29499
- toolResult,
29500
- clientLogs,
29501
- onClearHistory,
29502
- onClearLogs,
29503
- onToggleCollapse: toggleCollapse
29504
- }
29505
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
29506
- "div",
29507
- {
29508
- className: "h-full flex items-center justify-center bg-gradient-to-r from-muted/20 via-muted/30 to-muted/20 cursor-pointer hover:bg-gradient-to-r hover:from-muted/30 hover:via-muted/40 hover:to-muted/30 transition-all duration-200",
29509
- onClick: toggleCollapse,
29510
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-4 text-muted-foreground", children: [
29511
- /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "w-5 h-5" }),
29512
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: "History & Results" }),
29513
- requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 py-1 text-xs bg-primary/10 text-primary rounded-full", children: requestHistory.length }),
29514
- clientLogs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 py-1 text-xs bg-blue-500/10 text-blue-500 rounded-full", children: clientLogs.length }),
29515
- /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 rotate-180" })
29516
- ] })
29517
- }
29518
- ) })
29507
+ isCollapsed ? (
29508
+ // Collapsed: tab bar
29509
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex items-center", children: [
29510
+ TAB_CONFIG.map(({ key, label }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
29511
+ "button",
29512
+ {
29513
+ onClick: () => {
29514
+ setActiveTab(key);
29515
+ setIsCollapsed(false);
29516
+ },
29517
+ className: `flex items-center h-full px-4 text-sm font-medium transition-colors duration-200 ${activeTab === key ? "border-b-2 border-primary text-foreground" : "text-muted-foreground hover:text-foreground"}`,
29518
+ children: [
29519
+ label,
29520
+ counts[key] > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1 px-1 rounded bg-muted/30 text-xs", children: counts[key] })
29521
+ ]
29522
+ },
29523
+ key
29524
+ )),
29525
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-auto pr-3 cursor-pointer", onClick: toggleCollapse, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
29526
+ ChevronDown,
29527
+ {
29528
+ className: `w-5 h-5 transform transition-transform duration-200 ${isCollapsed ? "rotate-180" : "rotate-0"}`
29529
+ }
29530
+ ) })
29531
+ ] })
29532
+ ) : (
29533
+ // Expanded: full panel
29534
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
29535
+ TabbedHistoryPanel,
29536
+ {
29537
+ requestHistory,
29538
+ toolResult,
29539
+ clientLogs,
29540
+ onClearHistory,
29541
+ onClearLogs,
29542
+ onToggleCollapse: toggleCollapse,
29543
+ activeTab,
29544
+ setActiveTab
29545
+ }
29546
+ )
29547
+ )
29519
29548
  ]
29520
29549
  }
29521
29550
  );
@@ -33971,8 +34000,8 @@ const SelectSeparator = reactExports.forwardRef(({ className, ...props }, ref2)
33971
34000
  SelectSeparator.displayName = Separator$1.displayName;
33972
34001
  const useTheme = () => {
33973
34002
  const [theme, setTheme] = reactExports.useState(() => {
33974
- const savedTheme = localStorage.getItem("theme");
33975
- return savedTheme || "system";
34003
+ const savedTheme2 = localStorage.getItem("theme");
34004
+ return savedTheme2 || "system";
33976
34005
  });
33977
34006
  reactExports.useEffect(() => {
33978
34007
  const darkModeMediaQuery = window.matchMedia(
@@ -33999,7 +34028,10 @@ const useTheme = () => {
33999
34028
  const setThemeWithSideEffect = reactExports.useCallback((newTheme) => {
34000
34029
  setTheme(newTheme);
34001
34030
  localStorage.setItem("theme", newTheme);
34002
- if (newTheme !== "system") {
34031
+ if (newTheme === "system") {
34032
+ const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
34033
+ document.documentElement.classList.toggle("dark", isDark);
34034
+ } else {
34003
34035
  document.documentElement.classList.toggle("dark", newTheme === "dark");
34004
34036
  }
34005
34037
  }, []);
@@ -34008,7 +34040,7 @@ const useTheme = () => {
34008
34040
  [theme, setThemeWithSideEffect]
34009
34041
  );
34010
34042
  };
34011
- const version$1 = "0.3.4";
34043
+ const version$1 = "0.3.5";
34012
34044
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
34013
34045
  createPopperScope
34014
34046
  ]);
@@ -36590,10 +36622,11 @@ const ClientFormSection = ({
36590
36622
  const [sseUrlString, setSseUrlString] = reactExports.useState("");
36591
36623
  const [multipleClients, setMultipleClients] = reactExports.useState([]);
36592
36624
  const [isMultipleMode, setIsMultipleMode] = reactExports.useState(false);
36593
- const [isManualConfigExpanded, setIsManualConfigExpanded] = reactExports.useState(false);
36625
+ const [isManualConfigExpanded, setIsManualConfigExpanded] = reactExports.useState(true);
36594
36626
  const { toast: toast2 } = useToast();
36595
36627
  const [showImportDialog, setShowImportDialog] = reactExports.useState(false);
36596
36628
  const [nameError, setNameError] = reactExports.useState("");
36629
+ const [isNameTouched, setIsNameTouched] = reactExports.useState(false);
36597
36630
  reactExports.useEffect(() => {
36598
36631
  var _a2, _b;
36599
36632
  if (clientFormConfig.transportType === "stdio" && "args" in clientFormConfig) {
@@ -36605,12 +36638,13 @@ const ClientFormSection = ({
36605
36638
  }
36606
36639
  }, [clientFormConfig]);
36607
36640
  reactExports.useEffect(() => {
36641
+ if (!isNameTouched) return;
36608
36642
  if (clientFormName.trim()) {
36609
36643
  setNameError("");
36610
36644
  } else {
36611
36645
  setNameError("Client name is required");
36612
36646
  }
36613
- }, [clientFormName]);
36647
+ }, [clientFormName, isNameTouched]);
36614
36648
  const handleArgsChange = (newArgsString) => {
36615
36649
  setArgsString(newArgsString);
36616
36650
  if (clientFormConfig.transportType === "stdio") {
@@ -37035,13 +37069,14 @@ const ClientFormSection = ({
37035
37069
  ),
37036
37070
  isManualConfigExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
37037
37071
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37038
- /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "client-name", className: "text-sm font-medium", children: "Name" }),
37072
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "client-name", className: "text-sm font-medium", children: "Name*" }),
37039
37073
  /* @__PURE__ */ jsxRuntimeExports.jsx(
37040
37074
  Input,
37041
37075
  {
37042
37076
  id: "client-name",
37043
37077
  value: clientFormName,
37044
37078
  onChange: (e) => setClientFormName(e.target.value),
37079
+ onBlur: () => setIsNameTouched(true),
37045
37080
  placeholder: "Enter client name",
37046
37081
  className: `max-w-md ${nameError ? "border-red-500 focus:border-red-500 focus:ring-red-500" : ""}`
37047
37082
  }
@@ -39253,7 +39288,7 @@ const ListPane = ({
39253
39288
  " items"
39254
39289
  ] })
39255
39290
  ] }),
39256
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 overflow-y-auto max-h-96", children: filteredItems.length > 0 ? filteredItems.map((item, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
39291
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4 overflow-y-auto max-h-[calc(100vh-300px)]", children: filteredItems.length > 0 ? filteredItems.map((item, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
39257
39292
  "div",
39258
39293
  {
39259
39294
  className: "cursor-pointer",
@@ -43297,48 +43332,54 @@ const ToolsTab = ({
43297
43332
  ] }),
43298
43333
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-1", children: [
43299
43334
  request.isFavorite && /* @__PURE__ */ jsxRuntimeExports.jsx(Star, { className: "w-3 h-3 text-yellow-500 fill-current" }),
43300
- /* @__PURE__ */ jsxRuntimeExports.jsx(
43301
- Button,
43302
- {
43303
- onClick: (e) => {
43304
- e.stopPropagation();
43305
- handleRenameRequest(request.id, request.name);
43306
- },
43307
- size: "sm",
43308
- variant: "ghost",
43309
- className: "h-6 w-6 p-0 hover:bg-primary/20 hover:text-primary opacity-0 group-hover:opacity-100 transition-opacity",
43310
- title: "Rename request",
43311
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Pen, { className: "w-3 h-3" })
43312
- }
43313
- ),
43314
- /* @__PURE__ */ jsxRuntimeExports.jsx(
43315
- Button,
43316
- {
43317
- onClick: (e) => {
43318
- e.stopPropagation();
43319
- handleDuplicateRequest(request);
43320
- },
43321
- size: "sm",
43322
- variant: "ghost",
43323
- className: "h-6 w-6 p-0 hover:bg-blue-500/20 hover:text-blue-500 opacity-0 group-hover:opacity-100 transition-opacity",
43324
- title: "Duplicate request",
43325
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPlus, { className: "w-3 h-3" })
43326
- }
43327
- ),
43328
- /* @__PURE__ */ jsxRuntimeExports.jsx(
43329
- Button,
43330
- {
43331
- onClick: (e) => {
43332
- e.stopPropagation();
43333
- handleDeleteRequest(request.id);
43334
- },
43335
- size: "sm",
43336
- variant: "ghost",
43337
- className: "h-6 w-6 p-0 hover:bg-destructive/20 hover:text-destructive opacity-0 group-hover:opacity-100 transition-opacity",
43338
- title: "Delete request",
43339
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-3 h-3" })
43340
- }
43341
- )
43335
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
43336
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
43337
+ Button,
43338
+ {
43339
+ onClick: (e) => {
43340
+ e.stopPropagation();
43341
+ handleRenameRequest(request.id, request.name);
43342
+ },
43343
+ size: "sm",
43344
+ variant: "ghost",
43345
+ className: "h-6 w-6 p-0 hover:bg-primary/20 hover:text-primary opacity-0 group-hover:opacity-100 transition-opacity",
43346
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Pen, { className: "w-3 h-3" })
43347
+ }
43348
+ ) }),
43349
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", children: "Rename" })
43350
+ ] }),
43351
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
43352
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
43353
+ Button,
43354
+ {
43355
+ onClick: (e) => {
43356
+ e.stopPropagation();
43357
+ handleDuplicateRequest(request);
43358
+ },
43359
+ size: "sm",
43360
+ variant: "ghost",
43361
+ className: "h-6 w-6 p-0 hover:bg-blue-500/20 hover:text-blue-500 opacity-0 group-hover:opacity-100 transition-opacity",
43362
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPlus, { className: "w-3 h-3" })
43363
+ }
43364
+ ) }),
43365
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", children: "Duplicate" })
43366
+ ] }),
43367
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
43368
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
43369
+ Button,
43370
+ {
43371
+ onClick: (e) => {
43372
+ e.stopPropagation();
43373
+ handleDeleteRequest(request.id);
43374
+ },
43375
+ size: "sm",
43376
+ variant: "ghost",
43377
+ className: "h-6 w-6 p-0 hover:bg-destructive/20 hover:text-destructive opacity-0 group-hover:opacity-100 transition-opacity",
43378
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-3 h-3" })
43379
+ }
43380
+ ) }),
43381
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", children: "Delete" })
43382
+ ] })
43342
43383
  ] })
43343
43384
  ] }),
43344
43385
  request.description && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground/80 mb-1.5 line-clamp-2", children: request.description }),
@@ -43372,7 +43413,7 @@ const ToolsTab = ({
43372
43413
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-white dark:bg-gray-900 rounded-lg p-3 shadow-sm border border-gray-100 dark:border-gray-800 hover:shadow-md hover:border-blue-200 dark:hover:border-blue-800 transition-all duration-200 group", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col space-y-2.5", children: [
43373
43414
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
43374
43415
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [
43375
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-lg", children: "🛠️" }),
43416
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Hammer, { className: "w-5 h-5 text-muted-foreground" }) }),
43376
43417
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 px-2.5 py-1 rounded-md border border-slate-300 dark:border-slate-600 text-slate-800 dark:text-slate-200 font-medium shadow-sm", children: tool.name })
43377
43418
  ] }),
43378
43419
  parameters.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-400 dark:text-gray-600 font-medium", children: [
@@ -43810,13 +43851,13 @@ const ToolCallApproval = ({
43810
43851
  onApprove,
43811
43852
  onReject
43812
43853
  }) => {
43813
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-4 p-4 border border-amber-200 dark:border-amber-800 rounded-xl bg-amber-50 dark:bg-amber-900/30 mb-2", children: [
43854
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-4 p-4 border border-slate-200 dark:border-slate-700 rounded-xl bg-slate-50 dark:bg-slate-800 mb-2", children: [
43814
43855
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
43815
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-medium text-amber-800 dark:text-amber-200 mb-1", children: [
43856
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-medium text-slate-800 dark:text-slate-200 mb-1", children: [
43816
43857
  "Approve tool call: ",
43817
43858
  toolCall.name
43818
43859
  ] }),
43819
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-amber-700 dark:text-amber-300 bg-amber-100 dark:bg-amber-900/50 p-2 rounded font-mono overflow-auto max-h-28", children: JSON.stringify(toolCall.input, null, 2) })
43860
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-slate-700 dark:text-slate-300 bg-slate-100 dark:bg-slate-700 p-2 rounded font-mono overflow-auto max-h-28", children: JSON.stringify(toolCall.input, null, 2) })
43820
43861
  ] }),
43821
43862
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col justify-center gap-2", children: [
43822
43863
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -43919,7 +43960,7 @@ const ToolSelector = ({
43919
43960
  ),
43920
43961
  disabled: loading,
43921
43962
  children: [
43922
- /* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "w-3 h-3 text-slate-400" }),
43963
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "w-3 h-3 text-slate-400" }),
43923
43964
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-slate-700 dark:text-slate-200 font-medium", children: "Tools" }),
43924
43965
  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: [
43925
43966
  enabledToolCount,
@@ -44481,18 +44522,15 @@ const Chat2 = ({
44481
44522
  },
44482
44523
  idx
44483
44524
  )),
44484
- hasPendingToolCalls && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-6 mb-2", children: [
44485
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 text-sm text-amber-600 dark:text-amber-400 font-medium", children: "Pending Tool Calls:" }),
44486
- Array.from(pendingToolCalls.values()).map((toolCall) => /* @__PURE__ */ jsxRuntimeExports.jsx(
44487
- ToolCallApproval,
44488
- {
44489
- toolCall,
44490
- onApprove: handleApproveToolCall,
44491
- onReject: handleRejectToolCall
44492
- },
44493
- toolCall.id
44494
- ))
44495
- ] }),
44525
+ hasPendingToolCalls && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-6 mb-2", children: Array.from(pendingToolCalls.values()).map((toolCall) => /* @__PURE__ */ jsxRuntimeExports.jsx(
44526
+ ToolCallApproval,
44527
+ {
44528
+ toolCall,
44529
+ onApprove: handleApproveToolCall,
44530
+ onReject: handleRejectToolCall
44531
+ },
44532
+ toolCall.id
44533
+ )) }),
44496
44534
  loading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-3 px-6 py-4", children: [
44497
44535
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-slate-100 dark:bg-slate-800 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
44498
44536
  ProviderLogo,
@@ -51609,7 +51647,7 @@ class Client extends Protocol {
51609
51647
  return this.notification({ method: "notifications/roots/list_changed" });
51610
51648
  }
51611
51649
  }
51612
- const version = "0.3.4";
51650
+ const version = "0.3.5";
51613
51651
  const packageJson = {
51614
51652
  version
51615
51653
  };
@@ -62225,7 +62263,7 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
62225
62263
  });
62226
62264
  };
62227
62265
  const renderOAuthCallback = (onOAuthConnect) => {
62228
- const OAuthCallback = React.lazy(() => __vitePreload(() => import("./OAuthCallback-59IQqASq.js"), true ? [] : void 0));
62266
+ const OAuthCallback = React.lazy(() => __vitePreload(() => import("./OAuthCallback-CaYMoLGO.js"), true ? [] : void 0));
62229
62267
  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(
62230
62268
  reactExports.Suspense,
62231
62269
  {
@@ -62239,7 +62277,7 @@ const renderOAuthCallback = (onOAuthConnect) => {
62239
62277
  };
62240
62278
  const renderOAuthDebugCallback = (onOAuthDebugConnect) => {
62241
62279
  const OAuthDebugCallback = React.lazy(
62242
- () => __vitePreload(() => import("./OAuthDebugCallback-Bm010sVQ.js"), true ? [] : void 0)
62280
+ () => __vitePreload(() => import("./OAuthDebugCallback-CBFeYzo9.js"), true ? [] : void 0)
62243
62281
  );
62244
62282
  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(
62245
62283
  reactExports.Suspense,
@@ -62724,6 +62762,15 @@ const App = () => {
62724
62762
  /* @__PURE__ */ jsxRuntimeExports.jsx(StarGitHubModal, { isOpen: showStarModal, onClose: handleCloseStarModal })
62725
62763
  ] });
62726
62764
  };
62765
+ const savedTheme = localStorage.getItem("theme");
62766
+ if (savedTheme === "dark") {
62767
+ document.documentElement.classList.add("dark");
62768
+ } else if (savedTheme === "light") {
62769
+ document.documentElement.classList.remove("dark");
62770
+ } else {
62771
+ const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
62772
+ document.documentElement.classList.toggle("dark", isDark);
62773
+ }
62727
62774
  clientExports.createRoot(document.getElementById("root")).render(
62728
62775
  /* @__PURE__ */ jsxRuntimeExports.jsxs(reactExports.StrictMode, { children: [
62729
62776
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) }),
@@ -3,7 +3,6 @@
3
3
 
4
4
  /* Custom animations and modern styling for the MCP Inspector */
5
5
  #root {
6
- margin: 0 auto;
7
6
  font-family:
8
7
  "Inter",
9
8
  -apple-system,
@@ -1052,9 +1051,6 @@ video {
1052
1051
  .-right-4 {
1053
1052
  right: -1rem;
1054
1053
  }
1055
- .-top-0\.5 {
1056
- top: -0.125rem;
1057
- }
1058
1054
  .-top-1\.5 {
1059
1055
  top: -0.375rem;
1060
1056
  }
@@ -1238,9 +1234,6 @@ video {
1238
1234
  width: 1rem;
1239
1235
  height: 1rem;
1240
1236
  }
1241
- .h-0\.5 {
1242
- height: 0.125rem;
1243
- }
1244
1237
  .h-1 {
1245
1238
  height: 0.25rem;
1246
1239
  }
@@ -1322,6 +1315,9 @@ video {
1322
1315
  .max-h-\[90vh\] {
1323
1316
  max-height: 90vh;
1324
1317
  }
1318
+ .max-h-\[calc\(100vh-300px\)\] {
1319
+ max-height: calc(100vh - 300px);
1320
+ }
1325
1321
  .max-h-screen {
1326
1322
  max-height: 100vh;
1327
1323
  }
@@ -1482,6 +1478,10 @@ video {
1482
1478
  --tw-translate-y: -50%;
1483
1479
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1484
1480
  }
1481
+ .rotate-0 {
1482
+ --tw-rotate: 0deg;
1483
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1484
+ }
1485
1485
  .rotate-180 {
1486
1486
  --tw-rotate: 180deg;
1487
1487
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -1619,11 +1619,6 @@ video {
1619
1619
  margin-right: calc(0.75rem * var(--tw-space-x-reverse));
1620
1620
  margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
1621
1621
  }
1622
- .space-x-4 > :not([hidden]) ~ :not([hidden]) {
1623
- --tw-space-x-reverse: 0;
1624
- margin-right: calc(1rem * var(--tw-space-x-reverse));
1625
- margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
1626
- }
1627
1622
  .space-y-1 > :not([hidden]) ~ :not([hidden]) {
1628
1623
  --tw-space-y-reverse: 0;
1629
1624
  margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
@@ -1741,10 +1736,6 @@ video {
1741
1736
  .border-dashed {
1742
1737
  border-style: dashed;
1743
1738
  }
1744
- .border-amber-200 {
1745
- --tw-border-opacity: 1;
1746
- border-color: rgb(253 230 138 / var(--tw-border-opacity, 1));
1747
- }
1748
1739
  .border-amber-300 {
1749
1740
  --tw-border-opacity: 1;
1750
1741
  border-color: rgb(252 211 77 / var(--tw-border-opacity, 1));
@@ -1863,10 +1854,6 @@ video {
1863
1854
  --tw-bg-opacity: 1;
1864
1855
  background-color: rgb(254 243 199 / var(--tw-bg-opacity, 1));
1865
1856
  }
1866
- .bg-amber-50 {
1867
- --tw-bg-opacity: 1;
1868
- background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));
1869
- }
1870
1857
  .bg-background {
1871
1858
  background-color: hsl(var(--background));
1872
1859
  }
@@ -1893,15 +1880,9 @@ video {
1893
1880
  --tw-bg-opacity: 1;
1894
1881
  background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
1895
1882
  }
1896
- .bg-blue-500\/10 {
1897
- background-color: rgb(59 130 246 / 0.1);
1898
- }
1899
1883
  .bg-border {
1900
1884
  background-color: hsl(var(--border));
1901
1885
  }
1902
- .bg-border\/50 {
1903
- background-color: hsl(var(--border) / 0.5);
1904
- }
1905
1886
  .bg-card {
1906
1887
  background-color: hsl(var(--card));
1907
1888
  }
@@ -2062,11 +2043,6 @@ video {
2062
2043
  --tw-gradient-to: rgb(55 65 81 / 0) var(--tw-gradient-to-position);
2063
2044
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
2064
2045
  }
2065
- .from-muted\/20 {
2066
- --tw-gradient-from: hsl(var(--muted) / 0.2) var(--tw-gradient-from-position);
2067
- --tw-gradient-to: hsl(var(--muted) / 0) var(--tw-gradient-to-position);
2068
- --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
2069
- }
2070
2046
  .from-muted\/30 {
2071
2047
  --tw-gradient-from: hsl(var(--muted) / 0.3) var(--tw-gradient-from-position);
2072
2048
  --tw-gradient-to: hsl(var(--muted) / 0) var(--tw-gradient-to-position);
@@ -2292,6 +2268,9 @@ video {
2292
2268
  .pr-10 {
2293
2269
  padding-right: 2.5rem;
2294
2270
  }
2271
+ .pr-3 {
2272
+ padding-right: 0.75rem;
2273
+ }
2295
2274
  .pr-6 {
2296
2275
  padding-right: 1.5rem;
2297
2276
  }
@@ -2384,14 +2363,6 @@ video {
2384
2363
  --tw-text-opacity: 1;
2385
2364
  color: rgb(217 119 6 / var(--tw-text-opacity, 1));
2386
2365
  }
2387
- .text-amber-700 {
2388
- --tw-text-opacity: 1;
2389
- color: rgb(180 83 9 / var(--tw-text-opacity, 1));
2390
- }
2391
- .text-amber-800 {
2392
- --tw-text-opacity: 1;
2393
- color: rgb(146 64 14 / var(--tw-text-opacity, 1));
2394
- }
2395
2366
  .text-blue-500 {
2396
2367
  --tw-text-opacity: 1;
2397
2368
  color: rgb(59 130 246 / var(--tw-text-opacity, 1));
@@ -2622,14 +2593,6 @@ video {
2622
2593
  --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
2623
2594
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
2624
2595
  }
2625
- .shadow-black\/10 {
2626
- --tw-shadow-color: rgb(0 0 0 / 0.1);
2627
- --tw-shadow: var(--tw-shadow-colored);
2628
- }
2629
- .shadow-black\/5 {
2630
- --tw-shadow-color: rgb(0 0 0 / 0.05);
2631
- --tw-shadow: var(--tw-shadow-colored);
2632
- }
2633
2596
  .outline-none {
2634
2597
  outline: 2px solid transparent;
2635
2598
  outline-offset: 2px;
@@ -2684,21 +2647,25 @@ video {
2684
2647
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2685
2648
  transition-duration: 150ms;
2686
2649
  }
2650
+ .transition-shadow {
2651
+ transition-property: box-shadow;
2652
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2653
+ transition-duration: 150ms;
2654
+ }
2655
+ .transition-transform {
2656
+ transition-property: transform;
2657
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2658
+ transition-duration: 150ms;
2659
+ }
2687
2660
  .duration-200 {
2688
2661
  transition-duration: 200ms;
2689
2662
  }
2690
2663
  .duration-300 {
2691
2664
  transition-duration: 300ms;
2692
2665
  }
2693
- .duration-500 {
2694
- transition-duration: 500ms;
2695
- }
2696
2666
  .ease-in-out {
2697
2667
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2698
2668
  }
2699
- .ease-out {
2700
- transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
2701
- }
2702
2669
  @keyframes enter {
2703
2670
 
2704
2671
  from {
@@ -2734,15 +2701,9 @@ video {
2734
2701
  .duration-300 {
2735
2702
  animation-duration: 300ms;
2736
2703
  }
2737
- .duration-500 {
2738
- animation-duration: 500ms;
2739
- }
2740
2704
  .ease-in-out {
2741
2705
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2742
2706
  }
2743
- .ease-out {
2744
- animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
2745
- }
2746
2707
  .running {
2747
2708
  animation-play-state: running;
2748
2709
  }
@@ -3001,41 +2962,22 @@ h1 {
3001
2962
  background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1));
3002
2963
  }
3003
2964
 
3004
- .hover\:bg-gradient-to-r:hover {
3005
- background-image: linear-gradient(to right, var(--tw-gradient-stops));
3006
- }
3007
-
3008
2965
  .hover\:from-blue-700:hover {
3009
2966
  --tw-gradient-from: #1d4ed8 var(--tw-gradient-from-position);
3010
2967
  --tw-gradient-to: rgb(29 78 216 / 0) var(--tw-gradient-to-position);
3011
2968
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
3012
2969
  }
3013
2970
 
3014
- .hover\:from-muted\/30:hover {
3015
- --tw-gradient-from: hsl(var(--muted) / 0.3) var(--tw-gradient-from-position);
3016
- --tw-gradient-to: hsl(var(--muted) / 0) var(--tw-gradient-to-position);
3017
- --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
3018
- }
3019
-
3020
2971
  .hover\:from-secondary\/30:hover {
3021
2972
  --tw-gradient-from: hsl(var(--secondary) / 0.3) var(--tw-gradient-from-position);
3022
2973
  --tw-gradient-to: hsl(var(--secondary) / 0) var(--tw-gradient-to-position);
3023
2974
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
3024
2975
  }
3025
2976
 
3026
- .hover\:via-muted\/40:hover {
3027
- --tw-gradient-to: hsl(var(--muted) / 0) var(--tw-gradient-to-position);
3028
- --tw-gradient-stops: var(--tw-gradient-from), hsl(var(--muted) / 0.4) var(--tw-gradient-via-position), var(--tw-gradient-to);
3029
- }
3030
-
3031
2977
  .hover\:to-blue-800:hover {
3032
2978
  --tw-gradient-to: #1e40af var(--tw-gradient-to-position);
3033
2979
  }
3034
2980
 
3035
- .hover\:to-muted\/30:hover {
3036
- --tw-gradient-to: hsl(var(--muted) / 0.3) var(--tw-gradient-to-position);
3037
- }
3038
-
3039
2981
  .hover\:to-secondary\/20:hover {
3040
2982
  --tw-gradient-to: hsl(var(--secondary) / 0.2) var(--tw-gradient-to-position);
3041
2983
  }
@@ -3487,11 +3429,6 @@ h1 {
3487
3429
  border-color: rgb(217 119 6 / var(--tw-border-opacity, 1));
3488
3430
  }
3489
3431
 
3490
- .dark\:border-amber-800:is(.dark *) {
3491
- --tw-border-opacity: 1;
3492
- border-color: rgb(146 64 14 / var(--tw-border-opacity, 1));
3493
- }
3494
-
3495
3432
  .dark\:border-blue-800:is(.dark *) {
3496
3433
  --tw-border-opacity: 1;
3497
3434
  border-color: rgb(30 64 175 / var(--tw-border-opacity, 1));
@@ -3587,10 +3524,6 @@ h1 {
3587
3524
  border-color: rgb(133 77 14 / 0.5);
3588
3525
  }
3589
3526
 
3590
- .dark\:bg-amber-900\/30:is(.dark *) {
3591
- background-color: rgb(120 53 15 / 0.3);
3592
- }
3593
-
3594
3527
  .dark\:bg-amber-900\/50:is(.dark *) {
3595
3528
  background-color: rgb(120 53 15 / 0.5);
3596
3529
  }
@@ -3751,16 +3684,6 @@ h1 {
3751
3684
  --tw-gradient-to: rgb(30 41 59 / 0.5) var(--tw-gradient-to-position);
3752
3685
  }
3753
3686
 
3754
- .dark\:text-amber-200:is(.dark *) {
3755
- --tw-text-opacity: 1;
3756
- color: rgb(253 230 138 / var(--tw-text-opacity, 1));
3757
- }
3758
-
3759
- .dark\:text-amber-300:is(.dark *) {
3760
- --tw-text-opacity: 1;
3761
- color: rgb(252 211 77 / var(--tw-text-opacity, 1));
3762
- }
3763
-
3764
3687
  .dark\:text-amber-400:is(.dark *) {
3765
3688
  --tw-text-opacity: 1;
3766
3689
  color: rgb(251 191 36 / var(--tw-text-opacity, 1));
@@ -5,10 +5,10 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/mcp_jam.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>MCPJam Inspector</title>
8
- <script type="module" crossorigin src="/assets/index-B_8Xm9gw.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-BT47S2Qb.css">
8
+ <script type="module" crossorigin src="/assets/index-DQYTYcqe.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-DegSReJM.css">
10
10
  </head>
11
11
  <body>
12
- <div id="root"></div>
12
+ <div id="root" class="w-full"></div>
13
13
  </body>
14
14
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpjam/inspector",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "MCPJam inspector",
5
5
  "license": "Apache-2.0",
6
6
  "author": "MCPJam (https://mcpjam.com)",
@@ -51,6 +51,7 @@
51
51
  "ajv": "^8.17.1",
52
52
  "concurrently": "^9.0.1",
53
53
  "dotenv": "^16.5.0",
54
+ "lucide-react": "^0.525.0",
54
55
  "open": "^10.1.0",
55
56
  "openai": "^5.7.0",
56
57
  "shell-quote": "^1.8.2",