@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.js CHANGED
@@ -9545,6 +9545,193 @@ function headerTemplateToRows(headerTemplate, nextRowId) {
9545
9545
  });
9546
9546
  }
9547
9547
 
9548
+ /**
9549
+ * Serialize the current form state into a bare MCP JSON config string.
9550
+ *
9551
+ * Output format (stdio):
9552
+ * {
9553
+ * "type": "stdio",
9554
+ * "command": "npx",
9555
+ * "args": ["-y", "package-name"],
9556
+ * "env": { "API_KEY": "${API_KEY}" }
9557
+ * }
9558
+ *
9559
+ * Output format (HTTP):
9560
+ * {
9561
+ * "type": "streamable_http",
9562
+ * "url": "https://example.com/mcp",
9563
+ * "headerTemplate": { "Authorization": "Bearer {{apiKey}}" }
9564
+ * }
9565
+ *
9566
+ * Credential values are NOT embedded — env values use ${FIELD_NAME} syntax
9567
+ * to reference credential fields entered separately in the form.
9568
+ *
9569
+ * @param {string} name - The provider name (unused in output, kept for API compat)
9570
+ * @param {string} transport - "stdio" or "streamable_http"
9571
+ * @param {object} fields - { command, args, envMappingRows, url, headerRows }
9572
+ * @returns {string} Formatted JSON string
9573
+ */
9574
+ function formStateToMcpJson(name, transport, fields) {
9575
+ var _fields$command = fields.command,
9576
+ command = _fields$command === void 0 ? "" : _fields$command,
9577
+ _fields$args = fields.args,
9578
+ args = _fields$args === void 0 ? "" : _fields$args,
9579
+ _fields$envMappingRow = fields.envMappingRows,
9580
+ envMappingRows = _fields$envMappingRow === void 0 ? [] : _fields$envMappingRow,
9581
+ _fields$url = fields.url,
9582
+ url = _fields$url === void 0 ? "" : _fields$url,
9583
+ _fields$headerRows = fields.headerRows,
9584
+ headerRows = _fields$headerRows === void 0 ? [] : _fields$headerRows;
9585
+ var serverConfig;
9586
+ if (transport === "stdio") {
9587
+ var argsArray = args.trim().split(/\s+/).filter(Boolean);
9588
+ var env = {};
9589
+ envMappingRows.forEach(function (row) {
9590
+ var envVar = row.envVar.trim();
9591
+ var credField = row.credField.trim();
9592
+ if (envVar && credField) {
9593
+ env[envVar] = "${".concat(credField, "}");
9594
+ }
9595
+ });
9596
+ serverConfig = {
9597
+ type: "stdio",
9598
+ command: command.trim()
9599
+ };
9600
+ if (argsArray.length > 0) serverConfig.args = argsArray;
9601
+ if (Object.keys(env).length > 0) serverConfig.env = env;
9602
+ } else {
9603
+ // streamable_http
9604
+ serverConfig = {
9605
+ type: "streamable_http",
9606
+ url: url.trim()
9607
+ };
9608
+ var headerTemplate = {};
9609
+ headerRows.forEach(function (row) {
9610
+ var hName = row.headerName.trim();
9611
+ var hValue = row.headerValue.trim();
9612
+ if (hName && hValue) {
9613
+ headerTemplate[hName] = hValue;
9614
+ }
9615
+ });
9616
+ if (Object.keys(headerTemplate).length > 0) serverConfig.headerTemplate = headerTemplate;
9617
+ }
9618
+ return JSON.stringify(serverConfig, null, 2);
9619
+ }
9620
+
9621
+ /**
9622
+ * Parse an MCP JSON config string back into form state.
9623
+ *
9624
+ * Accepts multiple input formats:
9625
+ * - Bare config: { "command": ..., "args": [...], "env": { "KEY": "${FIELD}" } }
9626
+ * - Wrapped: { "mcpServers": { "name": { ... } } } — unwraps and uses key as providerName
9627
+ *
9628
+ * Transport detection:
9629
+ * - Explicit `type` or `transport` field
9630
+ * - Inferred: `url` present → streamable_http, `command` present → stdio
9631
+ *
9632
+ * stdio env value parsing:
9633
+ * - "${FIELD_NAME}" → envVar = key, credField = FIELD_NAME (reference syntax)
9634
+ * - "literal-value" → envVar = key, credField = key, credentialData[key] = value
9635
+ *
9636
+ * @param {string} jsonString - The JSON to parse
9637
+ * @param {Function} nextRowId - Function that returns a unique row ID
9638
+ * @returns {{ providerName, transport, command, args, envMappingRows, url, headerRows, credentialData, error }}
9639
+ */
9640
+ function mcpJsonToFormState(jsonString, nextRowId) {
9641
+ var parsed;
9642
+ try {
9643
+ parsed = JSON.parse(jsonString);
9644
+ } catch (e) {
9645
+ return {
9646
+ error: "Invalid JSON: ".concat(e.message)
9647
+ };
9648
+ }
9649
+ var providerName = "";
9650
+ var serverConfig;
9651
+ if (parsed.mcpServers && _typeof(parsed.mcpServers) === "object") {
9652
+ var entries = Object.entries(parsed.mcpServers);
9653
+ if (entries.length === 0) {
9654
+ return {
9655
+ error: "No server found in mcpServers"
9656
+ };
9657
+ }
9658
+ var _entries$ = _slicedToArray(entries[0], 2);
9659
+ providerName = _entries$[0];
9660
+ serverConfig = _entries$[1];
9661
+ } else if (parsed.command || parsed.url || parsed.type || parsed.transport) {
9662
+ serverConfig = parsed;
9663
+ } else {
9664
+ return {
9665
+ error: "Unrecognized format: expected a server config with command, url, or type"
9666
+ };
9667
+ }
9668
+
9669
+ // Determine transport from type/transport field or infer from contents
9670
+ var explicitType = serverConfig.type || serverConfig.transport;
9671
+ var transport;
9672
+ if (explicitType) {
9673
+ transport = explicitType === "stdio" ? "stdio" : "streamable_http";
9674
+ } else {
9675
+ transport = serverConfig.url ? "streamable_http" : "stdio";
9676
+ }
9677
+ var result = {
9678
+ providerName: providerName,
9679
+ transport: transport,
9680
+ command: "",
9681
+ args: "",
9682
+ envMappingRows: [],
9683
+ url: "",
9684
+ headerRows: [],
9685
+ credentialData: {},
9686
+ error: null
9687
+ };
9688
+ if (transport === "stdio") {
9689
+ result.command = serverConfig.command || "";
9690
+ result.args = (serverConfig.args || []).join(" ");
9691
+ if (serverConfig.env && _typeof(serverConfig.env) === "object") {
9692
+ Object.entries(serverConfig.env).forEach(function (_ref5) {
9693
+ var _ref6 = _slicedToArray(_ref5, 2),
9694
+ envVar = _ref6[0],
9695
+ value = _ref6[1];
9696
+ // Check for ${FIELD_NAME} reference syntax
9697
+ var refMatch = typeof value === "string" && value.match(/^\$\{(.+)\}$/);
9698
+ if (refMatch) {
9699
+ // Reference syntax — credField is the extracted name, no credential value
9700
+ result.envMappingRows.push({
9701
+ id: nextRowId(),
9702
+ envVar: envVar,
9703
+ credField: refMatch[1]
9704
+ });
9705
+ } else {
9706
+ // Literal value — use envVar as credField and store the value
9707
+ result.envMappingRows.push({
9708
+ id: nextRowId(),
9709
+ envVar: envVar,
9710
+ credField: envVar
9711
+ });
9712
+ result.credentialData[envVar] = value || "";
9713
+ }
9714
+ });
9715
+ }
9716
+ } else {
9717
+ result.url = serverConfig.url || "";
9718
+ var headers = serverConfig.headers || serverConfig.headerTemplate || {};
9719
+ if (_typeof(headers) === "object") {
9720
+ Object.entries(headers).forEach(function (_ref7) {
9721
+ var _ref8 = _slicedToArray(_ref7, 2),
9722
+ headerName = _ref8[0],
9723
+ headerValue = _ref8[1];
9724
+ result.headerRows.push({
9725
+ id: nextRowId(),
9726
+ headerName: headerName,
9727
+ headerValue: headerValue
9728
+ });
9729
+ });
9730
+ }
9731
+ }
9732
+ return result;
9733
+ }
9734
+
9548
9735
  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; }
