@mcpjam/inspector 0.2.3 → 0.2.4

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.
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-CfsBsNUt.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-DuorYCq_.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-DkLMDxkx.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-DaNmVTKt.js"])))=>i.map(i=>d[i]);
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -16608,6 +16608,17 @@ const TriangleAlert = createLucideIcon("TriangleAlert", [
16608
16608
  ["path", { d: "M12 9v4", key: "juzpu7" }],
16609
16609
  ["path", { d: "M12 17h.01", key: "p32p05" }]
16610
16610
  ]);
16611
+ /**
16612
+ * @license lucide-react v0.447.0 - ISC
16613
+ *
16614
+ * This source code is licensed under the ISC license.
16615
+ * See the LICENSE file in the root directory of this source tree.
16616
+ */
16617
+ const Upload = createLucideIcon("Upload", [
16618
+ ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }],
16619
+ ["polyline", { points: "17 8 12 3 7 8", key: "t8dd8p" }],
16620
+ ["line", { x1: "12", x2: "12", y1: "3", y2: "15", key: "widbto" }]
16621
+ ]);
16611
16622
  /**
16612
16623
  * @license lucide-react v0.447.0 - ISC
16613
16624
  *
@@ -17648,6 +17659,7 @@ const AuthDebugger = ({
17648
17659
  authState,
17649
17660
  updateAuthState
17650
17661
  }) => {
17662
+ const [showFullToken, setShowFullToken] = reactExports.useState(false);
17651
17663
  const startOAuthFlow = reactExports.useCallback(() => {
17652
17664
  if (!serverUrl) {
17653
17665
  updateAuthState({
@@ -17772,9 +17784,19 @@ const AuthDebugger = ({
17772
17784
  authState.loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Loading authentication status..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
17773
17785
  authState.oauthTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
17774
17786
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: "Access Token:" }),
17775
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-muted p-2 rounded-md text-xs overflow-x-auto", children: [
17776
- authState.oauthTokens.access_token.substring(0, 25),
17777
- "..."
17787
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
17788
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-muted p-2 rounded-md text-xs overflow-x-auto pr-10", children: showFullToken ? authState.oauthTokens.access_token : "********************************" }),
17789
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
17790
+ Button,
17791
+ {
17792
+ variant: "ghost",
17793
+ size: "sm",
17794
+ className: "absolute right-1 top-1 h-6 w-6 p-0 hover:bg-muted-foreground/10",
17795
+ onClick: () => setShowFullToken(!showFullToken),
17796
+ title: showFullToken ? "Hide token" : "Show full token",
17797
+ children: showFullToken ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "h-3 w-3" })
17798
+ }
17799
+ )
17778
17800
  ] })
17779
17801
  ] }),
17780
17802
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-4", children: [
@@ -17813,6 +17835,61 @@ const AuthDebugger = ({
17813
17835
  ] });
17814
17836
  };
17815
17837
  const ConsoleTab = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg h-full font-mono text-sm overflow-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "opacity-50", children: "Welcome to MCP Client Console" }) });
17838
+ function useDraggablePane(initialHeight) {
17839
+ const [height, setHeight] = reactExports.useState(initialHeight);
17840
+ const [isDragging, setIsDragging] = reactExports.useState(false);
17841
+ const dragStartY = reactExports.useRef(0);
17842
+ const dragStartHeight = reactExports.useRef(0);
17843
+ const handleDragStart = reactExports.useCallback(
17844
+ (e) => {
17845
+ setIsDragging(true);
17846
+ dragStartY.current = e.clientY;
17847
+ dragStartHeight.current = height;
17848
+ document.body.style.userSelect = "none";
17849
+ },
17850
+ [height]
17851
+ );
17852
+ const handleDragMove = reactExports.useCallback(
17853
+ (e) => {
17854
+ if (!isDragging) return;
17855
+ const deltaY = dragStartY.current - e.clientY;
17856
+ const newHeight = Math.max(
17857
+ 100,
17858
+ Math.min(800, dragStartHeight.current + deltaY)
17859
+ );
17860
+ setHeight(newHeight);
17861
+ },
17862
+ [isDragging]
17863
+ );
17864
+ const handleDragEnd = reactExports.useCallback(() => {
17865
+ setIsDragging(false);
17866
+ document.body.style.userSelect = "";
17867
+ }, []);
17868
+ const resetHeight = reactExports.useCallback(() => {
17869
+ setHeight(initialHeight);
17870
+ }, [initialHeight]);
17871
+ reactExports.useEffect(() => {
17872
+ if (!isDragging) {
17873
+ setHeight(initialHeight);
17874
+ }
17875
+ }, [initialHeight, isDragging]);
17876
+ reactExports.useEffect(() => {
17877
+ if (isDragging) {
17878
+ window.addEventListener("mousemove", handleDragMove);
17879
+ window.addEventListener("mouseup", handleDragEnd);
17880
+ return () => {
17881
+ window.removeEventListener("mousemove", handleDragMove);
17882
+ window.removeEventListener("mouseup", handleDragEnd);
17883
+ };
17884
+ }
17885
+ }, [isDragging, handleDragMove, handleDragEnd]);
17886
+ return {
17887
+ height,
17888
+ isDragging,
17889
+ handleDragStart,
17890
+ resetHeight
17891
+ };
17892
+ }
17816
17893
  function getDataType(value) {
17817
17894
  if (Array.isArray(value)) return "array";
17818
17895
  if (value === null) return "null";
@@ -18106,133 +18183,368 @@ const JsonNode = reactExports.memo(
18106
18183
  }
18107
18184
  );
18108
18185
  JsonNode.displayName = "JsonNode";
18109
- function useDraggablePane(initialHeight) {
18110
- const [height, setHeight] = reactExports.useState(initialHeight);
18111
- const [isDragging, setIsDragging] = reactExports.useState(false);
18112
- const dragStartY = reactExports.useRef(0);
18113
- const dragStartHeight = reactExports.useRef(0);
18114
- const handleDragStart = reactExports.useCallback(
18115
- (e) => {
18116
- setIsDragging(true);
18117
- dragStartY.current = e.clientY;
18118
- dragStartHeight.current = height;
18119
- document.body.style.userSelect = "none";
18120
- },
18121
- [height]
18122
- );
18123
- const handleDragMove = reactExports.useCallback(
18124
- (e) => {
18125
- if (!isDragging) return;
18126
- const deltaY = dragStartY.current - e.clientY;
18127
- const newHeight = Math.max(
18128
- 100,
18129
- Math.min(800, dragStartHeight.current + deltaY)
18130
- );
18131
- setHeight(newHeight);
18186
+ const RequestHistoryItem = ({ request, index: index2, totalRequests }) => {
18187
+ const [isExpanded, setIsExpanded] = reactExports.useState(false);
18188
+ const toggleExpansion = () => {
18189
+ setIsExpanded(!isExpanded);
18190
+ };
18191
+ const requestData = JSON.parse(request.request);
18192
+ const requestNumber = totalRequests - index2;
18193
+ const formatTimestamp = (timestamp) => {
18194
+ const date = new Date(timestamp);
18195
+ return date.toLocaleTimeString("en-US", {
18196
+ hour12: true,
18197
+ hour: "2-digit",
18198
+ minute: "2-digit",
18199
+ second: "2-digit"
18200
+ });
18201
+ };
18202
+ const formatLatency = (latency) => {
18203
+ if (latency === void 0) return void 0;
18204
+ return `${latency}ms`;
18205
+ };
18206
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "text-sm bg-gradient-to-r from-secondary/50 via-secondary/70 to-secondary/50 backdrop-blur-sm p-4 rounded-xl border border-border/30 hover:border-border/60 transition-all duration-200 hover:shadow-lg", children: [
18207
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18208
+ RequestHeader,
18209
+ {
18210
+ requestNumber,
18211
+ method: requestData.method,
18212
+ server: requestData.server,
18213
+ timestamp: formatTimestamp(request.timestamp),
18214
+ latency: formatLatency(request.latency),
18215
+ isExpanded,
18216
+ onToggle: toggleExpansion
18217
+ }
18218
+ ),
18219
+ isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx(
18220
+ RequestDetails,
18221
+ {
18222
+ requestData: request.request,
18223
+ responseData: request.response
18224
+ }
18225
+ )
18226
+ ] });
18227
+ };
18228
+ const RequestHeader = ({ requestNumber, method, server, timestamp, latency, isExpanded, onToggle }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
18229
+ "header",
18230
+ {
18231
+ className: "flex justify-between items-center cursor-pointer group",
18232
+ onClick: onToggle,
18233
+ role: "button",
18234
+ tabIndex: 0,
18235
+ onKeyDown: (e) => {
18236
+ if (e.key === "Enter" || e.key === " ") {
18237
+ e.preventDefault();
18238
+ onToggle();
18239
+ }
18132
18240
  },
18133
- [isDragging]
18134
- );
18135
- const handleDragEnd = reactExports.useCallback(() => {
18136
- setIsDragging(false);
18137
- document.body.style.userSelect = "";
18138
- }, []);
18139
- const resetHeight = reactExports.useCallback(() => {
18140
- setHeight(initialHeight);
18141
- }, [initialHeight]);
18142
- reactExports.useEffect(() => {
18143
- if (!isDragging) {
18144
- setHeight(initialHeight);
18241
+ "aria-expanded": isExpanded,
18242
+ "aria-label": `Request ${requestNumber}: ${method}`,
18243
+ children: [
18244
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RequestInfo, { requestNumber, method, server, timestamp, latency }),
18245
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandIcon, { isExpanded })
18246
+ ]
18247
+ }
18248
+ );
18249
+ const RequestInfo = ({ requestNumber, method, server, timestamp, latency }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18250
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RequestBadge, { number: requestNumber }),
18251
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TimeStamp, { timestamp }),
18252
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MethodLabel, { method, server }),
18253
+ latency && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground font-mono", children: latency })
18254
+ ] });
18255
+ const RequestBadge = ({ number }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
18256
+ "span",
18257
+ {
18258
+ className: "flex items-center justify-center w-6 h-6 bg-primary/10 text-primary text-xs font-bold rounded-full",
18259
+ "aria-label": `Request number ${number}`,
18260
+ children: number
18261
+ }
18262
+ );
18263
+ const TimeStamp = ({ timestamp }) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground font-mono", children: timestamp });
18264
+ const MethodLabel = ({ method, server }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono font-semibold text-foreground", children: [
18265
+ method,
18266
+ server && ` (${server})`
18267
+ ] });
18268
+ const ExpandIcon = ({ isExpanded }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
18269
+ "span",
18270
+ {
18271
+ className: "text-muted-foreground group-hover:text-foreground transition-colors duration-200",
18272
+ "aria-hidden": "true",
18273
+ children: isExpanded ? "▼" : "▶"
18274
+ }
18275
+ );
18276
+ const RequestDetails = ({ requestData, responseData }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mt-4 space-y-4", "aria-label": "Request and response details", children: [
18277
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RequestSection, { title: "Request", data: requestData }),
18278
+ responseData && /* @__PURE__ */ jsxRuntimeExports.jsx(RequestSection, { title: "Response", data: responseData })
18279
+ ] });
18280
+ const RequestSection = ({ title: title2, data: data2 }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
18281
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SectionHeader, { title: title2 }),
18282
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18283
+ JsonView,
18284
+ {
18285
+ data: data2,
18286
+ className: "bg-background/80 backdrop-blur-sm border border-border/20 rounded-lg"
18145
18287
  }
