@trops/dash-core 0.1.52 → 0.1.54

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.esm.js CHANGED
@@ -9526,6 +9526,193 @@ function headerTemplateToRows(headerTemplate, nextRowId) {
9526
9526
  });
9527
9527
  }
9528
9528
 
9529
+ /**
9530
+ * Serialize the current form state into a bare MCP JSON config string.
9531
+ *
9532
+ * Output format (stdio):
9533
+ * {
9534
+ * "type": "stdio",
9535
+ * "command": "npx",
9536
+ * "args": ["-y", "package-name"],
9537
+ * "env": { "API_KEY": "${API_KEY}" }
9538
+ * }
9539
+ *
9540
+ * Output format (HTTP):
9541
+ * {
9542
+ * "type": "streamable_http",
9543
+ * "url": "https://example.com/mcp",
9544
+ * "headerTemplate": { "Authorization": "Bearer {{apiKey}}" }
9545
+ * }
9546
+ *
9547
+ * Credential values are NOT embedded — env values use ${FIELD_NAME} syntax
9548
+ * to reference credential fields entered separately in the form.
9549
+ *
9550
+ * @param {string} name - The provider name (unused in output, kept for API compat)
9551
+ * @param {string} transport - "stdio" or "streamable_http"
9552
+ * @param {object} fields - { command, args, envMappingRows, url, headerRows }
9553
+ * @returns {string} Formatted JSON string
9554
+ */
9555
+ function formStateToMcpJson(name, transport, fields) {
9556
+ var _fields$command = fields.command,
9557
+ command = _fields$command === void 0 ? "" : _fields$command,
9558
+ _fields$args = fields.args,
9559
+ args = _fields$args === void 0 ? "" : _fields$args,
9560
+ _fields$envMappingRow = fields.envMappingRows,
9561
+ envMappingRows = _fields$envMappingRow === void 0 ? [] : _fields$envMappingRow,
9562
+ _fields$url = fields.url,
9563
+ url = _fields$url === void 0 ? "" : _fields$url,
9564
+ _fields$headerRows = fields.headerRows,
9565
+ headerRows = _fields$headerRows === void 0 ? [] : _fields$headerRows;
9566
+ var serverConfig;
9567
+ if (transport === "stdio") {
9568
+ var argsArray = args.trim().split(/\s+/).filter(Boolean);
9569
+ var env = {};
9570
+ envMappingRows.forEach(function (row) {
9571
+ var envVar = row.envVar.trim();
9572
+ var credField = row.credField.trim();
9573
+ if (envVar && credField) {
9574
+ env[envVar] = "${".concat(credField, "}");
9575
+ }
9576
+ });
9577
+ serverConfig = {
9578
+ type: "stdio",
9579
+ command: command.trim()
9580
+ };
9581
+ if (argsArray.length > 0) serverConfig.args = argsArray;
9582
+ if (Object.keys(env).length > 0) serverConfig.env = env;
9583
+ } else {
9584
+ // streamable_http
9585
+ serverConfig = {
9586
+ type: "streamable_http",
9587
+ url: url.trim()
9588
+ };
9589
+ var headerTemplate = {};
9590
+ headerRows.forEach(function (row) {
9591
+ var hName = row.headerName.trim();
9592
+ var hValue = row.headerValue.trim();
9593
+ if (hName && hValue) {
9594
+ headerTemplate[hName] = hValue;
9595
+ }
9596
+ });
9597
+ if (Object.keys(headerTemplate).length > 0) serverConfig.headerTemplate = headerTemplate;
9598
+ }
9599
+ return JSON.stringify(serverConfig, null, 2);
9600
+ }
9601
+
9602
+ /**
9603
+ * Parse an MCP JSON config string back into form state.
9604
+ *
9605
+ * Accepts multiple input formats:
9606
+ * - Bare config: { "command": ..., "args": [...], "env": { "KEY": "${FIELD}" } }
9607
+ * - Wrapped: { "mcpServers": { "name": { ... } } } — unwraps and uses key as providerName
9608
+ *
9609
+ * Transport detection:
9610
+ * - Explicit `type` or `transport` field
9611
+ * - Inferred: `url` present → streamable_http, `command` present → stdio
9612
+ *
9613
+ * stdio env value parsing:
9614
+ * - "${FIELD_NAME}" → envVar = key, credField = FIELD_NAME (reference syntax)
9615
+ * - "literal-value" → envVar = key, credField = key, credentialData[key] = value
9616
+ *
9617
+ * @param {string} jsonString - The JSON to parse
9618
+ * @param {Function} nextRowId - Function that returns a unique row ID
9619
+ * @returns {{ providerName, transport, command, args, envMappingRows, url, headerRows, credentialData, error }}
9620
+ */
9621
+ function mcpJsonToFormState(jsonString, nextRowId) {
9622
+ var parsed;
9623
+ try {
9624
+ parsed = JSON.parse(jsonString);
9625
+ } catch (e) {
9626
+ return {
9627
+ error: "Invalid JSON: ".concat(e.message)
9628
+ };
9629
+ }
9630
+ var providerName = "";
9631
+ var serverConfig;
9632
+ if (parsed.mcpServers && _typeof(parsed.mcpServers) === "object") {
9633
+ var entries = Object.entries(parsed.mcpServers);
9634
+ if (entries.length === 0) {
9635
+ return {
9636
+ error: "No server found in mcpServers"
9637
+ };
9638
+ }
9639
+ var _entries$ = _slicedToArray(entries[0], 2);
9640
+ providerName = _entries$[0];
9641
+ serverConfig = _entries$[1];
9642
+ } else if (parsed.command || parsed.url || parsed.type || parsed.transport) {
9643
+ serverConfig = parsed;
9644
+ } else {
9645
+ return {
9646
+ error: "Unrecognized format: expected a server config with command, url, or type"
9647
+ };
9648
+ }
9649
+
9650
+ // Determine transport from type/transport field or infer from contents
9651
+ var explicitType = serverConfig.type || serverConfig.transport;
9652
+ var transport;
9653
+ if (explicitType) {
9654
+ transport = explicitType === "stdio" ? "stdio" : "streamable_http";
9655
+ } else {
9656
+ transport = serverConfig.url ? "streamable_http" : "stdio";
9657
+ }
9658
+ var result = {
9659
+ providerName: providerName,
9660
+ transport: transport,
9661
+ command: "",
9662
+ args: "",
9663
+ envMappingRows: [],
9664
+ url: "",
9665
+ headerRows: [],
9666
+ credentialData: {},
9667
+ error: null
9668
+ };
9669
+ if (transport === "stdio") {
9670
+ result.command = serverConfig.command || "";
9671
+ result.args = (serverConfig.args || []).join(" ");
9672
+ if (serverConfig.env && _typeof(serverConfig.env) === "object") {
9673
+ Object.entries(serverConfig.env).forEach(function (_ref5) {
9674
+ var _ref6 = _slicedToArray(_ref5, 2),
9675
+ envVar = _ref6[0],
9676
+ value = _ref6[1];
9677
+ // Check for ${FIELD_NAME} reference syntax
9678
+ var refMatch = typeof value === "string" && value.match(/^\$\{(.+)\}$/);
9679
+ if (refMatch) {
9680
+ // Reference syntax — credField is the extracted name, no credential value
9681
+ result.envMappingRows.push({
9682
+ id: nextRowId(),
9683
+ envVar: envVar,
9684
+ credField: refMatch[1]
9685
+ });
9686
+ } else {
9687
+ // Literal value — use envVar as credField and store the value
9688
+ result.envMappingRows.push({
9689
+ id: nextRowId(),
9690
+ envVar: envVar,
9691
+ credField: envVar
9692
+ });
9693
+ result.credentialData[envVar] = value || "";
9694
+ }
9695
+ });
9696
+ }
9697
+ } else {
9698
+ result.url = serverConfig.url || "";
9699
+ var headers = serverConfig.headers || serverConfig.headerTemplate || {};
9700
+ if (_typeof(headers) === "object") {
9701
+ Object.entries(headers).forEach(function (_ref7) {
9702
+ var _ref8 = _slicedToArray(_ref7, 2),
9703
+ headerName = _ref8[0],
9704
+ headerValue = _ref8[1];
9705
+ result.headerRows.push({
9706
+ id: nextRowId(),
9707
+ headerName: headerName,
9708
+ headerValue: headerValue
9709
+ });
9710
+ });
9711
+ }
9712
+ }
9713
+ return result;
9714
+ }
9715
+
9529
9716
  function ownKeys$p(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9530
9717
  function _objectSpread$p(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$p(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$p(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9531
9718
  var AdvancedMcpConfig = function AdvancedMcpConfig(_ref) {
@@ -26215,29 +26402,57 @@ function buildMcpConfig(transport, _ref) {
26215
26402
  *
26216
26403
  * Form for configuring a custom MCP server (not from the catalog).
26217
26404
  * Supports stdio and streamable_http transports with dynamic field derivation.
26405
+ * Used for both creating new and editing existing MCP providers.
26218
26406
  *
26219
26407
  * @param {Function} onSave - (providerName, providerType, credentials, mcpConfig) => void
26220
- * @param {Function} onBack - Called when the user wants to return to the catalog
26408
+ * @param {Function} onBack - Called when the user wants to return
26409
+ * @param {boolean} isEditMode - Whether we're editing an existing provider
26410
+ * @param {string} initialName - Pre-populated provider name (edit mode)
26411
+ * @param {string} initialTransport - Pre-populated transport type (edit mode)
26412
+ * @param {string} initialCommand - Pre-populated command (edit mode)
26413
+ * @param {string} initialArgs - Pre-populated args string (edit mode)
26414
+ * @param {Array} initialEnvMappingRows - Pre-populated env mapping rows (edit mode)
26415
+ * @param {string} initialUrl - Pre-populated URL (edit mode)
26416
+ * @param {Array} initialHeaderRows - Pre-populated header rows (edit mode)
26417
+ * @param {object} initialCredentials - Pre-populated credential values (edit mode)
26221
26418
  */
26222
26419
  var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26223
26420
  var _testResult$tools;
26224
26421
  var onSave = _ref2.onSave,
26225
- onBack = _ref2.onBack;
26422
+ onBack = _ref2.onBack,
26423
+ _ref2$isEditMode = _ref2.isEditMode,
26424
+ isEditMode = _ref2$isEditMode === void 0 ? false : _ref2$isEditMode,
26425
+ _ref2$initialName = _ref2.initialName,
26426
+ initialName = _ref2$initialName === void 0 ? "" : _ref2$initialName,
26427
+ _ref2$initialTranspor = _ref2.initialTransport,
26428
+ initialTransport = _ref2$initialTranspor === void 0 ? "stdio" : _ref2$initialTranspor,
26429
+ _ref2$initialCommand = _ref2.initialCommand,
26430
+ initialCommand = _ref2$initialCommand === void 0 ? "" : _ref2$initialCommand,
26431
+ _ref2$initialArgs = _ref2.initialArgs,
26432
+ initialArgs = _ref2$initialArgs === void 0 ? "" : _ref2$initialArgs,
26433
+ _ref2$initialEnvMappi = _ref2.initialEnvMappingRows,
26434
+ initialEnvMappingRows = _ref2$initialEnvMappi === void 0 ? [] : _ref2$initialEnvMappi,
26435
+ _ref2$initialUrl = _ref2.initialUrl,
26436
+ initialUrl = _ref2$initialUrl === void 0 ? "" : _ref2$initialUrl,
26437
+ _ref2$initialHeaderRo = _ref2.initialHeaderRows,
26438
+ initialHeaderRows = _ref2$initialHeaderRo === void 0 ? [] : _ref2$initialHeaderRo,
26439
+ _ref2$initialCredenti = _ref2.initialCredentials,
26440
+ initialCredentials = _ref2$initialCredenti === void 0 ? {} : _ref2$initialCredenti;
26226
26441
  var appContext = useContext(AppContext);
26227
26442
  var dashApi = appContext === null || appContext === void 0 ? void 0 : appContext.dashApi;
26228
26443
 
26229
26444
  // Transport selection
26230
- var _useState = useState("stdio"),
26445
+ var _useState = useState(initialTransport),
26231
26446
  _useState2 = _slicedToArray(_useState, 2),
26232
26447
  transport = _useState2[0],
26233
26448
  setTransport = _useState2[1];
26234
26449
 
26235
26450
  // Common
26236
- var _useState3 = useState(""),
26451
+ var _useState3 = useState(initialName),
26237
26452
  _useState4 = _slicedToArray(_useState3, 2),
26238
26453
  providerName = _useState4[0],
26239
26454
  setProviderName = _useState4[1];
26240
- var _useState5 = useState({}),
26455
+ var _useState5 = useState(initialCredentials),
26241
26456
  _useState6 = _slicedToArray(_useState5, 2),
26242
26457
  credentialData = _useState6[0],
26243
26458
  setCredentialData = _useState6[1];
@@ -26255,34 +26470,51 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26255
26470
  setTestResult = _useState10[1];
26256
26471
 
26257
26472
  // stdio fields
26258
- var _useState11 = useState(""),
26473
+ var _useState11 = useState(initialCommand),
26259
26474
  _useState12 = _slicedToArray(_useState11, 2),
26260
26475
  command = _useState12[0],
26261
26476
  setCommand = _useState12[1];
26262
- var _useState13 = useState(""),
26477
+ var _useState13 = useState(initialArgs),
26263
26478
  _useState14 = _slicedToArray(_useState13, 2),
26264
26479
  args = _useState14[0],
26265
26480
  setArgs = _useState14[1];
26266
- var _useState15 = useState([]),
26481
+ var _useState15 = useState(initialEnvMappingRows),
26267
26482
  _useState16 = _slicedToArray(_useState15, 2),
26268
26483
  envMappingRows = _useState16[0],
26269
26484
  setEnvMappingRows = _useState16[1];
26270
26485
 
26271
26486
  // HTTP fields
26272
- var _useState17 = useState(""),
26487
+ var _useState17 = useState(initialUrl),
26273
26488
  _useState18 = _slicedToArray(_useState17, 2),
26274
26489
  url = _useState18[0],
26275
26490
  setUrl = _useState18[1];
26276
- var _useState19 = useState([]),
26491
+ var _useState19 = useState(initialHeaderRows),
26277
26492
  _useState20 = _slicedToArray(_useState19, 2),
26278
26493
  headerRows = _useState20[0],
26279
26494
  setHeaderRows = _useState20[1];
26280
26495
 
26496
+ // JSON editor state
26497
+ var _useState21 = useState("form"),
26498
+ _useState22 = _slicedToArray(_useState21, 2),
26499
+ viewMode = _useState22[0],
26500
+ setViewMode = _useState22[1]; // "form" | "json"
26501
+ var _useState23 = useState(""),
26502
+ _useState24 = _slicedToArray(_useState23, 2),
26503
+ jsonText = _useState24[0],
26504
+ setJsonText = _useState24[1];
26505
+ var _useState25 = useState(null),
26506
+ _useState26 = _slicedToArray(_useState25, 2),
26507
+ jsonError = _useState26[0],
26508
+ setJsonError = _useState26[1];
26509
+
26281
26510
  // Clear credential data when transport changes (derived fields change entirely)
26511
+ // Only in create mode — in edit mode the initial transport is set correctly
26282
26512
  useEffect(function () {
26283
- setCredentialData({});
26284
- setTestResult(null);
26285
- }, [transport]);
26513
+ if (!isEditMode) {
26514
+ setCredentialData({});
26515
+ setTestResult(null);
26516
+ }
26517
+ }, [transport, isEditMode]);
26286
26518
 
26287
26519
  // Build mcpConfig from current state
26288
26520
  var mcpConfig = useMemo(function () {
@@ -26364,6 +26596,38 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26364
26596
  }
26365
26597
  };
26366
26598
 
26599
+ // --- JSON toggle handlers ---
26600
+ var handleSwitchToJson = function handleSwitchToJson() {
26601
+ var json = formStateToMcpJson(providerName, transport, {
26602
+ command: command,
26603
+ args: args,
26604
+ envMappingRows: envMappingRows,
26605
+ url: url,
26606
+ headerRows: headerRows,
26607
+ credentialData: credentialData
26608
+ });
26609
+ setJsonText(json);
26610
+ setJsonError(null);
26611
+ setViewMode("json");
26612
+ };
26613
+ var handleSwitchToForm = function handleSwitchToForm() {
26614
+ var result = mcpJsonToFormState(jsonText, nextRowId);
26615
+ if (result.error) {
26616
+ setJsonError(result.error);
26617
+ return;
26618
+ }
26619
+ setProviderName(result.providerName || providerName);
26620
+ setTransport(result.transport);
26621
+ setCommand(result.command);
26622
+ setArgs(result.args);
26623
+ setEnvMappingRows(result.envMappingRows);
26624
+ setUrl(result.url);
26625
+ setHeaderRows(result.headerRows);
26626
+ setCredentialData(result.credentialData);
26627
+ setJsonError(null);
26628
+ setViewMode("form");
26629
+ };
26630
+
26367
26631
  // --- validation ---
26368
26632
  var validateForm = function validateForm() {
26369
26633
  var errors = {};
@@ -26423,6 +26687,28 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26423
26687
 
26424
26688
  // --- save ---
26425
26689
  var handleSave = function handleSave() {
26690
+ // If in JSON mode, parse JSON first to update form state
26691
+ if (viewMode === "json") {
26692
+ var result = mcpJsonToFormState(jsonText, nextRowId);
26693
+ if (result.error) {
26694
+ setJsonError(result.error);
26695
+ return;
26696
+ }
26697
+ var name = (result.providerName || providerName || "").trim();
26698
+ if (!name) {
26699
+ setJsonError("Provider name is required");
26700
+ return;
26701
+ }
26702
+ var config = buildMcpConfig(result.transport, {
26703
+ command: result.command,
26704
+ args: result.args,
26705
+ envMappingRows: result.envMappingRows,
26706
+ url: result.url,
26707
+ headerRows: result.headerRows
26708
+ });
26709
+ onSave(name, "custom", result.credentialData, config);
26710
+ return;
26711
+ }
26426
26712
  if (!validateForm()) return;
26427
26713
  onSave(providerName.trim(), "custom", credentialData, mcpConfig);
26428
26714
  };
@@ -26441,58 +26727,11 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26441
26727
  })
26442
26728
  }), /*#__PURE__*/jsxs("div", {
26443
26729
  children: [/*#__PURE__*/jsx(SubHeading3, {
26444
- title: "Configure Custom MCP Server",
26730
+ title: isEditMode ? "Edit MCP Server" : "Configure Custom MCP Server",
26445
26731
  padding: false
26446
26732
  }), /*#__PURE__*/jsx("p", {
26447
26733
  className: "text-sm opacity-50 mt-1",
26448
- children: "Define a custom MCP server connection"
26449
- })]
26450
- })]
26451
- }), /*#__PURE__*/jsxs("div", {
26452
- className: "space-y-2",
26453
- children: [/*#__PURE__*/jsx("p", {
26454
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26455
- children: "Transport Type"
26456
- }), /*#__PURE__*/jsxs("div", {
26457
- className: "grid grid-cols-2 gap-3",
26458
- children: [/*#__PURE__*/jsxs(Card2, {
26459
- hover: true,
26460
- selected: transport === "stdio",
26461
- onClick: function onClick() {
26462
- return setTransport("stdio");
26463
- },
26464
- className: "text-left",
26465
- children: [/*#__PURE__*/jsxs("div", {
26466
- className: "flex items-center gap-2 mb-1",
26467
- children: [/*#__PURE__*/jsx(Icon2, {
26468
- icon: "terminal"
26469
- }), /*#__PURE__*/jsx("span", {
26470
- className: "font-semibold text-sm",
26471
- children: "Local Process (stdio)"
26472
- })]
26473
- }), /*#__PURE__*/jsx("p", {
26474
- className: "text-xs opacity-50",
26475
- children: "Spawn a local command as a child process"
26476
- })]
26477
- }), /*#__PURE__*/jsxs(Card2, {
26478
- hover: true,
26479
- selected: transport === "streamable_http",
26480
- onClick: function onClick() {
26481
- return setTransport("streamable_http");
26482
- },
26483
- className: "text-left",
26484
- children: [/*#__PURE__*/jsxs("div", {
26485
- className: "flex items-center gap-2 mb-1",
26486
- children: [/*#__PURE__*/jsx(Icon2, {
26487
- icon: "globe"
26488
- }), /*#__PURE__*/jsx("span", {
26489
- className: "font-semibold text-sm",
26490
- children: "Remote Server (HTTP)"
26491
- })]
26492
- }), /*#__PURE__*/jsx("p", {
26493
- className: "text-xs opacity-50",
26494
- children: "Connect to a remote MCP server via HTTP"
26495
- })]
26734
+ children: isEditMode ? "Modify this MCP server configuration" : "Define a custom MCP server connection"
26496
26735
  })]
26497
26736
  })]
26498
26737
  }), /*#__PURE__*/jsxs("div", {
@@ -26520,231 +26759,315 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26520
26759
  className: "text-sm text-red-400",
26521
26760
  children: formErrors.providerName
26522
26761
  })]