9549
9736
  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; }
9550
9737
  var AdvancedMcpConfig = function AdvancedMcpConfig(_ref) {
@@ -26234,29 +26421,57 @@ function buildMcpConfig(transport, _ref) {
26234
26421
  *
26235
26422
  * Form for configuring a custom MCP server (not from the catalog).
26236
26423
  * Supports stdio and streamable_http transports with dynamic field derivation.
26424
+ * Used for both creating new and editing existing MCP providers.
26237
26425
  *
26238
26426
  * @param {Function} onSave - (providerName, providerType, credentials, mcpConfig) => void
26239
- * @param {Function} onBack - Called when the user wants to return to the catalog
26427
+ * @param {Function} onBack - Called when the user wants to return
26428
+ * @param {boolean} isEditMode - Whether we're editing an existing provider
26429
+ * @param {string} initialName - Pre-populated provider name (edit mode)
26430
+ * @param {string} initialTransport - Pre-populated transport type (edit mode)
26431
+ * @param {string} initialCommand - Pre-populated command (edit mode)
26432
+ * @param {string} initialArgs - Pre-populated args string (edit mode)
26433
+ * @param {Array} initialEnvMappingRows - Pre-populated env mapping rows (edit mode)
26434
+ * @param {string} initialUrl - Pre-populated URL (edit mode)
26435
+ * @param {Array} initialHeaderRows - Pre-populated header rows (edit mode)
26436
+ * @param {object} initialCredentials - Pre-populated credential values (edit mode)
26240
26437
  */
26241
26438
  var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26242
26439
  var _testResult$tools;
26243
26440
  var onSave = _ref2.onSave,
26244
- onBack = _ref2.onBack;
26441
+ onBack = _ref2.onBack,
26442
+ _ref2$isEditMode = _ref2.isEditMode,
26443
+ isEditMode = _ref2$isEditMode === void 0 ? false : _ref2$isEditMode,
26444
+ _ref2$initialName = _ref2.initialName,
26445
+ initialName = _ref2$initialName === void 0 ? "" : _ref2$initialName,
26446
+ _ref2$initialTranspor = _ref2.initialTransport,
26447
+ initialTransport = _ref2$initialTranspor === void 0 ? "stdio" : _ref2$initialTranspor,
26448
+ _ref2$initialCommand = _ref2.initialCommand,
26449
+ initialCommand = _ref2$initialCommand === void 0 ? "" : _ref2$initialCommand,
26450
+ _ref2$initialArgs = _ref2.initialArgs,
26451
+ initialArgs = _ref2$initialArgs === void 0 ? "" : _ref2$initialArgs,
26452
+ _ref2$initialEnvMappi = _ref2.initialEnvMappingRows,
26453
+ initialEnvMappingRows = _ref2$initialEnvMappi === void 0 ? [] : _ref2$initialEnvMappi,
26454
+ _ref2$initialUrl = _ref2.initialUrl,
26455
+ initialUrl = _ref2$initialUrl === void 0 ? "" : _ref2$initialUrl,
26456
+ _ref2$initialHeaderRo = _ref2.initialHeaderRows,
26457
+ initialHeaderRows = _ref2$initialHeaderRo === void 0 ? [] : _ref2$initialHeaderRo,
26458
+ _ref2$initialCredenti = _ref2.initialCredentials,
26459
+ initialCredentials = _ref2$initialCredenti === void 0 ? {} : _ref2$initialCredenti;
26245
26460
  var appContext = React.useContext(AppContext);
26246
26461
  var dashApi = appContext === null || appContext === void 0 ? void 0 : appContext.dashApi;
26247
26462
 
26248
26463
  // Transport selection
26249
- var _useState = React.useState("stdio"),
26464
+ var _useState = React.useState(initialTransport),
26250
26465
  _useState2 = _slicedToArray(_useState, 2),
26251
26466
  transport = _useState2[0],
26252
26467
  setTransport = _useState2[1];
26253
26468
 
26254
26469
  // Common
26255
- var _useState3 = React.useState(""),
26470
+ var _useState3 = React.useState(initialName),
26256
26471
  _useState4 = _slicedToArray(_useState3, 2),
26257
26472
  providerName = _useState4[0],
26258
26473
  setProviderName = _useState4[1];
26259
- var _useState5 = React.useState({}),
26474
+ var _useState5 = React.useState(initialCredentials),
26260
26475
  _useState6 = _slicedToArray(_useState5, 2),
26261
26476
  credentialData = _useState6[0],
26262
26477
  setCredentialData = _useState6[1];
@@ -26274,34 +26489,51 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26274
26489
  setTestResult = _useState10[1];
26275
26490
 
26276
26491
  // stdio fields
26277
- var _useState11 = React.useState(""),
26492
+ var _useState11 = React.useState(initialCommand),
26278
26493
  _useState12 = _slicedToArray(_useState11, 2),
26279
26494
  command = _useState12[0],
26280
26495
  setCommand = _useState12[1];
26281
- var _useState13 = React.useState(""),
26496
+ var _useState13 = React.useState(initialArgs),
26282
26497
  _useState14 = _slicedToArray(_useState13, 2),
26283
26498
  args = _useState14[0],
26284
26499
  setArgs = _useState14[1];
26285
- var _useState15 = React.useState([]),
26500
+ var _useState15 = React.useState(initialEnvMappingRows),
26286
26501
  _useState16 = _slicedToArray(_useState15, 2),
26287
26502
  envMappingRows = _useState16[0],
26288
26503
  setEnvMappingRows = _useState16[1];
26289
26504
 
26290
26505
  // HTTP fields
26291
- var _useState17 = React.useState(""),
26506
+ var _useState17 = React.useState(initialUrl),
26292
26507
  _useState18 = _slicedToArray(_useState17, 2),
26293
26508
  url = _useState18[0],
26294
26509
  setUrl = _useState18[1];
26295
- var _useState19 = React.useState([]),
26510
+ var _useState19 = React.useState(initialHeaderRows),
26296
26511
  _useState20 = _slicedToArray(_useState19, 2),
26297
26512
  headerRows = _useState20[0],
26298
26513
  setHeaderRows = _useState20[1];
26299
26514
 
26515
+ // JSON editor state
26516
+ var _useState21 = React.useState("form"),
26517
+ _useState22 = _slicedToArray(_useState21, 2),
26518
+ viewMode = _useState22[0],
26519
+ setViewMode = _useState22[1]; // "form" | "json"
26520
+ var _useState23 = React.useState(""),
26521
+ _useState24 = _slicedToArray(_useState23, 2),
26522
+ jsonText = _useState24[0],
26523
+ setJsonText = _useState24[1];
26524
+ var _useState25 = React.useState(null),
26525
+ _useState26 = _slicedToArray(_useState25, 2),
26526
+ jsonError = _useState26[0],
26527
+ setJsonError = _useState26[1];
26528
+
26300
26529
  // Clear credential data when transport changes (derived fields change entirely)
26530
+ // Only in create mode — in edit mode the initial transport is set correctly
26301
26531
  React.useEffect(function () {
26302
- setCredentialData({});
26303
- setTestResult(null);
26304
- }, [transport]);
26532
+ if (!isEditMode) {
26533
+ setCredentialData({});
26534
+ setTestResult(null);
26535
+ }
26536
+ }, [transport, isEditMode]);
26305
26537
 