18146
- }, [initialHeight, isDragging]);
18288
+ )
18289
+ ] });
18290
+ const SectionHeader = ({ title: title2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "flex items-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground text-sm", children: title2 }) });
18291
+ const ActivityTab = ({
18292
+ requestHistory,
18293
+ onClearHistory,
18294
+ onToggleCollapse,
18295
+ showHeader = true
18296
+ }) => {
18297
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex-1 overflow-y-auto ${showHeader ? "p-6 border-r border-border/20" : ""}`, children: [
18298
+ showHeader && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18299
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18300
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-5 h-5 text-primary" }),
18301
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "All Activity" })
18302
+ ] }),
18303
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18304
+ requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18305
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-muted-foreground bg-muted/50 px-3 py-1 rounded-full", children: [
18306
+ requestHistory.length,
18307
+ " request",
18308
+ requestHistory.length !== 1 ? "s" : ""
18309
+ ] }),
18310
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18311
+ "button",
18312
+ {
18313
+ onClick: onClearHistory,
18314
+ className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
18315
+ title: "Clear all activity",
18316
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-4 h-4 text-muted-foreground group-hover:text-destructive" })
18317
+ }
18318
+ )
18319
+ ] }),
18320
+ onToggleCollapse && /* @__PURE__ */ jsxRuntimeExports.jsx(
18321
+ "button",
18322
+ {
18323
+ onClick: onToggleCollapse,
18324
+ className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18325
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18326
+ }
18327
+ )
18328
+ ] })
18329
+ ] }),
18330
+ requestHistory.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18331
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-12 h-12 text-muted-foreground/40 mb-4" }),
18332
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No activity yet" }),
18333
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "MCP requests and responses will appear here" })
18334
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18335
+ !showHeader && requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18336
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-muted-foreground bg-muted/50 px-3 py-1 rounded-full", children: [
18337
+ requestHistory.length,
18338
+ " request",
18339
+ requestHistory.length !== 1 ? "s" : ""
18340
+ ] }),
18341
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18342
+ "button",
18343
+ {
18344
+ onClick: onClearHistory,
18345
+ className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
18346
+ title: "Clear all activity",
18347
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-4 h-4 text-muted-foreground group-hover:text-destructive" })
18348
+ }
18349
+ )
18350
+ ] }),
18351
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-4", children: requestHistory.slice().reverse().map((request, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
18352
+ RequestHistoryItem,
18353
+ {
18354
+ request,
18355
+ index: index2,
18356
+ totalRequests: requestHistory.length
18357
+ },
18358
+ index2
18359
+ )) })
18360
+ ] })
18361
+ ] });
18362
+ };
18363
+ const ToolResult = ({ toolResult }) => {
18364
+ if (!toolResult) return null;
18365
+ if ("content" in toolResult) {
18366
+ const parsedResult = CallToolResultSchema.safeParse(toolResult);
18367
+ if (!parsedResult.success) {
18368
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18369
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Invalid Tool Result:" }),
18370
+ /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult }),
18371
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Errors:" }),
18372
+ parsedResult.error.errors.map((error, idx) => /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: error }, idx))
18373
+ ] });
18374
+ }
18375
+ const structuredResult = parsedResult.data;
18376
+ const isError = structuredResult.isError ?? false;
18377
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18378
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "font-semibold mb-2", children: [
18379
+ "Tool Result:",
18380
+ " ",
18381
+ isError ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-600 font-semibold", children: "Error" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-green-600 font-semibold", children: "Success" })
18382
+ ] }),
18383
+ structuredResult.content.map((item, index2) => {
18384
+ var _a2, _b;
18385
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
18386
+ item.type === "text" && /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.text, isError }),
18387
+ item.type === "image" && /* @__PURE__ */ jsxRuntimeExports.jsx(
18388
+ "img",
18389
+ {
18390
+ src: `data:${item.mimeType};base64,${item.data}`,
18391
+ alt: "Tool result image",
18392
+ className: "max-w-full h-auto"
18393
+ }
18394
+ ),
18395
+ item.type === "resource" && (((_b = (_a2 = item.resource) == null ? void 0 : _a2.mimeType) == null ? void 0 : _b.startsWith("audio/")) ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18396
+ "audio",
18397
+ {
18398
+ controls: true,
18399
+ src: `data:${item.resource.mimeType};base64,${item.resource.blob}`,
18400
+ className: "w-full",
18401
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
18402
+ }
18403
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource }))
18404
+ ] }, index2);
18405
+ })
18406
+ ] });
18407
+ } else if ("toolResult" in toolResult) {
18408
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18409
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Tool Result (Legacy):" }),
18410
+ /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult.toolResult })
18411
+ ] });
18412
+ }
18413
+ return null;
18414
+ };
18415
+ const ResultsTab = ({ toolResult, onToggleCollapse, showHeader = true }) => {
18416
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex-1 overflow-y-auto ${showHeader ? "p-6" : ""}`, children: [
18417
+ showHeader && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18418
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18419
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollText, { className: "w-5 h-5 text-primary" }),
18420
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Results" })
18421
+ ] }),
18422
+ onToggleCollapse && /* @__PURE__ */ jsxRuntimeExports.jsx(
18423
+ "button",
18424
+ {
18425
+ onClick: onToggleCollapse,
18426
+ className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18427
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18428
+ }
18429
+ )
18430
+ ] }),
18431
+ !toolResult ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18432
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-12 h-12 rounded-full bg-muted/20 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-2xl", children: "🎯" }) }),
18433
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No results yet" }),
18434
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "Tool execution results will appear here" })
18435
+ ] }) : /* @__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 }) })
18436
+ ] });
18437
+ };
18438
+ const TabbedHistoryPanel = ({
18439
+ requestHistory,
18440
+ toolResult,
18441
+ onClearHistory,
18442
+ onToggleCollapse
18443
+ }) => {
18444
+ const [activeTab, setActiveTab] = reactExports.useState("activity");
18445
+ const [isToolResultError, setIsToolResultError] = reactExports.useState(false);
18147
18446
  reactExports.useEffect(() => {
18148
- if (isDragging) {
18149
- window.addEventListener("mousemove", handleDragMove);
18150
- window.addEventListener("mouseup", handleDragEnd);
18151
- return () => {
18152
- window.removeEventListener("mousemove", handleDragMove);
18153
- window.removeEventListener("mouseup", handleDragEnd);
18154
- };
18447
+ if (toolResult) {
18448
+ console.log("toolResult", toolResult);
18449
+ setIsToolResultError(toolResult.isError === true);
18450
+ setActiveTab("results");
18155
18451
  }
18156
- }, [isDragging, handleDragMove, handleDragEnd]);
18157
- return {
18158
- height,
18159
- isDragging,
18160
- handleDragStart,
18161
- resetHeight
18452
+ }, [toolResult]);
18453
+ const renderActivityTabButton = () => {
18454
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
18455
+ "button",
18456
+ {
18457
+ onClick: () => setActiveTab("activity"),
18458
+ className: `flex items-center space-x-2 px-4 py-2 rounded-lg transition-all duration-200 ${activeTab === "activity" ? "bg-primary/10 text-primary border border-primary/20" : "text-muted-foreground hover:text-foreground hover:bg-accent/50"}`,
18459
+ children: [
18460
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-4 h-4" }),
18461
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: "Activity" }),
18462
+ requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 py-1 text-xs bg-primary/10 text-primary rounded-full", children: requestHistory.length })
18463
+ ]
18464
+ },
18465
+ "activity"
18466
+ );
18162
18467
  };
18163
- }
18468
+ const renderResultsTabButton = () => {
18469
+ console.log("isToolResultError", isToolResultError);
18470
+ const renderCircleIndicator = () => {
18471
+ if (toolResult && !isToolResultError) {
18472
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-2 h-2 bg-green-500 rounded-full" });
18473
+ } else if (toolResult && isToolResultError) {
18474
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-2 h-2 bg-red-500 rounded-full" });
18475
+ } else {
18476
+ return null;
18477
+ }
18478
+ };
18479
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
18480
+ "button",
18481
+ {
18482
+ onClick: () => setActiveTab("results"),
18483
+ className: `flex items-center space-x-2 px-4 py-2 rounded-lg transition-all duration-200 ${activeTab === "results" ? "bg-primary/10 text-primary border border-primary/20" : "text-muted-foreground hover:text-foreground hover:bg-accent/50"}`,
18484
+ children: [
18485
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollText, { className: "w-4 h-4" }),
18486
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: "Results" }),
18487
+ renderCircleIndicator()
18488
+ ]
18489
+ },
18490
+ "results"
18491
+ );
18492
+ };
18493
+ const renderTabContent = () => {
18494
+ switch (activeTab) {
18495
+ case "activity":
18496
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
18497
+ ActivityTab,
18498
+ {
18499
+ requestHistory,
18500
+ onClearHistory,
18501
+ showHeader: false
18502
+ }
18503
+ ) });
18504
+ case "results":
18505
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-y-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ResultsTab, { toolResult, showHeader: false }) });
18506
+ default:
18507
+ return null;
18508
+ }
18509
+ };
18510
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-transparent flex flex-col h-full", children: [
18511
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-border/20 px-6 py-3", children: [
18512
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-1", children: [
18513
+ renderActivityTabButton(),
18514
+ renderResultsTabButton()
18515
+ ] }),
18516
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18517
+ "button",
18518
+ {
18519
+ onClick: onToggleCollapse,
18520
+ className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18521
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18522
+ }
18523
+ )
18524
+ ] }),
18525
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: renderTabContent() })
18526
+ ] });
18527
+ };
18164
18528
  const HistoryAndNotifications = ({
18165
18529
  requestHistory,
18166
18530
  toolResult,
18167
18531
  onClearHistory
18168
18532
  }) => {
18169
- const [expandedRequests, setExpandedRequests] = reactExports.useState({});
18170
18533
  const [isHistoryCollapsed, setIsHistoryCollapsed] = reactExports.useState(true);
18171
18534
  const {
18172
18535
  height: historyPaneHeight,
18173
18536
  handleDragStart,
18174
18537
  resetHeight
18175
- } = useDraggablePane(isHistoryCollapsed ? 60 : 500);
18176
- const toggleRequestExpansion = (index2) => {
18177
- setExpandedRequests((prev) => ({ ...prev, [index2]: !prev[index2] }));
18178
- };
18538
+ } = useDraggablePane(500);
18539
+ const toggleCollapse = reactExports.useCallback(() => {
18540
+ setIsHistoryCollapsed(!isHistoryCollapsed);
18541
+ }, [isHistoryCollapsed]);
18179
18542
  reactExports.useEffect(() => {
18180
18543
  if (toolResult) {
18181
18544
  resetHeight();
18182
18545
  setIsHistoryCollapsed(false);
18183
18546
  }
18184
- }, [toolResult]);
18185
- const renderToolResult = () => {
18186
- if (!toolResult) return null;
18187
- if ("content" in toolResult) {
18188
- const parsedResult = CallToolResultSchema.safeParse(toolResult);
18189
- if (!parsedResult.success) {
18190
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18191
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Invalid Tool Result:" }),
18192
- /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult }),
18193
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Errors:" }),
18194
- parsedResult.error.errors.map((error, idx) => /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: error }, idx))
18195
- ] });
18196
- }
18197
- const structuredResult = parsedResult.data;
18198
- const isError = structuredResult.isError ?? false;
18199
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18200
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "font-semibold mb-2", children: [
18201
- "Tool Result:",
18202
- " ",
18203
- isError ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-600 font-semibold", children: "Error" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-green-600 font-semibold", children: "Success" })
18204
- ] }),
18205
- structuredResult.content.map((item, index2) => {
18206
- var _a2, _b;
18207
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
18208
- item.type === "text" && /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.text, isError }),
18209
- item.type === "image" && /* @__PURE__ */ jsxRuntimeExports.jsx(
18210
- "img",
18211
- {
18212
- src: `data:${item.mimeType};base64,${item.data}`,
18213
- alt: "Tool result image",
18214
- className: "max-w-full h-auto"
18215
- }
18216
- ),
18217
- item.type === "resource" && (((_b = (_a2 = item.resource) == null ? void 0 : _a2.mimeType) == null ? void 0 : _b.startsWith("audio/")) ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18218
- "audio",
18219
- {
18220
- controls: true,
18221
- src: `data:${item.resource.mimeType};base64,${item.resource.blob}`,
18222
- className: "w-full",
18223
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
18224
- }
18225
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource }))
18226
- ] }, index2);
18227
- })
18228
- ] });
18229
- } else if ("toolResult" in toolResult) {
18230
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18231
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Tool Result (Legacy):" }),
18232
- /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult.toolResult })
18233
- ] });
18234
- }
18235
- };
18547
+ }, [toolResult, resetHeight]);
18236
18548
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
18237
18549
  "div",
