@mcpjam/inspector 0.2.2 → 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-B9WXxW14.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-Dypsoomr.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);
@@ -16321,6 +16321,22 @@ const FolderTree = createLucideIcon("FolderTree", [
16321
16321
  ["path", { d: "M3 5a2 2 0 0 0 2 2h3", key: "f2jnh7" }],
16322
16322
  ["path", { d: "M3 3v13a2 2 0 0 0 2 2h3", key: "k8epm1" }]
16323
16323
  ]);
16324
+ /**
16325
+ * @license lucide-react v0.447.0 - ISC
16326
+ *
16327
+ * This source code is licensed under the ISC license.
16328
+ * See the LICENSE file in the root directory of this source tree.
16329
+ */
16330
+ const Github = createLucideIcon("Github", [
16331
+ [
16332
+ "path",
16333
+ {
16334
+ d: "M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",
16335
+ key: "tonef"
16336
+ }
16337
+ ],
16338
+ ["path", { d: "M9 18c-4.51 2-5-2-7-2", key: "9comsn" }]
16339
+ ]);
16324
16340
  /**
16325
16341
  * @license lucide-react v0.447.0 - ISC
16326
16342
  *
@@ -16592,6 +16608,17 @@ const TriangleAlert = createLucideIcon("TriangleAlert", [
16592
16608
  ["path", { d: "M12 9v4", key: "juzpu7" }],
16593
16609
  ["path", { d: "M12 17h.01", key: "p32p05" }]
16594
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
+ ]);
16595
16622
  /**
16596
16623
  * @license lucide-react v0.447.0 - ISC
16597
16624
  *
@@ -17632,6 +17659,7 @@ const AuthDebugger = ({
17632
17659
  authState,
17633
17660
  updateAuthState
17634
17661
  }) => {
17662
+ const [showFullToken, setShowFullToken] = reactExports.useState(false);
17635
17663
  const startOAuthFlow = reactExports.useCallback(() => {
17636
17664
  if (!serverUrl) {
17637
17665
  updateAuthState({
@@ -17756,9 +17784,19 @@ const AuthDebugger = ({
17756
17784
  authState.loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Loading authentication status..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
17757
17785
  authState.oauthTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
17758
17786
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: "Access Token:" }),
17759
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-muted p-2 rounded-md text-xs overflow-x-auto", children: [
17760
- authState.oauthTokens.access_token.substring(0, 25),
17761
- "..."
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
+ )
17762
17800
  ] })
17763
17801
  ] }),
17764
17802
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-4", children: [
@@ -17797,6 +17835,61 @@ const AuthDebugger = ({
17797
17835
  ] });
17798
17836
  };
17799
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
+ }
17800
17893
  function getDataType(value) {
17801
17894
  if (Array.isArray(value)) return "array";
17802
17895
  if (value === null) return "null";
@@ -18090,133 +18183,368 @@ const JsonNode = reactExports.memo(
18090
18183
  }
18091
18184
  );
18092
18185
  JsonNode.displayName = "JsonNode";
18093
- function useDraggablePane(initialHeight) {
18094
- const [height, setHeight] = reactExports.useState(initialHeight);
18095
- const [isDragging, setIsDragging] = reactExports.useState(false);
18096
- const dragStartY = reactExports.useRef(0);
18097
- const dragStartHeight = reactExports.useRef(0);
18098
- const handleDragStart = reactExports.useCallback(
18099
- (e) => {
18100
- setIsDragging(true);
18101
- dragStartY.current = e.clientY;
18102
- dragStartHeight.current = height;
18103
- document.body.style.userSelect = "none";
18104
- },
18105
- [height]
18106
- );
18107
- const handleDragMove = reactExports.useCallback(
18108
- (e) => {
18109
- if (!isDragging) return;
18110
- const deltaY = dragStartY.current - e.clientY;
18111
- const newHeight = Math.max(
18112
- 100,
18113
- Math.min(800, dragStartHeight.current + deltaY)
18114
- );
18115
- 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
+ }
18116
18240
  },
18117
- [isDragging]
18118
- );
18119
- const handleDragEnd = reactExports.useCallback(() => {
18120
- setIsDragging(false);
18121
- document.body.style.userSelect = "";
18122
- }, []);
18123
- const resetHeight = reactExports.useCallback(() => {
18124
- setHeight(initialHeight);
18125
- }, [initialHeight]);
18126
- reactExports.useEffect(() => {
18127
- if (!isDragging) {
18128
- 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"
18129
18287
  }
18130
- }, [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);
18131
18446
  reactExports.useEffect(() => {
18132
- if (isDragging) {
18133
- window.addEventListener("mousemove", handleDragMove);
18134
- window.addEventListener("mouseup", handleDragEnd);
18135
- return () => {
18136
- window.removeEventListener("mousemove", handleDragMove);
18137
- window.removeEventListener("mouseup", handleDragEnd);
18138
- };
18447
+ if (toolResult) {
18448
+ console.log("toolResult", toolResult);
18449
+ setIsToolResultError(toolResult.isError === true);
18450
+ setActiveTab("results");
18139
18451
  }
18140
- }, [isDragging, handleDragMove, handleDragEnd]);
18141
- return {
18142
- height,
18143
- isDragging,
18144
- handleDragStart,
18145
- 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
+ );
18146
18467
  };
18147
- }
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
+ };
18148
18528
  const HistoryAndNotifications = ({
18149
18529
  requestHistory,
18150
18530
  toolResult,
18151
18531
  onClearHistory
18152
18532
  }) => {
18153
- const [expandedRequests, setExpandedRequests] = reactExports.useState({});
18154
18533
  const [isHistoryCollapsed, setIsHistoryCollapsed] = reactExports.useState(true);
18155
18534
  const {
18156
18535
  height: historyPaneHeight,
18157
18536
  handleDragStart,
18158
18537
  resetHeight
18159
- } = useDraggablePane(isHistoryCollapsed ? 60 : 500);
18160
- const toggleRequestExpansion = (index2) => {
18161
- setExpandedRequests((prev) => ({ ...prev, [index2]: !prev[index2] }));
18162
- };
18538
+ } = useDraggablePane(500);
18539
+ const toggleCollapse = reactExports.useCallback(() => {
18540
+ setIsHistoryCollapsed(!isHistoryCollapsed);
18541
+ }, [isHistoryCollapsed]);
18163
18542
  reactExports.useEffect(() => {
18164
18543
  if (toolResult) {
18165
18544
  resetHeight();
18166
18545
  setIsHistoryCollapsed(false);
18167
18546
  }
18168
- }, [toolResult]);
18169
- const renderToolResult = () => {
18170
- if (!toolResult) return null;
18171
- if ("content" in toolResult) {
18172
- const parsedResult = CallToolResultSchema.safeParse(toolResult);
18173
- if (!parsedResult.success) {
18174
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18175
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Invalid Tool Result:" }),
18176
- /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult }),
18177
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Errors:" }),
18178
- parsedResult.error.errors.map((error, idx) => /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: error }, idx))
18179
- ] });
18180
- }
18181
- const structuredResult = parsedResult.data;
18182
- const isError = structuredResult.isError ?? false;
18183
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18184
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "font-semibold mb-2", children: [
18185
- "Tool Result:",
18186
- " ",
18187
- 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" })
18188
- ] }),
18189
- structuredResult.content.map((item, index2) => {
18190
- var _a2, _b;
18191
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
18192
- item.type === "text" && /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.text, isError }),
18193
- item.type === "image" && /* @__PURE__ */ jsxRuntimeExports.jsx(
18194
- "img",
18195
- {
18196
- src: `data:${item.mimeType};base64,${item.data}`,
18197
- alt: "Tool result image",
18198
- className: "max-w-full h-auto"
18199
- }
18200
- ),
18201
- item.type === "resource" && (((_b = (_a2 = item.resource) == null ? void 0 : _a2.mimeType) == null ? void 0 : _b.startsWith("audio/")) ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18202
- "audio",
18203
- {
18204
- controls: true,
18205
- src: `data:${item.resource.mimeType};base64,${item.resource.blob}`,
18206
- className: "w-full",
18207
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
18208
- }
18209
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource }))
18210
- ] }, index2);
18211
- })
18212
- ] });
18213
- } else if ("toolResult" in toolResult) {
18214
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18215
- /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold mb-2", children: "Tool Result (Legacy):" }),
18216
- /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: toolResult.toolResult })
18217
- ] });
18218
- }
18219
- };
18547
+ }, [toolResult, resetHeight]);
18220
18548
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
18221
18549
  "div",