26306
26538
  // Build mcpConfig from current state
26307
26539
  var mcpConfig = React.useMemo(function () {
@@ -26383,6 +26615,38 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26383
26615
  }
26384
26616
  };
26385
26617
 
26618
+ // --- JSON toggle handlers ---
26619
+ var handleSwitchToJson = function handleSwitchToJson() {
26620
+ var json = formStateToMcpJson(providerName, transport, {
26621
+ command: command,
26622
+ args: args,
26623
+ envMappingRows: envMappingRows,
26624
+ url: url,
26625
+ headerRows: headerRows,
26626
+ credentialData: credentialData
26627
+ });
26628
+ setJsonText(json);
26629
+ setJsonError(null);
26630
+ setViewMode("json");
26631
+ };
26632
+ var handleSwitchToForm = function handleSwitchToForm() {
26633
+ var result = mcpJsonToFormState(jsonText, nextRowId);
26634
+ if (result.error) {
26635
+ setJsonError(result.error);
26636
+ return;
26637
+ }
26638
+ setProviderName(result.providerName || providerName);
26639
+ setTransport(result.transport);
26640
+ setCommand(result.command);
26641
+ setArgs(result.args);
26642
+ setEnvMappingRows(result.envMappingRows);
26643
+ setUrl(result.url);
26644
+ setHeaderRows(result.headerRows);
26645
+ setCredentialData(result.credentialData);
26646
+ setJsonError(null);
26647
+ setViewMode("form");
26648
+ };
26649
+
26386
26650
  // --- validation ---