26523
- }), transport === "stdio" && /*#__PURE__*/jsxs("div", {
26524
- className: "space-y-4",
26525
- children: [/*#__PURE__*/jsx("div", {
26526
- className: "border-t border-white/10 pt-4",
26527
- children: /*#__PURE__*/jsx("p", {
26762
+ }), /*#__PURE__*/jsxs("div", {
26763
+ className: "flex items-center gap-1",
26764
+ children: [/*#__PURE__*/jsx("button", {
26765
+ onClick: function onClick() {
26766
+ if (viewMode === "json") handleSwitchToForm();
26767
+ },
26768
+ 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"),
26769
+ children: "Form"
26770
+ }), /*#__PURE__*/jsx("button", {
26771
+ onClick: function onClick() {
26772
+ if (viewMode === "form") handleSwitchToJson();
26773
+ },
26774
+ 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"),
26775
+ children: "JSON"
26776
+ })]
26777
+ }), jsonError && /*#__PURE__*/jsx("p", {
26778
+ className: "text-sm text-red-400",
26779
+ children: jsonError
26780
+ }), viewMode === "json" && /*#__PURE__*/jsxs("div", {
26781
+ className: "space-y-2",
26782
+ children: [/*#__PURE__*/jsx("p", {
26783
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26784
+ children: "MCP Server Configuration (JSON)"
26785
+ }), /*#__PURE__*/jsx("p", {
26786
+ className: "text-sm opacity-50",
26787
+ children: "Paste a standard MCP config JSON (compatible with Claude Desktop, Cursor, etc.)"
26788
+ }), /*#__PURE__*/jsx(CodeEditorInline, {
26789
+ code: jsonText,
26790
+ setCode: function setCode(val) {
26791
+ setJsonText(val);
26792
+ setJsonError(null);
26793
+ },
26794
+ language: "json",
26795
+ placeholder: '{\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "${API_KEY}"\n }\n}'
26796
+ })]
26797
+ }), viewMode === "form" && /*#__PURE__*/jsxs(Fragment, {
26798
+ children: [/*#__PURE__*/jsxs("div", {
26799
+ className: "space-y-2",
26800
+ children: [/*#__PURE__*/jsx("p", {
26528
26801
  className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26529
- children: "Process Configuration"
26530
- })
26531
- }), /*#__PURE__*/jsxs("div", {
26532
- className: "flex flex-col gap-2",
26533
- children: [/*#__PURE__*/jsx(FormLabel, {
26534
- label: "Command",
26535
- required: true
26536
- }), /*#__PURE__*/jsx("p", {
26537
- className: "text-sm opacity-50",
26538
- children: "The executable to run (e.g., npx, node, python)"
26539
- }), /*#__PURE__*/jsx(InputText, {
26540
- value: command,
26541
- onChange: function onChange(value) {
26542
- setCommand(value);
26543
- if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
26544
- setFormErrors(function (prev) {
26545
- var next = _objectSpread$5({}, prev);
26546
- delete next.command;
26547
- return next;
26548
- });
26549
- }
26550
- },
26551
- placeholder: "e.g., npx"
26552
- }), formErrors.command && /*#__PURE__*/jsx("p", {
26553
- className: "text-sm text-red-400",
26554
- children: formErrors.command
26555
- })]
26556
- }), /*#__PURE__*/jsxs("div", {
26557
- className: "flex flex-col gap-2",
26558
- children: [/*#__PURE__*/jsx(FormLabel, {
26559
- label: "Arguments"
26560
- }), /*#__PURE__*/jsx("p", {
26561
- className: "text-sm opacity-50",
26562
- children: "Space-separated arguments passed to the command"
26563
- }), /*#__PURE__*/jsx(InputText, {
26564
- value: args,
26565
- onChange: setArgs,
26566
- placeholder: "e.g., -y @modelcontextprotocol/server-github"
26567
- })]
26568
- }), /*#__PURE__*/jsxs("div", {
26569
- className: "space-y-3",
26570
- children: [/*#__PURE__*/jsx("div", {
26571
- className: "flex items-center justify-between",
26572
- children: /*#__PURE__*/jsxs("div", {
26573
- children: [/*#__PURE__*/jsx(FormLabel, {
26574
- label: "Environment Variable Mapping"
26802
+ children: "Transport Type"
26803
+ }), /*#__PURE__*/jsxs("div", {
26804
+ className: "grid grid-cols-2 gap-3",
26805
+ children: [/*#__PURE__*/jsxs(Card2, {
26806
+ hover: true,
26807
+ selected: transport === "stdio",
26808
+ onClick: function onClick() {
26809
+ return setTransport("stdio");
26810
+ },
26811
+ className: "text-left",
26812
+ children: [/*#__PURE__*/jsxs("div", {
26813
+ className: "flex items-center gap-2 mb-1",
26814
+ children: [/*#__PURE__*/jsx(Icon2, {
26815
+ icon: "terminal"
26816
+ }), /*#__PURE__*/jsx("span", {
26817
+ className: "font-semibold text-sm",
26818
+ children: "Local Process (stdio)"
26819
+ })]
26575
26820
  }), /*#__PURE__*/jsx("p", {
26576
- className: "text-sm opacity-50 mt-1",
26577
- children: "Map environment variables to credential fields"
26821
+ className: "text-xs opacity-50",
26822
+ children: "Spawn a local command as a child process"
26578
26823
  })]
26824
+ }), /*#__PURE__*/jsxs(Card2, {
26825
+ hover: true,
26826
+ selected: transport === "streamable_http",
26827
+ onClick: function onClick() {
26828
+ return setTransport("streamable_http");
26829
+ },
26830
+ className: "text-left",
26831
+ children: [/*#__PURE__*/jsxs("div", {
26832
+ className: "flex items-center gap-2 mb-1",
26833
+ children: [/*#__PURE__*/jsx(Icon2, {
26834
+ icon: "globe"
26835
+ }), /*#__PURE__*/jsx("span", {
26836
+ className: "font-semibold text-sm",
26837
+ children: "Remote Server (HTTP)"
26838
+ })]
26839
+ }), /*#__PURE__*/jsx("p", {
26840
+ className: "text-xs opacity-50",
26841
+ children: "Connect to a remote MCP server via HTTP"
26842
+ })]
26843
+ })]
26844
+ })]
26845
+ }), transport === "stdio" && /*#__PURE__*/jsxs("div", {
26846
+ className: "space-y-4",
26847
+ children: [/*#__PURE__*/jsx("div", {
26848
+ className: "border-t border-white/10 pt-4",
26849
+ children: /*#__PURE__*/jsx("p", {
26850
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26851
+ children: "Process Configuration"
26579
26852
  })
26580
- }), envMappingRows.map(function (row) {
26581
- return /*#__PURE__*/jsxs("div", {
26582
- className: "flex items-center gap-2",
26583
- children: [/*#__PURE__*/jsx("div", {
26584
- className: "flex-1",
26585
- children: /*#__PURE__*/jsx(InputText, {
26586
- value: row.envVar,
26587
- onChange: function onChange(value) {
26588
- return updateEnvRow(row.id, "envVar", value);
26853
+ }), /*#__PURE__*/jsxs("div", {
26854
+ className: "flex flex-col gap-2",
26855
+ children: [/*#__PURE__*/jsx(FormLabel, {
26856
+ label: "Command",
26857
+ required: true
26858
+ }), /*#__PURE__*/jsx("p", {
26859
+ className: "text-sm opacity-50",
26860
+ children: "The executable to run (e.g., npx, node, python)"
26861
+ }), /*#__PURE__*/jsx(InputText, {
26862
+ value: command,
26863
+ onChange: function onChange(value) {
26864
+ setCommand(value);
26865
+ if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
26866
+ setFormErrors(function (prev) {
26867
+ var next = _objectSpread$5({}, prev);
26868
+ delete next.command;
26869
+ return next;
26870
+ });
26871
+ }
26872
+ },
26873
+ placeholder: "e.g., npx"
26874
+ }), formErrors.command && /*#__PURE__*/jsx("p", {
26875
+ className: "text-sm text-red-400",
26876
+ children: formErrors.command
26877
+ })]
26878
+ }), /*#__PURE__*/jsxs("div", {
26879
+ className: "flex flex-col gap-2",
26880
+ children: [/*#__PURE__*/jsx(FormLabel, {
26881
+ label: "Arguments"
26882
+ }), /*#__PURE__*/jsx("p", {
26883
+ className: "text-sm opacity-50",
26884
+ children: "Space-separated arguments passed to the command"
26885
+ }), /*#__PURE__*/jsx(InputText, {
26886
+ value: args,
26887
+ onChange: setArgs,
26888
+ placeholder: "e.g., -y @modelcontextprotocol/server-github"
26889
+ })]
26890
+ }), /*#__PURE__*/jsxs("div", {
26891
+ className: "space-y-3",
26892
+ children: [/*#__PURE__*/jsx("div", {
26893
+ className: "flex items-center justify-between",
26894
+ children: /*#__PURE__*/jsxs("div", {
26895
+ children: [/*#__PURE__*/jsx(FormLabel, {
26896
+ label: "Environment Variable Mapping"
26897
+ }), /*#__PURE__*/jsx("p", {
26898
+ className: "text-sm opacity-50 mt-1",
26899
+ children: "Map environment variables to credential fields"
26900
+ })]
26901
+ })
26902
+ }), envMappingRows.map(function (row) {
26903
+ return /*#__PURE__*/jsxs("div", {
26904
+ className: "flex items-center gap-2",
26905
+ children: [/*#__PURE__*/jsx("div", {
26906
+ className: "flex-1",
26907
+ children: /*#__PURE__*/jsx(InputText, {
26908
+ value: row.envVar,
26909
+ onChange: function onChange(value) {
26910
+ return updateEnvRow(row.id, "envVar", value);
26911
+ },
26912
+ placeholder: "ENV_VAR_NAME"
26913
+ })
26914
+ }), /*#__PURE__*/jsx("span", {
26915
+ className: "opacity-30 text-sm shrink-0",
26916
+ children: "\u2192"
26917
+ }), /*#__PURE__*/jsx("div", {
26918
+ className: "flex-1",
26919
+ children: /*#__PURE__*/jsx(InputText, {
26920
+ value: row.credField,
26921
+ onChange: function onChange(value) {
26922
+ return updateEnvRow(row.id, "credField", value);
26923
+ },
26924
+ placeholder: "credentialField"
26925
+ })
26926
+ }), /*#__PURE__*/jsx("button", {
26927
+ onClick: function onClick() {
26928
+ return removeEnvRow(row.id);
26589
26929
  },
26590
- placeholder: "ENV_VAR_NAME"
26591
- })
26930
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26931
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
26932
+ icon: "times",
26933
+ className: "text-sm"
26934
+ })
26935
+ })]
26936
+ }, row.id);
26937
+ }), /*#__PURE__*/jsxs("button", {
26938
+ onClick: addEnvRow,
26939
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26940
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
26941
+ icon: "plus",
26942
+ className: "text-xs"
26592
26943
  }), /*#__PURE__*/jsx("span", {
26593
- className: "opacity-30 text-sm shrink-0",
26594
- children: "\u2192"
26595
- }), /*#__PURE__*/jsx("div", {
26596
- className: "flex-1",
26597
- children: /*#__PURE__*/jsx(InputText, {
26598
- value: row.credField,
26599
- onChange: function onChange(value) {
26600
- return updateEnvRow(row.id, "credField", value);
26601
- },
26602
- placeholder: "credentialField"
26603
- })
26604
- }), /*#__PURE__*/jsx("button", {
26605
- onClick: function onClick() {
26606
- return removeEnvRow(row.id);
26607
- },
26608
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26609
- children: /*#__PURE__*/jsx(FontAwesomeIcon, {
26610
- icon: "times",
26611
- className: "text-sm"
26612
- })
26944
+ children: "Add Environment Variable"
26613
26945
  })]
26614
- }, row.id);
26615
- }), /*#__PURE__*/jsxs("button", {
26616
- onClick: addEnvRow,
26617
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26618
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
26619
- icon: "plus",
26620
- className: "text-xs"
26621
- }), /*#__PURE__*/jsx("span", {
26622
- children: "Add Environment Variable"
26623
26946
  })]
26624
26947
  })]
26625
- })]
26626
- }), transport === "streamable_http" && /*#__PURE__*/jsxs("div", {
26627
- className: "space-y-4",
26628
- children: [/*#__PURE__*/jsx("div", {
26629
- className: "border-t border-white/10 pt-4",
26630
- children: /*#__PURE__*/jsx("p", {
26631
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26632
- children: "Server Configuration"
26633
- })
26634
- }), /*#__PURE__*/jsxs("div", {
26635
- className: "flex flex-col gap-2",
26636
- children: [/*#__PURE__*/jsx(FormLabel, {
26637
- label: "Server URL",
26638
- required: true
26639
- }), /*#__PURE__*/jsxs("p", {
26640
- className: "text-sm opacity-50",
26641
- children: ["Use", " ", /*#__PURE__*/jsx("code", {
26642
- className: "text-xs bg-white/10 px-1 py-0.5 rounded",
26643
- children: "{{fieldName}}"
26644
- }), " ", "for values provided as credentials"]
26645
- }), /*#__PURE__*/jsx(InputText, {
26646
- value: url,
26647
- onChange: function onChange(value) {
26648
- setUrl(value);
26649
- if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
26650
- setFormErrors(function (prev) {
26651
- var next = _objectSpread$5({}, prev);
26652
- delete next.url;
26653
- return next;
26654
- });
26655
- }
26656
- },
26657
- placeholder: "e.g., https://mcp.example.com/sse"
26658
- }), formErrors.url && /*#__PURE__*/jsx("p", {
26659
- className: "text-sm text-red-400",
26660
- children: formErrors.url
26661
- })]
26662
- }), /*#__PURE__*/jsxs("div", {
26663
- className: "space-y-3",
26664
- children: [/*#__PURE__*/jsxs("div", {
26948
+ }), transport === "streamable_http" && /*#__PURE__*/jsxs("div", {
26949
+ className: "space-y-4",
26950
+ children: [/*#__PURE__*/jsx("div", {
26951
+ className: "border-t border-white/10 pt-4",
26952
+ children: /*#__PURE__*/jsx("p", {
26953
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26954
+ children: "Server Configuration"
26955
+ })
26956
+ }), /*#__PURE__*/jsxs("div", {
26957
+ className: "flex flex-col gap-2",
26665
26958
  children: [/*#__PURE__*/jsx(FormLabel, {
26666
- label: "Request Headers"
26959
+ label: "Server URL",
26960
+ required: true
26667
26961
  }), /*#__PURE__*/jsxs("p", {
26668
- className: "text-sm opacity-50 mt-1",
26962
+ className: "text-sm opacity-50",
26669
26963
  children: ["Use", " ", /*#__PURE__*/jsx("code", {
26670
26964
  className: "text-xs bg-white/10 px-1 py-0.5 rounded",
26671
26965
  children: "{{fieldName}}"
26672
- }), " ", "in values for credential placeholders"]
26966
+ }), " ", "for values provided as credentials"]
26967
+ }), /*#__PURE__*/jsx(InputText, {
26968
+ value: url,
26969
+ onChange: function onChange(value) {
26970
+ setUrl(value);
26971
+ if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
26972
+ setFormErrors(function (prev) {
26973
+ var next = _objectSpread$5({}, prev);
26974
+ delete next.url;
26975
+ return next;
26976
+ });
26977
+ }
26978
+ },
26979
+ placeholder: "e.g., https://mcp.example.com/sse"
26980
+ }), formErrors.url && /*#__PURE__*/jsx("p", {
26981
+ className: "text-sm text-red-400",
26982
+ children: formErrors.url
26673
26983
  })]
26674
- }), headerRows.map(function (row) {
26675
- return /*#__PURE__*/jsxs("div", {
26676
- className: "flex items-center gap-2",
26677
- children: [/*#__PURE__*/jsx("div", {
26678
- className: "flex-1",
26679
- children: /*#__PURE__*/jsx(InputText, {
26680
- value: row.headerName,
26681
- onChange: function onChange(value) {
26682
- return updateHeaderRow(row.id, "headerName", value);
26984
+ }), /*#__PURE__*/jsxs("div", {
26985
+ className: "space-y-3",
26986
+ children: [/*#__PURE__*/jsxs("div", {
26987
+ children: [/*#__PURE__*/jsx(FormLabel, {
26988
+ label: "Request Headers"
26989
+ }), /*#__PURE__*/jsxs("p", {
26990
+ className: "text-sm opacity-50 mt-1",
26991
+ children: ["Use", " ", /*#__PURE__*/jsx("code", {
26992
+ className: "text-xs bg-white/10 px-1 py-0.5 rounded",
26993
+ children: "{{fieldName}}"
26994
+ }), " ", "in values for credential placeholders"]
26995
+ })]
26996
+ }), headerRows.map(function (row) {
26997
+ return /*#__PURE__*/jsxs("div", {
26998
+ className: "flex items-center gap-2",
26999
+ children: [/*#__PURE__*/jsx("div", {
27000
+ className: "flex-1",
27001
+ children: /*#__PURE__*/jsx(InputText, {
27002
+ value: row.headerName,
27003
+ onChange: function onChange(value) {
27004
+ return updateHeaderRow(row.id, "headerName", value);
27005
+ },
27006
+ placeholder: "Header-Name"
27007
+ })
27008
+ }), /*#__PURE__*/jsx("span", {
27009
+ className: "opacity-30 text-sm shrink-0",
27010
+ children: ":"
27011
+ }), /*#__PURE__*/jsx("div", {
27012
+ className: "flex-1",
27013
+ children: /*#__PURE__*/jsx(InputText, {
27014
+ value: row.headerValue,
27015
+ onChange: function onChange(value) {
27016
+ return updateHeaderRow(row.id, "headerValue", value);
27017
+ },
27018
+ placeholder: "Bearer {{apiKey}}"
27019
+ })
27020
+ }), /*#__PURE__*/jsx("button", {
27021
+ onClick: function onClick() {
27022
+ return removeHeaderRow(row.id);
26683
27023
  },
26684
- placeholder: "Header-Name"
26685
- })
27024
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27025
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
27026
+ icon: "times",
27027
+ className: "text-sm"
27028
+ })
27029
+ })]
27030
+ }, row.id);
27031
+ }), /*#__PURE__*/jsxs("button", {
27032
+ onClick: addHeaderRow,
27033
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27034
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
27035
+ icon: "plus",
27036
+ className: "text-xs"
26686
27037
  }), /*#__PURE__*/jsx("span", {
26687
- className: "opacity-30 text-sm shrink-0",
26688
- children: ":"
26689
- }), /*#__PURE__*/jsx("div", {
26690
- className: "flex-1",
26691
- children: /*#__PURE__*/jsx(InputText, {
26692
- value: row.headerValue,
26693
- onChange: function onChange(value) {
26694
- return updateHeaderRow(row.id, "headerValue", value);
26695
- },
26696
- placeholder: "Bearer {{apiKey}}"
26697
- })
26698
- }), /*#__PURE__*/jsx("button", {
26699
- onClick: function onClick() {
26700
- return removeHeaderRow(row.id);
26701
- },
26702
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26703
- children: /*#__PURE__*/jsx(FontAwesomeIcon, {
26704
- icon: "times",
26705
- className: "text-sm"
26706
- })
27038
+ children: "Add Header"
26707
27039
  })]
26708
- }, row.id);
26709
- }), /*#__PURE__*/jsxs("button", {
26710
- onClick: addHeaderRow,
26711
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26712
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
26713
- icon: "plus",
26714
- className: "text-xs"
26715
- }), /*#__PURE__*/jsx("span", {
26716
- children: "Add Header"
26717
27040
  })]
26718
27041
  })]
26719
- })]
26720
- }), formFields.length > 0 && /*#__PURE__*/jsxs(Fragment, {
26721
- children: [/*#__PURE__*/jsxs("div", {
26722
- className: "border-t border-white/10 pt-4",
26723
- children: [/*#__PURE__*/jsx("p", {
26724
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26725
- children: "Credentials"
26726
- }), /*#__PURE__*/jsx("p", {
26727
- className: "text-sm opacity-50 mt-1",
26728
- children: "Values for the fields referenced in your configuration above"
26729
- })]
26730
- }), formFields.map(function (field) {
26731
- return /*#__PURE__*/jsxs("div", {
26732
- className: "flex flex-col gap-2",
26733
- children: [/*#__PURE__*/jsx(FormLabel, {
26734
- label: field.displayName,
26735
- required: field.required
26736
- }), /*#__PURE__*/jsx(InputText, {
26737
- type: field.secret ? "password" : "text",
26738
- value: credentialData[field.key] || "",
26739
- onChange: function onChange(value) {
26740
- return handleCredentialChange(field.key, value);
26741
- },
26742
- placeholder: "Enter ".concat(field.displayName.toLowerCase())
26743
- }), formErrors[field.key] && /*#__PURE__*/jsx("p", {
26744
- className: "text-sm text-red-400",
26745
- children: formErrors[field.key]
27042
+ }), formFields.length > 0 && /*#__PURE__*/jsxs(Fragment, {
27043
+ children: [/*#__PURE__*/jsxs("div", {
27044
+ className: "border-t border-white/10 pt-4",
27045
+ children: [/*#__PURE__*/jsx("p", {
27046
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27047
+ children: "Credentials"
27048
+ }), /*#__PURE__*/jsx("p", {
27049
+ className: "text-sm opacity-50 mt-1",
27050
+ children: "Values for the fields referenced in your configuration above"
26746
27051
  })]
26747
- }, field.key);
27052
+ }), formFields.map(function (field) {
27053
+ return /*#__PURE__*/jsxs("div", {
27054
+ className: "flex flex-col gap-2",
27055
+ children: [/*#__PURE__*/jsx(FormLabel, {
27056
+ label: field.displayName,
27057
+ required: field.required
27058
+ }), /*#__PURE__*/jsx(InputText, {
27059
+ type: field.secret ? "password" : "text",
27060
+ value: credentialData[field.key] || "",
27061
+ onChange: function onChange(value) {
27062
+ return handleCredentialChange(field.key, value);
27063
+ },
27064
+ placeholder: "Enter ".concat(field.displayName.toLowerCase())
27065
+ }), formErrors[field.key] && /*#__PURE__*/jsx("p", {
27066
+ className: "text-sm text-red-400",
27067
+ children: formErrors[field.key]
27068
+ })]
27069
+ }, field.key);
27070
+ })]
26748
27071
  })]
26749
27072
  }), testResult && /*#__PURE__*/jsxs("div", {
26750
27073
  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"),
@@ -26782,7 +27105,7 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26782
27105
  onClick: handleTestConnection,
26783
27106
  size: "sm"
26784
27107
  }), /*#__PURE__*/jsx(Button, {
26785
- title: "Save MCP Server",
27108
+ title: isEditMode ? "Save Changes" : "Save MCP Server",
26786
27109
  onClick: handleSave,
26787
27110
  size: "sm"
26788
27111
  })]
@@ -27350,6 +27673,16 @@ var ProvidersSection = function ProvidersSection(_ref) {
27350
27673
  _useState14 = _slicedToArray(_useState13, 2),
27351
27674
  isAddingMcp = _useState14[0],
27352
27675
  setIsAddingMcp = _useState14[1];
27676
+ var _useState15 = useState(false),
27677
+ _useState16 = _slicedToArray(_useState15, 2),
27678
+ isEditingMcp = _useState16[0],
27679
+ setIsEditingMcp = _useState16[1];
27680
+
27681
+ // Row ID counter for env/header rows in MCP edit mode
27682
+ var nextRowIdRef = useRef(0);
27683
+ var nextRowId = function nextRowId() {
27684
+ return "prov_row_".concat(++nextRowIdRef.current);
27685
+ };
27353
27686
  var providerEntries = Object.entries(providers);
27354
27687
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
27355
27688
 
@@ -27370,6 +27703,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27370
27703
  setFormCredentials({});
27371
27704
  setIsCreating(false);
27372
27705
  setIsEditing(false);
27706
+ setIsEditingMcp(false);
27373
27707
  }
27374
27708
  function handleSave() {
27375
27709
  if (!formName.trim() || !dashApi || !appId) return;
@@ -27392,11 +27726,17 @@ var ProvidersSection = function ProvidersSection(_ref) {
27392
27726
  }
27393
27727
  function handleStartEdit(name, provider) {
27394
27728
  setSelectedName(name);
27395
- setFormName(name);
27396
- setFormType(provider.type || "");
27397
- setFormCredentials(provider.credentials || {});
27398
- setIsEditing(true);
27399
27729
  setIsCreating(false);
27730
+ if (provider.providerClass === "mcp") {
27731
+ setIsEditingMcp(true);
27732
+ setIsEditing(false);
27733
+ } else {
27734
+ setFormName(name);
27735
+ setFormType(provider.type || "");
27736
+ setFormCredentials(provider.credentials || {});
27737
+ setIsEditing(true);
27738
+ setIsEditingMcp(false);
27739
+ }
27400
27740
  }
27401
27741
  function handleSaveEdit() {
27402
27742
  if (!formName.trim() || !dashApi || !appId) return;
@@ -27456,6 +27796,30 @@ var ProvidersSection = function ProvidersSection(_ref) {
27456
27796
  });
27457
27797
  }
27458
27798
 
27799
+ // Handle MCP provider editing via CustomMcpServerForm
27800
+ function handleMcpEditSave(providerName, providerType, mcpCredentials, mcpConfig) {
27801
+ if (!dashApi || !appId) return;
27802
+ var originalName = selectedName;
27803
+
27804
+ // Delete old if name changed
27805
+ if (originalName && originalName !== providerName) {
27806
+ dashApi.deleteProvider(appId, originalName, function () {}, function () {});
27807
+ }
27808
+ dashApi.saveProvider(appId, providerName, {
27809
+ providerType: providerType,
27810
+ credentials: mcpCredentials,
27811
+ providerClass: "mcp",
27812
+ mcpConfig: mcpConfig
27813
+ }, function () {
27814
+ setSelectedName(providerName);
27815
+ setIsEditingMcp(false);
27816
+ resetForm();
27817
+ refreshProviders && refreshProviders();
27818
+ }, function (e, err) {
27819
+ return (void 0);
27820
+ });
27821
+ }
27822
+
27459
27823
  // Respond to external create trigger from header
27460
27824
  var prevCreateRequested = useRef(false);
27461
27825
  useEffect(function () {
@@ -27574,6 +27938,23 @@ var ProvidersSection = function ProvidersSection(_ref) {
27574
27938
  setIsCreating(false);
27575
27939
  }
27576
27940
  });
27941
+ } else if (isEditingMcp && selectedName && selectedProvider) {
27942
+ var mc = selectedProvider.mcpConfig || {};
27943
+ detailContent = /*#__PURE__*/jsx(CustomMcpServerForm, {
27944
+ isEditMode: true,
27945
+ initialName: selectedName,
27946
+ initialTransport: mc.transport || "stdio",
27947
+ initialCommand: mc.command || "",
27948
+ initialArgs: (mc.args || []).join(" "),
27949
+ initialEnvMappingRows: envMappingToRows(mc.envMapping, nextRowId),
27950
+ initialUrl: mc.url || "",
27951
+ initialHeaderRows: headerTemplateToRows(mc.headerTemplate, nextRowId),
27952
+ initialCredentials: selectedProvider.credentials || {},
27953
+ onSave: handleMcpEditSave,
27954
+ onBack: function onBack() {
27955
+ return setIsEditingMcp(false);
27956
+ }
27957
+ });
27577
27958
  } else if (selectedName && selectedProvider) {
27578
27959
  detailContent = /*#__PURE__*/jsx(ProviderDetail, {
27579
27960
  providerName: selectedName,
@@ -33379,5 +33760,5 @@ var WorkspaceMenu = function WorkspaceMenu(_ref) {
33379
33760
 
33380
33761
  ComponentManager.registerContainerTypes(LayoutContainer, LayoutGridContainer);
33381
33762
 
33382
- export { ALGOLIA_ANALYTICS_FOR_QUERY, ALGOLIA_ANALYTICS_FOR_QUERY_COMPLETE, ALGOLIA_ANALYTICS_FOR_QUERY_ERROR, ALGOLIA_LIST_INDICES, ALGOLIA_LIST_INDICES_COMPLETE, ALGOLIA_LIST_INDICES_ERROR, AVAILABLE_COLORS, AddMenuItemModal, AdvancedMcpConfig, AppContext, AppSettingsModal, AppThemeScope, AppWrapper, CHOOSE_FILE, CHOOSE_FILE_COMPLETE, CHOOSE_FILE_ERROR, ColorModel, ComponentConfigModel, ComponentManager, ContextModel, DATA_JSON_TO_CSV_FILE, DATA_JSON_TO_CSV_FILE_COMPLETE, DATA_JSON_TO_CSV_FILE_ERROR, DATA_JSON_TO_CSV_STRING, DATA_JSON_TO_CSV_STRING_COMPLETE, DATA_JSON_TO_CSV_STRING_ERROR, DATA_READ_FROM_FILE, DATA_READ_FROM_FILE_COMPLETE, DATA_READ_FROM_FILE_ERROR, DATA_SAVE_TO_FILE, DATA_SAVE_TO_FILE_COMPLETE, DATA_SAVE_TO_FILE_ERROR, DashCommandPalette, DashNavbar, DashSidebar, DashTabBar, DashboardStage as Dashboard, DashboardApi, DashboardContext, DashboardFooter, DashboardHeader, DashboardMenuItem, DashboardModel, DashboardMonitor, DashboardPublisher, DashboardStage, DashboardThemeProvider, DashboardWrapper, ElectronDashboardApi, ErrorBoundary, ExternalWidget, GRID_CELL_WIDGET_TYPE, HARMONY_STRATEGIES, LAYOUT_LIST, LAYOUT_LIST_COMPLETE, LAYOUT_LIST_ERROR, LAYOUT_SAVE, LAYOUT_SAVE_COMPLETE, LAYOUT_SAVE_ERROR, Layout, LayoutBuilder, LayoutBuilderAddItemModal, LayoutBuilderConfigContainerMenuItem, LayoutBuilderConfigMenuItem, LayoutBuilderConfigModal, LayoutBuilderEditItemModal, LayoutBuilderEventModal, LayoutBuilderGridItem, LayoutContainer, LayoutDragBuilder, LayoutDragBuilderEdit, LayoutGridContainer, LayoutManagerModal, LayoutModel, LayoutQuickAddMenu, MCP_CALL_TOOL_COMPLETE, MCP_CALL_TOOL_ERROR, MCP_GET_CATALOG_COMPLETE, MCP_GET_CATALOG_ERROR, MCP_LIST_RESOURCES_COMPLETE, MCP_LIST_RESOURCES_ERROR, MCP_LIST_TOOLS_COMPLETE, MCP_LIST_TOOLS_ERROR, MCP_READ_RESOURCE_COMPLETE, MCP_READ_RESOURCE_ERROR, MCP_SERVER_STATUS_COMPLETE, MCP_SERVER_STATUS_ERROR, MCP_START_SERVER_COMPLETE, MCP_START_SERVER_ERROR, MCP_STOP_SERVER_COMPLETE, MCP_STOP_SERVER_ERROR, MENU_ITEMS_DELETE, MENU_ITEMS_DELETE_COMPLETE, MENU_ITEMS_DELETE_ERROR, MENU_ITEMS_LIST, MENU_ITEMS_LIST_COMPLETE, MENU_ITEMS_LIST_ERROR, MENU_ITEMS_SAVE, MENU_ITEMS_SAVE_COMPLETE, MENU_ITEMS_SAVE_ERROR, MainMenu, MainMenuItem, MainMenuSection, McpServerPicker, MenuItemModel, MenuSlideOverlay, MergeCellsModal, MissingProviderPrompt, MockDashboardApi, PROVIDER_DELETE_COMPLETE, PROVIDER_DELETE_ERROR, PROVIDER_GET_COMPLETE, PROVIDER_GET_ERROR, PROVIDER_LIST_COMPLETE, PROVIDER_LIST_ERROR, PROVIDER_SAVE_COMPLETE, PROVIDER_SAVE_ERROR, PanelCode, PanelEditItem, PanelEditItemHandlers, ProviderContext, ProviderErrorBoundary, ProviderForm, ProviderSelector, SECURE_STORAGE_ENCRYPT_STRING, SECURE_STORAGE_ENCRYPT_STRING_COMPLETE, SECURE_STORAGE_ENCRYPT_STRING_ERROR, SECURE_STORE_ENCRYPTION_CHECK, SECURE_STORE_ENCRYPTION_CHECK_COMPLETE, SECURE_STORE_ENCRYPTION_CHECK_ERROR, SECURE_STORE_GET_DATA, SECURE_STORE_GET_DATA_COMPLETE, SECURE_STORE_GET_DATA_ERROR, SECURE_STORE_SET_DATA, SECURE_STORE_SET_DATA_COMPLETE, SECURE_STORE_SET_DATA_ERROR, SETTINGS_GET, SETTINGS_GET_COMPLETE, SETTINGS_GET_ERROR, SETTINGS_SAVE, SETTINGS_SAVE_COMPLETE, SETTINGS_SAVE_ERROR, SIDEBAR_WIDGET_TYPE, SettingsModel, SideMenu, SplitCellModal, THEME_DELETE, THEME_DELETE_COMPLETE, THEME_DELETE_ERROR, THEME_LIST, THEME_LIST_COMPLETE, THEME_LIST_ERROR, THEME_SAVE, THEME_SAVE_COMPLETE, THEME_SAVE_ERROR, ThemeApi, ThemeManagerModal, ThemeModel, ThemeWrapper, WORKSPACE_DELETE, WORKSPACE_DELETE_COMPLETE, WORKSPACE_DELETE_ERROR, WORKSPACE_LIST, WORKSPACE_LIST_COMPLETE, WORKSPACE_LIST_ERROR, WORKSPACE_SAVE, WORKSPACE_SAVE_COMPLETE, WORKSPACE_SAVE_ERROR, WebDashboardApi, Widget, WidgetApi, WidgetConfigPanel, WidgetContext, WidgetFactory, WidgetPopoutStage, WidgetProviderWrapper, WidgetSidebar, Workspace, WorkspaceContext, WorkspaceFooter, WorkspaceMenu, WorkspaceModel, addChildToLayoutItem, addItemToItemLayout, buildMcpConfigFromOverrides, canHaveChildren, changeDirectionForLayoutItem, createProviderRegistry, deriveFormFields, envMappingToRows, evaluateBundle, extractWidgetConfigs, formatFieldName, generateCustomTheme, generateHarmonyTheme, generateRandomTheme, generateThemeName, getBorderStyle, getChildrenForLayoutItem, getComponentInLayout, getContainerBorderColor, getContainerColor, getIndexOfLayoutChildrenForItem, getIndexOfLayoutItem, getLayoutItemById, getLayoutItemForWorkspace, getNearestParentWorkspace, getNextHighestId, getNextHighestItemInLayout, getNextHighestOrder, getNextHighestParentId, getNextLowestItemInLayout, getParentForLayoutItem, getParentWorkspaceForItem, getThemePresets, getWidgetsForWorkspace, getWorkspacesForWorkspace, headerTemplateToRows, isContainer, isLikelySecret, isMaxOrderForItem, isMinOrderForItem, isWidget, isWidgetResolvable, isWorkspace, layoutItemHasWorkspaceAsChild, loadWidgetBundle, numChildrenForLayout, removeItemFromLayout, renderComponent, renderGridLayout, renderGridLayoutFlow, _renderLayout as renderLayout, renderLayoutMenu, replaceItemInLayout, resolveIcon, setHostModules, traverseParentTree, updateLayoutItem, updateParentForItem, useDashboard, useMcpProvider, useProvider, useProviderClient, useWidgetEvents, useWidgetProviders, validateCellMerge, validateGridCell, validateGridPlacement, validateWidgetPlacement, withProviderDetection };
33763
+ export { ALGOLIA_ANALYTICS_FOR_QUERY, ALGOLIA_ANALYTICS_FOR_QUERY_COMPLETE, ALGOLIA_ANALYTICS_FOR_QUERY_ERROR, ALGOLIA_LIST_INDICES, ALGOLIA_LIST_INDICES_COMPLETE, ALGOLIA_LIST_INDICES_ERROR, AVAILABLE_COLORS, AddMenuItemModal, AdvancedMcpConfig, AppContext, AppSettingsModal, AppThemeScope, AppWrapper, CHOOSE_FILE, CHOOSE_FILE_COMPLETE, CHOOSE_FILE_ERROR, ColorModel, ComponentConfigModel, ComponentManager, ContextModel, DATA_JSON_TO_CSV_FILE, DATA_JSON_TO_CSV_FILE_COMPLETE, DATA_JSON_TO_CSV_FILE_ERROR, DATA_JSON_TO_CSV_STRING, DATA_JSON_TO_CSV_STRING_COMPLETE, DATA_JSON_TO_CSV_STRING_ERROR, DATA_READ_FROM_FILE, DATA_READ_FROM_FILE_COMPLETE, DATA_READ_FROM_FILE_ERROR, DATA_SAVE_TO_FILE, DATA_SAVE_TO_FILE_COMPLETE, DATA_SAVE_TO_FILE_ERROR, DashCommandPalette, DashNavbar, DashSidebar, DashTabBar, DashboardStage as Dashboard, DashboardApi, DashboardContext, DashboardFooter, DashboardHeader, DashboardMenuItem, DashboardModel, DashboardMonitor, DashboardPublisher, DashboardStage, DashboardThemeProvider, DashboardWrapper, ElectronDashboardApi, ErrorBoundary, ExternalWidget, GRID_CELL_WIDGET_TYPE, HARMONY_STRATEGIES, LAYOUT_LIST, LAYOUT_LIST_COMPLETE, LAYOUT_LIST_ERROR, LAYOUT_SAVE, LAYOUT_SAVE_COMPLETE, LAYOUT_SAVE_ERROR, Layout, LayoutBuilder, LayoutBuilderAddItemModal, LayoutBuilderConfigContainerMenuItem, LayoutBuilderConfigMenuItem, LayoutBuilderConfigModal, LayoutBuilderEditItemModal, LayoutBuilderEventModal, LayoutBuilderGridItem, LayoutContainer, LayoutDragBuilder, LayoutDragBuilderEdit, LayoutGridContainer, LayoutManagerModal, LayoutModel, LayoutQuickAddMenu, MCP_CALL_TOOL_COMPLETE, MCP_CALL_TOOL_ERROR, MCP_GET_CATALOG_COMPLETE, MCP_GET_CATALOG_ERROR, MCP_LIST_RESOURCES_COMPLETE, MCP_LIST_RESOURCES_ERROR, MCP_LIST_TOOLS_COMPLETE, MCP_LIST_TOOLS_ERROR, MCP_READ_RESOURCE_COMPLETE, MCP_READ_RESOURCE_ERROR, MCP_SERVER_STATUS_COMPLETE, MCP_SERVER_STATUS_ERROR, MCP_START_SERVER_COMPLETE, MCP_START_SERVER_ERROR, MCP_STOP_SERVER_COMPLETE, MCP_STOP_SERVER_ERROR, MENU_ITEMS_DELETE, MENU_ITEMS_DELETE_COMPLETE, MENU_ITEMS_DELETE_ERROR, MENU_ITEMS_LIST, MENU_ITEMS_LIST_COMPLETE, MENU_ITEMS_LIST_ERROR, MENU_ITEMS_SAVE, MENU_ITEMS_SAVE_COMPLETE, MENU_ITEMS_SAVE_ERROR, MainMenu, MainMenuItem, MainMenuSection, McpServerPicker, MenuItemModel, MenuSlideOverlay, MergeCellsModal, MissingProviderPrompt, MockDashboardApi, PROVIDER_DELETE_COMPLETE, PROVIDER_DELETE_ERROR, PROVIDER_GET_COMPLETE, PROVIDER_GET_ERROR, PROVIDER_LIST_COMPLETE, PROVIDER_LIST_ERROR, PROVIDER_SAVE_COMPLETE, PROVIDER_SAVE_ERROR, PanelCode, PanelEditItem, PanelEditItemHandlers, ProviderContext, ProviderErrorBoundary, ProviderForm, ProviderSelector, SECURE_STORAGE_ENCRYPT_STRING, SECURE_STORAGE_ENCRYPT_STRING_COMPLETE, SECURE_STORAGE_ENCRYPT_STRING_ERROR, SECURE_STORE_ENCRYPTION_CHECK, SECURE_STORE_ENCRYPTION_CHECK_COMPLETE, SECURE_STORE_ENCRYPTION_CHECK_ERROR, SECURE_STORE_GET_DATA, SECURE_STORE_GET_DATA_COMPLETE, SECURE_STORE_GET_DATA_ERROR, SECURE_STORE_SET_DATA, SECURE_STORE_SET_DATA_COMPLETE, SECURE_STORE_SET_DATA_ERROR, SETTINGS_GET, SETTINGS_GET_COMPLETE, SETTINGS_GET_ERROR, SETTINGS_SAVE, SETTINGS_SAVE_COMPLETE, SETTINGS_SAVE_ERROR, SIDEBAR_WIDGET_TYPE, SettingsModel, SideMenu, SplitCellModal, THEME_DELETE, THEME_DELETE_COMPLETE, THEME_DELETE_ERROR, THEME_LIST, THEME_LIST_COMPLETE, THEME_LIST_ERROR, THEME_SAVE, THEME_SAVE_COMPLETE, THEME_SAVE_ERROR, ThemeApi, ThemeManagerModal, ThemeModel, ThemeWrapper, WORKSPACE_DELETE, WORKSPACE_DELETE_COMPLETE, WORKSPACE_DELETE_ERROR, WORKSPACE_LIST, WORKSPACE_LIST_COMPLETE, WORKSPACE_LIST_ERROR, WORKSPACE_SAVE, WORKSPACE_SAVE_COMPLETE, WORKSPACE_SAVE_ERROR, WebDashboardApi, Widget, WidgetApi, WidgetConfigPanel, WidgetContext, WidgetFactory, WidgetPopoutStage, WidgetProviderWrapper, WidgetSidebar, Workspace, WorkspaceContext, WorkspaceFooter, WorkspaceMenu, WorkspaceModel, addChildToLayoutItem, addItemToItemLayout, buildMcpConfigFromOverrides, canHaveChildren, changeDirectionForLayoutItem, createProviderRegistry, deriveFormFields, envMappingToRows, evaluateBundle, extractWidgetConfigs, formStateToMcpJson, formatFieldName, generateCustomTheme, generateHarmonyTheme, generateRandomTheme, generateThemeName, getBorderStyle, getChildrenForLayoutItem, getComponentInLayout, getContainerBorderColor, getContainerColor, getIndexOfLayoutChildrenForItem, getIndexOfLayoutItem, getLayoutItemById, getLayoutItemForWorkspace, getNearestParentWorkspace, getNextHighestId, getNextHighestItemInLayout, getNextHighestOrder, getNextHighestParentId, getNextLowestItemInLayout, getParentForLayoutItem, getParentWorkspaceForItem, getThemePresets, getWidgetsForWorkspace, getWorkspacesForWorkspace, headerTemplateToRows, isContainer, isLikelySecret, isMaxOrderForItem, isMinOrderForItem, isWidget, isWidgetResolvable, isWorkspace, layoutItemHasWorkspaceAsChild, loadWidgetBundle, mcpJsonToFormState, numChildrenForLayout, removeItemFromLayout, renderComponent, renderGridLayout, renderGridLayoutFlow, _renderLayout as renderLayout, renderLayoutMenu, replaceItemInLayout, resolveIcon, setHostModules, traverseParentTree, updateLayoutItem, updateParentForItem, useDashboard, useMcpProvider, useProvider, useProviderClient, useWidgetEvents, useWidgetProviders, validateCellMerge, validateGridCell, validateGridPlacement, validateWidgetPlacement, withProviderDetection };
33383
33764
  //# sourceMappingURL=index.esm.js.map