@trops/dash-core 0.1.65 → 0.1.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -26533,94 +26533,105 @@ var ProviderDetail = function ProviderDetail(_ref) {
26533
26533
  text: isMcp ? "MCP Server" : "API Credentials"
26534
26534
  })]
26535
26535
  })]
26536
- }), isMcp && provider.mcpConfig && /*#__PURE__*/jsxRuntime.jsxs("div", {
26537
- className: "space-y-4",
26538
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26539
- className: "border-t border-white/10 pt-4",
26540
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26541
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider mb-3",
26542
- children: "MCP Server Configuration"
26543
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26544
- className: "space-y-2 text-sm",
26545
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26546
- className: "flex gap-2",
26547
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26548
- className: "opacity-50 w-20",
26549
- children: "Transport:"
26550
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26551
- children: provider.mcpConfig.transport === "streamable_http" ? "Streamable HTTP" : "stdio"
26552
- })]
26553
- }), provider.mcpConfig.transport === "streamable_http" ? /*#__PURE__*/jsxRuntime.jsxs("div", {
26554
- className: "flex gap-2",
26555
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26556
- className: "opacity-50 w-20",
26557
- children: "Endpoint:"
26558
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26559
- className: "text-xs opacity-70",
26560
- children: "Remote hosted server"
26561
- })]
26562
- }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26536
+ }), isMcp && provider.mcpConfig && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26537
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26538
+ className: "space-y-4",
26539
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26540
+ className: "border-t border-white/10 pt-4",
26541
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26542
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider mb-3",
26543
+ children: "Server Configuration"
26544
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26545
+ className: "space-y-2 text-sm",
26563
26546
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26564
26547
  className: "flex gap-2",
26565
26548
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26566
26549
  className: "opacity-50 w-20",
26567
- children: "Command:"
26568
- }), /*#__PURE__*/jsxRuntime.jsxs("code", {
26569
- className: "text-xs bg-white/5 px-2 py-0.5 rounded",
26570
- children: [provider.mcpConfig.command, " ", (provider.mcpConfig.args || []).join(" ")]
26550
+ children: "Transport:"
26551
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26552
+ children: provider.mcpConfig.transport === "streamable_http" ? "Streamable HTTP" : "stdio"
26571
26553
  })]
26572
- }), provider.mcpConfig.envMapping && Object.keys(provider.mcpConfig.envMapping).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
26554
+ }), provider.mcpConfig.transport === "streamable_http" ? /*#__PURE__*/jsxRuntime.jsxs("div", {
26573
26555
  className: "flex gap-2",
26574
26556
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26575
26557
  className: "opacity-50 w-20",
26576
- children: "Env Vars:"
26558
+ children: "Endpoint:"
26577
26559
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
26578
- className: "text-xs",
26579
- children: Object.keys(provider.mcpConfig.envMapping).join(", ")
26560
+ className: "text-xs opacity-70",
26561
+ children: "Remote hosted server"
26562
+ })]
26563
+ }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26564
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26565
+ className: "flex gap-2",
26566
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26567
+ className: "opacity-50 w-20",
26568
+ children: "Command:"
26569
+ }), /*#__PURE__*/jsxRuntime.jsxs("code", {
26570
+ className: "text-xs bg-white/5 px-2 py-0.5 rounded",
26571
+ children: [provider.mcpConfig.command, " ", (provider.mcpConfig.args || []).join(" ")]
26572
+ })]
26573
+ }), provider.mcpConfig.envMapping && Object.keys(provider.mcpConfig.envMapping).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
26574
+ className: "flex gap-2",
26575
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
26576
+ className: "opacity-50 w-20",
26577
+ children: "Env Vars:"
26578
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26579
+ className: "text-xs",
26580
+ children: Object.keys(provider.mcpConfig.envMapping).join(", ")
26581
+ })]
26580
26582
  })]
26581
26583
  })]
26582
26584
  })]
26583
- })]
26584
- }), authResult && /*#__PURE__*/jsxRuntime.jsx("div", {
26585
- className: "p-3 rounded-lg text-sm ".concat(authResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
26586
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26587
- className: "flex items-center gap-2",
26588
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26589
- icon: authResult.success ? "circle-check" : "circle-exclamation"
26590
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26591
- children: authResult.message
26592
- })]
26593
- })
26594
- }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
26595
- className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
26596
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26597
- className: "flex items-center gap-2",
26598
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26599
- icon: testResult.success ? "circle-check" : "circle-exclamation"
26600
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26601
- children: testResult.message
26602
- })]
26603
26585
  })
26604
- }), (testResult === null || testResult === void 0 ? void 0 : testResult.success) && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools && /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
26605
- tools: testResult.tools,
26606
- selectedTools: selectedTools,
26607
- onSelectionChange: setSelectedTools
26608
- }), !testResult && (provider === null || provider === void 0 ? void 0 : provider.allowedTools) && provider.allowedTools.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
26609
- className: "space-y-2",
26610
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26611
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26612
- children: "Allowed Tools"
26613
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
26614
- className: "flex flex-wrap gap-1",
26615
- children: provider.allowedTools.map(function (tool) {
26616
- return /*#__PURE__*/jsxRuntime.jsx("span", {
26617
- className: "text-xs font-mono px-2 py-0.5 rounded bg-white/5 opacity-70",
26618
- children: tool
26619
- }, tool);
26586
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26587
+ className: "space-y-4",
26588
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26589
+ className: "border-t border-white/10 pt-4",
26590
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
26591
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider mb-3",
26592
+ children: "Connection & Tools"
26620
26593
  })
26621
- }), /*#__PURE__*/jsxRuntime.jsxs("p", {
26622
- className: "text-xs opacity-40",
26623
- children: [provider.allowedTools.length, " tool", provider.allowedTools.length !== 1 ? "s" : "", " allowed \u2014 test connection to modify"]
26594
+ }), authResult && /*#__PURE__*/jsxRuntime.jsx("div", {
26595
+ className: "p-3 rounded-lg text-sm ".concat(authResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
26596
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26597
+ className: "flex items-center gap-2",
26598
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26599
+ icon: authResult.success ? "circle-check" : "circle-exclamation"
26600
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26601
+ children: authResult.message
26602
+ })]
26603
+ })
26604
+ }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
26605
+ className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
26606
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26607
+ className: "flex items-center gap-2",
26608
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26609
+ icon: testResult.success ? "circle-check" : "circle-exclamation"
26610
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26611
+ children: testResult.message
26612
+ })]
26613
+ })
26614
+ }), (testResult === null || testResult === void 0 ? void 0 : testResult.success) && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools && /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
26615
+ tools: testResult.tools,
26616
+ selectedTools: selectedTools,
26617
+ onSelectionChange: setSelectedTools
26618
+ }), !testResult && (provider === null || provider === void 0 ? void 0 : provider.allowedTools) && provider.allowedTools.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
26619
+ className: "space-y-2",
26620
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26621
+ className: "flex flex-wrap gap-1",
26622
+ children: provider.allowedTools.map(function (tool) {
26623
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
26624
+ className: "text-xs font-mono px-2 py-0.5 rounded bg-white/5 opacity-70",
26625
+ children: tool
26626
+ }, tool);
26627
+ })
26628
+ }), /*#__PURE__*/jsxRuntime.jsxs("p", {
26629
+ className: "text-xs opacity-40",
26630
+ children: [provider.allowedTools.length, " tool", provider.allowedTools.length !== 1 ? "s" : "", " allowed \u2014 test connection to modify"]
26631
+ })]
26632
+ }), !testResult && (!(provider !== null && provider !== void 0 && provider.allowedTools) || provider.allowedTools.length === 0) && /*#__PURE__*/jsxRuntime.jsx("p", {
26633
+ className: "text-sm opacity-40",
26634
+ children: "No tools configured \u2014 use Test Connection to discover available tools."
26624
26635
  })]
26625
26636
  })]
26626
26637
  })]
@@ -26817,19 +26828,25 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26817
26828
  selectedTools = _useState22[0],
26818
26829
  setSelectedTools = _useState22[1];
26819
26830
 