26387
26651
  var validateForm = function validateForm() {
26388
26652
  var errors = {};
@@ -26442,6 +26706,28 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26442
26706
 
26443
26707
  // --- save ---
26444
26708
  var handleSave = function handleSave() {
26709
+ // If in JSON mode, parse JSON first to update form state
26710
+ if (viewMode === "json") {
26711
+ var result = mcpJsonToFormState(jsonText, nextRowId);
26712
+ if (result.error) {
26713
+ setJsonError(result.error);
26714
+ return;
26715
+ }
26716
+ var name = (result.providerName || providerName || "").trim();
26717
+ if (!name) {
26718
+ setJsonError("Provider name is required");
26719
+ return;
26720
+ }
26721
+ var config = buildMcpConfig(result.transport, {
26722
+ command: result.command,
26723
+ args: result.args,
26724
+ envMappingRows: result.envMappingRows,
26725
+ url: result.url,
26726
+ headerRows: result.headerRows
26727
+ });
26728
+ onSave(name, "custom", result.credentialData, config);
26729
+ return;
26730
+ }
26445
26731
  if (!validateForm()) return;
26446
26732
  onSave(providerName.trim(), "custom", credentialData, mcpConfig);
26447
26733
  };
@@ -26460,58 +26746,11 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26460
26746
  })
26461
26747
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26462
26748
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
26463
- title: "Configure Custom MCP Server",
26749
+ title: isEditMode ? "Edit MCP Server" : "Configure Custom MCP Server",
26464
26750
  padding: false
26465
26751
  }), /*#__PURE__*/jsxRuntime.jsx("p", {
26466
26752
  className: "text-sm opacity-50 mt-1",
26467
- children: "Define a custom MCP server connection"
26468
- })]
26469
- })]
26470
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26471
- className: "space-y-2",
26472
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26473
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26474
- children: "Transport Type"
26475
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26476
- className: "grid grid-cols-2 gap-3",
26477
- children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
26478
- hover: true,
26479
- selected: transport === "stdio",
26480
- onClick: function onClick() {
26481
- return setTransport("stdio");
26482
- },
26483
- className: "text-left",
26484
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26485
- className: "flex items-center gap-2 mb-1",
26486
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
26487
- icon: "terminal"
26488
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26489
- className: "font-semibold text-sm",
26490
- children: "Local Process (stdio)"
26491
- })]
26492
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
26493
- className: "text-xs opacity-50",
26494
- children: "Spawn a local command as a child process"
26495
- })]
26496
- }), /*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
26497
- hover: true,
26498
- selected: transport === "streamable_http",
26499
- onClick: function onClick() {
26500
- return setTransport("streamable_http");
26501
- },
26502
- className: "text-left",
26503
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26504
- className: "flex items-center gap-2 mb-1",
26505
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
26506
- icon: "globe"
26507
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26508
- className: "font-semibold text-sm",
26509
- children: "Remote Server (HTTP)"
26510
- })]
26511
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
26512
- className: "text-xs opacity-50",
26513
- children: "Connect to a remote MCP server via HTTP"
26514
- })]
26753
+ children: isEditMode ? "Modify this MCP server configuration" : "Define a custom MCP server connection"
26515
26754
  })]
26516
26755
  })]
26517
26756
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -26539,231 +26778,315 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26539
26778
  className: "text-sm text-red-400",
26540
26779
  children: formErrors.providerName
26541
26780
  })]
26542
- }), transport === "stdio" && /*#__PURE__*/jsxRuntime.jsxs("div", {
26543
- className: "space-y-4",
26544
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26545
- className: "border-t border-white/10 pt-4",
26546
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
26781
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26782
+ className: "flex items-center gap-1",
26783
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
26784
+ onClick: function onClick() {
26785
+ if (viewMode === "json") handleSwitchToForm();
26786
+ },
26787
+ 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"),
26788
+ children: "Form"
26789
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
26790
+ onClick: function onClick() {
26791
+ if (viewMode === "form") handleSwitchToJson();
26792
+ },
26793
+ 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"),
26794
+ children: "JSON"
26795
+ })]
26796
+ }), jsonError && /*#__PURE__*/jsxRuntime.jsx("p", {
26797
+ className: "text-sm text-red-400",
26798
+ children: jsonError
26799
+ }), viewMode === "json" && /*#__PURE__*/jsxRuntime.jsxs("div", {
26800
+ className: "space-y-2",
26801
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26802
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26803
+ children: "MCP Server Configuration (JSON)"
26804
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
26805
+ className: "text-sm opacity-50",
26806
+ children: "Paste a standard MCP config JSON (compatible with Claude Desktop, Cursor, etc.)"
26807
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.CodeEditorInline, {
26808
+ code: jsonText,
26809
+ setCode: function setCode(val) {
26810
+ setJsonText(val);
26811
+ setJsonError(null);
26812
+ },
26813
+ language: "json",
26814
+ placeholder: '{\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "${API_KEY}"\n }\n}'
26815
+ })]
26816
+ }), viewMode === "form" && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26817
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26818
+ className: "space-y-2",
26819
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26547
26820
  className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26548