18222
18550
  {
@@ -18232,118 +18560,19 @@ const HistoryAndNotifications = ({
18232
18560
  onMouseDown: handleDragStart
18233
18561
  }
18234
18562
  ),
18235
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full overflow-hidden", children: !isHistoryCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-transparent flex h-full", children: [
18236
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-6 border-r border-border/20", children: [
18237
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18238
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18239
- /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-5 h-5 text-primary" }),
18240
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "All Activity" })
18241
- ] }),
18242
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18243
- requestHistory.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18244
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-muted-foreground bg-muted/50 px-3 py-1 rounded-full", children: [
18245
- requestHistory.length,
18246
- " request",
18247
- requestHistory.length !== 1 ? "s" : ""
18248
- ] }),
18249
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18250
- "button",
18251
- {
18252
- onClick: onClearHistory,
18253
- className: "p-2 rounded-lg hover:bg-destructive/10 hover:text-destructive transition-all duration-200 group",
18254
- title: "Clear all activity",
18255
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "w-4 h-4 text-muted-foreground group-hover:text-destructive" })
18256
- }
18257
- )
18258
- ] }),
18259
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18260
- "button",
18261
- {
18262
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18263
- className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18264
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18265
- }
18266
- )
18267
- ] })
18268
- ] }),
18269
- requestHistory.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18270
- /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-12 h-12 text-muted-foreground/40 mb-4" }),
18271
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No activity yet" }),
18272
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "MCP requests and responses will appear here" })
18273
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-4", children: requestHistory.slice().reverse().map((request, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
18274
- "li",
18275
- {
18276
- 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",
18277
- children: [
18278
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
18279
- "div",
18280
- {
18281
- className: "flex justify-between items-center cursor-pointer group",
18282
- onClick: () => toggleRequestExpansion(
18283
- requestHistory.length - 1 - index2
18284
- ),
18285
- children: [
18286
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
18287
- /* @__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 }),
18288
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-foreground", children: JSON.parse(request.request).method })
18289
- ] }),
18290
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors duration-200", children: expandedRequests[requestHistory.length - 1 - index2] ? "▼" : "▶" })
18291
- ]
18292
- }
18293
- ),
18294
- expandedRequests[requestHistory.length - 1 - index2] && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 space-y-4", children: [
18295
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
18296
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground text-sm", children: "Request" }) }),
18297
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18298
- JsonView,
18299
- {
18300
- data: request.request,
18301
- className: "bg-background/80 backdrop-blur-sm border border-border/20 rounded-lg"
18302
- }
18303
- )
18304
- ] }),
18305
- request.response && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
18306
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground text-sm", children: "Response" }) }),
18307
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18308
- JsonView,
18309
- {
18310
- data: request.response,
18311
- className: "bg-background/80 backdrop-blur-sm border border-border/20 rounded-lg"
18312
- }
18313
- )
18314
- ] })
18315
- ] })
18316
- ]
18317
- },
18318
- index2
18319
- )) })
18320
- ] }),
18321
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-6", children: [
18322
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
18323
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-foreground flex items-center space-x-2", children: [
18324
- /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollText, { className: "w-5 h-5 text-primary" }),
18325
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Results" })
18326
- ] }),
18327
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18328
- "button",
18329
- {
18330
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18331
- className: "p-2 rounded-lg hover:bg-accent/50 transition-all duration-200",
18332
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-5 h-5 text-muted-foreground hover:text-foreground" })
18333
- }
18334
- )
18335
- ] }),
18336
- !toolResult ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
18337
- /* @__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: "🎯" }) }),
18338
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-lg font-medium mb-2", children: "No results yet" }),
18339
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground/60 text-sm", children: "Tool execution results will appear here" })
18340
- ] }) : /* @__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() })
18341
- ] })
18342
- ] }) : /* @__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(
18343
18572
  "div",
18344
18573
  {
18345
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",
18346
- onClick: () => setIsHistoryCollapsed(!isHistoryCollapsed),
18575
+ onClick: toggleCollapse,
18347
18576
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-4 text-muted-foreground", children: [
18348
18577
  /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "w-5 h-5" }),
18349
18578
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: "History & Results" }),
@@ -19433,7 +19662,7 @@ var hideOthers = function(originalTarget, parentNode, markerName) {
19433
19662
  var DIALOG_NAME = "Dialog";
19434
19663
  var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
19435
19664
  var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
19436
- var Dialog = (props) => {
19665
+ var Dialog$1 = (props) => {
19437
19666
  const {
19438
19667
  __scopeDialog,
19439
19668
  children,
@@ -19467,7 +19696,7 @@ var Dialog = (props) => {
19467
19696
  }
19468
19697
  );
19469
19698
  };
19470
- Dialog.displayName = DIALOG_NAME;
19699
+ Dialog$1.displayName = DIALOG_NAME;
19471
19700
  var TRIGGER_NAME$4 = "DialogTrigger";
19472
19701
  var DialogTrigger = reactExports.forwardRef(
19473
19702
  (props, forwardedRef) => {
@@ -19728,7 +19957,7 @@ var DescriptionWarning = ({ contentRef, descriptionId }) => {
19728
19957
  }, [MESSAGE, contentRef, descriptionId]);
19729
19958
  return null;
19730
19959
  };
19731
- var Root$2 = Dialog;
19960
+ var Root$2 = Dialog$1;
19732
19961
  var Portal$2 = DialogPortal$1;
19733
19962
  var Overlay = DialogOverlay$1;
19734
19963
  var Content$1 = DialogContent$1;
@@ -20027,6 +20256,7 @@ function B({ asChild: r2, children: o }, n) {
20027
20256
  return r2 && reactExports.isValidElement(o) ? reactExports.cloneElement(Me(o), { ref: o.ref }, n(o.props.children)) : n(o);
20028
20257
  }
20029
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;
20030
20260
  const DialogPortal = Portal$2;
20031
20261
  const DialogOverlay = reactExports.forwardRef(({ className, ...props }, ref2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
20032
20262
  Overlay,
@@ -20062,6 +20292,20 @@ const DialogContent = reactExports.forwardRef(({ className, children, ...props }
20062
20292
  )
20063
20293
  ] }));
20064
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";
20065
20309
  const DialogTitle = reactExports.forwardRef(({ className, ...props }, ref2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
20066
20310
  Title,
20067
20311
  {
@@ -26524,7 +26768,7 @@ const ToolRunCard = ({
26524
26768
  const isUpdatingExistingRequest = currentRequestId !== null;
26525
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: [
26526
26770
  /* @__PURE__ */ jsxRuntimeExports.jsx(ToolHeader, { tool: selectedTool }),
26527
- /* @__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: [
26528
26772
  /* @__PURE__ */ jsxRuntimeExports.jsx(
26529
26773
  ParametersSection,
26530
26774
  {
@@ -26533,15 +26777,6 @@ const ToolRunCard = ({
26533
26777
  onParamChange: handleParamChange
26534
26778
  }
26535
26779
  ),
26536
- /* @__PURE__ */ jsxRuntimeExports.jsx(
26537
- ActionButtons,
26538
- {
26539
- onSave: handleOpenSaveDialog,
26540
- onRun: handleRunTool,
26541
- isRunning: isToolRunning,
26542
- isUpdating: isUpdatingExistingRequest
26543
- }
26544
- ),
26545
26780
  /* @__PURE__ */ jsxRuntimeExports.jsx(
26546
26781
  SaveDialog,
26547
26782
  {
@@ -26556,7 +26791,16 @@ const ToolRunCard = ({
26556
26791
  onDescriptionChange: setSaveRequestDescription
26557
26792
  }
26558
26793
  )
26559
- ] }) : /* @__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
+ ) })
26560
26804
  ] });
26561
26805
  };
26562
26806
  const ToolsTab = ({
@@ -28609,7 +28853,7 @@ const useTheme = () => {
28609
28853
  [theme, setThemeWithSideEffect]
28610
28854
  );
28611
28855
  };
28612
- const version$1 = "0.2.2";
28856
+ const version$1 = "0.2.4";
28613
28857
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
28614
28858
  createPopperScope
28615
28859
  ]);
@@ -29640,6 +29884,475 @@ const SettingsTab = ({
29640
29884
  ] })
29641
29885
  ] }) });
29642
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
+ };
29643
30356
  const ConnectionSection = ({
29644
30357
  connectionStatus,
29645
30358
  transportType,
@@ -29665,12 +30378,14 @@ const ConnectionSection = ({
29665
30378
  loggingSupported,
29666
30379
  config,
29667
30380
  setConfig,
29668
- hideActionButtons
30381
+ hideActionButtons,
30382
+ onImportServers
29669
30383
  }) => {
29670
30384
  const [activeTab, setActiveTab] = reactExports.useState("connection");
29671
30385
  const [shownEnvVars, setShownEnvVars] = reactExports.useState(/* @__PURE__ */ new Set());
29672
30386
  const [copiedServerEntry, setCopiedServerEntry] = reactExports.useState(false);
29673
30387
  const [copiedServerFile, setCopiedServerFile] = reactExports.useState(false);
30388
+ const [showImportDialog, setShowImportDialog] = reactExports.useState(false);
29674
30389
  const { toast: toast2 } = useToast();
29675
30390
  const reportError2 = reactExports.useCallback(
29676
30391
  (error) => {
@@ -29766,7 +30481,8 @@ const ConnectionSection = ({
29766
30481
  { key: "auth", label: "Auth" },
29767
30482
  ...transportType === "stdio" ? [{ key: "env", label: "Environment" }] : [],
29768
30483
  { key: "config", label: "Configuration" },
29769
- ...loggingSupported ? [{ key: "logging", label: "Logging" }] : []
30484
+ ...loggingSupported ? [{ key: "logging", label: "Logging" }] : [],
30485
+ ...onImportServers ? [{ key: "import", label: "Import" }] : []
29770
30486
  ].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29771
30487
  "button",
29772
30488
  {
@@ -30004,6 +30720,21 @@ const ConnectionSection = ({
30004
30720
  }
30005
30721
  )
30006
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
+ )
30007
30738
  ] })
30008
30739
  ] });
30009
30740
  };