26820
- // JSON editor state
26821
- var _useState23 = React.useState("form"),
26831
+ // Wizard step state
26832
+ var _useState23 = React.useState(0),
26822
26833
  _useState24 = _slicedToArray(_useState23, 2),
26823
- viewMode = _useState24[0],
26824
- setViewMode = _useState24[1]; // "form" | "json"
26825
- var _useState25 = React.useState(""),
26834
+ wizardStep = _useState24[0],
26835
+ setWizardStep = _useState24[1];
26836
+
26837
+ // JSON editor state
26838
+ var _useState25 = React.useState("form"),
26826
26839
  _useState26 = _slicedToArray(_useState25, 2),
26827
- jsonText = _useState26[0],
26828
- setJsonText = _useState26[1];
26829
- var _useState27 = React.useState(null),
26840
+ viewMode = _useState26[0],
26841
+ setViewMode = _useState26[1]; // "form" | "json"
26842
+ var _useState27 = React.useState(""),
26830
26843
  _useState28 = _slicedToArray(_useState27, 2),
26831
- jsonError = _useState28[0],
26832
- setJsonError = _useState28[1];
26844
+ jsonText = _useState28[0],
26845
+ setJsonText = _useState28[1];
26846
+ var _useState29 = React.useState(null),
26847
+ _useState30 = _slicedToArray(_useState29, 2),
26848
+ jsonError = _useState30[0],
26849
+ setJsonError = _useState30[1];
26833
26850
 
26834
26851
  // Clear credential data when transport changes (derived fields change entirely)
26835
26852
  // Only in create mode — in edit mode the initial transport is set correctly
@@ -26840,6 +26857,23 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26840
26857
  }
26841
26858
  }, [transport, isEditMode]);
26842
26859
 
26860
+ // Wizard step navigation with validation gates
26861
+ var handleWizardStepChange = function handleWizardStepChange(newStep) {
26862
+ if (newStep < wizardStep) {
26863
+ setWizardStep(newStep);
26864
+ return;
26865
+ }
26866
+ // Step 0→1: validate form (skip validation in JSON mode, handled on save)
26867
+ if (wizardStep === 0 && newStep >= 1) {
26868
+ if (viewMode === "form" && !validateForm()) return;
26869
+ }
26870
+ // Step 1→2: require test success OR edit mode with existing tools
26871
+ if (wizardStep === 1 && newStep >= 2) {
26872
+ if (!(testResult !== null && testResult !== void 0 && testResult.success) && !(isEditMode && initialAllowedTools)) return;
26873
+ }
26874
+ setWizardStep(newStep);
26875
+ };
26876
+
26843
26877
  // Build mcpConfig from current state
26844
26878
  var mcpConfig = React.useMemo(function () {
26845
26879
  return buildMcpConfig(transport, {
@@ -26851,6 +26885,16 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26851
26885
  });
26852
26886
  }, [transport, command, args, envMappingRows, url, headerRows]);
26853
26887
 
26888
+ // Invalidate test result when config changes after a test
26889
+ var mcpConfigRef = React.useRef(mcpConfig);
26890
+ React.useEffect(function () {
26891
+ if (mcpConfigRef.current !== mcpConfig && testResult) {
26892
+ setTestResult(null);
26893
+ setSelectedTools(initialAllowedTools);
26894
+ }
26895
+ mcpConfigRef.current = mcpConfig;
26896
+ }, [mcpConfig, testResult, initialAllowedTools]);
26897
+
26854
26898
  // Derive credential fields from the live mcpConfig
26855
26899
  var formFields = React.useMemo(function () {
26856
26900
  return deriveFormFields(mcpConfig, initialCredentialSchema);
@@ -27051,414 +27095,487 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
27051
27095
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
27052
27096
  className: "flex flex-col flex-1 min-h-0",
27053
27097
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27054
- className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-5",
27055
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27056
- className: "flex items-center gap-3",
27057
- children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27058
- onClick: onBack,
27059
- className: "text-gray-400 hover:text-gray-200 transition-colors",
27060
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27061
- icon: "arrow-left",
27062
- className: "text-lg"
27063
- })
27064
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27065
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
27066
- title: isEditMode ? "Edit MCP Server" : "Configure Custom MCP Server",
27067
- padding: false
27068
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27069
- className: "text-sm opacity-50 mt-1",
27070
- children: isEditMode ? "Modify this MCP server configuration" : "Define a custom MCP server connection"
27071
- })]
27072
- })]
27073
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27074
- className: "flex flex-col gap-2",
27075
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27076
- label: "Provider Name",
27077
- required: true
27078
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27079
- className: "text-sm opacity-50",
27080
- children: "A name to identify this MCP server (e.g., \"My Custom Server\")"
27081
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27082
- value: providerName,
27083
- onChange: function onChange(value) {
27084
- setProviderName(value);
27085
- if (formErrors.providerName && value !== null && value !== void 0 && value.trim()) {
27086
- setFormErrors(function (prev) {
27087
- var next = _objectSpread$5({}, prev);
27088
- delete next.providerName;
27089
- return next;
27090
- });
27091
- }
27092
- },
27093
- placeholder: "Enter provider name"
27094
- }), formErrors.providerName && /*#__PURE__*/jsxRuntime.jsx("p", {
27095
- className: "text-sm text-red-400",
27096
- children: formErrors.providerName
27097
- })]
27098
+ className: "flex items-center gap-3 px-6 pt-6 pb-2",
27099
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27100
+ onClick: onBack,
27101
+ className: "text-gray-400 hover:text-gray-200 transition-colors",
27102
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27103
+ icon: "arrow-left",
27104
+ className: "text-lg"
27105
+ })
27098
27106
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27099
- className: "flex items-center gap-1",
27100
- children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27101
- onClick: function onClick() {
27102
- if (viewMode === "json") handleSwitchToForm();
27103
- },
27104
- className: "px-3 py-1 text-xs font-medium rounded-l transition-colors ".concat(viewMode === "form" ? "bg-white/10 text-white" : "text-white/50 hover:text-white/70"),
27105
- children: "Form"
27106
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
27107
- onClick: function onClick() {
27108
- if (viewMode === "form") handleSwitchToJson();
27109
- },
27110
- className: "px-3 py-1 text-xs font-medium rounded-r transition-colors ".concat(viewMode === "json" ? "bg-white/10 text-white" : "text-white/50 hover:text-white/70"),
27111
- children: "JSON"
27112
- })]
27113
- }), jsonError && /*#__PURE__*/jsxRuntime.jsx("p", {
27114
- className: "text-sm text-red-400",
27115
- children: jsonError
27116
- }), viewMode === "json" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27117
- className: "space-y-2",
27118
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27119
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27120
- children: "MCP Server Configuration (JSON)"
27107
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
27108
+ title: isEditMode ? "Edit MCP Server" : "Configure Custom MCP Server",
27109
+ padding: false
27121
27110
  }), /*#__PURE__*/jsxRuntime.jsx("p", {
27122
- className: "text-sm opacity-50",
27123
- children: "Paste a standard MCP config JSON (compatible with Claude Desktop, Cursor, etc.)"
27124
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.CodeEditorInline, {
27125
- code: jsonText,
27126
- setCode: function setCode(val) {
27127
- setJsonText(val);
27128
- setJsonError(null);
27129
- },
27130
- language: "json",
27131
- placeholder: '{\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "${API_KEY}"\n }\n}'
27111
+ className: "text-sm opacity-50 mt-1",
27112
+ children: isEditMode ? "Modify this MCP server configuration" : "Define a custom MCP server connection"
27132
27113
  })]
