@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.
@@ -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$$9$1 = require('child_process');
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$$9$1;
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(serverName);
22018
+ const existing = activeServers.get(key);
21948
22019
  if (existing && existing.status === STATUS$1.CONNECTED && existing.client) {
21949
- console.log(`[mcpController] Server already connected: ${serverName}`);
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(serverName)) {
22031
+ if (pendingStarts.has(key)) {
21961
22032
  console.log(
21962
- `[mcpController] Server already starting, deduplicating: ${serverName}`,
22033
+ `[mcpController] Server already starting, deduplicating: ${key}`,
21963
22034
  );
21964
- return pendingStarts.get(serverName);
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(serverName)) {
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(serverName, {
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(serverName, {
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: ${serverName} (${tools.length} tools, ${resources.length} resources)`,
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(serverName, {
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(serverName);
22269
+ pendingStarts.delete(key);
22193
22270
  }
22194
22271
  })();
22195
22272
 
22196
- pendingStarts.set(serverName, startPromise);
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(serverName)) {
22290
+ if (pendingStarts.has(key)) {
22212
22291
  try {
22213
- await pendingStarts.get(serverName);
22292
+ await pendingStarts.get(key);
22214
22293
  } catch (e) {
22215
22294
  /* stopping anyway */
22216
22295
  }
22217
22296
  }
22218
22297
 
22219
- const server = activeServers.get(serverName);
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: ${serverName}`);
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 ${serverName}:`,
22315
+ `[mcpController] Error closing client for ${key}:`,
22237
22316
  closeError.message,
22238
22317
  );
22239
22318
  }
22240
22319
  }
22241
22320
 
22242
- activeServers.delete(serverName);
22321
+ activeServers.delete(key);
22243
22322
 
22244
- console.log(`[mcpController] Server stopped: ${serverName}`);
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(serverName);
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(serverName);
22366
+ const server = activeServers.get(key);
22285
22367
  if (!server || !server.client) {
22286
- throw new Error(`Server not connected: ${serverName}`);
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: ${serverName}/${toolName}`);
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
- // Writes always hit the source (and we invalidate the server's cache).
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 key = `mcp:${serverName}:${toolName}:${JSON.stringify(args || {})}`;
22334
- return responseCache$2.get(key, doCall, {
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:${serverName}:`);
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(serverName);
22452
+ const server = activeServers.get(key);
22366
22453
  if (!server || !server.client) {
22367
- throw new Error(`Server not connected: ${serverName}`);
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(serverName);
22492
+ const server = activeServers.get(key);
22404
22493
  if (!server || !server.client) {
22405
- throw new Error(`Server not connected: ${serverName}`);
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(serverName);
22532
+ const server = activeServers.get(key);
22442
22533
  if (!server || !server.client) {
22443
- throw new Error(`Server not connected: ${serverName}`);
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 server = activeServers.get(serverName);
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$$9$1;
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
- for (const [serverName] of activeServers) {
22736
- promises.push(mcpController$3.stopServer(null, serverName));
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$$9$1;
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) => ipcRenderer$i.invoke(MCP_LIST_TOOLS, { 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