@trops/dash-core 0.1.170 → 0.1.171

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.
@@ -828,49 +828,57 @@ var themeFromUrlEvents$1 = {
828
828
  * IPC communication between main and renderer processes.
829
829
  */
830
830
 
831
- const WS_CONNECT$1 = "ws-connect";
832
- const WS_CONNECT_COMPLETE = "ws-connect-complete";
833
- const WS_CONNECT_ERROR = "ws-connect-error";
834
-
835
- const WS_DISCONNECT$1 = "ws-disconnect";
836
- const WS_DISCONNECT_COMPLETE = "ws-disconnect-complete";
837
- const WS_DISCONNECT_ERROR = "ws-disconnect-error";
838
-
839
- const WS_SEND$1 = "ws-send";
840
- const WS_SEND_COMPLETE = "ws-send-complete";
841
- const WS_SEND_ERROR = "ws-send-error";
842
-
843
- const WS_STATUS$1 = "ws-status";
844
- const WS_STATUS_COMPLETE = "ws-status-complete";
845
- const WS_STATUS_ERROR = "ws-status-error";
846
-
847
- const WS_MESSAGE$1 = "ws-message";
848
-
849
- const WS_STATUS_CHANGE$1 = "ws-status-change";
850
-
851
- const WS_GET_ALL$1 = "ws-get-all";
852
- const WS_GET_ALL_COMPLETE = "ws-get-all-complete";
853
- const WS_GET_ALL_ERROR = "ws-get-all-error";
854
-
855
- var webSocketEvents$1 = {
856
- WS_CONNECT: WS_CONNECT$1,
857
- WS_CONNECT_COMPLETE,
858
- WS_CONNECT_ERROR,
859
- WS_DISCONNECT: WS_DISCONNECT$1,
860
- WS_DISCONNECT_COMPLETE,
861
- WS_DISCONNECT_ERROR,
862
- WS_SEND: WS_SEND$1,
863
- WS_SEND_COMPLETE,
864
- WS_SEND_ERROR,
865
- WS_STATUS: WS_STATUS$1,
866
- WS_STATUS_COMPLETE,
867
- WS_STATUS_ERROR,
868
- WS_MESSAGE: WS_MESSAGE$1,
869
- WS_STATUS_CHANGE: WS_STATUS_CHANGE$1,
870
- WS_GET_ALL: WS_GET_ALL$1,
871
- WS_GET_ALL_COMPLETE,
872
- WS_GET_ALL_ERROR,
873
- };
831
+ var webSocketEvents$1;
832
+ var hasRequiredWebSocketEvents;
833
+
834
+ function requireWebSocketEvents () {
835
+ if (hasRequiredWebSocketEvents) return webSocketEvents$1;
836
+ hasRequiredWebSocketEvents = 1;
837
+ const WS_CONNECT = "ws-connect";
838
+ const WS_CONNECT_COMPLETE = "ws-connect-complete";
839
+ const WS_CONNECT_ERROR = "ws-connect-error";
840
+
841
+ const WS_DISCONNECT = "ws-disconnect";
842
+ const WS_DISCONNECT_COMPLETE = "ws-disconnect-complete";
843
+ const WS_DISCONNECT_ERROR = "ws-disconnect-error";
844
+
845
+ const WS_SEND = "ws-send";
846
+ const WS_SEND_COMPLETE = "ws-send-complete";
847
+ const WS_SEND_ERROR = "ws-send-error";
848
+
849
+ const WS_STATUS = "ws-status";
850
+ const WS_STATUS_COMPLETE = "ws-status-complete";
851
+ const WS_STATUS_ERROR = "ws-status-error";
852
+
853
+ const WS_MESSAGE = "ws-message";
854
+
855
+ const WS_STATUS_CHANGE = "ws-status-change";
856
+
857
+ const WS_GET_ALL = "ws-get-all";
858
+ const WS_GET_ALL_COMPLETE = "ws-get-all-complete";
859
+ const WS_GET_ALL_ERROR = "ws-get-all-error";
860
+
861
+ webSocketEvents$1 = {
862
+ WS_CONNECT,
863
+ WS_CONNECT_COMPLETE,
864
+ WS_CONNECT_ERROR,
865
+ WS_DISCONNECT,
866
+ WS_DISCONNECT_COMPLETE,
867
+ WS_DISCONNECT_ERROR,
868
+ WS_SEND,
869
+ WS_SEND_COMPLETE,
870
+ WS_SEND_ERROR,
871
+ WS_STATUS,
872
+ WS_STATUS_COMPLETE,
873
+ WS_STATUS_ERROR,
874
+ WS_MESSAGE,
875
+ WS_STATUS_CHANGE,
876
+ WS_GET_ALL,
877
+ WS_GET_ALL_COMPLETE,
878
+ WS_GET_ALL_ERROR,
879
+ };
880
+ return webSocketEvents$1;
881
+ }
874
882
 
875
883
  /**
876
884
  * Event Constants File - MCP Dash Server Events
@@ -923,7 +931,7 @@ const sessionEvents = sessionEvents$1;
923
931
  const notificationEvents = notificationEvents$1;
924
932
  const schedulerEvents = schedulerEvents$1;
925
933
  const themeFromUrlEvents = themeFromUrlEvents$1;
926
- const webSocketEvents = webSocketEvents$1;
934
+ const webSocketEvents = requireWebSocketEvents();
927
935
  const mcpDashServerEvents = mcpDashServerEvents$1;
928
936
 
929
937
  const publicEvents = {
@@ -1207,7 +1215,7 @@ const { getFileContents: getFileContents$7 } = file;
1207
1215
  const configFilename$5 = "workspaces.json";
1208
1216
  const appName$7 = "Dashboard";
1209
1217
 
1210
- const workspaceController$1 = {
1218
+ const workspaceController$2 = {
1211
1219
  /**
1212
1220
  * createWorkspace
1213
1221
  *
@@ -1449,7 +1457,7 @@ const workspaceController$1 = {
1449
1457
  },
1450
1458
  };
1451
1459
 
1452
- var workspaceController_1 = workspaceController$1;
1460
+ var workspaceController_1 = workspaceController$2;
1453
1461
 
1454
1462
  const { app: app$9 } = require$$0$2;
1455
1463
  const path$f = require$$1$2;
@@ -1459,7 +1467,7 @@ const { getFileContents: getFileContents$6 } = file;
1459
1467
  const configFilename$4 = "themes.json";
1460
1468
  const appName$6 = "Dashboard";
1461
1469
 
1462
- const themeController$3 = {
1470
+ const themeController$4 = {
1463
1471
  /**
1464
1472
  * saveTheme
1465
1473
  * Create a new Theme that can be used in the application
@@ -1590,7 +1598,7 @@ const themeController$3 = {
1590
1598
  },
1591
1599
  };
1592
1600
 
1593
- var themeController_1 = themeController$3;
1601
+ var themeController_1 = themeController$4;
1594
1602
 
1595
1603
  /**
1596
1604
  * Utils/tranaform
@@ -31843,7 +31851,7 @@ const path$2 = require$$1$2;
31843
31851
  const { app: app$2, dialog: dialog$1 } = require$$0$2;
31844
31852
  const AdmZip$1 = require$$3$4;
31845
31853
 
31846
- const themeController$2 = themeController_1;
31854
+ const themeController$3 = themeController_1;
31847
31855
  const registryController$1 = registryController$2;
31848
31856
  const registryApiController$1 = registryApiController$2;
31849
31857
  const {
@@ -31950,7 +31958,7 @@ function extractColors(themeData) {
31950
31958
  async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
31951
31959
  try {
31952
31960
  // Read the theme data
31953
- const themesResult = themeController$2.listThemesForApplication(win, appId);
31961
+ const themesResult = themeController$3.listThemesForApplication(win, appId);
31954
31962
  if (themesResult.error) {
31955
31963
  return {
31956
31964
  success: false,
@@ -32161,7 +32169,7 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
32161
32169
  const themeKey = pkg.displayName || pkg.name;
32162
32170
 
32163
32171
  // Save via themeController
32164
- const saveResult = themeController$2.saveThemeForApplication(
32172
+ const saveResult = themeController$3.saveThemeForApplication(
32165
32173
  win,
32166
32174
  appId,
32167
32175
  themeKey,
@@ -32198,7 +32206,7 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
32198
32206
  */
32199
32207
  function getThemePublishPreview$1(appId, themeKey) {
32200
32208
  try {
32201
- const themesResult = themeController$2.listThemesForApplication(null, appId);
32209
+ const themesResult = themeController$3.listThemesForApplication(null, appId);
32202
32210
  if (themesResult.error) {
32203
32211
  return {
32204
32212
  success: false,
@@ -32265,7 +32273,7 @@ const {
32265
32273
  applyEventWiringToLayout,
32266
32274
  } = dashboardConfigUtils$1;
32267
32275
  const { searchRegistry, getPackage } = registryController$2;
32268
- const themeController$1 = themeController_1;
32276
+ const themeController$2 = themeController_1;
32269
32277
 
32270
32278
  const configFilename = "workspaces.json";
32271
32279
  const appName$1 = "Dashboard";
@@ -32345,7 +32353,7 @@ async function exportDashboardConfig$1(
32345
32353
  // 4. Bundle theme if workspace has a themeKey
32346
32354
  if (workspace.themeKey) {
32347
32355
  try {
32348
- const themeResult = themeController$1.listThemesForApplication(
32356
+ const themeResult = themeController$2.listThemesForApplication(
32349
32357
  win,
32350
32358
  appId,
32351
32359
  );
@@ -32700,7 +32708,7 @@ async function processDashboardConfig(
32700
32708
  if (dashboardConfig.theme) {
32701
32709
  const bundledTheme = dashboardConfig.theme;
32702
32710
  try {
32703
- const themeResult = themeController$1.listThemesForApplication(win, appId);
32711
+ const themeResult = themeController$2.listThemesForApplication(win, appId);
32704
32712
  const existingThemes = themeResult.themes || {};
32705
32713
  const themeKey = bundledTheme.key;
32706
32714
 
@@ -32714,7 +32722,7 @@ async function processDashboardConfig(
32714
32722
  installedAt: new Date().toISOString(),
32715
32723
  };
32716
32724
  }
32717
- themeController$1.saveThemeForApplication(
32725
+ themeController$2.saveThemeForApplication(
32718
32726
  win,
32719
32727
  appId,
32720
32728
  themeKey,
@@ -33112,7 +33120,7 @@ async function prepareDashboardForPublish$1(
33112
33120
  // 4. Bundle theme if workspace has a themeKey
33113
33121
  if (workspace.themeKey) {
33114
33122
  try {
33115
- const themeResult = themeController$1.listThemesForApplication(
33123
+ const themeResult = themeController$2.listThemesForApplication(
33116
33124
  win,
33117
33125
  appId,
33118
33126
  );
@@ -45243,7 +45251,7 @@ function interpolate(template, credentials) {
45243
45251
  * @param {object} extra - Additional fields (error, retryCount, retryIn, etc.)
45244
45252
  */
45245
45253
  function broadcastStatusChange(providerName, status, extra = {}) {
45246
- const { WS_STATUS_CHANGE } = webSocketEvents$1;
45254
+ const { WS_STATUS_CHANGE } = requireWebSocketEvents();
45247
45255
  const { BrowserWindow } = require$$0$2;
45248
45256
 
45249
45257
  const payload = { provider: providerName, status, ...extra };
@@ -45261,7 +45269,7 @@ function broadcastStatusChange(providerName, status, extra = {}) {
45261
45269
  * @param {*} data - The message data
45262
45270
  */
45263
45271
  function broadcastMessage(providerName, data) {
45264
- const { WS_MESSAGE } = webSocketEvents$1;
45272
+ const { WS_MESSAGE } = requireWebSocketEvents();
45265
45273
  const { BrowserWindow } = require$$0$2;
45266
45274
 
45267
45275
  const payload = {
@@ -66056,6 +66064,7 @@ let httpServer = null;
66056
66064
  let transport = null;
66057
66065
  let startTime = null;
66058
66066
  let connectionCount = 0;
66067
+ let activeWin = null;
66059
66068
 
66060
66069
  // --- Rate Limiting ---
66061
66070
  const RATE_LIMIT = 60; // requests per minute
@@ -66102,7 +66111,7 @@ const registeredResources = [];
66102
66111
  * Register a tool to be exposed via the MCP server.
66103
66112
  * Call this before starting the server (or restart after registering).
66104
66113
  */
66105
- function registerTool(toolDef) {
66114
+ function registerTool$1(toolDef) {
66106
66115
  registeredTools.push(toolDef);
66107
66116
  }
66108
66117
 
@@ -66144,8 +66153,43 @@ function saveMcpServerSettings(win, mcpSettings) {
66144
66153
  settingsController$1.saveSettingsForApplication(win, settings);
66145
66154
  }
66146
66155
 
66156
+ // --- App ID Resolution ---
66157
+ /**
66158
+ * Resolve the appId by scanning the userData/Dashboard directory for
66159
+ * subdirectories containing workspaces.json. Falls back to the default.
66160
+ */
66161
+ function resolveAppId() {
66162
+ const { app } = require$$0$2;
66163
+ const fs = require$$0$3;
66164
+ const path = require$$1$2;
66165
+ const dashboardDir = path.join(app.getPath("userData"), "Dashboard");
66166
+ try {
66167
+ const entries = fs.readdirSync(dashboardDir, { withFileTypes: true });
66168
+ for (const entry of entries) {
66169
+ if (entry.isDirectory()) {
66170
+ const wsFile = path.join(dashboardDir, entry.name, "workspaces.json");
66171
+ if (fs.existsSync(wsFile)) {
66172
+ return entry.name;
66173
+ }
66174
+ }
66175
+ }
66176
+ } catch (e) {
66177
+ // Directory may not exist yet
66178
+ }
66179
+ return "@trops/dash-electron";
66180
+ }
66181
+
66182
+ /**
66183
+ * Get the current server context (win + appId) for tool handlers.
66184
+ * Returns null if the server is not running.
66185
+ */
66186
+ function getServerContext() {
66187
+ if (!activeWin) return null;
66188
+ return { win: activeWin, appId: resolveAppId() };
66189
+ }
66190
+
66147
66191
  // --- Controller ---
66148
- const mcpDashServerController$2 = {
66192
+ const mcpDashServerController$3 = {
66149
66193
  /**
66150
66194
  * Start the MCP Dash server.
66151
66195
  * @param {BrowserWindow} win
@@ -66163,7 +66207,7 @@ const mcpDashServerController$2 = {
66163
66207
  const serverSettings = getMcpServerSettings(win);
66164
66208
  const port = options.port || serverSettings.port || 3141;
66165
66209
  const token =
66166
- serverSettings.token || mcpDashServerController$2.getOrCreateToken(win);
66210
+ serverSettings.token || mcpDashServerController$3.getOrCreateToken(win);
66167
66211
 
66168
66212
  // Create McpServer
66169
66213
  mcpServer = new McpServer({
@@ -66257,6 +66301,7 @@ const mcpDashServerController$2 = {
66257
66301
 
66258
66302
  startTime = Date.now();
66259
66303
  connectionCount = 0;
66304
+ activeWin = win;
66260
66305
  startCleanup();
66261
66306
 
66262
66307
  // Save enabled state
@@ -66317,6 +66362,7 @@ const mcpDashServerController$2 = {
66317
66362
  transport = null;
66318
66363
  startTime = null;
66319
66364
  connectionCount = 0;
66365
+ activeWin = null;
66320
66366
 
66321
66367
  // Update settings
66322
66368
  if (win) {
@@ -66339,8 +66385,8 @@ const mcpDashServerController$2 = {
66339
66385
  * Restart the server (stop + start).
66340
66386
  */
66341
66387
  restartServer: async (win, options = {}) => {
66342
- await mcpDashServerController$2.stopServer(win);
66343
- return mcpDashServerController$2.startServer(win, options);
66388
+ await mcpDashServerController$3.stopServer(win);
66389
+ return mcpDashServerController$3.startServer(win, options);
66344
66390
  },
66345
66391
 
66346
66392
  /**
@@ -66380,7 +66426,7 @@ const mcpDashServerController$2 = {
66380
66426
  const serverSettings = getMcpServerSettings(win);
66381
66427
  if (serverSettings.enabled) {
66382
66428
  console.log("[mcpDashServer] Auto-starting server...");
66383
- return mcpDashServerController$2.startServer(win, {
66429
+ return mcpDashServerController$3.startServer(win, {
66384
66430
  port: serverSettings.port,
66385
66431
  });
66386
66432
  }
@@ -66388,11 +66434,12 @@ const mcpDashServerController$2 = {
66388
66434
  },
66389
66435
 
66390
66436
  // Expose registration functions for other controllers
66391
- registerTool,
66437
+ registerTool: registerTool$1,
66392
66438
  registerResource,
66439
+ getServerContext,
66393
66440
  };
66394
66441
 
66395
- var mcpDashServerController_1 = mcpDashServerController$2;
66442
+ var mcpDashServerController_1 = mcpDashServerController$3;
66396
66443
 
66397
66444
  /**
66398
66445
  * clientFactories.js
@@ -66825,7 +66872,7 @@ const {
66825
66872
  matchTailwindFamily,
66826
66873
  generateThemeFromPalette,
66827
66874
  } = paletteToThemeMapper_1;
66828
- const mcpDashServerController$1 = mcpDashServerController_1;
66875
+ const mcpDashServerController$2 = mcpDashServerController_1;
66829
66876
 
66830
66877
  var controller = {
66831
66878
  showDialog,
@@ -66908,7 +66955,7 @@ var controller = {
66908
66955
  assignRoles,
66909
66956
  matchTailwindFamily,
66910
66957
  generateThemeFromPalette,
66911
- mcpDashServerController: mcpDashServerController$1,
66958
+ mcpDashServerController: mcpDashServerController$2,
66912
66959
  };
66913
66960
 
66914
66961
  const { ipcRenderer: ipcRenderer$q } = require$$0$2;
@@ -68921,6 +68968,488 @@ const mcpDashServerApi$2 = {
68921
68968
 
68922
68969
  var mcpDashServerApi_1 = mcpDashServerApi$2;
68923
68970
 
68971
+ /**
68972
+ * toolDefinitions.js
68973
+ *
68974
+ * MCP tool schemas for dashboard/workspace operations and app stats.
68975
+ * Each definition includes name, description, and JSON Schema inputSchema.
68976
+ */
68977
+
68978
+ const dashboardTools$1 = [
68979
+ {
68980
+ name: "list_dashboards",
68981
+ description: "List all dashboards with their IDs, names, and widget counts",
68982
+ inputSchema: {
68983
+ type: "object",
68984
+ properties: {},
68985
+ required: [],
68986
+ },
68987
+ },
68988
+ {
68989
+ name: "get_dashboard",
68990
+ description:
68991
+ "Get full details of a dashboard including layout and widgets. Omit dashboardId to get the active dashboard.",
68992
+ inputSchema: {
68993
+ type: "object",
68994
+ properties: {
68995
+ dashboardId: {
68996
+ type: "string",
68997
+ description:
68998
+ "Dashboard ID. Omit to get the currently active dashboard.",
68999
+ },
69000
+ },
69001
+ required: [],
69002
+ },
69003
+ },
69004
+ {
69005
+ name: "create_dashboard",
69006
+ description: "Create a new dashboard with the given name",
69007
+ inputSchema: {
69008
+ type: "object",
69009
+ properties: {
69010
+ name: {
69011
+ type: "string",
69012
+ description: "Display name for the new dashboard",
69013
+ },
69014
+ },
69015
+ required: ["name"],
69016
+ },
69017
+ },
69018
+ {
69019
+ name: "delete_dashboard",
69020
+ description:
69021
+ "Delete a dashboard by ID. Cannot delete the last remaining dashboard.",
69022
+ inputSchema: {
69023
+ type: "object",
69024
+ properties: {
69025
+ dashboardId: {
69026
+ type: "string",
69027
+ description: "ID of the dashboard to delete",
69028
+ },
69029
+ },
69030
+ required: ["dashboardId"],
69031
+ },
69032
+ },
69033
+ {
69034
+ name: "get_app_stats",
69035
+ description:
69036
+ "Get application statistics: counts of dashboards, widgets, themes, and providers",
69037
+ inputSchema: {
69038
+ type: "object",
69039
+ properties: {},
69040
+ required: [],
69041
+ },
69042
+ },
69043
+ ];
69044
+
69045
+ var toolDefinitions = { dashboardTools: dashboardTools$1 };
69046
+
69047
+ /**
69048
+ * toolHandlers.js
69049
+ *
69050
+ * MCP tool handlers for dashboard/workspace CRUD and app statistics.
69051
+ * Each handler delegates to existing controllers via getServerContext().
69052
+ */
69053
+ const mcpDashServerController$1 = mcpDashServerController_1;
69054
+ const workspaceController$1 = workspaceController_1;
69055
+ const themeController$1 = themeController_1;
69056
+ const providerController$1 = requireProviderController();
69057
+
69058
+ /**
69059
+ * Helper: get win + appId or throw a descriptive error.
69060
+ */
69061
+ function requireContext() {
69062
+ const ctx = mcpDashServerController$1.getServerContext();
69063
+ if (!ctx) {
69064
+ throw new Error("MCP server is not running or has no active window");
69065
+ }
69066
+ return ctx;
69067
+ }
69068
+
69069
+ /**
69070
+ * Helper: count widgets in a workspace's layout array.
69071
+ * Widgets are layout items whose component is registered and is not a container.
69072
+ */
69073
+ function countWidgets(layout) {
69074
+ if (!Array.isArray(layout)) return 0;
69075
+ return layout.filter(
69076
+ (item) =>
69077
+ item.component &&
69078
+ item.component !== "Container" &&
69079
+ item.component !== "LayoutContainer" &&
69080
+ item.component !== "LayoutGridContainer",
69081
+ ).length;
69082
+ }
69083
+
69084
+ /**
69085
+ * list_dashboards — Returns all workspaces with id, name, widget count, active state.
69086
+ */
69087
+ async function handleListDashboards$1() {
69088
+ const { win, appId } = requireContext();
69089
+ const result = workspaceController$1.listWorkspacesForApplication(win, appId);
69090
+
69091
+ if (result.error) {
69092
+ return {
69093
+ content: [
69094
+ {
69095
+ type: "text",
69096
+ text: JSON.stringify({ error: result.message }),
69097
+ },
69098
+ ],
69099
+ isError: true,
69100
+ };
69101
+ }
69102
+
69103
+ const dashboards = (result.workspaces || []).map((ws, index) => ({
69104
+ id: String(ws.id),
69105
+ name: ws.name || ws.label || `Dashboard ${index + 1}`,
69106
+ widgetCount: countWidgets(ws.layout),
69107
+ isActive: index === 0,
69108
+ }));
69109
+
69110
+ return {
69111
+ content: [{ type: "text", text: JSON.stringify(dashboards, null, 2) }],
69112
+ };
69113
+ }
69114
+
69115
+ /**
69116
+ * get_dashboard — Returns full details for a dashboard by ID (or the active one).
69117
+ */
69118
+ async function handleGetDashboard$1({ dashboardId }) {
69119
+ const { win, appId } = requireContext();
69120
+ const result = workspaceController$1.listWorkspacesForApplication(win, appId);
69121
+
69122
+ if (result.error) {
69123
+ return {
69124
+ content: [
69125
+ {
69126
+ type: "text",
69127
+ text: JSON.stringify({ error: result.message }),
69128
+ },
69129
+ ],
69130
+ isError: true,
69131
+ };
69132
+ }
69133
+
69134
+ const workspaces = result.workspaces || [];
69135
+ let workspace;
69136
+
69137
+ if (dashboardId) {
69138
+ workspace = workspaces.find((ws) => String(ws.id) === dashboardId);
69139
+ if (!workspace) {
69140
+ return {
69141
+ content: [
69142
+ {
69143
+ type: "text",
69144
+ text: JSON.stringify({
69145
+ error: `Dashboard not found: ${dashboardId}`,
69146
+ }),
69147
+ },
69148
+ ],
69149
+ isError: true,
69150
+ };
69151
+ }
69152
+ } else {
69153
+ // Return first workspace as the "active" one
69154
+ workspace = workspaces[0];
69155
+ if (!workspace) {
69156
+ return {
69157
+ content: [
69158
+ {
69159
+ type: "text",
69160
+ text: JSON.stringify({
69161
+ error: "No dashboards exist",
69162
+ }),
69163
+ },
69164
+ ],
69165
+ isError: true,
69166
+ };
69167
+ }
69168
+ }
69169
+
69170
+ const widgets = (workspace.layout || [])
69171
+ .filter(
69172
+ (item) =>
69173
+ item.component &&
69174
+ item.component !== "Container" &&
69175
+ item.component !== "LayoutContainer" &&
69176
+ item.component !== "LayoutGridContainer",
69177
+ )
69178
+ .map((item) => ({
69179
+ id: String(item.id),
69180
+ type: item.component,
69181
+ config: item.config || {},
69182
+ }));
69183
+
69184
+ const detail = {
69185
+ id: String(workspace.id),
69186
+ name: workspace.name || workspace.label || "Dashboard",
69187
+ layout: workspace.layout || [],
69188
+ widgets,
69189
+ theme: workspace.theme || null,
69190
+ };
69191
+
69192
+ return {
69193
+ content: [{ type: "text", text: JSON.stringify(detail, null, 2) }],
69194
+ };
69195
+ }
69196
+
69197
+ /**
69198
+ * create_dashboard — Creates a new workspace with the given name.
69199
+ */
69200
+ async function handleCreateDashboard$1({ name }) {
69201
+ if (!name || typeof name !== "string" || !name.trim()) {
69202
+ return {
69203
+ content: [
69204
+ {
69205
+ type: "text",
69206
+ text: JSON.stringify({
69207
+ error: "name is required and must be a non-empty string",
69208
+ }),
69209
+ },
69210
+ ],
69211
+ isError: true,
69212
+ };
69213
+ }
69214
+
69215
+ const { win, appId } = requireContext();
69216
+
69217
+ const newWorkspace = {
69218
+ id: Date.now(),
69219
+ name: name.trim(),
69220
+ label: name.trim(),
69221
+ type: "workspace",
69222
+ version: 1,
69223
+ menuId: 1,
69224
+ layout: [
69225
+ {
69226
+ id: 1,
69227
+ order: 1,
69228
+ component: "Container",
69229
+ parentId: 0,
69230
+ items: [],
69231
+ },
69232
+ ],
69233
+ };
69234
+
69235
+ const result = workspaceController$1.saveWorkspaceForApplication(
69236
+ win,
69237
+ appId,
69238
+ newWorkspace,
69239
+ );
69240
+
69241
+ if (result.error) {
69242
+ return {
69243
+ content: [
69244
+ {
69245
+ type: "text",
69246
+ text: JSON.stringify({ error: result.message }),
69247
+ },
69248
+ ],
69249
+ isError: true,
69250
+ };
69251
+ }
69252
+
69253
+ return {
69254
+ content: [
69255
+ {
69256
+ type: "text",
69257
+ text: JSON.stringify(
69258
+ { id: String(newWorkspace.id), name: newWorkspace.name },
69259
+ null,
69260
+ 2,
69261
+ ),
69262
+ },
69263
+ ],
69264
+ };
69265
+ }
69266
+
69267
+ /**
69268
+ * delete_dashboard — Deletes a workspace by ID. Rejects if it's the last one.
69269
+ */
69270
+ async function handleDeleteDashboard$1({ dashboardId }) {
69271
+ if (!dashboardId || typeof dashboardId !== "string") {
69272
+ return {
69273
+ content: [
69274
+ {
69275
+ type: "text",
69276
+ text: JSON.stringify({
69277
+ error: "dashboardId is required",
69278
+ }),
69279
+ },
69280
+ ],
69281
+ isError: true,
69282
+ };
69283
+ }
69284
+
69285
+ const { win, appId } = requireContext();
69286
+
69287
+ // Check how many dashboards exist
69288
+ const listResult = workspaceController$1.listWorkspacesForApplication(
69289
+ win,
69290
+ appId,
69291
+ );
69292
+ const workspaces = listResult.workspaces || [];
69293
+
69294
+ if (workspaces.length <= 1) {
69295
+ return {
69296
+ content: [
69297
+ {
69298
+ type: "text",
69299
+ text: JSON.stringify({
69300
+ error: "Cannot delete the last remaining dashboard",
69301
+ }),
69302
+ },
69303
+ ],
69304
+ isError: true,
69305
+ };
69306
+ }
69307
+
69308
+ // Verify the dashboard exists
69309
+ const exists = workspaces.some((ws) => String(ws.id) === dashboardId);
69310
+ if (!exists) {
69311
+ return {
69312
+ content: [
69313
+ {
69314
+ type: "text",
69315
+ text: JSON.stringify({
69316
+ error: `Dashboard not found: ${dashboardId}`,
69317
+ }),
69318
+ },
69319
+ ],
69320
+ isError: true,
69321
+ };
69322
+ }
69323
+
69324
+ // Use numeric ID if stored as number
69325
+ const targetWs = workspaces.find((ws) => String(ws.id) === dashboardId);
69326
+ const result = workspaceController$1.deleteWorkspaceForApplication(
69327
+ win,
69328
+ appId,
69329
+ targetWs.id,
69330
+ );
69331
+
69332
+ if (result.error) {
69333
+ return {
69334
+ content: [
69335
+ {
69336
+ type: "text",
69337
+ text: JSON.stringify({ error: result.message }),
69338
+ },
69339
+ ],
69340
+ isError: true,
69341
+ };
69342
+ }
69343
+
69344
+ return {
69345
+ content: [
69346
+ {
69347
+ type: "text",
69348
+ text: JSON.stringify({
69349
+ success: true,
69350
+ deleted: dashboardId,
69351
+ remaining: (result.workspaces || []).length,
69352
+ }),
69353
+ },
69354
+ ],
69355
+ };
69356
+ }
69357
+
69358
+ /**
69359
+ * get_app_stats — Returns counts of dashboards, widgets, themes, and providers.
69360
+ */
69361
+ async function handleGetAppStats$1() {
69362
+ const { win, appId } = requireContext();
69363
+
69364
+ // Dashboards + widget count
69365
+ const wsResult = workspaceController$1.listWorkspacesForApplication(win, appId);
69366
+ const workspaces = wsResult.workspaces || [];
69367
+ const dashboardCount = workspaces.length;
69368
+ const widgetCount = workspaces.reduce(
69369
+ (sum, ws) => sum + countWidgets(ws.layout),
69370
+ 0,
69371
+ );
69372
+
69373
+ // Themes
69374
+ const themeResult = themeController$1.listThemesForApplication(win, appId);
69375
+ const themes = themeResult.themes || {};
69376
+ const themeCount = Object.keys(themes).length;
69377
+
69378
+ // Providers
69379
+ const providerResult = providerController$1.listProviders(win, appId);
69380
+ const providers = providerResult.providers || {};
69381
+ const providerCount = Object.keys(providers).length;
69382
+
69383
+ const stats = {
69384
+ dashboardCount,
69385
+ widgetCount,
69386
+ themeCount,
69387
+ providerCount,
69388
+ };
69389
+
69390
+ return {
69391
+ content: [{ type: "text", text: JSON.stringify(stats, null, 2) }],
69392
+ };
69393
+ }
69394
+
69395
+ var toolHandlers = {
69396
+ handleListDashboards: handleListDashboards$1,
69397
+ handleGetDashboard: handleGetDashboard$1,
69398
+ handleCreateDashboard: handleCreateDashboard$1,
69399
+ handleDeleteDashboard: handleDeleteDashboard$1,
69400
+ handleGetAppStats: handleGetAppStats$1,
69401
+ };
69402
+
69403
+ /**
69404
+ * dashboardTools.js
69405
+ *
69406
+ * Registers dashboard/workspace MCP tools with the MCP Dash server.
69407
+ * Call registerDashboardTools() during app startup (before or after server start).
69408
+ */
69409
+
69410
+ const { registerTool } = mcpDashServerController_1;
69411
+ const { dashboardTools } = toolDefinitions;
69412
+ const {
69413
+ handleListDashboards,
69414
+ handleGetDashboard,
69415
+ handleCreateDashboard,
69416
+ handleDeleteDashboard,
69417
+ handleGetAppStats,
69418
+ } = toolHandlers;
69419
+
69420
+ // Map tool names to handler functions
69421
+ const handlerMap = {
69422
+ list_dashboards: handleListDashboards,
69423
+ get_dashboard: handleGetDashboard,
69424
+ create_dashboard: handleCreateDashboard,
69425
+ delete_dashboard: handleDeleteDashboard,
69426
+ get_app_stats: handleGetAppStats,
69427
+ };
69428
+
69429
+ /**
69430
+ * Register all dashboard tools with the MCP server controller.
69431
+ */
69432
+ function registerDashboardTools$1() {
69433
+ for (const tool of dashboardTools) {
69434
+ const handler = handlerMap[tool.name];
69435
+ if (!handler) {
69436
+ console.warn(`[dashboardTools] No handler found for tool: ${tool.name}`);
69437
+ continue;
69438
+ }
69439
+ registerTool({
69440
+ name: tool.name,
69441
+ description: tool.description,
69442
+ inputSchema: tool.inputSchema,
69443
+ handler,
69444
+ });
69445
+ }
69446
+ console.log(
69447
+ `[dashboardTools] Registered ${dashboardTools.length} dashboard tools`,
69448
+ );
69449
+ }
69450
+
69451
+ var dashboardTools_1 = { registerDashboardTools: registerDashboardTools$1 };
69452
+
68924
69453
  /**
68925
69454
  * dashboardRatingsApi.js
68926
69455
  *
@@ -69241,6 +69770,10 @@ const widgetRegistry = widgetRegistryExports;
69241
69770
  const widgetCompiler = widgetCompiler$1;
69242
69771
  const dynamicWidgetLoader = dynamicWidgetLoaderExports;
69243
69772
 
69773
+ // --- MCP Dash Server Tools ---
69774
+ const { registerDashboardTools } = dashboardTools_1;
69775
+ registerDashboardTools();
69776
+
69244
69777
  // --- Schema ---
69245
69778
  const dashboardConfigValidator = dashboardConfigValidator$1;
69246
69779
  const dashboardConfigUtils = dashboardConfigUtils$1;
@@ -69332,6 +69865,9 @@ var electron = {
69332
69865
 
69333
69866
  // Setup helpers
69334
69867
  setupCacheHandlers: clientCache.setupCacheHandlers.bind(clientCache),
69868
+
69869
+ // MCP Dash Server Tools
69870
+ registerDashboardTools,
69335
69871
  };
69336
69872
 
69337
69873
  var index = /*@__PURE__*/getDefaultExportFromCjs(electron);