@@ -30201,7 +30932,15 @@ const ConnectionSection = ({
30201
30932
  },
30202
30933
  index2
30203
30934
  )) })
30204
- ] }) })
30935
+ ] }) }),
30936
+ onImportServers && /* @__PURE__ */ jsxRuntimeExports.jsx(
30937
+ ConfigImportDialog,
30938
+ {
30939
+ open: showImportDialog,
30940
+ onOpenChange: setShowImportDialog,
30941
+ onImportServers
30942
+ }
30943
+ )
30205
30944
  ] });
30206
30945
  };
30207
30946
  const ClientFormSection = ({
@@ -30218,9 +30957,15 @@ const ClientFormSection = ({
30218
30957
  headerName,
30219
30958
  setHeaderName,
30220
30959
  onSave,
30221
- onCancel
30960
+ onCancel,
30961
+ onImportMultipleServers,
30962
+ onSaveMultiple
30222
30963
  }) => {
30223
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);
30224
30969
  reactExports.useEffect(() => {
30225
30970
  var _a2;
30226
30971
  if (clientFormConfig.transportType === "stdio" && "args" in clientFormConfig) {
@@ -30236,12 +30981,328 @@ const ClientFormSection = ({
30236
30981
  });
30237
30982
  }
30238
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
+ }
30239
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: [
30240
31279
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [
30241
31280
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold mb-2", children: isCreating ? "Create New Client" : `Edit Client: ${editingClientName}` }),
30242
31281
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground", children: "Configure your MCP client connection settings below." })
30243
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
+ ] }) }),
30244
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
+ ] }),
30245
31306
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
30246
31307
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium mb-2 block", children: "Client Name" }),
30247
31308
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -30346,7 +31407,70 @@ const ClientFormSection = ({
30346
31407
  }
30347
31408
  )