18238
18550
  {
@@ -18248,118 +18560,19 @@ const HistoryAndNotifications = ({
18248
18560
  onMouseDown: handleDragStart
18249
18561
  }
18250
18562
  ),
18251
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-hidden", children: !isHistoryCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-transparent flex h-full", children: [
18252
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-6 border-r border-border/20", children: [
18253
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18254
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18255
- /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-5 h-5 text-primary" }),
18256
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "All Activity" })
18257
- ] }),
18258
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18259
- requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18260
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-muted-foreground bg-muted/50 px-3 py-1 rounded-full", children: [
18261
- requestHistory.length,
18262
- " request",
18263
- requestHistory.length !== 1 ? "s" : ""
18264
- ] }),
18265
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18266
- "button",
18267
- {
18268
- onClick: onClearHistory,
18269
- className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
18270
- title: "Clear all activity",
18271
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-4 h-4 text-muted-foreground group-hover:text-destructive" })
18272
- }
18273
- )
18274
- ] }),
18275
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18276
- "button",
18277
- {
18278
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18279
- className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18280
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18281
- }
18282
- )
18283
- ] })
18284
- ] }),
18285
- requestHistory.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18286
- /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-12 h-12 text-muted-foreground/40 mb-4" }),
18287
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No activity yet" }),
18288
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "MCP requests and responses will appear here" })
18289
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-4", children: requestHistory.slice().reverse().map((request, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
18290
- "li",
18291
- {
18292
- className: "text-sm bg-gradient-to-r from-secondary/50 via-secondary/70 to-secondary/50 backdrop-blur-sm p-4 rounded-xl border border-border/30 hover:border-border/60 transition-all duration-200 hover:shadow-lg",
18293
- children: [
18294
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
18295
- "div",
18296
- {
18297
- className: "flex justify-between items-center cursor-pointer group",
18298
- onClick: () => toggleRequestExpansion(
18299
- requestHistory.length - 1 - index2
18300
- ),
18301
- children: [
18302
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18303
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center justify-center w-6 h-6 bg-primary/10 text-primary text-xs font-bold rounded-full", children: requestHistory.length - index2 }),
18304
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-foreground", children: JSON.parse(request.request).method })
18305
- ] }),
18306
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors duration-200", children: expandedRequests[requestHistory.length - 1 - index2] ? "▼" : "▶" })
18307
- ]
18308
- }
18309
- ),
18310
- expandedRequests[requestHistory.length - 1 - index2] && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 space-y-4", children: [
18311
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
18312
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground text-sm", children: "Request" }) }),
18313
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18314
- JsonView,
18315
- {
18316
- data: request.request,
18317
- className: "bg-background/80 backdrop-blur-sm border border-border/20 rounded-lg"
18318
- }
18319
- )
18320
- ] }),
18321
- request.response && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
18322
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground text-sm", children: "Response" }) }),
18323
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18324
- JsonView,
18325
- {
18326
- data: request.response,
18327
- className: "bg-background/80 backdrop-blur-sm border border-border/20 rounded-lg"
18328
- }
18329
- )
18330
- ] })
18331
- ] })
18332
- ]
18333
- },
18334
- index2
18335
- )) })
18336
- ] }),
18337
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-6", children: [
18338
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18339
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18340
- /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollText, { className: "w-5 h-5 text-primary" }),
18341
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Results" })
18342
- ] }),
18343
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18344
- "button",
18345
- {
18346
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18347
- className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18348
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18349
- }
18350
- )
18351
- ] }),
18352
- !toolResult ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18353
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-12 h-12 rounded-full bg-muted/20 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-2xl", children: "🎯" }) }),
18354
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No results yet" }),
18355
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "Tool execution results will appear here" })
18356
- ] }) : /* @__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: renderToolResult() })
18357
- ] })
18358
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
18563
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-hidden", children: !isHistoryCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18564
+ TabbedHistoryPanel,
18565
+ {
18566
+ requestHistory,
18567
+ toolResult,
18568
+ onClearHistory,
18569
+ onToggleCollapse: toggleCollapse
18570
+ }
18571
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
18359
18572
  "div",
18360
18573
  {
18361
18574
  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",
18362
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18575
+ onClick: toggleCollapse,
18363
18576
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-4 text-muted-foreground", children: [
18364
18577
  /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "w-5 h-5" }),
18365
18578
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: "History & Results" }),
@@ -19449,7 +19662,7 @@ var hideOthers = function(originalTarget, parentNode, markerName) {
19449
19662
  var DIALOG_NAME = "Dialog";
19450
19663
  var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
19451
19664
  var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
19452
- var Dialog = (props) => {
19665
+ var Dialog$1 = (props) => {
19453
19666
  const {
19454
19667
  __scopeDialog,
19455
19668
  children,
@@ -19483,7 +19696,7 @@ var Dialog = (props) => {
19483
19696
  }
19484
19697
  );
19485
19698
  };
19486
- Dialog.displayName = DIALOG_NAME;
19699
+ Dialog$1.displayName = DIALOG_NAME;
19487
19700
  var TRIGGER_NAME$4 = "DialogTrigger";
19488
19701
  var DialogTrigger = reactExports.forwardRef(
19489
19702
  (props, forwardedRef) => {
@@ -19744,7 +19957,7 @@ var DescriptionWarning = ({ contentRef, descriptionId }) => {
19744
19957
  }, [MESSAGE, contentRef, descriptionId]);
19745
19958
  return null;
19746
19959
  };
19747
- var Root$2 = Dialog;
19960
+ var Root$2 = Dialog$1;
19748
19961
  var Portal$2 = DialogPortal$1;
19749
19962
  var Overlay = DialogOverlay$1;
19750
19963
  var Content$1 = DialogContent$1;
@@ -20043,6 +20256,7 @@ function B({ asChild: r2, children: o }, n) {
20043
20256
  return r2 && reactExports.isValidElement(o) ? reactExports.cloneElement(Me(o), { ref: o.ref }, n(o.props.children)) : n(o);
20044
20257
  }
20045
20258
  var Te = { position: "absolute", width: "1px", height: "1px", padding: "0", margin: "-1px", overflow: "hidden", clip: "rect(0, 0, 0, 0)", whiteSpace: "nowrap", borderWidth: "0" };
20259
+ const Dialog = Root$2;
20046
20260
  const DialogPortal = Portal$2;
20047
20261
  const DialogOverlay = reactExports.forwardRef(({ className, ...props }, ref2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
20048
20262
  Overlay,
@@ -20078,6 +20292,20 @@ const DialogContent = reactExports.forwardRef(({ className, children, ...props }
20078
20292
  )
20079
20293
  ] }));
20080
20294
  DialogContent.displayName = Content$1.displayName;
20295
+ const DialogHeader = ({
20296
+ className,
20297
+ ...props
20298
+ }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
20299
+ "div",
20300
+ {
20301
+ className: cn(
20302
+ "flex flex-col space-y-1.5 text-center sm:text-left",
20303
+ className
20304
+ ),
20305
+ ...props
20306
+ }
20307
+ );
20308
+ DialogHeader.displayName = "DialogHeader";
20081
20309
  const DialogTitle = reactExports.forwardRef(({ className, ...props }, ref2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
20082
20310
  Title,
20083
20311
  {
@@ -26540,7 +26768,7 @@ const ToolRunCard = ({
26540
26768
  const isUpdatingExistingRequest = currentRequestId !== null;
26541
26769
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-gradient-to-br from-card/95 via-card to-card/95 backdrop-blur-sm rounded-xl shadow-lg border border-border/40 overflow-hidden transition-all duration-300 hover:shadow-xl hover:border-border/60", children: [
26542
26770
  /* @__PURE__ */ jsxRuntimeExports.jsx(ToolHeader, { tool: selectedTool }),
26543
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3", children: selectedTool ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
26771
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-y-auto max-h-96", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3", children: selectedTool ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
26544
26772
  /* @__PURE__ */ jsxRuntimeExports.jsx(
26545
26773
  ParametersSection,
26546
26774
  {
@@ -26549,15 +26777,6 @@ const ToolRunCard = ({
26549
26777
  onParamChange: handleParamChange
26550
26778
  }
26551
26779
  ),
26552
- /* @__PURE__ */ jsxRuntimeExports.jsx(
26553
- ActionButtons,
26554
- {
26555
- onSave: handleOpenSaveDialog,
26556
- onRun: handleRunTool,
26557
- isRunning: isToolRunning,
26558
- isUpdating: isUpdatingExistingRequest
26559
- }
26560
- ),
26561
26780
  /* @__PURE__ */ jsxRuntimeExports.jsx(
26562
26781
  SaveDialog,
26563
26782
  {
@@ -26572,7 +26791,16 @@ const ToolRunCard = ({
26572
26791
  onDescriptionChange: setSaveRequestDescription
26573
26792
  }
26574
26793
  )
26575
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, {}) })
26794
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, {}) }) }),
26795
+ selectedTool && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 border-t border-border/20 bg-gradient-to-r from-card/80 to-card/60", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
26796
+ ActionButtons,
26797
+ {
26798
+ onSave: handleOpenSaveDialog,
26799
+ onRun: handleRunTool,
26800
+ isRunning: isToolRunning,
26801
+ isUpdating: isUpdatingExistingRequest
26802
+ }
26803
+ ) })
26576
26804
  ] });
26577
26805
  };
26578
26806
  const ToolsTab = ({
@@ -28625,7 +28853,7 @@ const useTheme = () => {
28625
28853
  [theme, setThemeWithSideEffect]
28626
28854
  );
28627
28855
  };
28628
- const version$1 = "0.2.3";
28856
+ const version$1 = "0.2.4";
28629
28857
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
28630
28858
  createPopperScope
28631
28859
  ]);