27133
- }), viewMode === "form" && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27134
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27135
- className: "space-y-2",
27136
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27137
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27138
- children: "Transport Type"
27139
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27140
- className: "grid grid-cols-2 gap-3",
27141
- children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
27142
- hover: true,
27143
- selected: transport === "stdio",
27144
- onClick: function onClick() {
27145
- return setTransport("stdio");
27146
- },
27147
- className: "text-left",
27148
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27149
- className: "flex items-center gap-2 mb-1",
27150
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
27151
- icon: "terminal"
27152
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27153
- className: "font-semibold text-sm",
27154
- children: "Local Process (stdio)"
27155
- })]
27114
+ })]
27115
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27116
+ className: "flex-1 min-h-0 flex flex-col",
27117
+ children: /*#__PURE__*/jsxRuntime.jsxs(DashReact.Stepper, {
27118
+ activeStep: wizardStep,
27119
+ onStepChange: handleWizardStepChange,
27120
+ showNavigation: false,
27121
+ className: "flex-1 min-h-0 flex flex-col",
27122
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
27123
+ label: "Configure",
27124
+ description: "Server & credentials",
27125
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27126
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
27127
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27128
+ className: "flex flex-col gap-2",
27129
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27130
+ label: "Provider Name",
27131
+ required: true
27156
27132
  }), /*#__PURE__*/jsxRuntime.jsx("p", {
27157
- className: "text-xs opacity-50",
27158
- children: "Spawn a local command as a child process"
27133
+ className: "text-sm opacity-50",
27134
+ children: "A name to identify this MCP server (e.g., \"My Custom Server\")"
27135
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27136
+ value: providerName,
27137
+ onChange: function onChange(value) {
27138
+ setProviderName(value);
27139
+ if (formErrors.providerName && value !== null && value !== void 0 && value.trim()) {
27140
+ setFormErrors(function (prev) {
27141
+ var next = _objectSpread$5({}, prev);
27142
+ delete next.providerName;
27143
+ return next;
27144
+ });
27145
+ }
27146
+ },
27147
+ placeholder: "Enter provider name"
27148
+ }), formErrors.providerName && /*#__PURE__*/jsxRuntime.jsx("p", {
27149
+ className: "text-sm text-red-400",
27150
+ children: formErrors.providerName
27159
27151
  })]
27160
- }), /*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
27161
- hover: true,
27162
- selected: transport === "streamable_http",
27163
- onClick: function onClick() {
27164
- return setTransport("streamable_http");
27165
- },
27166
- className: "text-left",
27167
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27168
- className: "flex items-center gap-2 mb-1",
27169
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
27170
- icon: "globe"
27171
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27172
- className: "font-semibold text-sm",
27173
- children: "Remote Server (HTTP)"
27174
- })]
27175
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27176
- className: "text-xs opacity-50",
27177
- children: "Connect to a remote MCP server via HTTP"
27152
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27153
+ className: "flex items-center gap-1",
27154
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27155
+ onClick: function onClick() {
27156
+ if (viewMode === "json") handleSwitchToForm();
27157
+ },
27158
+ className: "px-3 py-1 text-xs font-medium rounded-l transition-colors ".concat(viewMode === "form" ? "bg-white/10 text-white" : "text-white/50 hover:text-white/70"),
27159
+ children: "Form"
27160
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
27161
+ onClick: function onClick() {
27162
+ if (viewMode === "form") handleSwitchToJson();
27163
+ },
27164
+ className: "px-3 py-1 text-xs font-medium rounded-r transition-colors ".concat(viewMode === "json" ? "bg-white/10 text-white" : "text-white/50 hover:text-white/70"),
27165
+ children: "JSON"
27178
27166
  })]
27179
- })]
27180
- })]
27181
- }), transport === "stdio" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27182
- className: "space-y-4",
27183
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27184
- className: "border-t border-white/10 pt-4",
27185
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
27186
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27187
- children: "Process Configuration"
27188
- })
27189
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27190
- className: "flex flex-col gap-2",
27191
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27192
- label: "Command",
27193
- required: true
27194
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27195
- className: "text-sm opacity-50",
27196
- children: "The executable to run (e.g., npx, node, python)"
27197
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27198
- value: command,
27199
- onChange: function onChange(value) {
27200
- setCommand(value);
27201
- if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
27202
- setFormErrors(function (prev) {
27203
- var next = _objectSpread$5({}, prev);
27204
- delete next.command;
27205
- return next;
27206
- });
27207
- }
27208
- },
27209
- placeholder: "e.g., npx"
27210
- }), formErrors.command && /*#__PURE__*/jsxRuntime.jsx("p", {
27167
+ }), jsonError && /*#__PURE__*/jsxRuntime.jsx("p", {
27211
27168
  className: "text-sm text-red-400",
27212
- children: formErrors.command
27213
- })]
27214
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27215
- className: "flex flex-col gap-2",
27216
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27217
- label: "Arguments"
27218
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27219
- className: "text-sm opacity-50",
27220
- children: "Space-separated arguments passed to the command"
27221
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27222
- value: args,
27223
- onChange: setArgs,
27224
- placeholder: "e.g., -y @modelcontextprotocol/server-github"
27225
- })]
27226
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27227
- className: "space-y-3",
27228
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27229
- className: "flex items-center justify-between",
27230
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27231
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27232
- label: "Environment Variable Mapping"
27233
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27234
- className: "text-sm opacity-50 mt-1",
27235
- children: "Map environment variables to credential fields"
27169
+ children: jsonError
27170
+ }), viewMode === "json" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27171
+ className: "space-y-2",
27172
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27173
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27174
+ children: "MCP Server Configuration (JSON)"
27175
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27176
+ className: "text-sm opacity-50",
27177
+ children: "Paste a standard MCP config JSON (compatible with Claude Desktop, Cursor, etc.)"
27178
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.CodeEditorInline, {
27179
+ code: jsonText,
27180
+ setCode: function setCode(val) {
27181
+ setJsonText(val);
27182
+ setJsonError(null);
27183
+ },
27184
+ language: "json",
27185
+ placeholder: '{\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "${API_KEY}"\n }\n}'
27186
+ })]
27187
+ }), viewMode === "form" && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27188
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27189
+ className: "space-y-2",
27190
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27191
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27192
+ children: "Transport Type"
27193
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27194
+ className: "grid grid-cols-2 gap-3",
27195
+ children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
27196
+ hover: true,
27197
+ selected: transport === "stdio",
27198
+ onClick: function onClick() {
27199
+ return setTransport("stdio");
27200
+ },
27201
+ className: "text-left",
27202
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27203
+ className: "flex items-center gap-2 mb-1",
27204
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
27205
+ icon: "terminal"
27206
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27207
+ className: "font-semibold text-sm",
27208
+ children: "Local Process (stdio)"
27209
+ })]
27210
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27211
+ className: "text-xs opacity-50",
27212
+ children: "Spawn a local command as a child process"
27213
+ })]
27214
+ }), /*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
27215
+ hover: true,
27216
+ selected: transport === "streamable_http",
27217
+ onClick: function onClick() {
27218
+ return setTransport("streamable_http");
27219
+ },
27220
+ className: "text-left",
27221
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27222
+ className: "flex items-center gap-2 mb-1",
27223
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
27224
+ icon: "globe"
27225
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27226
+ className: "font-semibold text-sm",
27227
+ children: "Remote Server (HTTP)"
27228
+ })]
27229
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27230
+ className: "text-xs opacity-50",
27231
+ children: "Connect to a remote MCP server via HTTP"
27232
+ })]
27233
+ })]
27236
27234
  })]
27237
- })
27238
- }), envMappingRows.map(function (row) {
27239
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
27240
- className: "flex items-center gap-2",
27235
+ }), transport === "stdio" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27236
+ className: "space-y-4",
27241
27237
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27242
- className: "flex-1",
27243
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27244
- value: row.envVar,
27245
- onChange: function onChange(value) {
27246
- return updateEnvRow(row.id, "envVar", value);
27247
- },
27248
- placeholder: "ENV_VAR_NAME"
27238
+ className: "border-t border-white/10 pt-4",
27239
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
27240
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27241
+ children: "Process Configuration"
27249
27242
  })
27250
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27251
- className: "opacity-30 text-sm shrink-0",
27252
- children: "\u2192"
27253
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
27254
- className: "flex-1",
27255
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27256
- value: row.credField,
27243
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27244
+ className: "flex flex-col gap-2",
27245
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27246
+ label: "Command",
27247
+ required: true
27248
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27249
+ className: "text-sm opacity-50",
27250
+ children: "The executable to run (e.g., npx, node, python)"
27251
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27252
+ value: command,
27257
27253
  onChange: function onChange(value) {
27258
- return updateEnvRow(row.id, "credField", value);
27254
+ setCommand(value);
27255
+ if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
27256
+ setFormErrors(function (prev) {
27257
+ var next = _objectSpread$5({}, prev);
27258
+ delete next.command;
27259
+ return next;
27260
+ });
27261
+ }
27259
27262
  },
27260
- placeholder: "credentialField"
27261
- })
27262
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
27263
- onClick: function onClick() {
27264
- return removeEnvRow(row.id);
27265
- },
27266
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27267
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27268
- icon: "times",
27269
- className: "text-sm"
27270
- })
27271
- })]
27272
- }, row.id);
27273
- }), /*#__PURE__*/jsxRuntime.jsxs("button", {
27274
- onClick: addEnvRow,
27275
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27276
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27277
- icon: "plus",
27278
- className: "text-xs"
27279
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27280
- children: "Add Environment Variable"
27281
- })]
27282
- })]
27283
- })]
27284
- }), transport === "streamable_http" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27285
- className: "space-y-4",
27286
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27287
- className: "border-t border-white/10 pt-4",
27288
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
27289
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27290
- children: "Server Configuration"
27291
- })
27292
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27293
- className: "flex flex-col gap-2",
27294
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27295
- label: "Server URL",
27296
- required: true
27297
- }), /*#__PURE__*/jsxRuntime.jsxs("p", {
27298
- className: "text-sm opacity-50",
27299
- children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
27300
- className: "text-xs bg-white/10 px-1 py-0.5 rounded",
27301
- children: "{{fieldName}}"
27302
- }), " ", "for values provided as credentials"]
27303
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27304
- value: url,
27305
- onChange: function onChange(value) {
27306
- setUrl(value);
27307
- if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
27308
- setFormErrors(function (prev) {
27309
- var next = _objectSpread$5({}, prev);
27310
- delete next.url;
27311
- return next;
27312
- });
27313
- }
27314
- },
27315
- placeholder: "e.g., https://mcp.example.com/sse"
27316
- }), formErrors.url && /*#__PURE__*/jsxRuntime.jsx("p", {
27317
- className: "text-sm text-red-400",
27318
- children: formErrors.url
27319
- })]
27320
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27321
- className: "space-y-3",
27322
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27323
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27324
- label: "Request Headers"
27325
- }), /*#__PURE__*/jsxRuntime.jsxs("p", {
27326
- className: "text-sm opacity-50 mt-1",
27327
- children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
27328
- className: "text-xs bg-white/10 px-1 py-0.5 rounded",
27329
- children: "{{fieldName}}"
27330
- }), " ", "in values for credential placeholders"]
27331
- })]
27332
- }), headerRows.map(function (row) {
27333
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
27334
- className: "flex items-center gap-2",
27263
+ placeholder: "e.g., npx"
27264
+ }), formErrors.command && /*#__PURE__*/jsxRuntime.jsx("p", {
27265
+ className: "text-sm text-red-400",
27266
+ children: formErrors.command
27267
+ })]
27268
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27269
+ className: "flex flex-col gap-2",
27270
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27271
+ label: "Arguments"
27272
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27273
+ className: "text-sm opacity-50",
27274
+ children: "Space-separated arguments passed to the command"
27275
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27276
+ value: args,
27277
+ onChange: setArgs,
27278
+ placeholder: "e.g., -y @modelcontextprotocol/server-github"
27279
+ })]
27280
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27281
+ className: "space-y-3",
27282
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27283
+ className: "flex items-center justify-between",
27284
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27285
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27286
+ label: "Environment Variable Mapping"
27287
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27288
+ className: "text-sm opacity-50 mt-1",
27289
+ children: "Map environment variables to credential fields"
27290
+ })]
27291
+ })
27292
+ }), envMappingRows.map(function (row) {
27293
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27294
+ className: "flex items-center gap-2",
27295
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27296
+ className: "flex-1",
27297
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27298
+ value: row.envVar,
27299
+ onChange: function onChange(value) {
27300
+ return updateEnvRow(row.id, "envVar", value);
27301
+ },
27302
+ placeholder: "ENV_VAR_NAME"
27303
+ })
27304
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27305
+ className: "opacity-30 text-sm shrink-0",
27306
+ children: "\u2192"
27307
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27308
+ className: "flex-1",
27309
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27310
+ value: row.credField,
27311
+ onChange: function onChange(value) {
27312
+ return updateEnvRow(row.id, "credField", value);
27313
+ },
27314
+ placeholder: "credentialField"
27315
+ })
27316
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
27317
+ onClick: function onClick() {
27318
+ return removeEnvRow(row.id);
27319
+ },
27320
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27321
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27322
+ icon: "times",
27323
+ className: "text-sm"
27324
+ })
27325
+ })]
27326
+ }, row.id);
27327
+ }), /*#__PURE__*/jsxRuntime.jsxs("button", {
27328
+ onClick: addEnvRow,
27329
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27330
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27331
+ icon: "plus",
27332
+ className: "text-xs"
27333
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27334
+ children: "Add Environment Variable"
27335
+ })]
27336
+ })]
27337
+ })]
27338
+ }), transport === "streamable_http" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27339
+ className: "space-y-4",
27335
27340
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27336
- className: "flex-1",
27337
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27338
- value: row.headerName,
27339
- onChange: function onChange(value) {
27340
- return updateHeaderRow(row.id, "headerName", value);
27341
- },
27342
- placeholder: "Header-Name"
27341
+ className: "border-t border-white/10 pt-4",
27342
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
27343
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27344
+ children: "Server Configuration"
27343
27345
  })