- children: "Process Configuration"
26549
- })
26550
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26551
- className: "flex flex-col gap-2",
26552
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26553
- label: "Command",
26554
- required: true
26555
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
26556
- className: "text-sm opacity-50",
26557
- children: "The executable to run (e.g., npx, node, python)"
26558
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26559
- value: command,
26560
- onChange: function onChange(value) {
26561
- setCommand(value);
26562
- if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
26563
- setFormErrors(function (prev) {
26564
- var next = _objectSpread$5({}, prev);
26565
- delete next.command;
26566
- return next;
26567
- });
26568
- }
26569
- },
26570
- placeholder: "e.g., npx"
26571
- }), formErrors.command && /*#__PURE__*/jsxRuntime.jsx("p", {
26572
- className: "text-sm text-red-400",
26573
- children: formErrors.command
26574
- })]
26575
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26576
- className: "flex flex-col gap-2",
26577
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26578
- label: "Arguments"
26579
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
26580
- className: "text-sm opacity-50",
26581
- children: "Space-separated arguments passed to the command"
26582
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26583
- value: args,
26584
- onChange: setArgs,
26585
- placeholder: "e.g., -y @modelcontextprotocol/server-github"
26586
- })]
26587
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26588
- className: "space-y-3",
26589
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26590
- className: "flex items-center justify-between",
26591
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26592
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26593
- label: "Environment Variable Mapping"
26821
+ children: "Transport Type"
26822
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26823
+ className: "grid grid-cols-2 gap-3",
26824
+ children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
26825
+ hover: true,
26826
+ selected: transport === "stdio",
26827
+ onClick: function onClick() {
26828
+ return setTransport("stdio");
26829
+ },
26830
+ className: "text-left",
26831
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26832
+ className: "flex items-center gap-2 mb-1",
26833
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
26834
+ icon: "terminal"
26835
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26836
+ className: "font-semibold text-sm",
26837
+ children: "Local Process (stdio)"
26838
+ })]
26594
26839
  }), /*#__PURE__*/jsxRuntime.jsx("p", {
26595
- className: "text-sm opacity-50 mt-1",
26596
- children: "Map environment variables to credential fields"
26840
+ className: "text-xs opacity-50",
26841
+ children: "Spawn a local command as a child process"
26597
26842
  })]
26843
+ }), /*#__PURE__*/jsxRuntime.jsxs(DashReact.Card2, {
26844
+ hover: true,
26845
+ selected: transport === "streamable_http",
26846
+ onClick: function onClick() {
26847
+ return setTransport("streamable_http");
26848
+ },
26849
+ className: "text-left",
26850
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26851
+ className: "flex items-center gap-2 mb-1",
26852
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Icon2, {
26853
+ icon: "globe"
26854
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26855
+ className: "font-semibold text-sm",
26856
+ children: "Remote Server (HTTP)"
26857
+ })]
26858
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
26859
+ className: "text-xs opacity-50",
26860
+ children: "Connect to a remote MCP server via HTTP"
26861
+ })]
26862
+ })]
26863
+ })]
26864
+ }), transport === "stdio" && /*#__PURE__*/jsxRuntime.jsxs("div", {
26865
+ className: "space-y-4",
26866
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26867
+ className: "border-t border-white/10 pt-4",
26868
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
26869
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26870
+ children: "Process Configuration"
26598
26871
  })
26599
- }), envMappingRows.map(function (row) {
26600
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
26601
- className: "flex items-center gap-2",
26602
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26603
- className: "flex-1",
26604
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26605
- value: row.envVar,
26606
- onChange: function onChange(value) {
26607
- return updateEnvRow(row.id, "envVar", value);
26872
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26873
+ className: "flex flex-col gap-2",
26874
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26875
+ label: "Command",
26876
+ required: true
26877
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
26878
+ className: "text-sm opacity-50",
26879
+ children: "The executable to run (e.g., npx, node, python)"
26880
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26881
+ value: command,
26882
+ onChange: function onChange(value) {
26883
+ setCommand(value);
26884
+ if (formErrors.command && value !== null && value !== void 0 && value.trim()) {
26885
+ setFormErrors(function (prev) {
26886
+ var next = _objectSpread$5({}, prev);
26887
+ delete next.command;
26888
+ return next;
26889
+ });
26890
+ }
26891
+ },
26892
+ placeholder: "e.g., npx"
26893
+ }), formErrors.command && /*#__PURE__*/jsxRuntime.jsx("p", {
26894
+ className: "text-sm text-red-400",
26895
+ children: formErrors.command
26896
+ })]
26897
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26898
+ className: "flex flex-col gap-2",
26899
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26900
+ label: "Arguments"
26901
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
26902
+ className: "text-sm opacity-50",
26903
+ children: "Space-separated arguments passed to the command"
26904
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26905
+ value: args,
26906
+ onChange: setArgs,
26907
+ placeholder: "e.g., -y @modelcontextprotocol/server-github"
26908
+ })]
26909
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26910
+ className: "space-y-3",
26911
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26912
+ className: "flex items-center justify-between",
26913
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
26914
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26915
+ label: "Environment Variable Mapping"
26916
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
26917
+ className: "text-sm opacity-50 mt-1",
26918
+ children: "Map environment variables to credential fields"
26919
+ })]
26920
+ })
26921
+ }), envMappingRows.map(function (row) {
26922
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
26923
+ className: "flex items-center gap-2",
26924
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26925
+ className: "flex-1",
26926
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26927
+ value: row.envVar,
26928
+ onChange: function onChange(value) {
26929
+ return updateEnvRow(row.id, "envVar", value);
26930
+ },
26931
+ placeholder: "ENV_VAR_NAME"
26932
+ })
26933
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26934
+ className: "opacity-30 text-sm shrink-0",
26935
+ children: "\u2192"
26936
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
26937
+ className: "flex-1",
26938
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26939
+ value: row.credField,
26940
+ onChange: function onChange(value) {
26941
+ return updateEnvRow(row.id, "credField", value);
26942
+ },
26943
+ placeholder: "credentialField"
26944
+ })
26945
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
26946
+ onClick: function onClick() {
26947
+ return removeEnvRow(row.id);
26608
26948
  },