@@ -29656,6 +29884,475 @@ const SettingsTab = ({
29656
29884
  ] })
29657
29885
  ] }) });
29658
29886
  };
29887
+ function isValidJSON(jsonString) {
29888
+ try {
29889
+ JSON.parse(jsonString);
29890
+ return true;
29891
+ } catch {
29892
+ return false;
29893
+ }
29894
+ }
29895
+ function isValidMCPConfig(config) {
29896
+ return typeof config === "object" && config !== null && "mcpServers" in config && typeof config.mcpServers === "object" && config.mcpServers !== null;
29897
+ }
29898
+ function isValidServerConfig(config) {
29899
+ if (typeof config !== "object" || config === null) {
29900
+ return false;
29901
+ }
29902
+ const configObj = config;
29903
+ const hasCommand = "command" in configObj && typeof configObj.command === "string";
29904
+ const hasUrl = "url" in configObj && typeof configObj.url === "string";
29905
+ return hasCommand || hasUrl;
29906
+ }
29907
+ function isSingleNamedServerConfig(config) {
29908
+ if (typeof config !== "object" || config === null) {
29909
+ return false;
29910
+ }
29911
+ const configObj = config;
29912
+ const keys = Object.keys(configObj);
29913
+ if (keys.length !== 1) {
29914
+ return false;
29915
+ }
29916
+ const serverConfig = configObj[keys[0]];
29917
+ return isValidServerConfig(serverConfig);
29918
+ }
29919
+ function validateMCPConfigStructure(config) {
29920
+ const errors = [];
29921
+ if (typeof config !== "object" || config === null) {
29922
+ errors.push("Configuration must be a JSON object");
29923
+ return { isGlobal: false, isSingleNamed: false, errors };
29924
+ }
29925
+ if (isValidMCPConfig(config)) {
29926
+ const mcpServers = config.mcpServers;
29927
+ const serverNames = Object.keys(mcpServers);
29928
+ if (serverNames.length === 0) {
29929
+ errors.push('"mcpServers" object is empty. Please add at least one server configuration');
29930
+ }
29931
+ return { isGlobal: true, isSingleNamed: false, errors };
29932
+ }
29933
+ if (isSingleNamedServerConfig(config)) {
29934
+ return { isGlobal: false, isSingleNamed: true, errors };
29935
+ }
29936
+ errors.push(
29937
+ 'Invalid configuration format. Please provide either:\n• A global config: {"mcpServers": {"server-name": {...}}}\n• A named server config: {"server-name": {"command": "npx", "args": [...]}}'
29938
+ );
29939
+ return { isGlobal: false, isSingleNamed: false, errors };
29940
+ }
29941
+ function convertToMCPJamServerConfig(entry) {
29942
+ if (entry.command) {
29943
+ return {
29944
+ transportType: "stdio",
29945
+ command: entry.command,
29946
+ args: entry.args,
29947
+ env: entry.env,
29948
+ timeout: entry.timeout,
29949
+ capabilities: entry.capabilities,
29950
+ enableServerLogs: entry.enableServerLogs
29951
+ };
29952
+ } else if (entry.url) {
29953
+ let transportType;
29954
+ if (entry.type) {
29955
+ transportType = entry.type === "sse" ? "sse" : "streamable-http";
29956
+ } else {
29957
+ transportType = entry.url.toLowerCase().includes("sse") ? "sse" : "streamable-http";
29958
+ }
29959
+ return {
29960
+ transportType,
29961
+ url: new URL(entry.url),
29962
+ requestInit: entry.requestInit,
29963
+ eventSourceInit: entry.eventSourceInit,
29964
+ reconnectionOptions: entry.reconnectionOptions,
29965
+ sessionId: entry.sessionId,
29966
+ timeout: entry.timeout,
29967
+ capabilities: entry.capabilities,
29968
+ enableServerLogs: entry.enableServerLogs
29969
+ };
29970
+ } else {
29971
+ throw new Error("Invalid server configuration: missing command or url");
29972
+ }
29973
+ }
29974
+ function validateServerConfig(name, entry) {
29975
+ const errors = [];
29976
+ if (!entry.command && !entry.url) {
29977
+ errors.push(
29978
+ `Server "${name}": Must have either 'command' (for STDIO) or 'url' (for HTTP/SSE). Example: {"command": "npx", "args": ["server-package"]} or {"url": "https://...", "type": "sse"}`
29979
+ );
29980
+ }
29981
+ if (entry.command && entry.url) {
29982
+ errors.push(
29983
+ `Server "${name}": Cannot have both 'command' and 'url'. Use 'command' for STDIO servers or 'url' for HTTP/SSE servers, but not both`
29984
+ );
29985
+ }
29986
+ if (entry.command) {
29987
+ if (typeof entry.command !== "string" || entry.command.trim() === "") {
29988
+ errors.push(
29989
+ `Server "${name}": 'command' must be a non-empty string. Example: "npx", "node", "python", etc.`
29990
+ );
29991
+ }
29992
+ if (entry.args && !Array.isArray(entry.args)) {
29993
+ errors.push(
29994
+ `Server "${name}": 'args' must be an array of strings. Example: ["@modelcontextprotocol/server-everything"] or ["build/index.js", "--port", "3000"]`
29995
+ );
29996
+ }
29997
+ if (entry.env && typeof entry.env !== "object") {
29998
+ errors.push(
29999
+ `Server "${name}": 'env' must be an object with string keys and values. Example: {"API_KEY": "your-key", "DEBUG": "true"}`
30000
+ );
30001
+ }
30002
+ }
30003
+ if (entry.url) {
30004
+ try {
30005
+ new URL(entry.url);
30006
+ } catch {
30007
+ errors.push(
30008
+ `Server "${name}": 'url' must be a valid URL. Example: "https://api.example.com/mcp" or "https://localhost:3000/sse"`
30009
+ );
30010
+ }
30011
+ if (entry.type && !["sse", "streamable-http"].includes(entry.type)) {
30012
+ errors.push(
30013
+ `Server "${name}": 'type' must be either 'sse' or 'streamable-http'. If not specified, defaults to 'streamable-http'`
30014
+ );
30015
+ }
30016
+ }
30017
+ return errors;
30018
+ }
30019
+ function parseConfigFile(jsonString) {
30020
+ const result = {
30021
+ success: false,
30022
+ servers: [],
30023
+ errors: []
30024
+ };
30025
+ if (!isValidJSON(jsonString)) {
30026
+ result.errors.push("Invalid JSON format. Please check for missing quotes, commas, or brackets");
30027
+ return result;
30028
+ }
30029
+ let parsedConfig;
30030
+ try {
30031
+ parsedConfig = JSON.parse(jsonString);
30032
+ } catch (error) {
30033
+ result.errors.push(`JSON parsing error: ${error instanceof Error ? error.message : String(error)}`);
30034
+ return result;
30035
+ }
30036
+ const { isGlobal, isSingleNamed, errors: structureErrors } = validateMCPConfigStructure(parsedConfig);
30037
+ if (structureErrors.length > 0) {
30038
+ result.errors.push(...structureErrors);
30039
+ return result;
30040
+ }
30041
+ const servers = [];
30042
+ const allErrors = [];
30043
+ if (isGlobal) {
30044
+ const validConfig = parsedConfig;
30045
+ for (const [serverName, serverConfig] of Object.entries(validConfig.mcpServers)) {
30046
+ if (typeof serverName !== "string" || serverName.trim() === "") {
30047
+ allErrors.push("Server names must be non-empty strings");
30048
+ continue;
30049
+ }
30050
+ const validationErrors = validateServerConfig(serverName, serverConfig);
30051
+ if (validationErrors.length > 0) {
30052
+ allErrors.push(...validationErrors);
30053
+ continue;
30054
+ }
30055
+ try {
30056
+ const mcpConfig = convertToMCPJamServerConfig(serverConfig);
30057
+ servers.push({
30058
+ name: serverName,
30059
+ config: mcpConfig
30060
+ });
30061
+ } catch (error) {
30062
+ allErrors.push(
30063
+ `Server "${serverName}": ${error instanceof Error ? error.message : String(error)}`
30064
+ );
30065
+ }
30066
+ }
30067
+ } else if (isSingleNamed) {
30068
+ const serverConfig = parsedConfig;
30069
+ const serverName = Object.keys(serverConfig)[0];
30070
+ const validationErrors = validateServerConfig(serverName, serverConfig[serverName]);
30071
+ if (validationErrors.length > 0) {
30072
+ allErrors.push(...validationErrors);
30073
+ } else {
30074
+ try {
30075
+ const mcpConfig = convertToMCPJamServerConfig(serverConfig[serverName]);
30076
+ servers.push({
30077
+ name: serverName,
30078
+ config: mcpConfig
30079
+ });
30080
+ } catch (error) {
30081
+ allErrors.push(
30082
+ `Server configuration: ${error instanceof Error ? error.message : String(error)}`
30083
+ );
30084
+ }
30085
+ }
30086
+ }
30087
+ result.servers = servers;
30088
+ result.errors = allErrors;
30089
+ result.success = allErrors.length === 0 && servers.length > 0;
30090
+ return result;
30091
+ }
30092
+ function generateExampleConfig() {
30093
+ const exampleConfig = {
30094
+ mcpServers: {
30095
+ "example-stdio-server": {
30096
+ command: "npx",
30097
+ args: ["@modelcontextprotocol/server-everything"],
30098
+ env: {
30099
+ API_KEY: "your-api-key",
30100
+ DEBUG: "true"
30101
+ }
30102
+ },
30103
+ "example-sse-server": {
30104
+ url: "https://api.example.com/mcp/sse",
30105
+ type: "sse"
30106
+ },
30107
+ "example-http-server": {
30108
+ url: "https://api.example.com/mcp/http",
30109
+ type: "streamable-http"
30110
+ }
30111
+ }
30112
+ };
30113
+ return JSON.stringify(exampleConfig, null, 2);
30114
+ }
30115
+ const ConfigImportDialog = ({
30116
+ open,
30117
+ onOpenChange,
30118
+ onImportServers
30119
+ }) => {
30120
+ const [configText, setConfigText] = reactExports.useState("");
30121
+ const [parseResult, setParseResult] = reactExports.useState(null);
30122
+ const [isValidating, setIsValidating] = reactExports.useState(false);
30123
+ const { toast: toast2 } = useToast();
30124
+ const handleConfigChange = reactExports.useCallback((value) => {
30125
+ setConfigText(value);
30126
+ setParseResult(null);
30127
+ }, []);
30128
+ const validateConfig = reactExports.useCallback(() => {
30129
+ if (!configText.trim()) {
30130
+ setParseResult({
30131
+ success: false,
30132
+ servers: [],
30133
+ errors: ["Please enter a configuration"]
30134
+ });
30135
+ return;
30136
+ }
30137
+ setIsValidating(true);
30138
+ try {
30139
+ const result = parseConfigFile(configText);
30140
+ setParseResult(result);
30141
+ } catch (error) {
30142
+ setParseResult({
30143
+ success: false,
30144
+ servers: [],
30145
+ errors: [`Unexpected error: ${error instanceof Error ? error.message : String(error)}`]
30146
+ });
30147
+ } finally {
30148
+ setIsValidating(false);
30149
+ }
30150
+ }, [configText]);
30151
+ const handleImport = reactExports.useCallback(() => {
30152
+ if ((parseResult == null ? void 0 : parseResult.success) && parseResult.servers.length > 0) {
30153
+ onImportServers(parseResult.servers);
30154
+ toast2({
30155
+ title: "Configuration imported",
30156
+ description: `Successfully imported ${parseResult.servers.length} server(s)`
30157
+ });
30158
+ onOpenChange(false);
30159
+ setConfigText("");
30160
+ setParseResult(null);
30161
+ }
30162
+ }, [parseResult, onImportServers, onOpenChange, toast2]);
30163
+ const handlePasteExample = reactExports.useCallback(() => {
30164
+ const example = generateExampleConfig();
30165
+ setConfigText(example);
30166
+ setParseResult(null);
30167
+ }, []);
30168
+ const handleCopyExample = reactExports.useCallback(async () => {
30169
+ try {
30170
+ const example = generateExampleConfig();
30171
+ await navigator.clipboard.writeText(example);
30172
+ toast2({
30173
+ title: "Example copied",
30174
+ description: "Example configuration has been copied to clipboard"
30175
+ });
30176
+ } catch {
30177
+ toast2({
30178
+ title: "Copy failed",
30179
+ description: "Failed to copy example configuration",
30180
+ variant: "destructive"
30181
+ });
30182
+ }
30183
+ }, [toast2]);
30184
+ const handleClose = reactExports.useCallback(() => {
30185
+ onOpenChange(false);
30186
+ setConfigText("");
30187
+ setParseResult(null);
30188
+ }, [onOpenChange]);
30189
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-4xl max-h-[90vh] flex flex-col", children: [
30190
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
30191
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
30192
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-5 w-5" }),
30193
+ "Import MCP Configuration"
30194
+ ] }),
30195
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogDescription, { children: [
30196
+ "Paste your MCP configuration JSON to import servers. Supports:",
30197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30198
+ "• ",
30199
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Global config" }),
30200
+ ': Complete mcp.json with "mcpServers" wrapper',
30201
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30202
+ "• ",
30203
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Named server" }),
30204
+ ": Single server with name key"
30205
+ ] })
30206
+ ] }),
30207
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col gap-4 min-h-0", children: [
30208
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
30209
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
30210
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Configuration JSON" }),
30211
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
30212
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
30213
+ Button,
30214
+ {
30215
+ variant: "outline",
30216
+ size: "sm",
30217
+ onClick: handlePasteExample,
30218
+ className: "h-7 px-2 text-xs",
30219
+ children: [
30220
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "h-3 w-3 mr-1" }),
30221
+ "Paste Example"
30222
+ ]
30223
+ }
30224
+ ),
30225
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
30226
+ Button,
30227
+ {
30228
+ variant: "outline",
30229
+ size: "sm",
30230
+ onClick: handleCopyExample,
30231
+ className: "h-7 px-2 text-xs",
30232
+ children: [
30233
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-3 w-3 mr-1" }),
30234
+ "Copy Example"
30235
+ ]
30236
+ }
30237
+ )
30238
+ ] })
30239
+ ] }),
30240
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30241
+ Textarea,
30242
+ {
30243
+ value: configText,
30244
+ onChange: (e) => handleConfigChange(e.target.value),
30245
+ placeholder: `Paste your configuration here. Supports two formats:
30246
+
30247
+ 1. Global config (complete mcp.json):
30248
+ {
30249
+ "mcpServers": {
30250
+ "my-server": {
30251
+ "command": "npx",
30252
+ "args": ["@modelcontextprotocol/server-everything"]
30253
+ }
30254
+ }
30255
+ }
30256
+
30257
+ 2. Named server config:
30258
+ {
30259
+ "everything": {
30260
+ "command": "npx",
30261
+ "args": ["@modelcontextprotocol/server-everything"]
30262
+ }
30263
+ }
30264
+
30265
+ or
30266
+
30267
+ {
30268
+ "my-sse-server": {
30269
+ "url": "https://api.example.com/mcp",
30270
+ "type": "sse"
30271
+ }
30272
+ }`,
30273
+ className: "font-mono text-xs min-h-[200px] resize-none"
30274
+ }
30275
+ )
30276
+ ] }),
30277
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
30278
+ Button,
30279
+ {
30280
+ onClick: validateConfig,
30281
+ disabled: !configText.trim() || isValidating,
30282
+ variant: "outline",
30283
+ className: "flex-1",
30284
+ children: isValidating ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30285
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-current mr-2" }),
30286
+ "Validating..."
30287
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30288
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 mr-2" }),
30289
+ "Validate Configuration"
30290
+ ] })
30291
+ }
30292
+ ) }),
30293
+ parseResult && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3 flex-1 min-h-0 overflow-y-auto", children: parseResult.success ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { children: [
30294
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "h-4 w-4" }),
30295
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Configuration Valid" }),
30296
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDescription, { children: [
30297
+ "Found ",
30298
+ parseResult.servers.length,
30299
+ " server(s) ready to import:",
30300
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 space-y-1", children: parseResult.servers.map((server) => {
30301
+ var _a2;
30302
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-xs font-mono", children: [
30303
+ "• ",
30304
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: server.name }),
30305
+ " (",
30306
+ server.config.transportType,
30307
+ ")",
30308
+ server.config.transportType === "stdio" && "command" in server.config && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground ml-2", children: [
30309
+ server.config.command,
30310
+ " ",
30311
+ (_a2 = server.config.args) == null ? void 0 : _a2.join(" ")
30312
+ ] }),
30313
+ server.config.transportType !== "stdio" && "url" in server.config && server.config.url && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground ml-2", children: server.config.url.toString() })
30314
+ ] }, server.name);
30315
+ }) })
30316
+ ] })
30317
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", children: [
30318
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
30319
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Configuration Invalid" }),
30320
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: parseResult.errors.map((error, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs font-mono", children: [
30321
+ "• ",
30322
+ error
30323
+ ] }, index2)) }) })
30324
+ ] }) })
30325
+ ] }),
30326
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-4 border-t", children: [
30327
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
30328
+ Button,
30329
+ {
30330
+ variant: "outline",
30331
+ onClick: handleClose,
30332
+ className: "flex-1",
30333
+ children: [
30334
+ /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "h-4 w-4 mr-2" }),
30335
+ "Cancel"
30336
+ ]
30337
+ }
30338
+ ),
30339
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
30340
+ Button,
30341
+ {
30342
+ onClick: handleImport,
30343
+ disabled: !(parseResult == null ? void 0 : parseResult.success) || parseResult.servers.length === 0,
30344
+ className: "flex-1",
30345
+ children: [
30346
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-4 w-4 mr-2" }),
30347
+ "Import ",
30348
+ (parseResult == null ? void 0 : parseResult.servers.length) || 0,
30349
+ " Server(s)"
30350
+ ]
30351
+ }
30352
+ )
30353
+ ] })
30354
+ ] }) });
30355
+ };
29659
30356
  const ConnectionSection = ({
29660
30357
  connectionStatus,
29661
30358
  transportType,
@@ -29681,12 +30378,14 @@ const ConnectionSection = ({
29681
30378
  loggingSupported,
29682
30379
  config,
29683
30380
  setConfig,
29684
- hideActionButtons
30381
+ hideActionButtons,
30382
+ onImportServers
29685
30383
  }) => {
29686
30384
  const [activeTab, setActiveTab] = reactExports.useState("connection");
29687
30385
  const [shownEnvVars, setShownEnvVars] = reactExports.useState(/* @__PURE__ */ new Set());
29688
30386
  const [copiedServerEntry, setCopiedServerEntry] = reactExports.useState(false);
29689
30387
  const [copiedServerFile, setCopiedServerFile] = reactExports.useState(false);
30388
+ const [showImportDialog, setShowImportDialog] = reactExports.useState(false);
29690
30389
  const { toast: toast2 } = useToast();
29691
30390
  const reportError2 = reactExports.useCallback(
29692
30391
  (error) => {
@@ -29782,7 +30481,8 @@ const ConnectionSection = ({
29782
30481
  { key: "auth", label: "Auth" },
29783
30482
  ...transportType === "stdio" ? [{ key: "env", label: "Environment" }] : [],
29784
30483
  { key: "config", label: "Configuration" },
29785
- ...loggingSupported ? [{ key: "logging", label: "Logging" }] : []
30484
+ ...loggingSupported ? [{ key: "logging", label: "Logging" }] : [],
30485
+ ...onImportServers ? [{ key: "import", label: "Import" }] : []
29786
30486
  ].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29787
30487
  "button",
29788
30488
  {
@@ -30020,6 +30720,21 @@ const ConnectionSection = ({
30020
30720
  }
30021
30721
  )
30022
30722
  ] })
30723
+ ] }),
30724
+ activeTab === "import" && onImportServers && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
30725
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold text-slate-800 dark:text-slate-200", children: "Import Configuration" }),
30726
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-slate-600 dark:text-slate-400", children: "Import multiple servers from a configuration file. Supports the same format used by Claude Desktop and Cursor." }),
30727
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
30728
+ Button,
30729
+ {
30730
+ onClick: () => setShowImportDialog(true),
30731
+ className: "w-full h-8 text-xs",
30732
+ children: [
30733
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-3 h-3 mr-2" }),
30734
+ "Import from Configuration File"
30735
+ ]
30736
+ }
30737
+ )
30023
30738
  ] })