27344
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27345
- className: "opacity-30 text-sm shrink-0",
27346
- children: ":"
27347
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
27348
- className: "flex-1",
27349
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27350
- value: row.headerValue,
27346
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27347
+ className: "flex flex-col gap-2",
27348
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27349
+ label: "Server URL",
27350
+ required: true
27351
+ }), /*#__PURE__*/jsxRuntime.jsxs("p", {
27352
+ className: "text-sm opacity-50",
27353
+ children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
27354
+ className: "text-xs bg-white/10 px-1 py-0.5 rounded",
27355
+ children: "{{fieldName}}"
27356
+ }), " ", "for values provided as credentials"]
27357
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27358
+ value: url,
27351
27359
  onChange: function onChange(value) {
27352
- return updateHeaderRow(row.id, "headerValue", value);
27360
+ setUrl(value);
27361
+ if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
27362
+ setFormErrors(function (prev) {
27363
+ var next = _objectSpread$5({}, prev);
27364
+ delete next.url;
27365
+ return next;
27366
+ });
27367
+ }
27353
27368
  },
27354
- placeholder: "Bearer {{apiKey}}"
27355
- })
27356
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
27357
- onClick: function onClick() {
27358
- return removeHeaderRow(row.id);
27359
- },
27360
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27361
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27362
- icon: "times",
27363
- className: "text-sm"
27364
- })
27369
+ placeholder: "e.g., https://mcp.example.com/sse"
27370
+ }), formErrors.url && /*#__PURE__*/jsxRuntime.jsx("p", {
27371
+ className: "text-sm text-red-400",
27372
+ children: formErrors.url
27373
+ })]
27374
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27375
+ className: "space-y-3",
27376
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27377
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27378
+ label: "Request Headers"
27379
+ }), /*#__PURE__*/jsxRuntime.jsxs("p", {
27380
+ className: "text-sm opacity-50 mt-1",
27381
+ children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
27382
+ className: "text-xs bg-white/10 px-1 py-0.5 rounded",
27383
+ children: "{{fieldName}}"
27384
+ }), " ", "in values for credential placeholders"]
27385
+ })]
27386
+ }), headerRows.map(function (row) {
27387
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27388
+ className: "flex items-center gap-2",
27389
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27390
+ className: "flex-1",
27391
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27392
+ value: row.headerName,
27393
+ onChange: function onChange(value) {
27394
+ return updateHeaderRow(row.id, "headerName", value);
27395
+ },
27396
+ placeholder: "Header-Name"
27397
+ })
27398
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27399
+ className: "opacity-30 text-sm shrink-0",
27400
+ children: ":"
27401
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27402
+ className: "flex-1",
27403
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27404
+ value: row.headerValue,
27405
+ onChange: function onChange(value) {
27406
+ return updateHeaderRow(row.id, "headerValue", value);
27407
+ },
27408
+ placeholder: "Bearer {{apiKey}}"
27409
+ })
27410
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
27411
+ onClick: function onClick() {
27412
+ return removeHeaderRow(row.id);
27413
+ },
27414
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27415
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27416
+ icon: "times",
27417
+ className: "text-sm"
27418
+ })
27419
+ })]
27420
+ }, row.id);
27421
+ }), /*#__PURE__*/jsxRuntime.jsxs("button", {
27422
+ onClick: addHeaderRow,
27423
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27424
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27425
+ icon: "plus",
27426
+ className: "text-xs"
27427
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27428
+ children: "Add Header"
27429
+ })]
27430
+ })]
27431
+ })]
27432
+ }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27433
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27434
+ className: "border-t border-white/10 pt-4",
27435
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27436
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27437
+ children: "Credentials"
27438
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27439
+ className: "text-sm opacity-50 mt-1",
27440
+ children: "Values for the fields referenced in your configuration above"
27441
+ })]
27442
+ }), formFields.map(function (field) {
27443
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27444
+ className: "flex flex-col gap-2",
27445
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27446
+ label: field.displayName,
27447
+ required: field.required
27448
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27449
+ className: "flex gap-2",
27450
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27451
+ className: "flex-1",
27452
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27453
+ type: field.secret ? "password" : "text",
27454
+ value: credentialData[field.key] || "",
27455
+ onChange: function onChange(value) {
27456
+ return handleCredentialChange(field.key, value);
27457
+ },
27458
+ placeholder: field.type === "file" ? "Select a file..." : "Enter ".concat(field.displayName.toLowerCase())
27459
+ })
27460
+ }), field.type === "file" && /*#__PURE__*/jsxRuntime.jsx("button", {
27461
+ onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
27462
+ var filepath;
27463
+ return _regeneratorRuntime.wrap(function (_context) {
27464
+ while (1) switch (_context.prev = _context.next) {
27465
+ case 0:
27466
+ _context.next = 1;
27467
+ return window.mainApi.dialog.chooseFile(true, ["json"]);
27468
+ case 1:
27469
+ filepath = _context.sent;
27470
+ if (filepath) handleCredentialChange(field.key, filepath);
27471
+ case 2:
27472
+ case "end":
27473
+ return _context.stop();
27474
+ }
27475
+ }, _callee);
27476
+ })),
27477
+ className: "px-3 py-1.5 text-sm rounded bg-white/10 hover:bg-white/20 transition-colors",
27478
+ children: "Browse"
27479
+ })]
27480
+ }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
27481
+ className: "text-sm text-red-400",
27482
+ children: formErrors[field.key]
27483
+ })]
27484
+ }, field.key);
27365
27485
  })]
