@trops/dash-core 0.1.447 → 0.1.449
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/electron/index.js +314 -30
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +76 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +76 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -424,6 +424,11 @@ const MCP_GET_CATALOG$1 = "mcp-get-catalog";
|
|
|
424
424
|
const MCP_GET_CATALOG_COMPLETE = "mcp-get-catalog-complete";
|
|
425
425
|
const MCP_GET_CATALOG_ERROR = "mcp-get-catalog-error";
|
|
426
426
|
|
|
427
|
+
const MCP_GET_KNOWN_EXTERNAL$1 = "mcp-get-known-external";
|
|
428
|
+
|
|
429
|
+
const MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$2 = "mcp-install-known-external-confirm";
|
|
430
|
+
const MCP_INSTALL_KNOWN_EXTERNAL_RESULT$2 = "mcp-install-known-external-result";
|
|
431
|
+
|
|
427
432
|
const MCP_RUN_AUTH$1 = "mcp-run-auth";
|
|
428
433
|
const MCP_RUN_AUTH_COMPLETE = "mcp-run-auth-complete";
|
|
429
434
|
const MCP_RUN_AUTH_ERROR = "mcp-run-auth-error";
|
|
@@ -453,6 +458,9 @@ var mcpEvents$1 = {
|
|
|
453
458
|
MCP_GET_CATALOG: MCP_GET_CATALOG$1,
|
|
454
459
|
MCP_GET_CATALOG_COMPLETE,
|
|
455
460
|
MCP_GET_CATALOG_ERROR,
|
|
461
|
+
MCP_GET_KNOWN_EXTERNAL: MCP_GET_KNOWN_EXTERNAL$1,
|
|
462
|
+
MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM: MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$2,
|
|
463
|
+
MCP_INSTALL_KNOWN_EXTERNAL_RESULT: MCP_INSTALL_KNOWN_EXTERNAL_RESULT$2,
|
|
456
464
|
MCP_RUN_AUTH: MCP_RUN_AUTH$1,
|
|
457
465
|
MCP_RUN_AUTH_COMPLETE,
|
|
458
466
|
MCP_RUN_AUTH_ERROR,
|
|
@@ -5296,7 +5304,7 @@ const layoutController$1 = {
|
|
|
5296
5304
|
|
|
5297
5305
|
var layoutController_1 = layoutController$1;
|
|
5298
5306
|
|
|
5299
|
-
var mcpController$
|
|
5307
|
+
var mcpController$4 = {exports: {}};
|
|
5300
5308
|
|
|
5301
5309
|
var streamableHttp$1 = {};
|
|
5302
5310
|
|
|
@@ -26032,7 +26040,7 @@ async function refreshGoogleOAuthToken(tokenRefresh) {
|
|
|
26032
26040
|
console.log("[mcpController] Google OAuth token refreshed successfully");
|
|
26033
26041
|
}
|
|
26034
26042
|
|
|
26035
|
-
const mcpController$
|
|
26043
|
+
const mcpController$3 = {
|
|
26036
26044
|
/**
|
|
26037
26045
|
* startServer
|
|
26038
26046
|
* Start an MCP server with the given config and credentials
|
|
@@ -26070,13 +26078,13 @@ const mcpController$2 = {
|
|
|
26070
26078
|
try {
|
|
26071
26079
|
// Stop if in stale/error state
|
|
26072
26080
|
if (activeServers.has(serverName)) {
|
|
26073
|
-
await mcpController$
|
|
26081
|
+
await mcpController$3.stopServer(win, serverName);
|
|
26074
26082
|
}
|
|
26075
26083
|
|
|
26076
26084
|
// Merge with catalog entry to pick up updated command/args
|
|
26077
26085
|
// (saved provider config may reference a stale or archived package)
|
|
26078
26086
|
try {
|
|
26079
|
-
const { catalog } = mcpController$
|
|
26087
|
+
const { catalog } = mcpController$3.getCatalog(win);
|
|
26080
26088
|
const catalogEntry = (catalog || []).find(
|
|
26081
26089
|
(entry) => entry.name === serverName,
|
|
26082
26090
|
);
|
|
@@ -26602,6 +26610,48 @@ const mcpController$2 = {
|
|
|
26602
26610
|
}
|
|
26603
26611
|
},
|
|
26604
26612
|
|
|
26613
|
+
/**
|
|
26614
|
+
* getKnownExternalCatalog
|
|
26615
|
+
* Load the curated allow-list of MCP servers known to exist outside the
|
|
26616
|
+
* built-in catalog. Used by the AI Widget Builder to suggest installable
|
|
26617
|
+
* servers and as the trust boundary for `install_known_mcp_server` —
|
|
26618
|
+
* the install tool will reject any id that doesn't appear here.
|
|
26619
|
+
*
|
|
26620
|
+
* @returns {{ success, servers } | { error, message, servers }}
|
|
26621
|
+
*/
|
|
26622
|
+
getKnownExternalCatalog: () => {
|
|
26623
|
+
try {
|
|
26624
|
+
const catalogPath = path$c.join(
|
|
26625
|
+
__dirname,
|
|
26626
|
+
"..",
|
|
26627
|
+
"mcp",
|
|
26628
|
+
"knownExternalMcpServers.json",
|
|
26629
|
+
);
|
|
26630
|
+
|
|
26631
|
+
if (!fs$8.existsSync(catalogPath)) {
|
|
26632
|
+
return { success: true, servers: [] };
|
|
26633
|
+
}
|
|
26634
|
+
|
|
26635
|
+
const catalogData = fs$8.readFileSync(catalogPath, "utf8");
|
|
26636
|
+
const catalog = JSON.parse(catalogData);
|
|
26637
|
+
|
|
26638
|
+
return {
|
|
26639
|
+
success: true,
|
|
26640
|
+
servers: catalog.servers || [],
|
|
26641
|
+
};
|
|
26642
|
+
} catch (error) {
|
|
26643
|
+
console.error(
|
|
26644
|
+
"[mcpController] Error loading known-external catalog:",
|
|
26645
|
+
error,
|
|
26646
|
+
);
|
|
26647
|
+
return {
|
|
26648
|
+
error: true,
|
|
26649
|
+
message: error.message,
|
|
26650
|
+
servers: [],
|
|
26651
|
+
};
|
|
26652
|
+
}
|
|
26653
|
+
},
|
|
26654
|
+
|
|
26605
26655
|
/**
|
|
26606
26656
|
* listConnectedServers
|
|
26607
26657
|
* Returns all connected servers with their cached tool lists.
|
|
@@ -26765,17 +26815,17 @@ const mcpController$2 = {
|
|
|
26765
26815
|
);
|
|
26766
26816
|
const promises = [];
|
|
26767
26817
|
for (const [serverName] of activeServers) {
|
|
26768
|
-
promises.push(mcpController$
|
|
26818
|
+
promises.push(mcpController$3.stopServer(null, serverName));
|
|
26769
26819
|
}
|
|
26770
26820
|
await Promise.allSettled(promises);
|
|
26771
26821
|
console.log("[mcpController] All servers stopped");
|
|
26772
26822
|
},
|
|
26773
26823
|
};
|
|
26774
26824
|
|
|
26775
|
-
mcpController$
|
|
26776
|
-
mcpController$
|
|
26825
|
+
mcpController$4.exports = mcpController$3;
|
|
26826
|
+
mcpController$4.exports.refreshGoogleOAuthToken = refreshGoogleOAuthToken;
|
|
26777
26827
|
|
|
26778
|
-
var mcpControllerExports = mcpController$
|
|
26828
|
+
var mcpControllerExports = mcpController$4.exports;
|
|
26779
26829
|
|
|
26780
26830
|
/**
|
|
26781
26831
|
* Scoped package identity utilities.
|
|
@@ -51231,7 +51281,7 @@ var jsonSchemaToZod_1 = { jsonSchemaToZod: jsonSchemaToZod$1, jsonSchemaProperty
|
|
|
51231
51281
|
|
|
51232
51282
|
const https$2 = require$$8$1;
|
|
51233
51283
|
const { randomUUID } = require$$1$6;
|
|
51234
|
-
const { BrowserWindow } = require$$0$1;
|
|
51284
|
+
const { BrowserWindow: BrowserWindow$1 } = require$$0$1;
|
|
51235
51285
|
const { McpServer } = mcp;
|
|
51236
51286
|
const {
|
|
51237
51287
|
StreamableHTTPServerTransport,
|
|
@@ -51275,7 +51325,7 @@ function broadcastStateChanged(toolName, result) {
|
|
|
51275
51325
|
/* leave null */
|
|
51276
51326
|
}
|
|
51277
51327
|
const payload = { toolName, result: parsed };
|
|
51278
|
-
for (const win of BrowserWindow.getAllWindows()) {
|
|
51328
|
+
for (const win of BrowserWindow$1.getAllWindows()) {
|
|
51279
51329
|
if (!win.isDestroyed()) {
|
|
51280
51330
|
try {
|
|
51281
51331
|
win.webContents.send("dash-mcp:state-changed", payload);
|
|
@@ -51341,7 +51391,7 @@ const registeredPrompts = [];
|
|
|
51341
51391
|
* Register a tool to be exposed via the MCP server.
|
|
51342
51392
|
* Call this before starting the server (or restart after registering).
|
|
51343
51393
|
*/
|
|
51344
|
-
function registerTool$
|
|
51394
|
+
function registerTool$7(toolDef) {
|
|
51345
51395
|
registeredTools.push(toolDef);
|
|
51346
51396
|
}
|
|
51347
51397
|
|
|
@@ -51722,7 +51772,7 @@ const mcpDashServerController$4 = {
|
|
|
51722
51772
|
},
|
|
51723
51773
|
|
|
51724
51774
|
// Expose registration functions for other controllers
|
|
51725
|
-
registerTool: registerTool$
|
|
51775
|
+
registerTool: registerTool$7,
|
|
51726
51776
|
registerResource: registerResource$1,
|
|
51727
51777
|
registerPrompt: registerPrompt$1,
|
|
51728
51778
|
getServerContext,
|
|
@@ -61842,7 +61892,7 @@ async function handleListProviders$1() {
|
|
|
61842
61892
|
* add_provider — Adds a new provider with encrypted credentials.
|
|
61843
61893
|
* Credentials are accepted on input but never returned in the response.
|
|
61844
61894
|
*/
|
|
61845
|
-
async function handleAddProvider$
|
|
61895
|
+
async function handleAddProvider$2({
|
|
61846
61896
|
name,
|
|
61847
61897
|
type,
|
|
61848
61898
|
providerClass,
|
|
@@ -62667,7 +62717,7 @@ var toolHandlers$1 = {
|
|
|
62667
62717
|
handleSearchRegistryThemes: handleSearchRegistryThemes$1,
|
|
62668
62718
|
handleSearchRegistryDashboards: handleSearchRegistryDashboards$1,
|
|
62669
62719
|
handleListProviders: handleListProviders$1,
|
|
62670
|
-
handleAddProvider: handleAddProvider$
|
|
62720
|
+
handleAddProvider: handleAddProvider$2,
|
|
62671
62721
|
handleRemoveProvider: handleRemoveProvider$1,
|
|
62672
62722
|
handleGetSetupGuide: handleGetSetupGuide$1,
|
|
62673
62723
|
handleSetLayout: handleSetLayout$1,
|
|
@@ -62692,7 +62742,7 @@ var toolHandlers$1 = {
|
|
|
62692
62742
|
*/
|
|
62693
62743
|
|
|
62694
62744
|
const Anthropic = require$$0$9;
|
|
62695
|
-
const mcpController$
|
|
62745
|
+
const mcpController$2 = mcpControllerExports;
|
|
62696
62746
|
const cliController$1 = cliController_1;
|
|
62697
62747
|
const toolDefinitions = toolDefinitions$1;
|
|
62698
62748
|
const toolHandlers = toolHandlers$1;
|
|
@@ -62988,7 +63038,7 @@ const llmController$1 = {
|
|
|
62988
63038
|
isError = true;
|
|
62989
63039
|
} else {
|
|
62990
63040
|
try {
|
|
62991
|
-
const mcpResult = await mcpController$
|
|
63041
|
+
const mcpResult = await mcpController$2.callTool(
|
|
62992
63042
|
win,
|
|
62993
63043
|
serverName,
|
|
62994
63044
|
toolBlock.name,
|
|
@@ -75880,6 +75930,9 @@ const {
|
|
|
75880
75930
|
MCP_READ_RESOURCE,
|
|
75881
75931
|
MCP_SERVER_STATUS,
|
|
75882
75932
|
MCP_GET_CATALOG,
|
|
75933
|
+
MCP_GET_KNOWN_EXTERNAL,
|
|
75934
|
+
MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM: MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1,
|
|
75935
|
+
MCP_INSTALL_KNOWN_EXTERNAL_RESULT: MCP_INSTALL_KNOWN_EXTERNAL_RESULT$1,
|
|
75883
75936
|
MCP_RUN_AUTH,
|
|
75884
75937
|
} = events$8;
|
|
75885
75938
|
|
|
@@ -75976,6 +76029,45 @@ const mcpApi$2 = {
|
|
|
75976
76029
|
*/
|
|
75977
76030
|
getCatalog: () => ipcRenderer$i.invoke(MCP_GET_CATALOG),
|
|
75978
76031
|
|
|
76032
|
+
/**
|
|
76033
|
+
* getKnownExternalCatalog
|
|
76034
|
+
* Load the curated allow-list of MCP servers known to exist outside the
|
|
76035
|
+
* built-in catalog. The AI Widget Builder reads this to advertise
|
|
76036
|
+
* "you can install <X> via Add Custom MCP" and as the trust boundary
|
|
76037
|
+
* for the `install_known_mcp_server` dash MCP tool — only ids in this
|
|
76038
|
+
* list are installable via that path.
|
|
76039
|
+
*
|
|
76040
|
+
* @returns {Promise<{ success, servers } | { error, message, servers }>}
|
|
76041
|
+
*/
|
|
76042
|
+
getKnownExternalCatalog: () => ipcRenderer$i.invoke(MCP_GET_KNOWN_EXTERNAL),
|
|
76043
|
+
|
|
76044
|
+
/**
|
|
76045
|
+
* onInstallKnownExternalConfirm
|
|
76046
|
+
* Subscribe to install-confirm requests emitted by the dash MCP server
|
|
76047
|
+
* tool `install_known_mcp_server`. The renderer renders a confirmation
|
|
76048
|
+
* modal and replies with { confirmed, credentials } via
|
|
76049
|
+
* sendInstallKnownExternalResult().
|
|
76050
|
+
*
|
|
76051
|
+
* @param {(payload: { id, requestId, server }) => void} callback
|
|
76052
|
+
* @returns {() => void} cleanup
|
|
76053
|
+
*/
|
|
76054
|
+
onInstallKnownExternalConfirm: (callback) => {
|
|
76055
|
+
const handler = (_e, data) => callback(data);
|
|
76056
|
+
ipcRenderer$i.on(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
|
|
76057
|
+
return () =>
|
|
76058
|
+
ipcRenderer$i.removeListener(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
|
|
76059
|
+
},
|
|
76060
|
+
|
|
76061
|
+
/**
|
|
76062
|
+
* sendInstallKnownExternalResult
|
|
76063
|
+
* Reply to a confirm request with the user's decision + credentials.
|
|
76064
|
+
*
|
|
76065
|
+
* @param {string} requestId
|
|
76066
|
+
* @param {{ confirmed: boolean, credentials?: object, error?: string }} result
|
|
76067
|
+
*/
|
|
76068
|
+
sendInstallKnownExternalResult: (requestId, result) =>
|
|
76069
|
+
ipcRenderer$i.send(MCP_INSTALL_KNOWN_EXTERNAL_RESULT$1, { requestId, result }),
|
|
76070
|
+
|
|
75979
76071
|
/**
|
|
75980
76072
|
* runAuth
|
|
75981
76073
|
* Run a one-shot auth command for an MCP server (e.g., OAuth browser flow)
|
|
@@ -77284,7 +77376,7 @@ var mcpDashServerApi_1 = mcpDashServerApi$2;
|
|
|
77284
77376
|
* Call registerDashboardTools() during app startup (before or after server start).
|
|
77285
77377
|
*/
|
|
77286
77378
|
|
|
77287
|
-
const { registerTool: registerTool$
|
|
77379
|
+
const { registerTool: registerTool$6 } = mcpDashServerController_1;
|
|
77288
77380
|
const { dashboardTools } = toolDefinitions$1;
|
|
77289
77381
|
const {
|
|
77290
77382
|
handleListDashboards,
|
|
@@ -77315,7 +77407,7 @@ function registerDashboardTools$1() {
|
|
|
77315
77407
|
console.warn(`[dashboardTools] No handler found for tool: ${tool.name}`);
|
|
77316
77408
|
continue;
|
|
77317
77409
|
}
|
|
77318
|
-
registerTool$
|
|
77410
|
+
registerTool$6({
|
|
77319
77411
|
name: tool.name,
|
|
77320
77412
|
description: tool.description,
|
|
77321
77413
|
inputSchema: tool.inputSchema,
|
|
@@ -77336,7 +77428,7 @@ var dashboardTools_1 = { registerDashboardTools: registerDashboardTools$1 };
|
|
|
77336
77428
|
* Call registerWidgetTools() during app startup (before or after server start).
|
|
77337
77429
|
*/
|
|
77338
77430
|
|
|
77339
|
-
const { registerTool: registerTool$
|
|
77431
|
+
const { registerTool: registerTool$5 } = mcpDashServerController_1;
|
|
77340
77432
|
const { widgetTools } = toolDefinitions$1;
|
|
77341
77433
|
const {
|
|
77342
77434
|
handleAddWidget,
|
|
@@ -77367,7 +77459,7 @@ function registerWidgetTools$1() {
|
|
|
77367
77459
|
console.warn(`[widgetTools] No handler found for tool: ${tool.name}`);
|
|
77368
77460
|
continue;
|
|
77369
77461
|
}
|
|
77370
|
-
registerTool$
|
|
77462
|
+
registerTool$5({
|
|
77371
77463
|
name: tool.name,
|
|
77372
77464
|
description: tool.description,
|
|
77373
77465
|
inputSchema: tool.inputSchema,
|
|
@@ -77386,7 +77478,7 @@ var widgetTools_1 = { registerWidgetTools: registerWidgetTools$1 };
|
|
|
77386
77478
|
* Call registerThemeTools() during app startup (before or after server start).
|
|
77387
77479
|
*/
|
|
77388
77480
|
|
|
77389
|
-
const { registerTool: registerTool$
|
|
77481
|
+
const { registerTool: registerTool$4 } = mcpDashServerController_1;
|
|
77390
77482
|
const { themeTools } = toolDefinitions$1;
|
|
77391
77483
|
const {
|
|
77392
77484
|
handleListThemes,
|
|
@@ -77417,7 +77509,7 @@ function registerThemeTools$1() {
|
|
|
77417
77509
|
console.warn(`[themeTools] No handler found for tool: ${tool.name}`);
|
|
77418
77510
|
continue;
|
|
77419
77511
|
}
|
|
77420
|
-
registerTool$
|
|
77512
|
+
registerTool$4({
|
|
77421
77513
|
name: tool.name,
|
|
77422
77514
|
description: tool.description,
|
|
77423
77515
|
inputSchema: tool.inputSchema,
|
|
@@ -77436,18 +77528,18 @@ var themeTools_1 = { registerThemeTools: registerThemeTools$1 };
|
|
|
77436
77528
|
* Call registerProviderTools() during app startup (before or after server start).
|
|
77437
77529
|
*/
|
|
77438
77530
|
|
|
77439
|
-
const { registerTool: registerTool$
|
|
77531
|
+
const { registerTool: registerTool$3 } = mcpDashServerController_1;
|
|
77440
77532
|
const { providerTools } = toolDefinitions$1;
|
|
77441
77533
|
const {
|
|
77442
77534
|
handleListProviders,
|
|
77443
|
-
handleAddProvider,
|
|
77535
|
+
handleAddProvider: handleAddProvider$1,
|
|
77444
77536
|
handleRemoveProvider,
|
|
77445
77537
|
} = toolHandlers$1;
|
|
77446
77538
|
|
|
77447
77539
|
// Map tool names to handler functions
|
|
77448
77540
|
const handlerMap$4 = {
|
|
77449
77541
|
list_providers: handleListProviders,
|
|
77450
|
-
add_provider: handleAddProvider,
|
|
77542
|
+
add_provider: handleAddProvider$1,
|
|
77451
77543
|
remove_provider: handleRemoveProvider,
|
|
77452
77544
|
};
|
|
77453
77545
|
|
|
@@ -77461,7 +77553,7 @@ function registerProviderTools$1() {
|
|
|
77461
77553
|
console.warn(`[providerTools] No handler found for tool: ${tool.name}`);
|
|
77462
77554
|
continue;
|
|
77463
77555
|
}
|
|
77464
|
-
registerTool$
|
|
77556
|
+
registerTool$3({
|
|
77465
77557
|
name: tool.name,
|
|
77466
77558
|
description: tool.description,
|
|
77467
77559
|
inputSchema: tool.inputSchema,
|
|
@@ -77482,7 +77574,7 @@ var providerTools_1 = { registerProviderTools: registerProviderTools$1 };
|
|
|
77482
77574
|
* Call registerGuideTools() during app startup.
|
|
77483
77575
|
*/
|
|
77484
77576
|
|
|
77485
|
-
const { registerTool: registerTool$
|
|
77577
|
+
const { registerTool: registerTool$2 } = mcpDashServerController_1;
|
|
77486
77578
|
const { guideTools } = toolDefinitions$1;
|
|
77487
77579
|
const { handleGetSetupGuide } = toolHandlers$1;
|
|
77488
77580
|
|
|
@@ -77497,7 +77589,7 @@ function registerGuideTools$1() {
|
|
|
77497
77589
|
console.warn(`[guideTools] No handler found for tool: ${tool.name}`);
|
|
77498
77590
|
continue;
|
|
77499
77591
|
}
|
|
77500
|
-
registerTool$
|
|
77592
|
+
registerTool$2({
|
|
77501
77593
|
name: tool.name,
|
|
77502
77594
|
description: tool.description,
|
|
77503
77595
|
inputSchema: tool.inputSchema,
|
|
@@ -77516,7 +77608,7 @@ var guideTools_1 = { registerGuideTools: registerGuideTools$1 };
|
|
|
77516
77608
|
* Call registerLayoutTools() during app startup (before or after server start).
|
|
77517
77609
|
*/
|
|
77518
77610
|
|
|
77519
|
-
const { registerTool } = mcpDashServerController_1;
|
|
77611
|
+
const { registerTool: registerTool$1 } = mcpDashServerController_1;
|
|
77520
77612
|
const { layoutTools } = toolDefinitions$1;
|
|
77521
77613
|
const {
|
|
77522
77614
|
handleSetLayout,
|
|
@@ -77540,7 +77632,7 @@ function registerLayoutTools$1() {
|
|
|
77540
77632
|
console.warn(`[layoutTools] No handler found for tool: ${tool.name}`);
|
|
77541
77633
|
continue;
|
|
77542
77634
|
}
|
|
77543
|
-
registerTool({
|
|
77635
|
+
registerTool$1({
|
|
77544
77636
|
name: tool.name,
|
|
77545
77637
|
description: tool.description,
|
|
77546
77638
|
inputSchema: tool.inputSchema,
|
|
@@ -77552,6 +77644,194 @@ function registerLayoutTools$1() {
|
|
|
77552
77644
|
|
|
77553
77645
|
var layoutTools_1 = { registerLayoutTools: registerLayoutTools$1 };
|
|
77554
77646
|
|
|
77647
|
+
/**
|
|
77648
|
+
* installExternalMcpTool.js
|
|
77649
|
+
*
|
|
77650
|
+
* Registers the `install_known_mcp_server` tool on Dash's own MCP server.
|
|
77651
|
+
*
|
|
77652
|
+
* Why this tool exists:
|
|
77653
|
+
* The AI Widget Builder asks Claude to use MCP-first when a user requests
|
|
77654
|
+
* a widget for an external service. The built-in catalog covers 13 servers;
|
|
77655
|
+
* for anything else the AI consults the curated allow-list at
|
|
77656
|
+
* `electron/mcp/knownExternalMcpServers.json`. To keep the user in control
|
|
77657
|
+
* (npm install + spawning a child process is a non-trivial trust grant),
|
|
77658
|
+
* the actual install is gated by a renderer-side confirmation modal: this
|
|
77659
|
+
* tool emits an IPC event with the curated entry, waits for the user's
|
|
77660
|
+
* response, and only then routes through the existing add-provider flow.
|
|
77661
|
+
*
|
|
77662
|
+
* Trust boundary: the `id` argument MUST match an entry in
|
|
77663
|
+
* knownExternalMcpServers.json. Any other id is rejected before the
|
|
77664
|
+
* confirmation modal is even shown.
|
|
77665
|
+
*
|
|
77666
|
+
* Returns one of:
|
|
77667
|
+
* - { success: true, name } — installed
|
|
77668
|
+
* - { success: false, declined } — user clicked Cancel
|
|
77669
|
+
* - { success: false, error } — id not in allow-list, IPC timeout, or
|
|
77670
|
+
* install error from add-provider flow
|
|
77671
|
+
*/
|
|
77672
|
+
|
|
77673
|
+
const { BrowserWindow } = require$$0$1;
|
|
77674
|
+
const { registerTool } = mcpDashServerController_1;
|
|
77675
|
+
const mcpController$1 = mcpControllerExports;
|
|
77676
|
+
const {
|
|
77677
|
+
MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM,
|
|
77678
|
+
MCP_INSTALL_KNOWN_EXTERNAL_RESULT,
|
|
77679
|
+
} = mcpEvents$1;
|
|
77680
|
+
const { handleAddProvider } = toolHandlers$1;
|
|
77681
|
+
const { ipcMain } = require$$0$1;
|
|
77682
|
+
|
|
77683
|
+
const CONFIRM_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes — user may stop to read
|
|
77684
|
+
|
|
77685
|
+
// Pending requests keyed by requestId so we can resolve when the result IPC arrives.
|
|
77686
|
+
const pendingRequests = new Map();
|
|
77687
|
+
|
|
77688
|
+
let resultListenerInstalled = false;
|
|
77689
|
+
function ensureResultListener() {
|
|
77690
|
+
if (resultListenerInstalled) return;
|
|
77691
|
+
resultListenerInstalled = true;
|
|
77692
|
+
ipcMain.on(MCP_INSTALL_KNOWN_EXTERNAL_RESULT, (_event, payload) => {
|
|
77693
|
+
const { requestId, result } = payload || {};
|
|
77694
|
+
const pending = pendingRequests.get(requestId);
|
|
77695
|
+
if (!pending) return;
|
|
77696
|
+
pendingRequests.delete(requestId);
|
|
77697
|
+
clearTimeout(pending.timer);
|
|
77698
|
+
pending.resolve(result || { confirmed: false });
|
|
77699
|
+
});
|
|
77700
|
+
}
|
|
77701
|
+
|
|
77702
|
+
function findEntryInAllowList(id) {
|
|
77703
|
+
const { servers } = mcpController$1.getKnownExternalCatalog();
|
|
77704
|
+
if (!Array.isArray(servers)) return null;
|
|
77705
|
+
return servers.find((s) => s && s.id === id) || null;
|
|
77706
|
+
}
|
|
77707
|
+
|
|
77708
|
+
function newRequestId() {
|
|
77709
|
+
return `mcp-install-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
77710
|
+
}
|
|
77711
|
+
|
|
77712
|
+
async function awaitUserConfirmation(server) {
|
|
77713
|
+
ensureResultListener();
|
|
77714
|
+
const requestId = newRequestId();
|
|
77715
|
+
return new Promise((resolve) => {
|
|
77716
|
+
const timer = setTimeout(() => {
|
|
77717
|
+
if (pendingRequests.has(requestId)) {
|
|
77718
|
+
pendingRequests.delete(requestId);
|
|
77719
|
+
resolve({ confirmed: false, error: "Install confirmation timed out" });
|
|
77720
|
+
}
|
|
77721
|
+
}, CONFIRM_TIMEOUT_MS);
|
|
77722
|
+
pendingRequests.set(requestId, { resolve, timer });
|
|
77723
|
+
|
|
77724
|
+
// Broadcast to all open windows; whichever has the modal mounted picks it up.
|
|
77725
|
+
const wins = BrowserWindow.getAllWindows();
|
|
77726
|
+
if (wins.length === 0) {
|
|
77727
|
+
pendingRequests.delete(requestId);
|
|
77728
|
+
clearTimeout(timer);
|
|
77729
|
+
resolve({ confirmed: false, error: "No window available" });
|
|
77730
|
+
return;
|
|
77731
|
+
}
|
|
77732
|
+
for (const win of wins) {
|
|
77733
|
+
if (!win.isDestroyed()) {
|
|
77734
|
+
win.webContents.send(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM, {
|
|
77735
|
+
requestId,
|
|
77736
|
+
id: server.id,
|
|
77737
|
+
server,
|
|
77738
|
+
});
|
|
77739
|
+
}
|
|
77740
|
+
}
|
|
77741
|
+
});
|
|
77742
|
+
}
|
|
77743
|
+
|
|
77744
|
+
function ok(payload) {
|
|
77745
|
+
return {
|
|
77746
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
77747
|
+
};
|
|
77748
|
+
}
|
|
77749
|
+
|
|
77750
|
+
function fail(payload) {
|
|
77751
|
+
return {
|
|
77752
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
77753
|
+
isError: true,
|
|
77754
|
+
};
|
|
77755
|
+
}
|
|
77756
|
+
|
|
77757
|
+
async function handleInstallKnownMcpServer({ id, name }) {
|
|
77758
|
+
if (!id || typeof id !== "string") {
|
|
77759
|
+
return fail({ success: false, error: "id is required" });
|
|
77760
|
+
}
|
|
77761
|
+
const server = findEntryInAllowList(id);
|
|
77762
|
+
if (!server) {
|
|
77763
|
+
return fail({
|
|
77764
|
+
success: false,
|
|
77765
|
+
error: `id "${id}" is not in the known-external MCP allow-list. The user can only install servers explicitly listed in knownExternalMcpServers.json.`,
|
|
77766
|
+
});
|
|
77767
|
+
}
|
|
77768
|
+
|
|
77769
|
+
const decision = await awaitUserConfirmation(server);
|
|
77770
|
+
if (!decision || !decision.confirmed) {
|
|
77771
|
+
if (decision?.error) {
|
|
77772
|
+
return fail({ success: false, error: decision.error });
|
|
77773
|
+
}
|
|
77774
|
+
return ok({ success: false, declined: true });
|
|
77775
|
+
}
|
|
77776
|
+
|
|
77777
|
+
// Route through the existing add-provider tool handler. The renderer
|
|
77778
|
+
// collected credentials in its modal — we trust those to match the
|
|
77779
|
+
// curated `credentialSchema`.
|
|
77780
|
+
const providerName = (name && name.trim()) || server.name || server.id;
|
|
77781
|
+
try {
|
|
77782
|
+
const addResult = await handleAddProvider({
|
|
77783
|
+
name: providerName,
|
|
77784
|
+
type: server.id,
|
|
77785
|
+
providerClass: "mcp",
|
|
77786
|
+
credentials: decision.credentials || {},
|
|
77787
|
+
mcpConfig: server.mcpConfig,
|
|
77788
|
+
});
|
|
77789
|
+
if (addResult?.isError) {
|
|
77790
|
+
// Surface add-provider's error text verbatim.
|
|
77791
|
+
return addResult;
|
|
77792
|
+
}
|
|
77793
|
+
return ok({ success: true, name: providerName, type: server.id });
|
|
77794
|
+
} catch (err) {
|
|
77795
|
+
return fail({ success: false, error: err.message });
|
|
77796
|
+
}
|
|
77797
|
+
}
|
|
77798
|
+
|
|
77799
|
+
const installExternalMcpToolDef = {
|
|
77800
|
+
name: "install_known_mcp_server",
|
|
77801
|
+
description:
|
|
77802
|
+
"Install an MCP server from Dash's curated known-external allow-list. The user is shown a confirmation modal before any install runs. Use this when the user asks for a widget that needs a service NOT in the built-in MCP catalog but IS in the known-external list. Returns { success, name } on install, { success: false, declined: true } if the user cancels, or an error if the id isn't allow-listed.",
|
|
77803
|
+
inputSchema: {
|
|
77804
|
+
type: "object",
|
|
77805
|
+
properties: {
|
|
77806
|
+
id: {
|
|
77807
|
+
type: "string",
|
|
77808
|
+
description:
|
|
77809
|
+
"The id of the server in the known-external catalog (e.g. 'trello', 'asana', 'stripe').",
|
|
77810
|
+
},
|
|
77811
|
+
name: {
|
|
77812
|
+
type: "string",
|
|
77813
|
+
description:
|
|
77814
|
+
"Optional display name for the resulting provider entry. Defaults to the catalog entry's name.",
|
|
77815
|
+
},
|
|
77816
|
+
},
|
|
77817
|
+
required: ["id"],
|
|
77818
|
+
},
|
|
77819
|
+
};
|
|
77820
|
+
|
|
77821
|
+
function registerInstallKnownMcpServerTool$1() {
|
|
77822
|
+
registerTool({
|
|
77823
|
+
...installExternalMcpToolDef,
|
|
77824
|
+
handler: handleInstallKnownMcpServer,
|
|
77825
|
+
});
|
|
77826
|
+
console.log("[installExternalMcpTool] Registered install_known_mcp_server");
|
|
77827
|
+
}
|
|
77828
|
+
|
|
77829
|
+
var installExternalMcpTool = {
|
|
77830
|
+
registerInstallKnownMcpServerTool: registerInstallKnownMcpServerTool$1,
|
|
77831
|
+
// Exported for tests
|
|
77832
|
+
handleInstallKnownMcpServer,
|
|
77833
|
+
};
|
|
77834
|
+
|
|
77555
77835
|
/**
|
|
77556
77836
|
* resourceDefinitions.js
|
|
77557
77837
|
*
|
|
@@ -78522,6 +78802,9 @@ const { registerThemeTools } = themeTools_1;
|
|
|
78522
78802
|
const { registerProviderTools } = providerTools_1;
|
|
78523
78803
|
const { registerGuideTools } = guideTools_1;
|
|
78524
78804
|
const { registerLayoutTools } = layoutTools_1;
|
|
78805
|
+
const {
|
|
78806
|
+
registerInstallKnownMcpServerTool,
|
|
78807
|
+
} = installExternalMcpTool;
|
|
78525
78808
|
const { registerResources } = resources;
|
|
78526
78809
|
const { registerPrompts } = promptRegistration;
|
|
78527
78810
|
registerDashboardTools();
|
|
@@ -78530,6 +78813,7 @@ registerThemeTools();
|
|
|
78530
78813
|
registerProviderTools();
|
|
78531
78814
|
registerGuideTools();
|
|
78532
78815
|
registerLayoutTools();
|
|
78816
|
+
registerInstallKnownMcpServerTool();
|
|
78533
78817
|
registerResources();
|
|
78534
78818
|
registerPrompts();
|
|
78535
78819
|
|