26609
- placeholder: "ENV_VAR_NAME"
26610
- })
26949
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26950
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26951
+ icon: "times",
26952
+ className: "text-sm"
26953
+ })
26954
+ })]
26955
+ }, row.id);
26956
+ }), /*#__PURE__*/jsxRuntime.jsxs("button", {
26957
+ onClick: addEnvRow,
26958
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26959
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26960
+ icon: "plus",
26961
+ className: "text-xs"
26611
26962
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
26612
- className: "opacity-30 text-sm shrink-0",
26613
- children: "\u2192"
26614
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
26615
- className: "flex-1",
26616
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26617
- value: row.credField,
26618
- onChange: function onChange(value) {
26619
- return updateEnvRow(row.id, "credField", value);
26620
- },
26621
- placeholder: "credentialField"
26622
- })
26623
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
26624
- onClick: function onClick() {
26625
- return removeEnvRow(row.id);
26626
- },
26627
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26628
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26629
- icon: "times",
26630
- className: "text-sm"
26631
- })
26963
+ children: "Add Environment Variable"
26632
26964
  })]
26633
- }, row.id);
26634
- }), /*#__PURE__*/jsxRuntime.jsxs("button", {
26635
- onClick: addEnvRow,
26636
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26637
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26638
- icon: "plus",
26639
- className: "text-xs"
26640
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26641
- children: "Add Environment Variable"
26642
26965
  })]
26643
26966
  })]
26644
- })]
26645
- }), transport === "streamable_http" && /*#__PURE__*/jsxRuntime.jsxs("div", {
26646
- className: "space-y-4",
26647
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26648
- className: "border-t border-white/10 pt-4",
26649
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
26650
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26651
- children: "Server Configuration"
26652
- })
26653
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26654
- className: "flex flex-col gap-2",
26655
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26656
- label: "Server URL",
26657
- required: true
26658
- }), /*#__PURE__*/jsxRuntime.jsxs("p", {
26659
- className: "text-sm opacity-50",
26660
- children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
26661
- className: "text-xs bg-white/10 px-1 py-0.5 rounded",
26662
- children: "{{fieldName}}"
26663
- }), " ", "for values provided as credentials"]
26664
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26665
- value: url,
26666
- onChange: function onChange(value) {
26667
- setUrl(value);
26668
- if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
26669
- setFormErrors(function (prev) {
26670
- var next = _objectSpread$5({}, prev);
26671
- delete next.url;
26672
- return next;
26673
- });
26674
- }
26675
- },
26676
- placeholder: "e.g., https://mcp.example.com/sse"
26677
- }), formErrors.url && /*#__PURE__*/jsxRuntime.jsx("p", {
26678
- className: "text-sm text-red-400",
26679
- children: formErrors.url
26680
- })]
26681
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26682
- className: "space-y-3",
26683
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26967
+ }), transport === "streamable_http" && /*#__PURE__*/jsxRuntime.jsxs("div", {
26968
+ className: "space-y-4",
26969
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26970
+ className: "border-t border-white/10 pt-4",
26971
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
26972
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26973
+ children: "Server Configuration"
26974
+ })
26975
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26976
+ className: "flex flex-col gap-2",
26684
26977
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26685
- label: "Request Headers"
26978
+ label: "Server URL",
26979
+ required: true
26686
26980
  }), /*#__PURE__*/jsxRuntime.jsxs("p", {
26687
- className: "text-sm opacity-50 mt-1",
26981
+ className: "text-sm opacity-50",
26688
26982
  children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
26689
26983
  className: "text-xs bg-white/10 px-1 py-0.5 rounded",
26690
26984
  children: "{{fieldName}}"
26691
- }), " ", "in values for credential placeholders"]
26985
+ }), " ", "for values provided as credentials"]
26986
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26987
+ value: url,
26988
+ onChange: function onChange(value) {
26989
+ setUrl(value);
26990
+ if (formErrors.url && value !== null && value !== void 0 && value.trim()) {
26991
+ setFormErrors(function (prev) {
26992
+ var next = _objectSpread$5({}, prev);
26993
+ delete next.url;
26994
+ return next;
26995
+ });
26996
+ }
26997
+ },
26998
+ placeholder: "e.g., https://mcp.example.com/sse"
26999
+ }), formErrors.url && /*#__PURE__*/jsxRuntime.jsx("p", {
27000
+ className: "text-sm text-red-400",
27001
+ children: formErrors.url
26692
27002
  })]
26693
- }), headerRows.map(function (row) {
26694
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
26695
- className: "flex items-center gap-2",
26696
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
26697
- className: "flex-1",
26698
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26699
- value: row.headerName,
26700
- onChange: function onChange(value) {
26701
- return updateHeaderRow(row.id, "headerName", value);
27003
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27004
+ className: "space-y-3",
27005
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27006
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27007
+ label: "Request Headers"
27008
+ }), /*#__PURE__*/jsxRuntime.jsxs("p", {
27009
+ className: "text-sm opacity-50 mt-1",
27010
+ children: ["Use", " ", /*#__PURE__*/jsxRuntime.jsx("code", {
27011
+ className: "text-xs bg-white/10 px-1 py-0.5 rounded",
27012
+ children: "{{fieldName}}"
27013
+ }), " ", "in values for credential placeholders"]
27014
+ })]
27015
+ }), headerRows.map(function (row) {
27016
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27017
+ className: "flex items-center gap-2",
27018
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27019
+ className: "flex-1",
27020
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27021
+ value: row.headerName,
27022
+ onChange: function onChange(value) {
27023
+ return updateHeaderRow(row.id, "headerName", value);
27024
+ },
27025
+ placeholder: "Header-Name"
27026
+ })
27027
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27028
+ className: "opacity-30 text-sm shrink-0",
27029
+ children: ":"
27030
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27031
+ className: "flex-1",
27032
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27033
+ value: row.headerValue,
27034
+ onChange: function onChange(value) {
27035
+ return updateHeaderRow(row.id, "headerValue", value);
27036
+ },
27037
+ placeholder: "Bearer {{apiKey}}"
27038
+ })
27039
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
27040
+ onClick: function onClick() {
27041
+ return removeHeaderRow(row.id);
26702
27042
  },