27366
- }, row.id);
27367
- }), /*#__PURE__*/jsxRuntime.jsxs("button", {
27368
- onClick: addHeaderRow,
27369
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27370
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27371
- icon: "plus",
27372
- className: "text-xs"
27373
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27374
- children: "Add Header"
27375
27486
  })]
27376
27487
  })]
27377
- })]
27378
- }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27379
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27380
- className: "border-t border-white/10 pt-4",
27381
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27382
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27383
- children: "Credentials"
27384
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27385
- className: "text-sm opacity-50 mt-1",
27386
- children: "Values for the fields referenced in your configuration above"
27387
- })]
27388
- }), formFields.map(function (field) {
27389
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
27390
- className: "flex flex-col gap-2",
27391
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27392
- label: field.displayName,
27393
- required: field.required
27394
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27395
- className: "flex gap-2",
27396
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27397
- className: "flex-1",
27398
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27399
- type: field.secret ? "password" : "text",
27400
- value: credentialData[field.key] || "",
27401
- onChange: function onChange(value) {
27402
- return handleCredentialChange(field.key, value);
27403
- },
27404
- placeholder: field.type === "file" ? "Select a file..." : "Enter ".concat(field.displayName.toLowerCase())
27405
- })
27406
- }), field.type === "file" && /*#__PURE__*/jsxRuntime.jsx("button", {
27407
- onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
27408
- var filepath;
27409
- return _regeneratorRuntime.wrap(function (_context) {
27410
- while (1) switch (_context.prev = _context.next) {
27411
- case 0:
27412
- _context.next = 1;
27413
- return window.mainApi.dialog.chooseFile(true, ["json"]);
27414
- case 1:
27415
- filepath = _context.sent;
27416
- if (filepath) handleCredentialChange(field.key, filepath);
27417
- case 2:
27418
- case "end":
27419
- return _context.stop();
27420
- }
27421
- }, _callee);
27422
- })),
27423
- className: "px-3 py-1.5 text-sm rounded bg-white/10 hover:bg-white/20 transition-colors",
27424
- children: "Browse"
27425
- })]
27426
- }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
27427
- className: "text-sm text-red-400",
27428
- children: formErrors[field.key]
27488
+ })
27489
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
27490
+ label: "Test",
27491
+ description: "Verify connection",
27492
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27493
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
27494
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27495
+ className: "flex flex-col items-center justify-center py-8 space-y-4",
27496
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27497
+ className: "text-sm opacity-60 text-center",
27498
+ children: "Test the connection to verify your configuration is correct."
27499
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27500
+ title: isTesting ? "Testing..." : "Test Connection",
27501
+ onClick: handleTestConnection,
27502
+ size: "md"
27429
27503
  })]
27430
- }, field.key);
27431
- })]
27504
+ }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
27505
+ className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
27506
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27507
+ className: "flex items-center gap-2",
27508
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27509
+ icon: testResult.success ? "circle-check" : "circle-exclamation"
27510
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27511
+ children: testResult.message
27512
+ })]
27513
+ })
27514
+ })]
27515
+ })
27516
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
27517
+ label: "Tools",
27518
+ description: "Select allowed tools",
27519
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
27520
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
27521
+ children: testResult !== null && testResult !== void 0 && testResult.success && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools ? /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
27522
+ tools: testResult.tools,
27523
+ selectedTools: selectedTools,
27524
+ onSelectionChange: setSelectedTools
27525
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
27526
+ className: "text-center py-8 opacity-50",
27527
+ children: "No tools available. Go back and test the connection first."
27528
+ })
27529
+ })
27432
27530
  })]
27433
- }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
27434
- className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
27435
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27436
- className: "flex items-center gap-2",
27437
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27438
- icon: testResult.success ? "circle-check" : "circle-exclamation"
27439
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27440
- children: testResult.message
27441
- })]
27442
- })
27443
- }), (testResult === null || testResult === void 0 ? void 0 : testResult.success) && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools && /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
27444
- tools: testResult.tools,
27445
- selectedTools: selectedTools,
27446
- onSelectionChange: setSelectedTools
27447
- })]
27531
+ })
27448
27532
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27449
- className: "flex-shrink-0 flex flex-row justify-end gap-2 px-6 py-4 border-t border-white/10",
27450
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27451
- title: "Cancel",
27452
- onClick: onBack,
27453
- size: "sm"
27454
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27455
- title: isTesting ? "Testing..." : "Test Connection",
27456
- onClick: handleTestConnection,
27457
- size: "sm"
27458
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27459
- title: isEditMode ? "Save Changes" : "Save MCP Server",
27460
- onClick: handleSave,
27461
- size: "sm"
27533
+ className: "flex-shrink-0 flex flex-row items-center px-6 py-4 border-t border-white/10",
27534
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27535
+ className: "flex flex-row gap-2",
27536
+ children: [wizardStep === 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27537
+ title: "Cancel",
27538
+ onClick: onBack,
27539
+ size: "sm"
27540
+ }), wizardStep > 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27541
+ title: "Back",
27542
+ onClick: function onClick() {
27543
+ return setWizardStep(wizardStep - 1);
27544
+ },
27545
+ size: "sm"
27546
+ })]
27547
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27548
+ className: "flex-1 text-center",
27549
+ children: /*#__PURE__*/jsxRuntime.jsxs("span", {
27550
+ className: "text-xs opacity-40",
27551
+ children: ["Step ", wizardStep + 1, " of 3"]
27552
+ })
27553
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27554
+ className: "flex flex-row gap-2",
27555
+ children: [wizardStep === 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27556
+ title: "Next",
27557
+ onClick: function onClick() {
27558
+ return handleWizardStepChange(1);
27559
+ },
27560
+ size: "sm"
27561
+ }), wizardStep === 1 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27562
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27563
+ title: isTesting ? "Testing..." : "Test Connection",
27564
+ onClick: handleTestConnection,
27565
+ size: "sm"
27566
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27567
+ title: "Next",
27568
+ onClick: function onClick() {
27569
+ return handleWizardStepChange(2);
27570
+ },
27571
+ disabled: !(testResult !== null && testResult !== void 0 && testResult.success) && !(isEditMode && initialAllowedTools),
27572
+ size: "sm"
27573
+ })]
27574
+ }), wizardStep === 2 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27575
+ title: isEditMode ? "Save Changes" : "Save MCP Server",
27576
+ onClick: handleSave,
27577
+ size: "sm"
27578
+ })]
27462
27579
  })]