30024
30739
  ] });
30025
30740
  };
@@ -30217,7 +30932,15 @@ const ConnectionSection = ({
30217
30932
  },
30218
30933
  index2
30219
30934
  )) })
30220
- ] }) })
30935
+ ] }) }),
30936
+ onImportServers && /* @__PURE__ */ jsxRuntimeExports.jsx(
30937
+ ConfigImportDialog,
30938
+ {
30939
+ open: showImportDialog,
30940
+ onOpenChange: setShowImportDialog,
30941
+ onImportServers
30942
+ }
30943
+ )
30221
30944
  ] });
30222
30945
  };
30223
30946
  const ClientFormSection = ({
@@ -30234,9 +30957,15 @@ const ClientFormSection = ({
30234
30957
  headerName,
30235
30958
  setHeaderName,
30236
30959
  onSave,
30237
- onCancel
30960
+ onCancel,
30961
+ onImportMultipleServers,
30962
+ onSaveMultiple
30238
30963
  }) => {
30239
30964
  const [argsString, setArgsString] = reactExports.useState("");
30965
+ const [multipleClients, setMultipleClients] = reactExports.useState([]);
30966
+ const [isMultipleMode, setIsMultipleMode] = reactExports.useState(false);
30967
+ const { toast: toast2 } = useToast();
30968
+ const [showImportDialog, setShowImportDialog] = reactExports.useState(false);
30240
30969
  reactExports.useEffect(() => {
30241
30970
  var _a2;
30242
30971
  if (clientFormConfig.transportType === "stdio" && "args" in clientFormConfig) {
@@ -30252,12 +30981,328 @@ const ClientFormSection = ({
30252
30981
  });
30253
30982
  }
30254
30983
  };
30984
+ const handleImportServers = (servers) => {
30985
+ var _a2;
30986
+ if (servers.length > 1) {
30987
+ const clients = servers.map((server, index2) => {
30988
+ var _a3;
30989
+ return {
30990
+ id: `client-${Date.now()}-${index2}`,
30991
+ name: server.name,
30992
+ config: server.config,
30993
+ argsString: server.config.transportType === "stdio" && "args" in server.config ? ((_a3 = server.config.args) == null ? void 0 : _a3.join(" ")) || "" : ""
30994
+ };
30995
+ });
30996
+ setMultipleClients(clients);
30997
+ setIsMultipleMode(true);
30998
+ toast2({
30999
+ title: "Multiple servers imported",
31000
+ description: `Imported ${servers.length} server configurations. Configure each client below.`
31001
+ });
31002
+ } else if (servers.length === 1) {
31003
+ const firstServer = servers[0];
31004
+ setClientFormConfig(firstServer.config);
31005
+ if (!clientFormName.trim()) {
31006
+ setClientFormName(firstServer.name);
31007
+ }
31008
+ if (firstServer.config.transportType === "stdio" && "args" in firstServer.config) {
31009
+ setArgsString(((_a2 = firstServer.config.args) == null ? void 0 : _a2.join(" ")) || "");
31010
+ }
31011
+ toast2({
31012
+ title: "Configuration imported",
31013
+ description: `Imported configuration for "${firstServer.name}".`
31014
+ });
31015
+ }
31016
+ if (onImportMultipleServers) {
31017
+ onImportMultipleServers(servers);
31018
+ }
31019
+ };
31020
+ const handleUpdateClient = (clientId, updates) => {
31021
+ setMultipleClients(
31022
+ (prev) => prev.map(
31023
+ (client2) => client2.id === clientId ? { ...client2, ...updates } : client2
31024
+ )
31025
+ );
31026
+ };
31027
+ const handleRemoveClient = (clientId) => {
31028
+ setMultipleClients((prev) => prev.filter((client2) => client2.id !== clientId));
31029
+ };
31030
+ const handleAddClient = () => {
31031
+ const newClient = {
31032
+ id: `client-${Date.now()}`,
31033
+ name: "",
31034
+ config: {
31035
+ transportType: "stdio",
31036
+ command: "npx",
31037
+ args: ["@modelcontextprotocol/server-everything"],
31038
+ env: {}
31039
+ },
31040
+ argsString: "@modelcontextprotocol/server-everything"
31041
+ };
31042
+ setMultipleClients((prev) => [...prev, newClient]);
31043
+ };
31044
+ const handleSaveAll = async () => {
31045
+ const validClients = multipleClients.filter((client2) => client2.name.trim());
31046
+ if (validClients.length === 0) {
31047
+ toast2({
31048
+ title: "No valid clients",
31049
+ description: "Please provide names for at least one client.",
31050
+ variant: "destructive"
31051
+ });
31052
+ return;
31053
+ }
31054
+ const names = validClients.map((c) => c.name.trim());
31055
+ const duplicates = names.filter((name, index2) => names.indexOf(name) !== index2);
31056
+ if (duplicates.length > 0) {
31057
+ toast2({
31058
+ title: "Duplicate client names",
31059
+ description: `Please ensure all client names are unique. Duplicates: ${[...new Set(duplicates)].join(", ")}`,
31060
+ variant: "destructive"
31061
+ });
31062
+ return;
31063
+ }
31064
+ if (onSaveMultiple) {
31065
+ try {
31066
+ const results = await onSaveMultiple(validClients.map((client2) => ({
31067
+ name: client2.name.trim(),
31068
+ config: client2.config
31069
+ })));
31070
+ if (results.success.length > 0) {
31071
+ toast2({
31072
+ title: "Clients created",
31073
+ description: `Successfully created ${results.success.length} client(s): ${results.success.join(", ")}`
31074
+ });
31075
+ }
31076
+ if (results.failed.length > 0) {
31077
+ toast2({
31078
+ title: "Some clients failed",
31079
+ description: `${results.failed.length} client(s) failed to create. Check console for details.`,
31080
+ variant: "destructive"
31081
+ });
31082
+ }
31083
+ } catch (error) {
31084
+ console.error("Failed to create clients:", error);
31085
+ toast2({
31086
+ title: "Creation failed",
31087
+ description: `Failed to create clients: ${error instanceof Error ? error.message : String(error)}`,
31088
+ variant: "destructive"
31089
+ });
31090
+ }
31091
+ }
31092
+ };
31093
+ const handleBackToSingle = () => {
31094
+ setIsMultipleMode(false);
31095
+ setMultipleClients([]);
31096
+ };
31097
+ if (isMultipleMode) {
31098
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-6xl mx-auto w-full", children: [
31099
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [
31100
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold mb-2", children: "Create Multiple Clients" }),
31101
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground", children: "Configure each imported server as a separate client. You can modify settings individually." })
31102
+ ] }),
31103
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
31104
+ multipleClients.map((client2, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border rounded-lg p-4 space-y-4", children: [
31105
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
31106
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-lg font-semibold", children: [
31107
+ "Client ",
31108
+ index2 + 1
31109
+ ] }),
31110
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31111
+ Button,
31112
+ {
31113
+ variant: "outline",
31114
+ size: "sm",
31115
+ onClick: () => handleRemoveClient(client2.id),
31116
+ className: "h-8 w-8 p-0",
31117
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "h-4 w-4" })
31118
+ }
31119
+ )
31120
+ ] }),
31121
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
31122
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium mb-2 block", children: "Client Name" }),
31123
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31124
+ Input,
31125
+ {
31126
+ value: client2.name,
31127
+ onChange: (e) => handleUpdateClient(client2.id, { name: e.target.value }),
31128
+ placeholder: "Enter client name",
31129
+ className: "w-full"
31130
+ }
31131
+ )
31132
+ ] }),
31133
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
31134
+ ConnectionSection,
31135
+ {
31136
+ connectionStatus: "disconnected",
31137
+ transportType: client2.config.transportType,
31138
+ setTransportType: (type2) => {
31139
+ let newConfig;
31140
+ let newArgsString = "";
31141
+ if (type2 === "stdio") {
31142
+ newConfig = {
31143
+ transportType: type2,
31144
+ command: "npx",
31145
+ args: ["@modelcontextprotocol/server-everything"],
31146
+ env: {}
31147
+ };
31148
+ newArgsString = "@modelcontextprotocol/server-everything";
31149
+ } else {
31150
+ newConfig = {
31151
+ transportType: type2,
31152
+ url: new URL("https://example.com")
31153
+ };
31154
+ }
31155
+ handleUpdateClient(client2.id, {
31156
+ config: newConfig,
31157
+ argsString: newArgsString
31158
+ });
31159
+ },
31160
+ command: client2.config.transportType === "stdio" && "command" in client2.config ? client2.config.command || "" : "",
31161
+ setCommand: (command) => {
31162
+ if (client2.config.transportType === "stdio") {
31163
+ handleUpdateClient(client2.id, {
31164
+ config: {
31165
+ ...client2.config,
31166
+ command
31167
+ }
31168
+ });
31169
+ }
31170
+ },
31171
+ args: client2.argsString,
31172
+ setArgs: (newArgsString) => {
31173
+ if (client2.config.transportType === "stdio") {
31174
+ handleUpdateClient(client2.id, {
31175
+ argsString: newArgsString,
31176
+ config: {
31177
+ ...client2.config,
31178
+ args: newArgsString.trim() ? newArgsString.split(/\s+/) : []
31179
+ }
31180
+ });
31181
+ }
31182
+ },
31183
+ sseUrl: "url" in client2.config && client2.config.url ? client2.config.url.toString() : "",
31184
+ setSseUrl: (url) => {
31185
+ if (client2.config.transportType !== "stdio") {
31186
+ handleUpdateClient(client2.id, {
31187
+ config: {
31188
+ ...client2.config,
31189
+ url: new URL(url)
31190
+ }
31191
+ });
31192
+ }
31193
+ },
31194
+ env: client2.config.transportType === "stdio" && "env" in client2.config ? client2.config.env || {} : {},
31195
+ setEnv: (env) => {
31196
+ if (client2.config.transportType === "stdio") {
31197
+ handleUpdateClient(client2.id, {
31198
+ config: {
31199
+ ...client2.config,
31200
+ env
31201
+ }
31202
+ });
31203
+ }
31204
+ },
31205
+ config,
31206
+ setConfig,
31207
+ bearerToken,
31208
+ setBearerToken,
31209
+ headerName,
31210
+ setHeaderName,
31211
+ onConnect: () => {
31212
+ },
31213
+ onDisconnect: () => {
31214
+ },
31215
+ stdErrNotifications: [],
31216
+ clearStdErrNotifications: () => {
31217
+ },
31218
+ logLevel: "debug",
31219
+ sendLogLevelRequest: async () => {
31220
+ },
31221
+ loggingSupported: false,
31222
+ hideActionButtons: true
31223
+ }
31224
+ ) })
31225
+ ] }, client2.id)),
31226
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
31227
+ Button,
31228
+ {
31229
+ variant: "outline",
31230
+ onClick: handleAddClient,
31231
+ className: "w-full",
31232
+ children: [
31233
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "h-4 w-4 mr-2" }),
31234
+ "Add Another Client"
31235
+ ]
31236
+ }
31237
+ ),
31238
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-3 pt-4 border-t", children: [
31239
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
31240
+ Button,
31241
+ {
31242
+ onClick: handleSaveAll,
31243
+ disabled: multipleClients.filter((c) => c.name.trim()).length === 0,
31244
+ className: "flex-1",
31245
+ children: [
31246
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { className: "h-4 w-4 mr-2" }),
31247
+ "Create ",
31248
+ multipleClients.filter((c) => c.name.trim()).length,
31249
+ " Client(s)"
31250
+ ]
31251
+ }
31252
+ ),
31253
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31254
+ Button,
31255
+ {
31256
+ variant: "outline",
31257
+ onClick: handleBackToSingle,
31258
+ className: "flex-1",
31259
+ children: "Back to Single Mode"
31260
+ }
31261
+ ),
31262
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31263
+ Button,
31264
+ {
31265
+ variant: "outline",
31266
+ onClick: onCancel,
31267
+ children: "Cancel"
31268
+ }
31269
+ )
31270
+ ] }),
31271
+ multipleClients.some((c) => !c.name.trim()) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-amber-600 text-sm", children: [
31272
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
31273
+ "Some clients don't have names and won't be created."
31274
+ ] })
31275
+ ] })
31276
+ ] }) });
31277
+ }
30255
31278
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-auto p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-4xl mx-auto w-full", children: [
30256
31279
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [
30257
31280
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold mb-2", children: isCreating ? "Create New Client" : `Edit Client: ${editingClientName}` }),
30258
31281
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground", children: "Configure your MCP client connection settings below." })
30259
31282
  ] }),