26703
- placeholder: "Header-Name"
26704
- })
27043
+ className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
27044
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27045
+ icon: "times",
27046
+ className: "text-sm"
27047
+ })
27048
+ })]
27049
+ }, row.id);
27050
+ }), /*#__PURE__*/jsxRuntime.jsxs("button", {
27051
+ onClick: addHeaderRow,
27052
+ className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
27053
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27054
+ icon: "plus",
27055
+ className: "text-xs"
26705
27056
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
26706
- className: "opacity-30 text-sm shrink-0",
26707
- children: ":"
26708
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
26709
- className: "flex-1",
26710
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26711
- value: row.headerValue,
26712
- onChange: function onChange(value) {
26713
- return updateHeaderRow(row.id, "headerValue", value);
26714
- },
26715
- placeholder: "Bearer {{apiKey}}"
26716
- })
26717
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
26718
- onClick: function onClick() {
26719
- return removeHeaderRow(row.id);
26720
- },
26721
- className: "text-gray-500 hover:text-red-400 transition-colors shrink-0",
26722
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26723
- icon: "times",
26724
- className: "text-sm"
26725
- })
27057
+ children: "Add Header"
26726
27058
  })]
26727
- }, row.id);
26728
- }), /*#__PURE__*/jsxRuntime.jsxs("button", {
26729
- onClick: addHeaderRow,
26730
- className: "text-sm text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1",
26731
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26732
- icon: "plus",
26733
- className: "text-xs"
26734
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
26735
- children: "Add Header"
26736
27059
  })]
26737
27060
  })]
26738
- })]
26739
- }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26740
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26741
- className: "border-t border-white/10 pt-4",
26742
- children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26743
- className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
26744
- children: "Credentials"
26745
- }), /*#__PURE__*/jsxRuntime.jsx("p", {
26746
- className: "text-sm opacity-50 mt-1",
26747
- children: "Values for the fields referenced in your configuration above"
26748
- })]
26749
- }), formFields.map(function (field) {
26750
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
26751
- className: "flex flex-col gap-2",
26752
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
26753
- label: field.displayName,
26754
- required: field.required
26755
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26756
- type: field.secret ? "password" : "text",
26757
- value: credentialData[field.key] || "",
26758
- onChange: function onChange(value) {
26759
- return handleCredentialChange(field.key, value);
26760
- },
26761
- placeholder: "Enter ".concat(field.displayName.toLowerCase())
26762
- }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
26763
- className: "text-sm text-red-400",
26764
- children: formErrors[field.key]
27061
+ }), formFields.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27062
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27063
+ className: "border-t border-white/10 pt-4",
27064
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
27065
+ className: "text-xs font-semibold opacity-40 uppercase tracking-wider",
27066
+ children: "Credentials"
27067
+ }), /*#__PURE__*/jsxRuntime.jsx("p", {
27068
+ className: "text-sm opacity-50 mt-1",
27069
+ children: "Values for the fields referenced in your configuration above"
26765
27070
  })]
26766
- }, field.key);
27071
+ }), formFields.map(function (field) {
27072
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27073
+ className: "flex flex-col gap-2",
27074
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FormLabel, {
27075
+ label: field.displayName,
27076
+ required: field.required
27077
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
27078
+ type: field.secret ? "password" : "text",
27079
+ value: credentialData[field.key] || "",
27080
+ onChange: function onChange(value) {
27081
+ return handleCredentialChange(field.key, value);
27082
+ },
27083
+ placeholder: "Enter ".concat(field.displayName.toLowerCase())
27084
+ }), formErrors[field.key] && /*#__PURE__*/jsxRuntime.jsx("p", {
27085
+ className: "text-sm text-red-400",
27086
+ children: formErrors[field.key]
27087
+ })]
27088
+ }, field.key);
27089
+ })]
26767
27090
  })]
26768
27091
  }), testResult && /*#__PURE__*/jsxRuntime.jsxs("div", {
26769
27092
  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"),
@@ -26801,7 +27124,7 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26801
27124
  onClick: handleTestConnection,
26802
27125
  size: "sm"
26803
27126
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26804
- title: "Save MCP Server",
27127
+ title: isEditMode ? "Save Changes" : "Save MCP Server",
26805
27128
  onClick: handleSave,
26806
27129
  size: "sm"
26807
27130
  })]