27463
27580
  })]
27464
27581
  });
@@ -27545,30 +27662,34 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
27545
27662
  _useState20 = _slicedToArray(_useState19, 2),
27546
27663
  selectedTools = _useState20[0],
27547
27664
  setSelectedTools = _useState20[1];
27665
+ var _useState21 = React.useState(0),
27666
+ _useState22 = _slicedToArray(_useState21, 2),
27667
+ wizardStep = _useState22[0],
27668
+ setWizardStep = _useState22[1];
27548
27669
 
27549
27670
  // Configuration form state
27550
- var _useState21 = React.useState(""),
27551
- _useState22 = _slicedToArray(_useState21, 2),
27552
- providerName = _useState22[0],
27553
- setProviderName = _useState22[1];
27554
- var _useState23 = React.useState({}),
27671
+ var _useState23 = React.useState(""),
27555
27672
  _useState24 = _slicedToArray(_useState23, 2),
27556
- credentialData = _useState24[0],
27557
- setCredentialData = _useState24[1];
27673
+ providerName = _useState24[0],
27674
+ setProviderName = _useState24[1];
27558
27675
  var _useState25 = React.useState({}),
27559
27676
  _useState26 = _slicedToArray(_useState25, 2),
27560
- formErrors = _useState26[0],
27561
- setFormErrors = _useState26[1];
27677
+ credentialData = _useState26[0],
27678
+ setCredentialData = _useState26[1];
27679
+ var _useState27 = React.useState({}),
27680
+ _useState28 = _slicedToArray(_useState27, 2),
27681
+ formErrors = _useState28[0],
27682
+ setFormErrors = _useState28[1];
27562
27683
 
27563
27684
  // Advanced config row state
27564
- var _useState27 = React.useState([]),
27565
- _useState28 = _slicedToArray(_useState27, 2),
27566
- envMappingRows = _useState28[0],
27567
- setEnvMappingRows = _useState28[1];
27568
27685
  var _useState29 = React.useState([]),
27569
27686
  _useState30 = _slicedToArray(_useState29, 2),
27570
- headerRows = _useState30[0],
27571
- setHeaderRows = _useState30[1];
27687
+ envMappingRows = _useState30[0],
27688
+ setEnvMappingRows = _useState30[1];
27689
+ var _useState31 = React.useState([]),
27690
+ _useState32 = _slicedToArray(_useState31, 2),
27691
+ headerRows = _useState32[0],
27692
+ setHeaderRows = _useState32[1];
27572
27693
  var rowIdRef = React.useRef(0);
27573
27694
  var nextRowId = function nextRowId() {
27574
27695
  return "cat_".concat(++rowIdRef.current);
@@ -27609,6 +27730,24 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
27609
27730
  });
27610
27731
  });
27611
27732
 
27733
+ // Wizard step navigation with validation gates
27734
+ var handleWizardStepChange = function handleWizardStepChange(newStep) {
27735
+ // Allow backward navigation freely
27736
+ if (newStep < wizardStep) {
27737
+ setWizardStep(newStep);
27738
+ return;
27739
+ }
27740
+ // Step 0→1: validate the configure form
27741
+ if (wizardStep === 0 && newStep >= 1) {
27742
+ if (!validateForm()) return;
27743
+ }
27744
+ // Step 1→2: require successful test
27745
+ if (wizardStep === 1 && newStep >= 2) {
27746
+ if (!(testResult !== null && testResult !== void 0 && testResult.success)) return;
27747
+ }
27748
+ setWizardStep(newStep);
27749
+ };
27750
+
27612
27751
  // Handle server selection -> show configuration form
27613
27752
  var handleSelectServer = function handleSelectServer(server) {
27614
27753
  var _server$mcpConfig, _server$mcpConfig2;
@@ -27619,6 +27758,7 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
27619
27758
  setProviderName(server.name);
27620
27759
  setCredentialData({});
27621
27760
  setFormErrors({});
27761
+ setWizardStep(0);
27622
27762
  setEnvMappingRows(envMappingToRows((_server$mcpConfig = server.mcpConfig) === null || _server$mcpConfig === void 0 ? void 0 : _server$mcpConfig.envMapping, nextRowId));
27623
27763
  setHeaderRows(headerTemplateToRows((_server$mcpConfig2 = server.mcpConfig) === null || _server$mcpConfig2 === void 0 ? void 0 : _server$mcpConfig2.headerTemplate, nextRowId));
27624
27764
  };
@@ -27749,6 +27889,7 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
27749
27889
  setFormErrors({});
27750
27890
  setEnvMappingRows([]);
27751
27891
  setHeaderRows([]);
27892
+ setWizardStep(0);
27752
27893
  };
27753
27894
 
27754
27895
  // Prune credential data when form fields change (advanced config removed a field)
@@ -27776,205 +27917,280 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
27776
27917
  });
27777
27918
  }
27778
27919
 
27779
- // ── Stage 2: Configuration Form ──
27920
+ // ── Stage 2: Configuration Form (3-step Stepper) ──
27780
27921
  if (isConfiguring && selectedServer) {
27781
27922
  var _testResult$tools;
27782
27923
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
27783
27924
  className: "flex flex-col flex-1 min-h-0",
27784
27925
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27785
- className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-5",
27786
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27787
- className: "flex items-center gap-3",
27788
- children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27789
- onClick: handleBack,
27790
- className: "text-gray-400 hover:text-gray-200 transition-colors",
27791
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27792
- icon: "arrow-left",
27793
- className: "text-lg"
27794
- })
27795
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27796
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
27797
- title: "Configure ".concat(selectedServer.name),
27798
- padding: false
27799
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
27800
- className: "text-sm opacity-50 mt-1",
27801
- children: selectedServer.description || "Configure the MCP server connection"
27802
- })]
27803
- })]
27804
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27805
- className: "bg-white/5 border border-white/10 rounded-lg p-4 space-y-3",
27806
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27807
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27808
- children: "MCP Server Connection"
27809
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27810
- className: "space-y-2 text-sm",
27811
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27812
- className: "flex gap-2",
27813
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27814
- className: "opacity-50 w-24 shrink-0",
27815
- children: "Transport:"
27816
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Tag, {
27817
- text: effectiveMcpConfig.transport === "streamable_http" ? "Streamable HTTP" : "stdio"
27818
- })]
27819
- }), effectiveMcpConfig.transport === "streamable_http" ? /*#__PURE__*/jsxRuntime.jsxs("div", {
27820
- className: "flex gap-2",
27821
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27822
- className: "opacity-50 w-24 shrink-0",
27823
- children: "Endpoint:"
27824
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27825
- className: "text-xs opacity-70",
27826
- children: "Remote hosted server (URL provided below)"
27827
- })]
27828
- }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27829
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27830
- className: "flex gap-2",
27831
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27832
- className: "opacity-50 w-24 shrink-0",
27833
- children: "Command:"
27834
- }), /*#__PURE__*/jsxRuntime.jsxs("code", {
27835
- className: "text-xs bg-white/5 px-2 py-0.5 rounded",
27836
- children: [effectiveMcpConfig.command, " ", (effectiveMcpConfig.args || []).join(" ")]
27837
- })]
27838
- }), effectiveMcpConfig.envMapping && Object.keys(effectiveMcpConfig.envMapping).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
27839
- className: "flex gap-2",
27840
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27841
- className: "opacity-50 w-24 shrink-0",
27842
- children: "Env Vars:"
27843
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27844
- className: "text-xs opacity-70",
27845
- children: Object.keys(effectiveMcpConfig.envMapping).join(", ")
27846
- })]
27847
- })]
27848
- })]
27849
- })]
27850
- }), /*#__PURE__*/jsxRuntime.jsx(AdvancedMcpConfig, {
27851
- transport: effectiveMcpConfig.transport || "stdio",
27852
- envMappingRows: envMappingRows,
27853
- onEnvMappingRowsChange: setEnvMappingRows,
27854
- headerRows: headerRows,
27855
- onHeaderRowsChange: setHeaderRows
27926
+ className: "flex items-center gap-3 px-6 pt-6 pb-2",
27927
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
27928
+ onClick: handleBack,
27929
+ className: "text-gray-400 hover:text-gray-200 transition-colors",
27930
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27931
+ icon: "arrow-left",
27932
+ className: "text-lg"
27933
+ })
27856
27934
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27857
- className: "flex flex-col gap-2",
27858
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27859
- label: "Provider Name",
27860
- required: true
27935
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
27936
+ title: "Configure ".concat(selectedServer.name),
27937
+ padding: false
27861
27938
  }), /*#__PURE__*/jsxRuntime.jsx("p", {
27862
- className: "text-sm opacity-50",
27863
- children: "A name to identify this MCP server instance (e.g., \"Algolia Production\")"
27864
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27865
- value: providerName,
27866
- onChange: function onChange(value) {
27867
- setProviderName(value);
27868
- if (formErrors.providerName && value !== null && value !== void 0 && value.trim()) {
27869
- setFormErrors(function (prev) {
27870
- var next = _objectSpread$4({}, prev);
27871
- delete next.providerName;
27872
- return next;
27873
- });
27874
- }
27875
- },
27876
- placeholder: "Enter provider name"
27877
- }), formErrors.providerName && /*#__PURE__*/jsxRuntime.jsx("p", {
27878
- className: "text-sm text-red-400",
27879
- children: formErrors.providerName
27939
+ className: "text-sm opacity-50 mt-1",
27940
+ children: selectedServer.description || "Configure the MCP server connection"
27880
27941
  })]