31283
+ isCreating && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-6 p-4 rounded-lg bg-card border border-border/50 shadow-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
31284
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-muted rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-5 w-5 text-muted-foreground" }) }),
31285
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
31286
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold mb-1", children: "Import Configuration" }),
31287
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "Import multiple servers from a configuration file. Supports the same format used by Claude Desktop and Cursor." }),
31288
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
31289
+ Button,
31290
+ {
31291
+ onClick: () => setShowImportDialog(true),
31292
+ size: "sm",
31293
+ children: [
31294
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-4 h-4 mr-2" }),
31295
+ "Import from Configuration File"
31296
+ ]
31297
+ }
31298
+ )
31299
+ ] })
31300
+ ] }) }),
30260
31301
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
31302
+ isCreating && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t pt-4", children: [
31303
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium mb-1", children: "Manual Configuration" }),
31304
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Or configure a single client manually with the options below." })
31305
+ ] }),
30261
31306
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
30262
31307
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium mb-2 block", children: "Client Name" }),
30263
31308
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -30362,7 +31407,15 @@ const ClientFormSection = ({
30362
31407
  }
30363
31408
  )
30364
31409
  ] })
30365
- ] })
31410
+ ] }),
31411
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31412
+ ConfigImportDialog,
31413
+ {
31414
+ open: showImportDialog,
31415
+ onOpenChange: setShowImportDialog,
31416
+ onImportServers: handleImportServers
31417
+ }
31418
+ )
30366
31419
  ] }) });