30348
31409
  ] })
30349
- ] })
31410
+ ] }),
31411
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31412
+ ConfigImportDialog,
31413
+ {
31414
+ open: showImportDialog,
31415
+ onOpenChange: setShowImportDialog,
31416
+ onImportServers: handleImportServers
31417
+ }
31418
+ )
31419
+ ] }) });
31420
+ };
31421
+ const StarGitHubModal = ({
31422
+ isOpen,
31423
+ onClose
31424
+ }) => {
31425
+ if (!isOpen) return null;
31426
+ const handleStarClick = () => {
31427
+ window.open("https://github.com/MCPJam/inspector", "_blank");
31428
+ onClose();
31429
+ };
31430
+ const handleDismiss = () => {
31431
+ onClose();
31432
+ };
31433
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-slate-800 rounded-2xl shadow-2xl max-w-md w-full mx-4 border border-slate-200 dark:border-slate-700", children: [
31434
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-6 border-b border-slate-200 dark:border-slate-700", children: [
31435
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-3", children: [
31436
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 bg-gradient-to-br from-gray-700 to-gray-900 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Github, { className: "w-5 h-5 text-white" }) }),
31437
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold text-slate-900 dark:text-slate-100", children: "Support us!" })
31438
+ ] }),
31439
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31440
+ "button",
31441
+ {
31442
+ onClick: handleDismiss,
31443
+ className: "p-1 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors",
31444
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "w-5 h-5 text-slate-500 dark:text-slate-400" })
31445
+ }
31446
+ )
31447
+ ] }),
31448
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6", children: [
31449
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-slate-600 dark:text-slate-300 text-center mb-6 leading-relaxed", children: "If you like the inspector, please consider giving the GitHub project a star!" }),
31450
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row gap-3", children: [
31451
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
31452
+ "button",
31453
+ {
31454
+ onClick: handleStarClick,
31455
+ className: "flex-1 bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white rounded-lg px-4 py-3 font-medium transition-all duration-200 flex items-center justify-center space-x-2 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5",
31456
+ children: [
31457
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Star, { className: "w-4 h-4 fill-current" }),
31458
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Star on GitHub" }),
31459
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "w-4 h-4" })
31460
+ ]
31461
+ }
31462
+ ),
31463
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
31464
+ "button",
31465
+ {
31466
+ onClick: handleDismiss,
31467
+ className: "flex-1 bg-slate-100 dark:bg-slate-700 hover:bg-slate-200 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-300 rounded-lg px-4 py-3 font-medium transition-colors",
31468
+ children: "Maybe later"
31469
+ }
31470
+ )
31471
+ ] })
31472
+ ] }),
31473
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-6 pb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-slate-500 dark:text-slate-400 text-center", children: "This message won't appear again once dismissed" }) })
30350
31474
  ] }) });
30351
31475
  };
30352
31476
  const SERVER_CONFIGS_STORAGE_KEY = "mcpServerConfigs_v1";
@@ -40809,7 +41933,7 @@ Anthropic.Models = Models2;
40809
41933
  Anthropic.Beta = Beta;
40810
41934
  const { HUMAN_PROMPT, AI_PROMPT } = Anthropic;
40811
41935
  const readline = {};
40812
- const version = "0.2.2";
41936
+ const version = "0.2.4";
40813
41937
  const packageJson = {
40814
41938
  version
40815
41939
  };
@@ -40835,17 +41959,20 @@ const getConfigOverridesFromQueryParams = (defaultConfig) => {
40835
41959
  for (const key of Object.keys(defaultConfig)) {
40836
41960
  const param = url.searchParams.get(key);
40837
41961
  if (param !== null) {
40838
- const defaultValue = defaultConfig[key].value;
40839
- let value = param;
40840
- if (typeof defaultValue === "number") {
40841
- value = Number(param);
40842
- } else if (typeof defaultValue === "boolean") {
40843
- value = param === "true";
40844
- }
40845
- overrides[key] = {
40846
- ...defaultConfig[key],
40847
- value
40848
- };
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
+ }
40849
41976
  }
40850
41977
  }