@@ -27369,6 +27692,16 @@ var ProvidersSection = function ProvidersSection(_ref) {
27369
27692
  _useState14 = _slicedToArray(_useState13, 2),
27370
27693
  isAddingMcp = _useState14[0],
27371
27694
  setIsAddingMcp = _useState14[1];
27695
+ var _useState15 = React.useState(false),
27696
+ _useState16 = _slicedToArray(_useState15, 2),
27697
+ isEditingMcp = _useState16[0],
27698
+ setIsEditingMcp = _useState16[1];
27699
+
27700
+ // Row ID counter for env/header rows in MCP edit mode
27701
+ var nextRowIdRef = React.useRef(0);
27702
+ var nextRowId = function nextRowId() {
27703
+ return "prov_row_".concat(++nextRowIdRef.current);
27704
+ };
27372
27705
  var providerEntries = Object.entries(providers);
27373
27706
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
27374
27707
 
@@ -27389,6 +27722,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27389
27722
  setFormCredentials({});
27390
27723
  setIsCreating(false);
27391
27724
  setIsEditing(false);
27725
+ setIsEditingMcp(false);
27392
27726
  }
27393
27727
  function handleSave() {
27394
27728
  if (!formName.trim() || !dashApi || !appId) return;
@@ -27411,11 +27745,17 @@ var ProvidersSection = function ProvidersSection(_ref) {
27411
27745
  }
27412
27746
  function handleStartEdit(name, provider) {
27413
27747
  setSelectedName(name);
27414
- setFormName(name);
27415
- setFormType(provider.type || "");
27416
- setFormCredentials(provider.credentials || {});
27417
- setIsEditing(true);
27418
27748
  setIsCreating(false);
27749
+ if (provider.providerClass === "mcp") {
27750
+ setIsEditingMcp(true);
27751
+ setIsEditing(false);
27752
+ } else {
27753
+ setFormName(name);
27754
+ setFormType(provider.type || "");
27755
+ setFormCredentials(provider.credentials || {});
27756
+ setIsEditing(true);
27757
+ setIsEditingMcp(false);
27758
+ }
27419
27759
  }
27420
27760
  function handleSaveEdit() {
27421
27761
  if (!formName.trim() || !dashApi || !appId) return;
@@ -27475,6 +27815,30 @@ var ProvidersSection = function ProvidersSection(_ref) {
27475
27815
  });
27476
27816
  }
27477
27817
 
27818
+ // Handle MCP provider editing via CustomMcpServerForm
27819
+ function handleMcpEditSave(providerName, providerType, mcpCredentials, mcpConfig) {
27820
+ if (!dashApi || !appId) return;
27821
+ var originalName = selectedName;
27822
+
27823
+ // Delete old if name changed
27824
+ if (originalName && originalName !== providerName) {
27825
+ dashApi.deleteProvider(appId, originalName, function () {}, function () {});
27826
+ }
27827
+ dashApi.saveProvider(appId, providerName, {
27828
+ providerType: providerType,
27829
+ credentials: mcpCredentials,
27830
+ providerClass: "mcp",
27831
+ mcpConfig: mcpConfig
27832
+ }, function () {
27833
+ setSelectedName(providerName);
27834
+ setIsEditingMcp(false);
27835
+ resetForm();
27836
+ refreshProviders && refreshProviders();
27837
+ }, function (e, err) {
27838
+ return (void 0);
27839
+ });
27840
+ }
27841
+
27478
27842
  // Respond to external create trigger from header
27479
27843
  var prevCreateRequested = React.useRef(false);
27480
27844
  React.useEffect(function () {
@@ -27593,6 +27957,23 @@ var ProvidersSection = function ProvidersSection(_ref) {
27593
27957
  setIsCreating(false);
27594
27958
  }
27595
27959
  });
27960
+ } else if (isEditingMcp && selectedName && selectedProvider) {
27961
+ var mc = selectedProvider.mcpConfig || {};
27962
+ detailContent = /*#__PURE__*/jsxRuntime.jsx(CustomMcpServerForm, {
27963
+ isEditMode: true,
27964
+ initialName: selectedName,
27965
+ initialTransport: mc.transport || "stdio",
27966
+ initialCommand: mc.command || "",
27967
+ initialArgs: (mc.args || []).join(" "),
27968
+ initialEnvMappingRows: envMappingToRows(mc.envMapping, nextRowId),
27969
+ initialUrl: mc.url || "",
27970
+ initialHeaderRows: headerTemplateToRows(mc.headerTemplate, nextRowId),
27971
+ initialCredentials: selectedProvider.credentials || {},
27972
+ onSave: handleMcpEditSave,
27973
+ onBack: function onBack() {
27974
+ return setIsEditingMcp(false);
27975
+ }
27976
+ });
27596
27977
  } else if (selectedName && selectedProvider) {
27597
27978
  detailContent = /*#__PURE__*/jsxRuntime.jsx(ProviderDetail, {
27598
27979
  providerName: selectedName,
@@ -33594,6 +33975,7 @@ exports.deriveFormFields = deriveFormFields;
33594
33975
  exports.envMappingToRows = envMappingToRows;
33595
33976
  exports.evaluateBundle = evaluateBundle;
33596
33977
  exports.extractWidgetConfigs = extractWidgetConfigs;
33978
+ exports.formStateToMcpJson = formStateToMcpJson;
33597
33979
  exports.formatFieldName = formatFieldName;
33598
33980
  exports.generateCustomTheme = generateCustomTheme;
33599
33981
  exports.generateHarmonyTheme = generateHarmonyTheme;
@@ -33629,6 +34011,7 @@ exports.isWidgetResolvable = isWidgetResolvable;
33629
34011
  exports.isWorkspace = isWorkspace;
33630
34012
  exports.layoutItemHasWorkspaceAsChild = layoutItemHasWorkspaceAsChild;
33631
34013
  exports.loadWidgetBundle = loadWidgetBundle;
34014
+ exports.mcpJsonToFormState = mcpJsonToFormState;
33632
34015
  exports.numChildrenForLayout = numChildrenForLayout;
33633
34016
  exports.removeItemFromLayout = removeItemFromLayout;
33634
34017
  exports.renderComponent = renderComponent;