27881
- }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27882
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27883
- className: "border-t border-white/10 pt-4",
27884
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
27885
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27886
- children: effectiveMcpConfig.transport === "streamable_http" ? "Server Configuration" : "Authentication"
27887
- })
27888
- }), formFields.map(function (field) {
27889
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
27890
- className: "flex flex-col gap-2",
27891
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27892
- label: field.displayName,
27893
- required: field.required
27894
- }), field.instructions && /*#__PURE__*/jsxRuntime.jsx("p", {
27895
- className: "text-sm opacity-50",
27896
- children: field.instructions
27942
+ })]
27943
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27944
+ className: "flex-1 min-h-0 flex flex-col",
27945
+ children: /*#__PURE__*/jsxRuntime.jsxs(DashReact.Stepper, {
27946
+ activeStep: wizardStep,
27947
+ onStepChange: handleWizardStepChange,
27948
+ showNavigation: false,
27949
+ className: "flex-1 min-h-0 flex flex-col",
27950
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
27951
+ label: "Configure",
27952
+ description: "Name & credentials",
27953
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27954
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
27955
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27956
+ className: "bg-white/5 border border-white/10 rounded-lg p-4 space-y-3",
27957
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27958
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27959
+ children: "MCP Server Connection"
27960
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27961
+ className: "space-y-2 text-sm",
27962
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27963
+ className: "flex gap-2",
27964
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27965
+ className: "opacity-50 w-24 shrink-0",
27966
+ children: "Transport:"
27967
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Tag, {
27968
+ text: effectiveMcpConfig.transport === "streamable_http" ? "Streamable HTTP" : "stdio"
27969
+ })]
27970
+ }), effectiveMcpConfig.transport === "streamable_http" ? /*#__PURE__*/jsxRuntime.jsxs("div", {
27971
+ className: "flex gap-2",
27972
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27973
+ className: "opacity-50 w-24 shrink-0",
27974
+ children: "Endpoint:"
27975
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27976
+ className: "text-xs opacity-70",
27977
+ children: "Remote hosted server (URL provided below)"
27978
+ })]
27979
+ }) : /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27980
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27981
+ className: "flex gap-2",
27982
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27983
+ className: "opacity-50 w-24 shrink-0",
27984
+ children: "Command:"
27985
+ }), /*#__PURE__*/jsxRuntime.jsxs("code", {
27986
+ className: "text-xs bg-white/5 px-2 py-0.5 rounded",
27987
+ children: [effectiveMcpConfig.command, " ", (effectiveMcpConfig.args || []).join(" ")]
27988
+ })]
27989
+ }), effectiveMcpConfig.envMapping && Object.keys(effectiveMcpConfig.envMapping).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
27990
+ className: "flex gap-2",
27991
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27992
+ className: "opacity-50 w-24 shrink-0",
27993
+ children: "Env Vars:"
27994
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27995
+ className: "text-xs opacity-70",
27996
+ children: Object.keys(effectiveMcpConfig.envMapping).join(", ")
27997
+ })]
27998
+ })]
27999
+ })]
28000
+ })]
28001
+ }), /*#__PURE__*/jsxRuntime.jsx(AdvancedMcpConfig, {
28002
+ transport: effectiveMcpConfig.transport || "stdio",
28003
+ envMappingRows: envMappingRows,
28004
+ onEnvMappingRowsChange: setEnvMappingRows,
28005
+ headerRows: headerRows,
28006
+ onHeaderRowsChange: setHeaderRows
27897
28007
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27898
- className: "flex gap-2",
28008
+ className: "flex flex-col gap-2",
28009
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
28010
+ label: "Provider Name",
28011
+ required: true
28012
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
28013
+ className: "text-sm opacity-50",
28014
+ children: "A name to identify this MCP server instance (e.g., \"Algolia Production\")"
28015
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
28016
+ value: providerName,
28017
+ onChange: function onChange(value) {
28018
+ setProviderName(value);
28019
+ if (formErrors.providerName && value !== null && value !== void 0 && value.trim()) {
28020
+ setFormErrors(function (prev) {
28021
+ var next = _objectSpread$4({}, prev);
28022
+ delete next.providerName;
28023
+ return next;
28024
+ });
28025
+ }
28026
+ },
28027
+ placeholder: "Enter provider name"
28028
+ }), formErrors.providerName && /*#__PURE__*/jsxRuntime.jsx("p", {
28029
+ className: "text-sm text-red-400",
28030
+ children: formErrors.providerName
28031
+ })]
28032
+ }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27899
28033
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27900
- className: "flex-1",
27901
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27902
- type: field.secret ? "password" : "text",
27903
- value: credentialData[field.key] || "",
27904
- onChange: function onChange(value) {
27905
- return handleCredentialChange(field.key, value);
27906
- },
27907
- placeholder: field.type === "file" ? "Select a file..." : "Enter ".concat(field.displayName.toLowerCase())
28034
+ className: "border-t border-white/10 pt-4",
28035
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
28036
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
28037
+ children: effectiveMcpConfig.transport === "streamable_http" ? "Server Configuration" : "Authentication"
27908
28038
  })