30367
31420
  };
30368
31421
  const StarGitHubModal = ({
@@ -40880,7 +41933,7 @@ Anthropic.Models = Models2;
40880
41933
  Anthropic.Beta = Beta;
40881
41934
  const { HUMAN_PROMPT, AI_PROMPT } = Anthropic;
40882
41935
  const readline = {};
40883
- const version = "0.2.3";
41936
+ const version = "0.2.4";
40884
41937
  const packageJson = {
40885
41938
  version
40886
41939
  };
@@ -40906,17 +41959,20 @@ const getConfigOverridesFromQueryParams = (defaultConfig) => {
40906
41959
  for (const key of Object.keys(defaultConfig)) {
40907
41960
  const param = url.searchParams.get(key);
40908
41961
  if (param !== null) {
40909
- const defaultValue = defaultConfig[key].value;
40910
- let value = param;
40911
- if (typeof defaultValue === "number") {
40912
- value = Number(param);
40913
- } else if (typeof defaultValue === "boolean") {
40914
- value = param === "true";
40915
- }
40916
- overrides[key] = {
40917
- ...defaultConfig[key],
40918
- value
40919
- };
41962
+ const defaultConfigItem = defaultConfig[key];
41963
+ if (defaultConfigItem) {
41964
+ const defaultValue = defaultConfigItem.value;
41965
+ let value = param;
41966
+ if (typeof defaultValue === "number") {
41967
+ value = Number(param);
41968
+ } else if (typeof defaultValue === "boolean") {
41969
+ value = param === "true";
41970
+ }
41971
+ overrides[key] = {
41972
+ ...defaultConfigItem,
41973
+ value
41974
+ };
41975
+ }
40920
41976
  }
40921
41977
  }
40922
41978
  return overrides;
@@ -40930,10 +41986,13 @@ const initializeInspectorConfig = (localStorageKey) => {
40930
41986
  ...JSON.parse(savedConfig)
40931
41987
  };
40932
41988
  for (const [key, value] of Object.entries(mergedConfig)) {
40933
- mergedConfig[key] = {
40934
- ...value,
40935
- label: DEFAULT_INSPECTOR_CONFIG[key].label
40936
- };
41989
+ const defaultConfigItem = DEFAULT_INSPECTOR_CONFIG[key];
41990
+ if (defaultConfigItem) {
41991
+ mergedConfig[key] = {
41992
+ ...value,
41993
+ label: defaultConfigItem.label
41994
+ };
41995
+ }
40937
41996
  }
40938
41997
  baseConfig = mergedConfig;
40939
41998
  } else {
@@ -42976,10 +44035,12 @@ const useMCPOperations = () => {
42976
44035
  setErrors((prev) => ({ ...prev, [tabKey]: null }));
42977
44036
  }, []);
42978
44037
  const addRequestHistory = reactExports.useCallback(
42979
- (request, response) => {
44038
+ (request, response, timestamp, latency) => {
42980
44039
  const requestEntry = {
42981
44040
  request: JSON.stringify(request, null, 2),
42982
- response: response ? JSON.stringify(response, null, 2) : void 0
44041
+ response: response ? JSON.stringify(response, null, 2) : void 0,
44042
+ timestamp: timestamp || (/* @__PURE__ */ new Date()).toISOString(),
44043
+ latency
42983
44044
  };
42984
44045
  setRequestHistory((prev) => [...prev, requestEntry]);
42985
44046
  },
@@ -42988,23 +44049,33 @@ const useMCPOperations = () => {
42988
44049
  const listResources = reactExports.useCallback(
42989
44050
  async (mcpAgent, selectedServerName) => {
42990
44051
  if (!mcpAgent) return;
44052
+ const startTime = performance.now();
44053
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
42991
44054
  if (selectedServerName === "all") {
42992
44055
  const allServerResources = await mcpAgent.getAllResources();
42993
44056
  const flatResources = allServerResources.flatMap(
42994
44057
  ({ resources: resources2 }) => resources2
42995
44058
  );
44059
+ const endTime = performance.now();
44060
+ const latency = Math.round(endTime - startTime);
42996
44061
  addRequestHistory(
42997
44062
  { method: "resources/list/all" },
42998
- { resources: flatResources }
44063
+ { resources: flatResources },
44064
+ operationTimestamp,
44065
+ latency
42999
44066
  );
43000
44067
  setResources(flatResources);
43001
44068
  } else {
43002
44069
  const client2 = mcpAgent.getClient(selectedServerName);
43003
44070
  if (client2) {
43004
44071
  const resourcesResponse = await client2.listResources();
44072
+ const endTime = performance.now();
44073
+ const latency = Math.round(endTime - startTime);
43005
44074
  addRequestHistory(
43006
44075
  { method: "resources/list", server: selectedServerName },
43007
- { resources: resourcesResponse.resources }
44076
+ { resources: resourcesResponse.resources },
44077
+ operationTimestamp,
44078
+ latency
43008
44079
  );
43009
44080
  setResources(resourcesResponse.resources);
43010
44081
  }
@@ -43015,15 +44086,21 @@ const useMCPOperations = () => {
43015
44086
  const listResourceTemplates = reactExports.useCallback(
43016
44087
  async (mcpAgent, selectedServerName) => {
43017
44088
  if (!mcpAgent) return;
44089
+ const startTime = performance.now();
44090
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43018
44091
  if (selectedServerName === "all") {
43019
44092
  const allServerResources = await mcpAgent.getAllResources();
43020
44093
  if (allServerResources.length > 0) {
43021
44094
  const client2 = mcpAgent.getClient(allServerResources[0].serverName);
43022
44095
  if (client2) {
43023
44096
  const templatesResponse = await client2.listResourceTemplates();
44097
+ const endTime = performance.now();
44098
+ const latency = Math.round(endTime - startTime);
43024
44099
  addRequestHistory(
43025
44100
  { method: "resourceTemplates/list/all" },
43026
- { resourceTemplates: templatesResponse.resourceTemplates }
44101
+ { resourceTemplates: templatesResponse.resourceTemplates },
44102
+ operationTimestamp,
44103
+ latency
43027
44104
  );
43028
44105
  setResourceTemplates(templatesResponse.resourceTemplates);
43029
44106
  }
@@ -43032,9 +44109,13 @@ const useMCPOperations = () => {
43032
44109
  const client2 = mcpAgent.getClient(selectedServerName);
43033
44110
  if (client2) {
43034
44111
  const templatesResponse = await client2.listResourceTemplates();
44112
+ const endTime = performance.now();
44113
+ const latency = Math.round(endTime - startTime);
43035
44114
  addRequestHistory(
43036
44115
  { method: "resourceTemplates/list", server: selectedServerName },
43037
- { resourceTemplates: templatesResponse.resourceTemplates }
44116
+ { resourceTemplates: templatesResponse.resourceTemplates },
44117
+ operationTimestamp,
44118
+ latency
43038
44119
  );
43039
44120
  setResourceTemplates(templatesResponse.resourceTemplates);
43040
44121
  }
@@ -43045,14 +44126,20 @@ const useMCPOperations = () => {
43045
44126
  const readResource = reactExports.useCallback(
43046
44127
  async (mcpAgent, selectedServerName, uri) => {
43047
44128
  if (!mcpAgent) return;
44129
+ const startTime = performance.now();
44130
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43048
44131
  if (selectedServerName !== "all") {
43049
44132
  const result = await mcpAgent.readResourceFromServer(
43050
44133
  selectedServerName,
43051
44134
  uri
43052
44135
  );
44136
+ const endTime = performance.now();
44137
+ const latency = Math.round(endTime - startTime);
43053
44138
  addRequestHistory(
43054
44139
  { method: "resources/read", server: selectedServerName, uri },
43055
- result
44140
+ result,
44141
+ operationTimestamp,
44142
+ latency
43056
44143
  );
43057
44144
  return result;
43058
44145
  } else {
@@ -43063,9 +44150,13 @@ const useMCPOperations = () => {
43063
44150
  serverName,
43064
44151
  uri
43065
44152
  );
44153
+ const endTime = performance.now();
44154
+ const latency = Math.round(endTime - startTime);
43066
44155
  addRequestHistory(
43067
44156
  { method: "resources/read", server: serverName, uri },
43068
- result
44157
+ result,
44158
+ operationTimestamp,
44159
+ latency
43069
44160
  );
43070
44161
  return result;
43071
44162
  }
@@ -43078,12 +44169,18 @@ const useMCPOperations = () => {
43078
44169
  const subscribeToResource = reactExports.useCallback(
43079
44170
  async (mcpAgent, selectedServerName, uri) => {
43080
44171
  if (!mcpAgent || selectedServerName === "all") return;
44172
+ const startTime = performance.now();
44173
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43081
44174
  const client2 = mcpAgent.getClient(selectedServerName);
43082
44175
  if (client2) {
43083
44176
  const result = await client2.subscribeResource({ uri });
44177
+ const endTime = performance.now();
44178
+ const latency = Math.round(endTime - startTime);
43084
44179
  addRequestHistory(
43085
44180
  { method: "resources/subscribe", server: selectedServerName, uri },
43086
- result
44181
+ result,
44182
+ operationTimestamp,
44183
+ latency
43087
44184
  );
43088
44185
  return result;
43089
44186
  }
@@ -43093,12 +44190,18 @@ const useMCPOperations = () => {
43093
44190
  const unsubscribeFromResource = reactExports.useCallback(
43094
44191
  async (mcpAgent, selectedServerName, uri) => {
43095
44192
  if (!mcpAgent || selectedServerName === "all") return;
44193
+ const startTime = performance.now();
44194
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43096
44195
  const client2 = mcpAgent.getClient(selectedServerName);
43097
44196
  if (client2) {
43098
44197
  const result = await client2.unsubscribeResource({ uri });
44198
+ const endTime = performance.now();
44199
+ const latency = Math.round(endTime - startTime);
43099
44200
  addRequestHistory(
43100
44201
  { method: "resources/unsubscribe", server: selectedServerName, uri },
43101
- result
44202
+ result,
44203
+ operationTimestamp,
44204
+ latency
43102
44205
  );
43103
44206
  return result;
43104
44207
  }
@@ -43108,21 +44211,31 @@ const useMCPOperations = () => {
43108
44211
  const listPrompts = reactExports.useCallback(
43109
44212
  async (mcpAgent, selectedServerName) => {
43110
44213
  if (!mcpAgent) return;
44214
+ const startTime = performance.now();
44215
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43111
44216
  if (selectedServerName === "all") {
43112
44217
  const allServerPrompts = await mcpAgent.getAllPrompts();
43113
44218
  const flatPrompts = allServerPrompts.flatMap(({ prompts: prompts2 }) => prompts2);
44219
+ const endTime = performance.now();
44220
+ const latency = Math.round(endTime - startTime);
43114
44221
  addRequestHistory(
43115
44222
  { method: "prompts/list/all" },
43116
- { prompts: flatPrompts }
44223
+ { prompts: flatPrompts },
44224
+ operationTimestamp,
44225
+ latency
43117
44226
  );
43118
44227
  setPrompts(flatPrompts);
43119
44228
  } else {
43120
44229
  const client2 = mcpAgent.getClient(selectedServerName);
43121
44230
  if (client2) {
43122
44231
  const promptsResponse = await client2.listPrompts();
44232
+ const endTime = performance.now();
44233
+ const latency = Math.round(endTime - startTime);
43123
44234
  addRequestHistory(
43124
44235
  { method: "prompts/list", server: selectedServerName },
43125
- { prompts: promptsResponse.prompts }
44236
+ { prompts: promptsResponse.prompts },
44237
+ operationTimestamp,
44238
+ latency
43126
44239
  );
43127
44240
  setPrompts(promptsResponse.prompts);
43128
44241
  }
@@ -43133,15 +44246,21 @@ const useMCPOperations = () => {
43133
44246
  const getPrompt = reactExports.useCallback(
43134
44247
  async (mcpAgent, selectedServerName, name, args = {}) => {
43135
44248
  if (!mcpAgent) return;
44249
+ const startTime = performance.now();
44250
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43136
44251
  if (selectedServerName !== "all") {
43137
44252
  const result = await mcpAgent.getPromptFromServer(
43138
44253
  selectedServerName,
43139
44254
  name,
43140
44255
  args
43141
44256
  );
44257
+ const endTime = performance.now();
44258
+ const latency = Math.round(endTime - startTime);
43142
44259
  addRequestHistory(
43143
44260
  { method: "prompts/get", server: selectedServerName, name, args },
43144
- result
44261
+ result,
44262
+ operationTimestamp,
44263
+ latency
43145
44264
  );
43146
44265
  return result;
43147
44266
  } else {
@@ -43153,9 +44272,13 @@ const useMCPOperations = () => {
43153
44272
  name,
43154
44273
  args
43155
44274
  );
44275
+ const endTime = performance.now();
44276
+ const latency = Math.round(endTime - startTime);
43156
44277
  addRequestHistory(
43157
44278
  { method: "prompts/get", server: serverName, name, args },
43158
- result
44279
+ result,
44280
+ operationTimestamp,
44281
+ latency
43159
44282
  );
43160
44283
  return result;
43161
44284
  }
@@ -43168,18 +44291,31 @@ const useMCPOperations = () => {
43168
44291
  const listTools = reactExports.useCallback(
43169
44292
  async (mcpAgent, selectedServerName) => {
43170
44293
  if (!mcpAgent) return;
44294
+ const startTime = performance.now();
44295
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43171
44296
  if (selectedServerName === "all") {
43172
44297
  const allServerTools = await mcpAgent.getAllTools();
43173
44298
  const flatTools = allServerTools.flatMap(({ tools: tools2 }) => tools2);
43174
- addRequestHistory({ method: "tools/list/all" }, { tools: flatTools });
44299
+ const endTime = performance.now();
44300
+ const latency = Math.round(endTime - startTime);
44301
+ addRequestHistory(
44302
+ { method: "tools/list/all" },
44303
+ { tools: flatTools },
44304
+ operationTimestamp,
44305
+ latency
44306
+ );
43175
44307
  setTools(flatTools);
43176
44308
  } else {
43177
44309
  const client2 = mcpAgent.getClient(selectedServerName);
43178
44310
  if (client2) {
43179
44311
  const toolsResponse = await client2.tools();
44312
+ const endTime = performance.now();
44313
+ const latency = Math.round(endTime - startTime);
43180
44314
  addRequestHistory(
43181
- { method: "tools/list" },
43182
- { tools: toolsResponse.tools }
44315
+ { method: "tools/list", server: selectedServerName },
44316
+ { tools: toolsResponse.tools },
44317
+ operationTimestamp,
44318
+ latency
43183
44319
  );
43184
44320
  setTools(toolsResponse.tools);
43185
44321
  }
@@ -43190,6 +44326,8 @@ const useMCPOperations = () => {
43190
44326
  const callTool = reactExports.useCallback(
43191
44327
  async (mcpAgent, selectedServerName, name, params) => {
43192
44328
  if (!mcpAgent) return;
44329
+ const startTime = performance.now();
44330
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43193
44331
  try {
43194
44332
  if (selectedServerName !== "all") {
43195
44333
  const result = await mcpAgent.callToolOnServer(
@@ -43197,9 +44335,13 @@ const useMCPOperations = () => {
43197
44335
  name,
43198
44336
  params
43199
44337
  );
44338
+ const endTime = performance.now();
44339
+ const latency = Math.round(endTime - startTime);
43200
44340
  addRequestHistory(
43201
44341
  { method: "tools/call", server: selectedServerName, name, params },
43202
- result
44342
+ result,
44343
+ operationTimestamp,
44344
+ latency
43203
44345
  );
43204
44346
  setToolResult(result);
43205
44347
  } else {
@@ -43211,9 +44353,13 @@ const useMCPOperations = () => {
43211
44353
  name,
43212
44354
  params
43213
44355
  );
44356
+ const endTime = performance.now();
44357
+ const latency = Math.round(endTime - startTime);
43214
44358
  addRequestHistory(
43215
44359
  { method: "tools/call", server: serverName, name, params },
43216
- result
44360
+ result,
44361
+ operationTimestamp,
44362
+ latency
43217
44363
  );
43218
44364
  setToolResult(result);
43219
44365
  return;
@@ -43222,6 +44368,8 @@ const useMCPOperations = () => {
43222
44368
  throw new Error(`Tool ${name} not found on any server`);
43223
44369
  }
43224
44370
  } catch (e) {
44371
+ const endTime = performance.now();
44372
+ const latency = Math.round(endTime - startTime);
43225
44373
  const toolResult2 = {
43226
44374
  content: [
43227
44375
  {
@@ -43233,7 +44381,9 @@ const useMCPOperations = () => {
43233
44381
  };
43234
44382
  addRequestHistory(
43235
44383
  { method: "tools/call", server: selectedServerName, name, params },
43236
- { error: e.message ?? String(e) }
44384
+ { error: e.message ?? String(e) },
44385
+ operationTimestamp,
44386
+ latency
43237
44387
  );
43238
44388
  setToolResult(toolResult2);
43239
44389
  }
@@ -43264,11 +44414,15 @@ const useMCPOperations = () => {
43264
44414
  if (!mcpAgent || selectedServerName === "all") {
43265
44415
  return [];
43266
44416
  }
44417
+ const startTime = performance.now();
44418
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43267
44419
  const client2 = mcpAgent.getClient(selectedServerName);
43268
44420
  if (!client2) {
43269
44421
  return [];
43270
44422
  }
43271
44423
  const result = await client2.handleCompletion(ref2, argName, value, signal);
44424
+ const endTime = performance.now();
44425
+ const latency = Math.round(endTime - startTime);
43272
44426
  addRequestHistory(
43273
44427
  {
43274
44428
  method: "completion",
@@ -43277,7 +44431,9 @@ const useMCPOperations = () => {
43277
44431
  argName,
43278
44432
  value
43279
44433
  },
43280
- { completions: result }
44434
+ { completions: result },
44435
+ operationTimestamp,
44436
+ latency
43281
44437
  );
43282
44438
  return result;
43283
44439
  },
@@ -43670,6 +44826,39 @@ const App = () => {
43670
44826
  console.error("Failed to save client:", error);
43671
44827
  }
43672
44828
  }, [serverState, handleAddServer, handleUpdateServer, handleRemoveServer]);
44829
+ const handleSaveMultiple = reactExports.useCallback(
44830
+ async (clients) => {
44831
+ const results = {
44832
+ success: [],
44833
+ failed: []
44834
+ };
44835
+ console.log(`🔄 Creating ${clients.length} client(s)...`);
44836
+ for (const client2 of clients) {
44837
+ try {
44838
+ console.log(`🔧 Creating client: "${client2.name}"`);
44839
+ await handleAddServer(client2.name, client2.config);
44840
+ results.success.push(client2.name);
44841
+ console.log(`✅ Successfully created client: "${client2.name}"`);
44842
+ } catch (error) {
44843
+ const errorMessage = error instanceof Error ? error.message : String(error);
44844
+ console.error(`❌ Failed to create client "${client2.name}":`, errorMessage);
44845
+ results.failed.push({ name: client2.name, error: errorMessage });
44846
+ }
44847
+ }
44848
+ serverState.handleCancelClientForm();
44849
+ if (results.success.length > 0) {
44850
+ console.log(`✅ Successfully created ${results.success.length} client(s): ${results.success.join(", ")}`);
44851
+ }
44852
+ if (results.failed.length > 0) {
44853
+ console.error(`❌ Failed to create ${results.failed.length} client(s):`, results.failed);
44854
+ results.failed.forEach(({ name, error }) => {
44855
+ console.error(` - ${name}: ${error}`);
44856
+ });
44857
+ }
44858
+ return results;
44859
+ },
44860
+ [handleAddServer, serverState]
44861
+ );
43673
44862
  const handleEditClient = reactExports.useCallback(
43674
44863
  (serverName) => {
43675
44864
  const serverConnections = connectionState.mcpAgent ? connectionState.mcpAgent.getAllConnectionInfo() : [];
@@ -43894,7 +45083,7 @@ const App = () => {
43894
45083
  }, []);
43895
45084
  if (window.location.pathname === "/oauth/callback") {
43896
45085
  const OAuthCallback = React.lazy(
43897
- () => __vitePreload(() => import("./OAuthCallback-CfsBsNUt.js"), true ? __vite__mapDeps([0,1]) : void 0)
45086
+ () => __vitePreload(() => import("./OAuthCallback-DkLMDxkx.js"), true ? __vite__mapDeps([0,1]) : void 0)
43898
45087
  );
43899
45088
  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(
43900
45089
  reactExports.Suspense,
@@ -43909,7 +45098,7 @@ const App = () => {
43909
45098
  }
43910
45099
  if (window.location.pathname === "/oauth/callback/debug") {
43911
45100
  const OAuthDebugCallback = React.lazy(
43912
- () => __vitePreload(() => import("./OAuthDebugCallback-DuorYCq_.js"), true ? __vite__mapDeps([2,1]) : void 0)
45101
+ () => __vitePreload(() => import("./OAuthDebugCallback-DaNmVTKt.js"), true ? __vite__mapDeps([2,1]) : void 0)
43913
45102
  );
43914
45103
  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(
43915
45104
  reactExports.Suspense,
@@ -43940,6 +45129,7 @@ const App = () => {
43940
45129
  headerName: configState.headerName,
43941
45130
  setHeaderName: configState.setHeaderName,
43942
45131
  onSave: handleSaveClient,
45132
+ onSaveMultiple: handleSaveMultiple,
43943
45133
  onCancel: serverState.handleCancelClientForm
43944
45134
  }
43945
45135
  );