@trops/dash-core 0.1.490 → 0.1.491
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 +195 -62
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +81 -42
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +81 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var require$$0$5 = require('@modelcontextprotocol/sdk/client/index.js');
|
|
|
17
17
|
var require$$1$4 = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
18
18
|
var require$$0$4 = require('pkce-challenge');
|
|
19
19
|
var require$$2$1 = require('os');
|
|
20
|
-
var require$$
|
|
20
|
+
var require$$10 = require('child_process');
|
|
21
21
|
var require$$3$2 = require('adm-zip');
|
|
22
22
|
var require$$4$1 = require('url');
|
|
23
23
|
var require$$2$2 = require('vm');
|
|
@@ -21522,6 +21522,69 @@ var permissionGate = {
|
|
|
21522
21522
|
PATH_ARG_KEYS,
|
|
21523
21523
|
};
|
|
21524
21524
|
|
|
21525
|
+
/**
|
|
21526
|
+
* mcpServerKey.js
|
|
21527
|
+
*
|
|
21528
|
+
* Slice 3a: per-workspace MCP server process isolation.
|
|
21529
|
+
*
|
|
21530
|
+
* `mcpController.activeServers` was historically keyed by `serverName`
|
|
21531
|
+
* alone, so two workspaces using the same MCP server type (e.g. both
|
|
21532
|
+
* using `filesystem`) shared one process. Slice 3a keys by the
|
|
21533
|
+
* compound `(workspaceId, serverName)` so each workspace gets its
|
|
21534
|
+
* own process. Slice 3b will configure each process with the union
|
|
21535
|
+
* of grants from widgets on that workspace; for now, processes are
|
|
21536
|
+
* simply isolated.
|
|
21537
|
+
*
|
|
21538
|
+
* Format: `<workspaceId>::<serverName>`. The `::` separator is
|
|
21539
|
+
* unlikely to appear in a UUID-shaped workspace id; serverName is
|
|
21540
|
+
* everything after the first `::` so server names containing `::`
|
|
21541
|
+
* round-trip cleanly.
|
|
21542
|
+
*
|
|
21543
|
+
* Callers without a workspace context (legacy IPC, dash MCP server
|
|
21544
|
+
* tools, AI Builder previews) supply `null`/`undefined` and land on
|
|
21545
|
+
* the `NO_WORKSPACE` sentinel bucket — that's the pre-Slice-3 bucket.
|
|
21546
|
+
*
|
|
21547
|
+
* NOTE: workspaceId is renderer-supplied. Slice 3a uses it only as a
|
|
21548
|
+
* process-isolation key, NOT as a trust boundary. Slice 3b will tie
|
|
21549
|
+
* server scope (e.g. filesystem `--allowed` paths) to it; that's when
|
|
21550
|
+
* the trust boundary appears.
|
|
21551
|
+
*/
|
|
21552
|
+
|
|
21553
|
+
const NO_WORKSPACE = "__no_workspace__";
|
|
21554
|
+
const SEP = "::";
|
|
21555
|
+
|
|
21556
|
+
function serverKey$1(workspaceId, serverName) {
|
|
21557
|
+
if (typeof serverName !== "string" || !serverName) {
|
|
21558
|
+
throw new Error("serverKey: serverName is required");
|
|
21559
|
+
}
|
|
21560
|
+
const wid =
|
|
21561
|
+
typeof workspaceId === "string" && workspaceId ? workspaceId : NO_WORKSPACE;
|
|
21562
|
+
return wid + SEP + serverName;
|
|
21563
|
+
}
|
|
21564
|
+
|
|
21565
|
+
function parseServerKey$1(key) {
|
|
21566
|
+
if (typeof key !== "string") {
|
|
21567
|
+
throw new Error("parseServerKey: key must be a string");
|
|
21568
|
+
}
|
|
21569
|
+
const idx = key.indexOf(SEP);
|
|
21570
|
+
if (idx < 0) {
|
|
21571
|
+
throw new Error(
|
|
21572
|
+
"parseServerKey: malformed key (no '::' separator): " + key,
|
|
21573
|
+
);
|
|
21574
|
+
}
|
|
21575
|
+
return {
|
|
21576
|
+
workspaceId: key.slice(0, idx),
|
|
21577
|
+
serverName: key.slice(idx + SEP.length),
|
|
21578
|
+
};
|
|
21579
|
+
}
|
|
21580
|
+
|
|
21581
|
+
var mcpServerKey = {
|
|
21582
|
+
serverKey: serverKey$1,
|
|
21583
|
+
parseServerKey: parseServerKey$1,
|
|
21584
|
+
NO_WORKSPACE,
|
|
21585
|
+
SEP,
|
|
21586
|
+
};
|
|
21587
|
+
|
|
21525
21588
|
/**
|
|
21526
21589
|
* mcpController.js
|
|
21527
21590
|
*
|
|
@@ -21547,6 +21610,7 @@ const fs$9 = require$$0$2;
|
|
|
21547
21610
|
const os$2 = require$$2$1;
|
|
21548
21611
|
const responseCache$2 = responseCache_1;
|
|
21549
21612
|
const { gateToolCall } = permissionGate;
|
|
21613
|
+
const { serverKey, parseServerKey } = mcpServerKey;
|
|
21550
21614
|
const { app: app$7 } = require$$0$1;
|
|
21551
21615
|
|
|
21552
21616
|
// Read the widget-MCP-enforcement feature flag from settings.json.
|
|
@@ -21703,7 +21767,7 @@ function getShellPath$1() {
|
|
|
21703
21767
|
return _shellPath$1;
|
|
21704
21768
|
}
|
|
21705
21769
|
|
|
21706
|
-
const { execSync } = require$$
|
|
21770
|
+
const { execSync } = require$$10;
|
|
21707
21771
|
const fallbackDirs = ["/usr/local/bin", "/opt/homebrew/bin"];
|
|
21708
21772
|
|
|
21709
21773
|
// Scan nvm versions, tracking both latest and best compatible version
|
|
@@ -21936,17 +22000,24 @@ const mcpController$3 = {
|
|
|
21936
22000
|
* startServer
|
|
21937
22001
|
* Start an MCP server with the given config and credentials
|
|
21938
22002
|
*
|
|
22003
|
+
* Slice 3a: server instances are keyed by `(workspaceId, serverName)`
|
|
22004
|
+
* so two workspaces using the same server type get separate processes.
|
|
22005
|
+
* Pass `null`/`undefined` workspaceId to land on the legacy
|
|
22006
|
+
* NO_WORKSPACE bucket (e.g. dash MCP server tools, AI Builder previews).
|
|
22007
|
+
*
|
|
21939
22008
|
* @param {BrowserWindow} win the main window
|
|
21940
22009
|
* @param {string} serverName unique name for this server instance
|
|
21941
22010
|
* @param {object} mcpConfig { transport, command, args, envMapping }
|
|
21942
22011
|
* @param {object} credentials decrypted credentials object
|
|
22012
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
21943
22013
|
* @returns {{ success, serverName, tools, status } | { error, message }}
|
|
21944
22014
|
*/
|
|
21945
|
-
startServer: async (win, serverName, mcpConfig, credentials) => {
|
|
22015
|
+
startServer: async (win, serverName, mcpConfig, credentials, workspaceId) => {
|
|
22016
|
+
const key = serverKey(workspaceId, serverName);
|
|
21946
22017
|
// 1. Already connected? Return existing connection
|
|
21947
|
-
const existing = activeServers.get(
|
|
22018
|
+
const existing = activeServers.get(key);
|
|
21948
22019
|
if (existing && existing.status === STATUS$1.CONNECTED && existing.client) {
|
|
21949
|
-
console.log(`[mcpController] Server already connected: ${
|
|
22020
|
+
console.log(`[mcpController] Server already connected: ${key}`);
|
|
21950
22021
|
return {
|
|
21951
22022
|
success: true,
|
|
21952
22023
|
serverName,
|
|
@@ -21957,19 +22028,19 @@ const mcpController$3 = {
|
|
|
21957
22028
|
}
|
|
21958
22029
|
|
|
21959
22030
|
// 2. Already starting? Piggyback on the pending promise
|
|
21960
|
-
if (pendingStarts.has(
|
|
22031
|
+
if (pendingStarts.has(key)) {
|
|
21961
22032
|
console.log(
|
|
21962
|
-
`[mcpController] Server already starting, deduplicating: ${
|
|
22033
|
+
`[mcpController] Server already starting, deduplicating: ${key}`,
|
|
21963
22034
|
);
|
|
21964
|
-
return pendingStarts.get(
|
|
22035
|
+
return pendingStarts.get(key);
|
|
21965
22036
|
}
|
|
21966
22037
|
|
|
21967
22038
|
// 3. Fresh start — wrap in a promise and track it
|
|
21968
22039
|
const startPromise = (async () => {
|
|
21969
22040
|
try {
|
|
21970
22041
|
// Stop if in stale/error state
|
|
21971
|
-
if (activeServers.has(
|
|
21972
|
-
await mcpController$3.stopServer(win, serverName);
|
|
22042
|
+
if (activeServers.has(key)) {
|
|
22043
|
+
await mcpController$3.stopServer(win, serverName, workspaceId);
|
|
21973
22044
|
}
|
|
21974
22045
|
|
|
21975
22046
|
// Merge with catalog entry to pick up updated command/args
|
|
@@ -22100,12 +22171,14 @@ const mcpController$3 = {
|
|
|
22100
22171
|
}
|
|
22101
22172
|
|
|
22102
22173
|
// Update status to connecting
|
|
22103
|
-
activeServers.set(
|
|
22174
|
+
activeServers.set(key, {
|
|
22104
22175
|
client: null,
|
|
22105
22176
|
transport,
|
|
22106
22177
|
tools: [],
|
|
22107
22178
|
resources: [],
|
|
22108
22179
|
status: STATUS$1.CONNECTING,
|
|
22180
|
+
workspaceId: workspaceId || null,
|
|
22181
|
+
serverName,
|
|
22109
22182
|
});
|
|
22110
22183
|
|
|
22111
22184
|
// Create MCP client
|
|
@@ -22139,16 +22212,18 @@ const mcpController$3 = {
|
|
|
22139
22212
|
}
|
|
22140
22213
|
|
|
22141
22214
|
// Store the active connection
|
|
22142
|
-
activeServers.set(
|
|
22215
|
+
activeServers.set(key, {
|
|
22143
22216
|
client,
|
|
22144
22217
|
transport,
|
|
22145
22218
|
tools,
|
|
22146
22219
|
resources,
|
|
22147
22220
|
status: STATUS$1.CONNECTED,
|
|
22221
|
+
workspaceId: workspaceId || null,
|
|
22222
|
+
serverName,
|
|
22148
22223
|
});
|
|
22149
22224
|
|
|
22150
22225
|
console.log(
|
|
22151
|
-
`[mcpController] Server connected: ${
|
|
22226
|
+
`[mcpController] Server connected: ${key} (${tools.length} tools, ${resources.length} resources)`,
|
|
22152
22227
|
);
|
|
22153
22228
|
|
|
22154
22229
|
return {
|
|
@@ -22173,13 +22248,15 @@ const mcpController$3 = {
|
|
|
22173
22248
|
}
|
|
22174
22249
|
|
|
22175
22250
|
// Mark as error state
|
|
22176
|
-
activeServers.set(
|
|
22251
|
+
activeServers.set(key, {
|
|
22177
22252
|
client: null,
|
|
22178
22253
|
transport: null,
|
|
22179
22254
|
tools: [],
|
|
22180
22255
|
resources: [],
|
|
22181
22256
|
status: STATUS$1.ERROR,
|
|
22182
22257
|
error: errorMessage,
|
|
22258
|
+
workspaceId: workspaceId || null,
|
|
22259
|
+
serverName,
|
|
22183
22260
|
});
|
|
22184
22261
|
|
|
22185
22262
|
return {
|
|
@@ -22189,11 +22266,11 @@ const mcpController$3 = {
|
|
|
22189
22266
|
status: STATUS$1.ERROR,
|
|
22190
22267
|
};
|
|
22191
22268
|
} finally {
|
|
22192
|
-
pendingStarts.delete(
|
|
22269
|
+
pendingStarts.delete(key);
|
|
22193
22270
|
}
|
|
22194
22271
|
})();
|
|
22195
22272
|
|
|
22196
|
-
pendingStarts.set(
|
|
22273
|
+
pendingStarts.set(key, startPromise);
|
|
22197
22274
|
return startPromise;
|
|
22198
22275
|
},
|
|
22199
22276
|
|
|
@@ -22203,20 +22280,22 @@ const mcpController$3 = {
|
|
|
22203
22280
|
*
|
|
22204
22281
|
* @param {BrowserWindow} win the main window
|
|
22205
22282
|
* @param {string} serverName the server to stop
|
|
22283
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
22206
22284
|
* @returns {{ success, serverName } | { error, message }}
|
|
22207
22285
|
*/
|
|
22208
|
-
stopServer: async (win, serverName) => {
|
|
22286
|
+
stopServer: async (win, serverName, workspaceId) => {
|
|
22287
|
+
const key = serverKey(workspaceId, serverName);
|
|
22209
22288
|
try {
|
|
22210
22289
|
// Wait for any in-flight start to finish before stopping
|
|
22211
|
-
if (pendingStarts.has(
|
|
22290
|
+
if (pendingStarts.has(key)) {
|
|
22212
22291
|
try {
|
|
22213
|
-
await pendingStarts.get(
|
|
22292
|
+
await pendingStarts.get(key);
|
|
22214
22293
|
} catch (e) {
|
|
22215
22294
|
/* stopping anyway */
|
|
22216
22295
|
}
|
|
22217
22296
|
}
|
|
22218
22297
|
|
|
22219
|
-
const server = activeServers.get(
|
|
22298
|
+
const server = activeServers.get(key);
|
|
22220
22299
|
if (!server) {
|
|
22221
22300
|
return {
|
|
22222
22301
|
success: true,
|
|
@@ -22225,7 +22304,7 @@ const mcpController$3 = {
|
|
|
22225
22304
|
};
|
|
22226
22305
|
}
|
|
22227
22306
|
|
|
22228
|
-
console.log(`[mcpController] Stopping server: ${
|
|
22307
|
+
console.log(`[mcpController] Stopping server: ${key}`);
|
|
22229
22308
|
|
|
22230
22309
|
// Close the client connection
|
|
22231
22310
|
if (server.client) {
|
|
@@ -22233,27 +22312,24 @@ const mcpController$3 = {
|
|
|
22233
22312
|
await server.client.close();
|
|
22234
22313
|
} catch (closeError) {
|
|
22235
22314
|
console.warn(
|
|
22236
|
-
`[mcpController] Error closing client for ${
|
|
22315
|
+
`[mcpController] Error closing client for ${key}:`,
|
|
22237
22316
|
closeError.message,
|
|
22238
22317
|
);
|
|
22239
22318
|
}
|
|
22240
22319
|
}
|
|
22241
22320
|
|
|
22242
|
-
activeServers.delete(
|
|
22321
|
+
activeServers.delete(key);
|
|
22243
22322
|
|
|
22244
|
-
console.log(`[mcpController] Server stopped: ${
|
|
22323
|
+
console.log(`[mcpController] Server stopped: ${key}`);
|
|
22245
22324
|
|
|
22246
22325
|
return {
|
|
22247
22326
|
success: true,
|
|
22248
22327
|
serverName,
|
|
22249
22328
|
};
|
|
22250
22329
|
} catch (error) {
|
|
22251
|
-
console.error(
|
|
22252
|
-
`[mcpController] Error stopping server ${serverName}:`,
|
|
22253
|
-
error,
|
|
22254
|
-
);
|
|
22330
|
+
console.error(`[mcpController] Error stopping server ${key}:`, error);
|
|
22255
22331
|
// Clean up anyway
|
|
22256
|
-
activeServers.delete(
|
|
22332
|
+
activeServers.delete(key);
|
|
22257
22333
|
return {
|
|
22258
22334
|
error: true,
|
|
22259
22335
|
message: error.message,
|
|
@@ -22270,6 +22346,10 @@ const mcpController$3 = {
|
|
|
22270
22346
|
* @param {string} toolName the tool to call
|
|
22271
22347
|
* @param {object} args arguments for the tool
|
|
22272
22348
|
* @param {Array<string>} allowedTools optional whitelist of allowed tool names
|
|
22349
|
+
* @param {string|null} widgetId the widget originating the call (Slice 1+2)
|
|
22350
|
+
* @param {string|null} workspaceId the active workspace (Slice 3a) — used
|
|
22351
|
+
* to scope the server process per workspace.
|
|
22352
|
+
* Slice 3b will tie path scope to this id.
|
|
22273
22353
|
* @returns {{ result } | { error, message }}
|
|
22274
22354
|
*/
|
|
22275
22355
|
callTool: async (
|
|
@@ -22279,11 +22359,13 @@ const mcpController$3 = {
|
|
|
22279
22359
|
args,
|
|
22280
22360
|
allowedTools = null,
|
|
22281
22361
|
widgetId = null,
|
|
22362
|
+
workspaceId = null,
|
|
22282
22363
|
) => {
|
|
22364
|
+
const key = serverKey(workspaceId, serverName);
|
|
22283
22365
|
try {
|
|
22284
|
-
const server = activeServers.get(
|
|
22366
|
+
const server = activeServers.get(key);
|
|
22285
22367
|
if (!server || !server.client) {
|
|
22286
|
-
throw new Error(`Server not connected: ${
|
|
22368
|
+
throw new Error(`Server not connected: ${key}`);
|
|
22287
22369
|
}
|
|
22288
22370
|
|
|
22289
22371
|
// Per-widget manifest gate. Activated by the
|
|
@@ -22316,7 +22398,7 @@ const mcpController$3 = {
|
|
|
22316
22398
|
}
|
|
22317
22399
|
|
|
22318
22400
|
const doCall = async () => {
|
|
22319
|
-
console.log(`[mcpController] Calling tool: ${
|
|
22401
|
+
console.log(`[mcpController] Calling tool: ${key}/${toolName}`);
|
|
22320
22402
|
const result = await server.client.callTool({
|
|
22321
22403
|
name: toolName,
|
|
22322
22404
|
arguments: args || {},
|
|
@@ -22327,18 +22409,21 @@ const mcpController$3 = {
|
|
|
22327
22409
|
};
|
|
22328
22410
|
};
|
|
22329
22411
|
|
|
22330
|
-
// Cache read-only tool calls with in-flight dedup.
|
|
22331
|
-
//
|
|
22412
|
+
// Cache read-only tool calls with in-flight dedup. Cache key is
|
|
22413
|
+
// scoped per (workspace, server, tool, args) so two workspaces
|
|
22414
|
+
// calling the same read on the same server type don't share a
|
|
22415
|
+
// cached response — they're separate processes with potentially
|
|
22416
|
+
// different scopes (Slice 3b will make that explicit).
|
|
22332
22417
|
if (isReadOnlyTool(toolName)) {
|
|
22333
|
-
const
|
|
22334
|
-
return responseCache$2.get(
|
|
22418
|
+
const cacheKey = `mcp:${key}:${toolName}:${JSON.stringify(args || {})}`;
|
|
22419
|
+
return responseCache$2.get(cacheKey, doCall, {
|
|
22335
22420
|
ttl: DEFAULT_TOOL_CACHE_TTL,
|
|
22336
22421
|
});
|
|
22337
22422
|
}
|
|
22338
22423
|
|
|
22339
22424
|
// Write/mutation: invalidate any cached reads for this server
|
|
22340
22425
|
// (safest default — broad invalidation when state changes)
|
|
22341
|
-
responseCache$2.invalidatePrefix(`mcp:${
|
|
22426
|
+
responseCache$2.invalidatePrefix(`mcp:${key}:`);
|
|
22342
22427
|
return doCall();
|
|
22343
22428
|
} catch (error) {
|
|
22344
22429
|
console.error(
|
|
@@ -22358,13 +22443,15 @@ const mcpController$3 = {
|
|
|
22358
22443
|
*
|
|
22359
22444
|
* @param {BrowserWindow} win the main window
|
|
22360
22445
|
* @param {string} serverName the server name
|
|
22446
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
22361
22447
|
* @returns {{ tools } | { error, message }}
|
|
22362
22448
|
*/
|
|
22363
|
-
listTools: async (win, serverName) => {
|
|
22449
|
+
listTools: async (win, serverName, workspaceId) => {
|
|
22450
|
+
const key = serverKey(workspaceId, serverName);
|
|
22364
22451
|
try {
|
|
22365
|
-
const server = activeServers.get(
|
|
22452
|
+
const server = activeServers.get(key);
|
|
22366
22453
|
if (!server || !server.client) {
|
|
22367
|
-
throw new Error(`Server not connected: ${
|
|
22454
|
+
throw new Error(`Server not connected: ${key}`);
|
|
22368
22455
|
}
|
|
22369
22456
|
|
|
22370
22457
|
// Refresh tool list from server
|
|
@@ -22396,13 +22483,15 @@ const mcpController$3 = {
|
|
|
22396
22483
|
*
|
|
22397
22484
|
* @param {BrowserWindow} win the main window
|
|
22398
22485
|
* @param {string} serverName the server name
|
|
22486
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
22399
22487
|
* @returns {{ resources } | { error, message }}
|
|
22400
22488
|
*/
|
|
22401
|
-
listResources: async (win, serverName) => {
|
|
22489
|
+
listResources: async (win, serverName, workspaceId) => {
|
|
22490
|
+
const key = serverKey(workspaceId, serverName);
|
|
22402
22491
|
try {
|
|
22403
|
-
const server = activeServers.get(
|
|
22492
|
+
const server = activeServers.get(key);
|
|
22404
22493
|
if (!server || !server.client) {
|
|
22405
|
-
throw new Error(`Server not connected: ${
|
|
22494
|
+
throw new Error(`Server not connected: ${key}`);
|
|
22406
22495
|
}
|
|
22407
22496
|
|
|
22408
22497
|
const resourcesResult = await server.client.listResources();
|
|
@@ -22434,13 +22523,15 @@ const mcpController$3 = {
|
|
|
22434
22523
|
* @param {BrowserWindow} win the main window
|
|
22435
22524
|
* @param {string} serverName the server name
|
|
22436
22525
|
* @param {string} uri the resource URI
|
|
22526
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
22437
22527
|
* @returns {{ resource } | { error, message }}
|
|
22438
22528
|
*/
|
|
22439
|
-
readResource: async (win, serverName, uri) => {
|
|
22529
|
+
readResource: async (win, serverName, uri, workspaceId) => {
|
|
22530
|
+
const key = serverKey(workspaceId, serverName);
|
|
22440
22531
|
try {
|
|
22441
|
-
const server = activeServers.get(
|
|
22532
|
+
const server = activeServers.get(key);
|
|
22442
22533
|
if (!server || !server.client) {
|
|
22443
|
-
throw new Error(`Server not connected: ${
|
|
22534
|
+
throw new Error(`Server not connected: ${key}`);
|
|
22444
22535
|
}
|
|
22445
22536
|
|
|
22446
22537
|
const result = await server.client.readResource({ uri });
|
|
@@ -22469,8 +22560,9 @@ const mcpController$3 = {
|
|
|
22469
22560
|
* @param {string} serverName the server name
|
|
22470
22561
|
* @returns {{ status, tools, error }}
|
|
22471
22562
|
*/
|
|
22472
|
-
getServerStatus: (win, serverName) => {
|
|
22473
|
-
const
|
|
22563
|
+
getServerStatus: (win, serverName, workspaceId) => {
|
|
22564
|
+
const key = serverKey(workspaceId, serverName);
|
|
22565
|
+
const server = activeServers.get(key);
|
|
22474
22566
|
if (!server) {
|
|
22475
22567
|
return {
|
|
22476
22568
|
serverName,
|
|
@@ -22603,7 +22695,7 @@ const mcpController$3 = {
|
|
|
22603
22695
|
* @returns {{ success } | { error, message }}
|
|
22604
22696
|
*/
|
|
22605
22697
|
runAuth: async (win, mcpConfig, credentials, authCommand) => {
|
|
22606
|
-
const { spawn } = require$$
|
|
22698
|
+
const { spawn } = require$$10;
|
|
22607
22699
|
|
|
22608
22700
|
const env = cleanEnvForChildProcess();
|
|
22609
22701
|
|
|
@@ -22732,12 +22824,39 @@ const mcpController$3 = {
|
|
|
22732
22824
|
`[mcpController] Stopping all servers (${activeServers.size} active)`,
|
|
22733
22825
|
);
|
|
22734
22826
|
const promises = [];
|
|
22735
|
-
|
|
22736
|
-
|
|
22827
|
+
// Slice 3a: keys are compound `(workspaceId, serverName)`. Parse
|
|
22828
|
+
// to call stopServer with the original args.
|
|
22829
|
+
for (const [key] of activeServers) {
|
|
22830
|
+
const { workspaceId, serverName } = parseServerKey(key);
|
|
22831
|
+
promises.push(mcpController$3.stopServer(null, serverName, workspaceId));
|
|
22737
22832
|
}
|
|
22738
22833
|
await Promise.allSettled(promises);
|
|
22739
22834
|
console.log("[mcpController] All servers stopped");
|
|
22740
22835
|
},
|
|
22836
|
+
|
|
22837
|
+
/**
|
|
22838
|
+
* stopServersForWorkspace
|
|
22839
|
+
* Stop every server keyed under the given workspaceId. Called when
|
|
22840
|
+
* a workspace unmounts so its scoped MCP processes don't leak.
|
|
22841
|
+
*
|
|
22842
|
+
* @param {string} workspaceId the workspace whose servers to stop
|
|
22843
|
+
*/
|
|
22844
|
+
stopServersForWorkspace: async (workspaceId) => {
|
|
22845
|
+
if (!workspaceId) return;
|
|
22846
|
+
const promises = [];
|
|
22847
|
+
for (const [key] of activeServers) {
|
|
22848
|
+
const parsed = parseServerKey(key);
|
|
22849
|
+
if (parsed.workspaceId !== workspaceId) continue;
|
|
22850
|
+
promises.push(
|
|
22851
|
+
mcpController$3.stopServer(null, parsed.serverName, workspaceId),
|
|
22852
|
+
);
|
|
22853
|
+
}
|
|
22854
|
+
if (promises.length === 0) return;
|
|
22855
|
+
console.log(
|
|
22856
|
+
`[mcpController] Stopping ${promises.length} server(s) for workspace ${workspaceId}`,
|
|
22857
|
+
);
|
|
22858
|
+
await Promise.allSettled(promises);
|
|
22859
|
+
},
|
|
22741
22860
|
};
|
|
22742
22861
|
|
|
22743
22862
|
mcpController$4.exports = mcpController$3;
|
|
@@ -47743,7 +47862,7 @@ var mcpDashServerController_1 = mcpDashServerController$4;
|
|
|
47743
47862
|
* can use the Chat widget without a separate API key.
|
|
47744
47863
|
*/
|
|
47745
47864
|
|
|
47746
|
-
const { spawn, execSync } = require$$
|
|
47865
|
+
const { spawn, execSync } = require$$10;
|
|
47747
47866
|
const {
|
|
47748
47867
|
LLM_STREAM_DELTA: LLM_STREAM_DELTA$2,
|
|
47749
47868
|
LLM_STREAM_TOOL_CALL: LLM_STREAM_TOOL_CALL$2,
|
|
@@ -62132,13 +62251,16 @@ const mcpApi$2 = {
|
|
|
62132
62251
|
* @param {string} serverName unique name for this server instance
|
|
62133
62252
|
* @param {object} mcpConfig { transport, command, args, envMapping }
|
|
62134
62253
|
* @param {object} credentials decrypted credentials object
|
|
62254
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a) —
|
|
62255
|
+
* server processes are keyed per workspace.
|
|
62135
62256
|
* @returns {Promise<{ success, serverName, tools, status } | { error, message }>}
|
|
62136
62257
|
*/
|
|
62137
|
-
startServer: (serverName, mcpConfig, credentials) =>
|
|
62258
|
+
startServer: (serverName, mcpConfig, credentials, workspaceId = null) =>
|
|
62138
62259
|
ipcRenderer$i.invoke(MCP_START_SERVER, {
|
|
62139
62260
|
serverName,
|
|
62140
62261
|
mcpConfig,
|
|
62141
62262
|
credentials,
|
|
62263
|
+
workspaceId,
|
|
62142
62264
|
}),
|
|
62143
62265
|
|
|
62144
62266
|
/**
|
|
@@ -62146,19 +62268,22 @@ const mcpApi$2 = {
|
|
|
62146
62268
|
* Stop a running MCP server
|
|
62147
62269
|
*
|
|
62148
62270
|
* @param {string} serverName the server to stop
|
|
62271
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
62149
62272
|
* @returns {Promise<{ success, serverName } | { error, message }>}
|
|
62150
62273
|
*/
|
|
62151
|
-
stopServer: (serverName) =>
|
|
62152
|
-
ipcRenderer$i.invoke(MCP_STOP_SERVER, { serverName }),
|
|
62274
|
+
stopServer: (serverName, workspaceId = null) =>
|
|
62275
|
+
ipcRenderer$i.invoke(MCP_STOP_SERVER, { serverName, workspaceId }),
|
|
62153
62276
|
|
|
62154
62277
|
/**
|
|
62155
62278
|
* listTools
|
|
62156
62279
|
* List available tools for a running MCP server
|
|
62157
62280
|
*
|
|
62158
62281
|
* @param {string} serverName the server name
|
|
62282
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
62159
62283
|
* @returns {Promise<{ tools } | { error, message }>}
|
|
62160
62284
|
*/
|
|
62161
|
-
listTools: (serverName
|
|
62285
|
+
listTools: (serverName, workspaceId = null) =>
|
|
62286
|
+
ipcRenderer$i.invoke(MCP_LIST_TOOLS, { serverName, workspaceId }),
|
|
62162
62287
|
|
|
62163
62288
|
/**
|
|
62164
62289
|
* callTool
|
|
@@ -62173,6 +62298,9 @@ const mcpApi$2 = {
|
|
|
62173
62298
|
* used to look up the widget's MCP permission manifest and gate
|
|
62174
62299
|
* the call accordingly. Should be the npm package name of the
|
|
62175
62300
|
* calling widget (e.g. "@trops/notes-summarizer").
|
|
62301
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a) —
|
|
62302
|
+
* the server process is scoped per (workspace, server). Slice 3b
|
|
62303
|
+
* will tie path scope to this id.
|
|
62176
62304
|
* @returns {Promise<{ result } | { error, message }>}
|
|
62177
62305
|
*/
|
|
62178
62306
|
callTool: (
|
|
@@ -62181,6 +62309,7 @@ const mcpApi$2 = {
|
|
|
62181
62309
|
args,
|
|
62182
62310
|
allowedTools = null,
|
|
62183
62311
|
widgetId = null,
|
|
62312
|
+
workspaceId = null,
|
|
62184
62313
|
) =>
|
|
62185
62314
|
ipcRenderer$i.invoke(MCP_CALL_TOOL, {
|
|
62186
62315
|
serverName,
|
|
@@ -62188,6 +62317,7 @@ const mcpApi$2 = {
|
|
|
62188
62317
|
args,
|
|
62189
62318
|
allowedTools,
|
|
62190
62319
|
widgetId,
|
|
62320
|
+
workspaceId,
|
|
62191
62321
|
}),
|
|
62192
62322
|
|
|
62193
62323
|
/**
|
|
@@ -62195,10 +62325,11 @@ const mcpApi$2 = {
|
|
|
62195
62325
|
* List available resources for a running MCP server
|
|
62196
62326
|
*
|
|
62197
62327
|
* @param {string} serverName the server name
|
|
62328
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
62198
62329
|
* @returns {Promise<{ resources } | { error, message }>}
|
|
62199
62330
|
*/
|
|
62200
|
-
listResources: (serverName) =>
|
|
62201
|
-
ipcRenderer$i.invoke(MCP_LIST_RESOURCES, { serverName }),
|
|
62331
|
+
listResources: (serverName, workspaceId = null) =>
|
|
62332
|
+
ipcRenderer$i.invoke(MCP_LIST_RESOURCES, { serverName, workspaceId }),
|
|
62202
62333
|
|
|
62203
62334
|
/**
|
|
62204
62335
|
* readResource
|
|
@@ -62206,20 +62337,22 @@ const mcpApi$2 = {
|
|
|
62206
62337
|
*
|
|
62207
62338
|
* @param {string} serverName the server name
|
|
62208
62339
|
* @param {string} uri the resource URI
|
|
62340
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
62209
62341
|
* @returns {Promise<{ resource } | { error, message }>}
|
|
62210
62342
|
*/
|
|
62211
|
-
readResource: (serverName, uri) =>
|
|
62212
|
-
ipcRenderer$i.invoke(MCP_READ_RESOURCE, { serverName, uri }),
|
|
62343
|
+
readResource: (serverName, uri, workspaceId = null) =>
|
|
62344
|
+
ipcRenderer$i.invoke(MCP_READ_RESOURCE, { serverName, uri, workspaceId }),
|
|
62213
62345
|
|
|
62214
62346
|
/**
|
|
62215
62347
|
* getServerStatus
|
|
62216
62348
|
* Get the connection status of a server
|
|
62217
62349
|
*
|
|
62218
62350
|
* @param {string} serverName the server name
|
|
62351
|
+
* @param {string|null} workspaceId active workspace id (Slice 3a)
|
|
62219
62352
|
* @returns {Promise<{ status, tools, error }>}
|
|
62220
62353
|
*/
|
|
62221
|
-
getServerStatus: (serverName) =>
|
|
62222
|
-
ipcRenderer$i.invoke(MCP_SERVER_STATUS, { serverName }),
|
|
62354
|
+
getServerStatus: (serverName, workspaceId = null) =>
|
|
62355
|
+
ipcRenderer$i.invoke(MCP_SERVER_STATUS, { serverName, workspaceId }),
|
|
62223
62356
|
|
|
62224
62357
|
/**
|
|
62225
62358
|
* getCatalog
|