27909
- }), field.type === "file" && /*#__PURE__*/jsxRuntime.jsx("button", {
27910
- onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
27911
- var filepath;
27912
- return _regeneratorRuntime.wrap(function (_context) {
27913
- while (1) switch (_context.prev = _context.next) {
27914
- case 0:
27915
- _context.next = 1;
27916
- return window.mainApi.dialog.chooseFile(true, ["json"]);
27917
- case 1:
27918
- filepath = _context.sent;
27919
- if (filepath) handleCredentialChange(field.key, filepath);
27920
- case 2:
27921
- case "end":
27922
- return _context.stop();
27923
- }
27924
- }, _callee);
27925
- })),
27926
- className: "px-3 py-1.5 text-sm rounded bg-white/10 hover:bg-white/20 transition-colors",
27927
- children: "Browse"
28039
+ }), formFields.map(function (field) {
28040
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
28041
+ className: "flex flex-col gap-2",
28042
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
28043
+ label: field.displayName,
28044
+ required: field.required
28045
+ }), field.instructions && /*#__PURE__*/jsxRuntime.jsx("p", {
28046
+ className: "text-sm opacity-50",
28047
+ children: field.instructions
28048
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
28049
+ className: "flex gap-2",
28050
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
28051
+ className: "flex-1",
28052
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
28053
+ type: field.secret ? "password" : "text",
28054
+ value: credentialData[field.key] || "",
28055
+ onChange: function onChange(value) {
28056
+ return handleCredentialChange(field.key, value);
28057
+ },
28058
+ placeholder: field.type === "file" ? "Select a file..." : "Enter ".concat(field.displayName.toLowerCase())
28059
+ })
28060
+ }), field.type === "file" && /*#__PURE__*/jsxRuntime.jsx("button", {
28061
+ onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
28062
+ var filepath;
28063
+ return _regeneratorRuntime.wrap(function (_context) {
28064
+ while (1) switch (_context.prev = _context.next) {
28065
+ case 0:
28066
+ _context.next = 1;
28067
+ return window.mainApi.dialog.chooseFile(true, ["json"]);
28068
+ case 1:
28069
+ filepath = _context.sent;
28070
+ if (filepath) handleCredentialChange(field.key, filepath);
28071
+ case 2:
28072
+ case "end":
28073
+ return _context.stop();
28074
+ }
28075
+ }, _callee);
28076
+ })),
28077
+ className: "px-3 py-1.5 text-sm rounded bg-white/10 hover:bg-white/20 transition-colors",
28078
+ children: "Browse"
28079
+ })]
28080
+ }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
28081
+ className: "text-sm text-red-400",
28082
+ children: formErrors[field.key]
28083
+ })]
28084
+ }, field.key);
27928
28085
  })]
27929
- }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
27930
- className: "text-sm text-red-400",
27931
- children: formErrors[field.key]
28086
+ }), authResult && /*#__PURE__*/jsxRuntime.jsx("div", {
28087
+ className: "p-3 rounded-lg text-sm ".concat(authResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
28088
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
28089
+ className: "flex items-center gap-2",
28090
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
28091
+ icon: authResult.success ? "circle-check" : "circle-exclamation"
28092
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
28093
+ children: authResult.message
28094
+ })]
28095
+ })
27932
28096
  })]
27933
- }, field.key);
28097
+ })
28098
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
28099
+ label: "Test",
28100
+ description: "Verify connection",
28101
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
28102
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
28103
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
28104
+ className: "flex flex-col items-center justify-center py-8 space-y-4",
28105
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
28106
+ className: "text-sm opacity-60 text-center",
28107
+ children: "Test the connection to verify your configuration is correct."
28108
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28109
+ title: isTesting ? "Testing..." : "Test Connection",
28110
+ onClick: handleTestConnection,
28111
+ size: "md"
28112
+ })]
28113
+ }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
28114
+ className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
28115
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
28116
+ className: "flex items-center gap-2",
28117
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
28118
+ icon: testResult.success ? "circle-check" : "circle-exclamation"
28119
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
28120
+ children: testResult.message
28121
+ })]
28122
+ })
28123
+ })]
28124
+ })
28125
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Stepper.Step, {
28126
+ label: "Tools",
28127
+ description: "Select allowed tools",
28128
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
28129
+ className: "flex-1 min-h-0 overflow-y-auto px-6 pb-4 space-y-5",
28130
+ children: testResult !== null && testResult !== void 0 && testResult.success && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools ? /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
28131
+ tools: testResult.tools,
28132
+ selectedTools: selectedTools,
28133
+ onSelectionChange: setSelectedTools
28134
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
28135
+ className: "text-center py-8 opacity-50",
28136
+ children: "No tools available. Go back and test the connection first."
28137
+ })
28138
+ })
27934
28139
  })]
27935
- }), authResult && /*#__PURE__*/jsxRuntime.jsx("div", {
27936
- className: "p-3 rounded-lg text-sm ".concat(authResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
27937
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27938
- className: "flex items-center gap-2",
27939
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27940
- icon: authResult.success ? "circle-check" : "circle-exclamation"
27941
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27942
- children: authResult.message
27943
- })]
28140
+ })
28141
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
28142
+ className: "flex-shrink-0 flex flex-row items-center px-6 py-4 border-t border-white/10",
28143
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
28144
+ className: "flex flex-row gap-2",
28145
+ children: [wizardStep === 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28146
+ title: "Cancel",
28147
+ onClick: onCancel,
28148
+ size: "sm"
28149
+ }), wizardStep > 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28150
+ title: "Back",
28151
+ onClick: function onClick() {
28152
+ return setWizardStep(wizardStep - 1);
28153
+ },
28154
+ size: "sm"
28155
+ })]
28156
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
28157
+ className: "flex-1 text-center",
28158
+ children: /*#__PURE__*/jsxRuntime.jsxs("span", {
28159
+ className: "text-xs opacity-40",
28160
+ children: ["Step ", wizardStep + 1, " of 3"]
27944
28161
  })
27945
- }), testResult && /*#__PURE__*/jsxRuntime.jsx("div", {
27946
- className: "p-3 rounded-lg text-sm ".concat(testResult.success ? "bg-green-900/30 border border-green-700 text-green-300" : "bg-red-900/30 border border-red-700 text-red-300"),
27947
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27948
- className: "flex items-center gap-2",
27949
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27950
- icon: testResult.success ? "circle-check" : "circle-exclamation"
27951
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
27952
- children: testResult.message
28162
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
28163
+ className: "flex flex-row gap-2",
28164
+ children: [wizardStep === 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
28165
+ children: [(selectedServer === null || selectedServer === void 0 ? void 0 : selectedServer.authCommand) && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28166
+ title: isAuthorizing ? "Authorizing..." : "Authorize",
28167
+ onClick: handleAuthorize,
28168
+ size: "sm"
28169
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28170
+ title: "Next",
28171
+ onClick: function onClick() {
28172
+ return handleWizardStepChange(1);
28173
+ },
28174
+ size: "sm"
27953
28175
  })]
27954
- })
27955
- }), (testResult === null || testResult === void 0 ? void 0 : testResult.success) && ((_testResult$tools = testResult.tools) === null || _testResult$tools === void 0 ? void 0 : _testResult$tools.length) > 0 && selectedTools && /*#__PURE__*/jsxRuntime.jsx(ToolSelector, {
27956
- tools: testResult.tools,
27957
- selectedTools: selectedTools,
27958
- onSelectionChange: setSelectedTools
27959
- })]
27960
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27961
- className: "flex-shrink-0 flex flex-row justify-end gap-2 px-6 py-4 border-t border-white/10",
27962
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27963
- title: "Cancel",
27964
- onClick: onCancel,
27965
- size: "sm"
27966
- }), (selectedServer === null || selectedServer === void 0 ? void 0 : selectedServer.authCommand) && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27967
- title: isAuthorizing ? "Authorizing..." : "Authorize",
27968
- onClick: handleAuthorize,
27969
- size: "sm"
27970
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27971
- title: isTesting ? "Testing..." : "Test Connection",
27972
- onClick: handleTestConnection,
27973
- size: "sm"
27974
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27975
- title: "Save MCP Server",
27976
- onClick: handleSaveProvider,
27977
- size: "sm"
28176
+ }), wizardStep === 1 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
28177
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28178
+ title: isTesting ? "Testing..." : "Test Connection",
28179
+ onClick: handleTestConnection,
28180
+ size: "sm"
28181
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28182
+ title: "Next",
28183
+ onClick: function onClick() {
28184
+ return handleWizardStepChange(2);
28185
+ },
28186
+ disabled: !(testResult !== null && testResult !== void 0 && testResult.success),
28187
+ size: "sm"
28188
+ })]
28189
+ }), wizardStep === 2 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
28190
+ title: "Save MCP Server",
28191
+ onClick: handleSaveProvider,
28192
+ size: "sm"
28193
+ })]
27978
28194
  })]
27979
28195
  })]
27980
28196
  });