40851
41978
  return overrides;
@@ -40859,10 +41986,13 @@ const initializeInspectorConfig = (localStorageKey) => {
40859
41986
  ...JSON.parse(savedConfig)
40860
41987
  };
40861
41988
  for (const [key, value] of Object.entries(mergedConfig)) {
40862
- mergedConfig[key] = {
40863
- ...value,
40864
- label: DEFAULT_INSPECTOR_CONFIG[key].label
40865
- };
41989
+ const defaultConfigItem = DEFAULT_INSPECTOR_CONFIG[key];
41990
+ if (defaultConfigItem) {
41991
+ mergedConfig[key] = {
41992
+ ...value,
41993
+ label: defaultConfigItem.label
41994
+ };
41995
+ }
40866
41996
  }
40867
41997
  baseConfig = mergedConfig;
40868
41998
  } else {
@@ -42905,10 +44035,12 @@ const useMCPOperations = () => {
42905
44035
  setErrors((prev) => ({ ...prev, [tabKey]: null }));
42906
44036
  }, []);
42907
44037
  const addRequestHistory = reactExports.useCallback(
42908
- (request, response) => {
44038
+ (request, response, timestamp, latency) => {
42909
44039
  const requestEntry = {
42910
44040
  request: JSON.stringify(request, null, 2),
42911
- 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
42912
44044
  };
42913
44045
  setRequestHistory((prev) => [...prev, requestEntry]);
42914
44046
  },
@@ -42917,23 +44049,33 @@ const useMCPOperations = () => {
42917
44049
  const listResources = reactExports.useCallback(
42918
44050
  async (mcpAgent, selectedServerName) => {
42919
44051
  if (!mcpAgent) return;
44052
+ const startTime = performance.now();
44053
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
42920
44054
  if (selectedServerName === "all") {
42921
44055
  const allServerResources = await mcpAgent.getAllResources();
42922
44056
  const flatResources = allServerResources.flatMap(
42923
44057
  ({ resources: resources2 }) => resources2
42924
44058
  );
44059
+ const endTime = performance.now();
44060
+ const latency = Math.round(endTime - startTime);
42925
44061
  addRequestHistory(
42926
44062
  { method: "resources/list/all" },
42927
- { resources: flatResources }
44063
+ { resources: flatResources },
44064
+ operationTimestamp,
44065
+ latency
42928
44066
  );
42929
44067
  setResources(flatResources);
42930
44068
  } else {
42931
44069
  const client2 = mcpAgent.getClient(selectedServerName);
42932
44070
  if (client2) {
42933
44071
  const resourcesResponse = await client2.listResources();
44072
+ const endTime = performance.now();
44073
+ const latency = Math.round(endTime - startTime);
42934
44074
  addRequestHistory(
42935
44075
  { method: "resources/list", server: selectedServerName },
42936
- { resources: resourcesResponse.resources }
44076
+ { resources: resourcesResponse.resources },
44077
+ operationTimestamp,
44078
+ latency
42937
44079
  );
42938
44080
  setResources(resourcesResponse.resources);
42939
44081
  }
@@ -42944,15 +44086,21 @@ const useMCPOperations = () => {
42944
44086
  const listResourceTemplates = reactExports.useCallback(
42945
44087
  async (mcpAgent, selectedServerName) => {
42946
44088
  if (!mcpAgent) return;
44089
+ const startTime = performance.now();
44090
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
42947
44091
  if (selectedServerName === "all") {
42948
44092
  const allServerResources = await mcpAgent.getAllResources();
42949
44093
  if (allServerResources.length > 0) {
42950
44094
  const client2 = mcpAgent.getClient(allServerResources[0].serverName);
42951
44095
  if (client2) {
42952
44096
  const templatesResponse = await client2.listResourceTemplates();
44097
+ const endTime = performance.now();
44098
+ const latency = Math.round(endTime - startTime);
42953
44099
  addRequestHistory(
42954
44100
  { method: "resourceTemplates/list/all" },
42955
- { resourceTemplates: templatesResponse.resourceTemplates }
44101
+ { resourceTemplates: templatesResponse.resourceTemplates },
44102
+ operationTimestamp,
44103
+ latency
42956
44104
  );
42957
44105
  setResourceTemplates(templatesResponse.resourceTemplates);
42958
44106
  }
@@ -42961,9 +44109,13 @@ const useMCPOperations = () => {
42961
44109
  const client2 = mcpAgent.getClient(selectedServerName);
42962
44110
  if (client2) {
42963
44111
  const templatesResponse = await client2.listResourceTemplates();
44112
+ const endTime = performance.now();
44113
+ const latency = Math.round(endTime - startTime);
42964
44114
  addRequestHistory(
42965
44115
  { method: "resourceTemplates/list", server: selectedServerName },
42966
- { resourceTemplates: templatesResponse.resourceTemplates }
44116
+ { resourceTemplates: templatesResponse.resourceTemplates },
44117
+ operationTimestamp,
44118
+ latency
42967
44119
  );
42968
44120
  setResourceTemplates(templatesResponse.resourceTemplates);
42969
44121
  }
@@ -42974,14 +44126,20 @@ const useMCPOperations = () => {
42974
44126
  const readResource = reactExports.useCallback(
42975
44127
  async (mcpAgent, selectedServerName, uri) => {
42976
44128
  if (!mcpAgent) return;
44129
+ const startTime = performance.now();
44130
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
42977
44131
  if (selectedServerName !== "all") {
42978
44132
  const result = await mcpAgent.readResourceFromServer(
42979
44133
  selectedServerName,
42980
44134
  uri
42981
44135
  );
44136
+ const endTime = performance.now();
44137
+ const latency = Math.round(endTime - startTime);
42982
44138
  addRequestHistory(
42983
44139
  { method: "resources/read", server: selectedServerName, uri },
42984
- result
44140
+ result,
44141
+ operationTimestamp,
44142
+ latency
42985
44143
  );
42986
44144
  return result;
42987
44145
  } else {
@@ -42992,9 +44150,13 @@ const useMCPOperations = () => {
42992
44150
  serverName,
42993
44151
  uri
42994
44152
  );
44153
+ const endTime = performance.now();
44154
+ const latency = Math.round(endTime - startTime);
42995
44155
  addRequestHistory(
42996
44156
  { method: "resources/read", server: serverName, uri },
42997
- result
44157
+ result,
44158
+ operationTimestamp,
44159
+ latency
42998
44160
  );
42999
44161
  return result;
43000
44162
  }
@@ -43007,12 +44169,18 @@ const useMCPOperations = () => {
43007
44169
  const subscribeToResource = reactExports.useCallback(
43008
44170
  async (mcpAgent, selectedServerName, uri) => {
43009
44171
  if (!mcpAgent || selectedServerName === "all") return;
44172
+ const startTime = performance.now();
44173
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43010
44174
  const client2 = mcpAgent.getClient(selectedServerName);
43011
44175
  if (client2) {
43012
44176
  const result = await client2.subscribeResource({ uri });
44177
+ const endTime = performance.now();
44178
+ const latency = Math.round(endTime - startTime);
43013
44179
  addRequestHistory(
43014
44180
  { method: "resources/subscribe", server: selectedServerName, uri },
43015
- result
44181
+ result,
44182
+ operationTimestamp,
44183
+ latency
43016
44184
  );
43017
44185
  return result;
43018
44186
  }
@@ -43022,12 +44190,18 @@ const useMCPOperations = () => {
43022
44190
  const unsubscribeFromResource = reactExports.useCallback(
43023
44191
  async (mcpAgent, selectedServerName, uri) => {
43024
44192
  if (!mcpAgent || selectedServerName === "all") return;
44193
+ const startTime = performance.now();
44194
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43025
44195
  const client2 = mcpAgent.getClient(selectedServerName);
43026
44196
  if (client2) {
43027
44197
  const result = await client2.unsubscribeResource({ uri });
44198
+ const endTime = performance.now();
44199
+ const latency = Math.round(endTime - startTime);
43028
44200
  addRequestHistory(
43029
44201
  { method: "resources/unsubscribe", server: selectedServerName, uri },
43030
- result
44202
+ result,
44203
+ operationTimestamp,
44204
+ latency
43031
44205
  );
43032
44206
  return result;
43033
44207
  }
@@ -43037,21 +44211,31 @@ const useMCPOperations = () => {
43037
44211
  const listPrompts = reactExports.useCallback(
43038
44212
  async (mcpAgent, selectedServerName) => {
43039
44213
  if (!mcpAgent) return;
44214
+ const startTime = performance.now();
44215
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43040
44216
  if (selectedServerName === "all") {
43041
44217
  const allServerPrompts = await mcpAgent.getAllPrompts();
43042
44218
  const flatPrompts = allServerPrompts.flatMap(({ prompts: prompts2 }) => prompts2);
44219
+ const endTime = performance.now();
44220
+ const latency = Math.round(endTime - startTime);
43043
44221
  addRequestHistory(
43044
44222
  { method: "prompts/list/all" },
43045
- { prompts: flatPrompts }
44223
+ { prompts: flatPrompts },
44224
+ operationTimestamp,
44225
+ latency
43046
44226
  );
43047
44227
  setPrompts(flatPrompts);
43048
44228
  } else {
43049
44229
  const client2 = mcpAgent.getClient(selectedServerName);
43050
44230
  if (client2) {
43051
44231
  const promptsResponse = await client2.listPrompts();
44232
+ const endTime = performance.now();
44233
+ const latency = Math.round(endTime - startTime);
43052
44234
  addRequestHistory(
43053
44235
  { method: "prompts/list", server: selectedServerName },
43054
- { prompts: promptsResponse.prompts }
44236
+ { prompts: promptsResponse.prompts },
44237
+ operationTimestamp,
44238
+ latency
43055
44239
  );
43056
44240
  setPrompts(promptsResponse.prompts);
43057
44241
  }
@@ -43062,15 +44246,21 @@ const useMCPOperations = () => {
43062
44246
  const getPrompt = reactExports.useCallback(
43063
44247
  async (mcpAgent, selectedServerName, name, args = {}) => {
43064
44248
  if (!mcpAgent) return;
44249
+ const startTime = performance.now();
44250
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43065
44251
  if (selectedServerName !== "all") {
43066
44252
  const result = await mcpAgent.getPromptFromServer(
43067
44253
  selectedServerName,
43068
44254
  name,
43069
44255
  args
43070
44256
  );
44257
+ const endTime = performance.now();
44258
+ const latency = Math.round(endTime - startTime);
43071
44259
  addRequestHistory(
43072
44260
  { method: "prompts/get", server: selectedServerName, name, args },
43073
- result
44261
+ result,
44262
+ operationTimestamp,
44263
+ latency
43074
44264
  );
43075
44265
  return result;
43076
44266
  } else {
@@ -43082,9 +44272,13 @@ const useMCPOperations = () => {
43082
44272
  name,
43083
44273
  args
43084
44274
  );
44275
+ const endTime = performance.now();
44276
+ const latency = Math.round(endTime - startTime);
43085
44277
  addRequestHistory(
43086
44278
  { method: "prompts/get", server: serverName, name, args },
43087
- result
44279
+ result,
44280
+ operationTimestamp,
44281
+ latency
43088
44282
  );
43089
44283
  return result;
43090
44284
  }
@@ -43097,18 +44291,31 @@ const useMCPOperations = () => {
43097
44291
  const listTools = reactExports.useCallback(
43098
44292
  async (mcpAgent, selectedServerName) => {
43099
44293
  if (!mcpAgent) return;
44294
+ const startTime = performance.now();
44295
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43100
44296
  if (selectedServerName === "all") {
43101
44297
  const allServerTools = await mcpAgent.getAllTools();
43102
44298
  const flatTools = allServerTools.flatMap(({ tools: tools2 }) => tools2);
43103
- 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
+ );
43104
44307
  setTools(flatTools);
43105
44308
  } else {
43106
44309
  const client2 = mcpAgent.getClient(selectedServerName);
43107
44310
  if (client2) {
43108
44311
  const toolsResponse = await client2.tools();
44312
+ const endTime = performance.now();
44313
+ const latency = Math.round(endTime - startTime);
43109
44314
  addRequestHistory(
43110
- { method: "tools/list" },
43111
- { tools: toolsResponse.tools }
44315
+ { method: "tools/list", server: selectedServerName },
44316
+ { tools: toolsResponse.tools },
44317
+ operationTimestamp,
44318
+ latency
43112
44319
  );
43113
44320
  setTools(toolsResponse.tools);
43114
44321
  }
@@ -43119,6 +44326,8 @@ const useMCPOperations = () => {
43119
44326
  const callTool = reactExports.useCallback(
43120
44327
  async (mcpAgent, selectedServerName, name, params) => {
43121
44328
  if (!mcpAgent) return;
44329
+ const startTime = performance.now();
44330
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43122
44331
  try {
43123
44332
  if (selectedServerName !== "all") {
43124
44333
  const result = await mcpAgent.callToolOnServer(
@@ -43126,9 +44335,13 @@ const useMCPOperations = () => {
43126
44335
  name,
43127
44336
  params
43128
44337
  );
44338
+ const endTime = performance.now();
44339
+ const latency = Math.round(endTime - startTime);
43129
44340
  addRequestHistory(
43130
44341
  { method: "tools/call", server: selectedServerName, name, params },
43131
- result
44342
+ result,
44343
+ operationTimestamp,
44344
+ latency
43132
44345
  );
43133
44346
  setToolResult(result);
43134
44347
  } else {
@@ -43140,9 +44353,13 @@ const useMCPOperations = () => {
43140
44353
  name,
43141
44354
  params
43142
44355
  );
44356
+ const endTime = performance.now();
44357
+ const latency = Math.round(endTime - startTime);
43143
44358
  addRequestHistory(
43144
44359
  { method: "tools/call", server: serverName, name, params },
43145
- result
44360
+ result,
44361
+ operationTimestamp,
44362
+ latency
43146
44363
  );
43147
44364
  setToolResult(result);
43148
44365
  return;
@@ -43151,6 +44368,8 @@ const useMCPOperations = () => {
43151
44368
  throw new Error(`Tool ${name} not found on any server`);
43152
44369
  }
43153
44370
  } catch (e) {
44371
+ const endTime = performance.now();
44372
+ const latency = Math.round(endTime - startTime);
43154
44373
  const toolResult2 = {
43155
44374
  content: [
43156
44375
  {
@@ -43162,7 +44381,9 @@ const useMCPOperations = () => {
43162
44381
  };
43163
44382
  addRequestHistory(
43164
44383
  { method: "tools/call", server: selectedServerName, name, params },
43165
- { error: e.message ?? String(e) }
44384
+ { error: e.message ?? String(e) },
44385
+ operationTimestamp,
44386
+ latency
43166
44387
  );
43167
44388
  setToolResult(toolResult2);
43168
44389
  }
@@ -43193,11 +44414,15 @@ const useMCPOperations = () => {
43193
44414
  if (!mcpAgent || selectedServerName === "all") {
43194
44415
  return [];
43195
44416
  }
44417
+ const startTime = performance.now();
44418
+ const operationTimestamp = (/* @__PURE__ */ new Date()).toISOString();
43196
44419
  const client2 = mcpAgent.getClient(selectedServerName);
43197
44420
  if (!client2) {
43198
44421
  return [];
43199
44422
  }
43200
44423
  const result = await client2.handleCompletion(ref2, argName, value, signal);
44424
+ const endTime = performance.now();
44425
+ const latency = Math.round(endTime - startTime);
43201
44426
  addRequestHistory(
43202
44427
  {
43203
44428
  method: "completion",
@@ -43206,7 +44431,9 @@ const useMCPOperations = () => {
43206
44431
  argName,
43207
44432
  value
43208
44433
  },
43209
- { completions: result }
44434
+ { completions: result },
44435
+ operationTimestamp,
44436
+ latency
43210
44437
  );
43211
44438
  return result;
43212
44439
  },
@@ -43444,6 +44671,7 @@ const App = () => {
43444
44671
  return hash || "tools";
43445
44672
  });
43446
44673
  const [isSidebarExpanded, setIsSidebarExpanded] = reactExports.useState(true);
44674
+ const [showStarModal, setShowStarModal] = reactExports.useState(false);
43447
44675
  reactExports.useEffect(() => {
43448
44676
  const handleHashChange = () => {
43449
44677
  const hash = window.location.hash.slice(1);
@@ -43454,6 +44682,20 @@ const App = () => {
43454
44682
  window.addEventListener("hashchange", handleHashChange);
43455
44683
  return () => window.removeEventListener("hashchange", handleHashChange);
43456
44684
  }, []);
44685
+ reactExports.useEffect(() => {
44686
+ const hasSeenStarModal = localStorage.getItem("hasSeenStarModal");
44687
+ if (hasSeenStarModal) {
44688
+ return;
44689
+ }
44690
+ const timer = setTimeout(() => {
44691
+ setShowStarModal(true);
44692
+ }, 15e3);
44693
+ return () => clearTimeout(timer);
44694
+ }, []);
44695
+ const handleCloseStarModal = () => {
44696
+ setShowStarModal(false);
44697
+ localStorage.setItem("hasSeenStarModal", "true");
44698
+ };
43457
44699
  const onStdErrNotification = reactExports.useCallback(
43458
44700
  (notification) => {
43459
44701
  mcpOperations.setStdErrNotifications((prev) => [...prev, notification]);
@@ -43584,6 +44826,39 @@ const App = () => {
43584
44826
  console.error("Failed to save client:", error);
43585
44827
  }
43586
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
+ );
43587
44862
  const handleEditClient = reactExports.useCallback(
43588
44863
  (serverName) => {
43589
44864
  const serverConnections = connectionState.mcpAgent ? connectionState.mcpAgent.getAllConnectionInfo() : [];
@@ -43808,7 +45083,7 @@ const App = () => {
43808
45083
  }, []);
43809
45084
  if (window.location.pathname === "/oauth/callback") {
43810
45085
  const OAuthCallback = React.lazy(
43811
- () => __vitePreload(() => import("./OAuthCallback-B9WXxW14.js"), true ? __vite__mapDeps([0,1]) : void 0)
45086
+ () => __vitePreload(() => import("./OAuthCallback-DkLMDxkx.js"), true ? __vite__mapDeps([0,1]) : void 0)
43812
45087
  );
43813
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(
43814
45089
  reactExports.Suspense,
@@ -43823,7 +45098,7 @@ const App = () => {
43823
45098
  }
43824
45099
  if (window.location.pathname === "/oauth/callback/debug") {
43825
45100
  const OAuthDebugCallback = React.lazy(
43826
- () => __vitePreload(() => import("./OAuthDebugCallback-Dypsoomr.js"), true ? __vite__mapDeps([2,1]) : void 0)
45101
+ () => __vitePreload(() => import("./OAuthDebugCallback-DaNmVTKt.js"), true ? __vite__mapDeps([2,1]) : void 0)
43827
45102
  );
43828
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(
43829
45104
  reactExports.Suspense,
@@ -43854,6 +45129,7 @@ const App = () => {
43854
45129
  headerName: configState.headerName,
43855
45130
  setHeaderName: configState.setHeaderName,
43856
45131
  onSave: handleSaveClient,
45132
+ onSaveMultiple: handleSaveMultiple,
43857
45133
  onCancel: serverState.handleCancelClientForm
43858
45134
  }
43859
45135
  );
@@ -44096,45 +45372,48 @@ const App = () => {
44096
45372
  };
44097
45373
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-auto p-6", children: !connectionState.mcpAgent || (currentClient == null ? void 0 : currentClient.connectionStatus) !== "connected" ? renderServerNotConnected() : serverHasNoCapabilities ? renderServerNoCapabilities() : renderCurrentPage() });
44098
45374
  };
44099
- return /* @__PURE__ */ jsxRuntimeExports.jsx(McpClientContext.Provider, { value: currentClient, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-screen bg-gradient-to-br from-slate-50/50 to-slate-100/50 dark:from-slate-900/50 dark:to-slate-800/50 flex overflow-hidden app-container", children: [
44100
- /* @__PURE__ */ jsxRuntimeExports.jsx(
44101
- Sidebar,
44102
- {
44103
- mcpAgent: connectionState.mcpAgent,
44104
- selectedServerName: serverState.selectedServerName,
44105
- onServerSelect: serverState.setSelectedServerName,
44106
- onRemoveServer: handleRemoveServer,
44107
- onConnectServer: connectionState.connectServer,
44108
- onDisconnectServer: connectionState.disconnectServer,
44109
- onCreateClient: serverState.handleCreateClient,
44110
- onEditClient: handleEditClient,
44111
- updateTrigger: connectionState.sidebarUpdateTrigger,
44112
- isExpanded: isSidebarExpanded,
44113
- onToggleExpanded: () => setIsSidebarExpanded(!isSidebarExpanded)
44114
- }
44115
- ),
44116
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
45375
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(McpClientContext.Provider, { value: currentClient, children: [
45376
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-screen bg-gradient-to-br from-slate-50/50 to-slate-100/50 dark:from-slate-900/50 dark:to-slate-800/50 flex overflow-hidden app-container", children: [
44117
45377
  /* @__PURE__ */ jsxRuntimeExports.jsx(
44118
- Tabs,
45378
+ Sidebar,
44119
45379
  {
44120
- currentPage,
44121
- onPageChange: setCurrentPage,
44122
- serverCapabilities,
44123
- pendingSampleRequests: mcpOperations.pendingSampleRequests,
44124
- shouldDisableAll: !connectionState.mcpAgent
45380
+ mcpAgent: connectionState.mcpAgent,
45381
+ selectedServerName: serverState.selectedServerName,
45382
+ onServerSelect: serverState.setSelectedServerName,
45383
+ onRemoveServer: handleRemoveServer,
45384
+ onConnectServer: connectionState.connectServer,
45385
+ onDisconnectServer: connectionState.disconnectServer,
45386
+ onCreateClient: serverState.handleCreateClient,
45387
+ onEditClient: handleEditClient,
45388
+ updateTrigger: connectionState.sidebarUpdateTrigger,
45389
+ isExpanded: isSidebarExpanded,
45390
+ onToggleExpanded: () => setIsSidebarExpanded(!isSidebarExpanded)
44125
45391
  }
44126
45392
  ),
44127
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-hidden overflow-y-auto", children: renderTabs() }),
44128
- /* @__PURE__ */ jsxRuntimeExports.jsx(
44129
- HistoryAndNotifications,
44130
- {
44131
- requestHistory,
44132
- toolResult: mcpOperations.toolResult,
44133
- onClearHistory: mcpOperations.clearRequestHistory
44134
- }
44135
- )
44136
- ] })
44137
- ] }) });
45393
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
45394
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45395
+ Tabs,
45396
+ {
45397
+ currentPage,
45398
+ onPageChange: setCurrentPage,
45399
+ serverCapabilities,
45400
+ pendingSampleRequests: mcpOperations.pendingSampleRequests,
45401
+ shouldDisableAll: !connectionState.mcpAgent
45402
+ }
45403
+ ),
45404
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col overflow-hidden overflow-y-auto", children: renderTabs() }),
45405
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
45406
+ HistoryAndNotifications,
45407
+ {
45408
+ requestHistory,
45409
+ toolResult: mcpOperations.toolResult,
45410
+ onClearHistory: mcpOperations.clearRequestHistory
45411
+ }
45412
+ )
45413
+ ] })
45414
+ ] }),
45415
+ /* @__PURE__ */ jsxRuntimeExports.jsx(StarGitHubModal, { isOpen: showStarModal, onClose: handleCloseStarModal })
45416
+ ] });
44138
45417
  };
44139
45418
  clientExports.createRoot(document.getElementById("root")).render(
44140
45419
  /* @__PURE__ */ jsxRuntimeExports.jsxs(reactExports.StrictMode, { children: [