@codingame/monaco-vscode-mcp-service-override 36.2.7 → 37.0.0

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.
Files changed (49) hide show
  1. package/package.json +2 -2
  2. package/vscode/src/vs/base/common/jsonRpcProtocol.d.ts +2 -2
  3. package/vscode/src/vs/platform/mcp/common/allowedMcpServers.d.ts +52 -0
  4. package/vscode/src/vs/platform/mcp/common/allowedMcpServers.js +180 -0
  5. package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.d.ts +4 -0
  6. package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.js +68 -12
  7. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +5 -1
  8. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +200 -92
  9. package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +3 -2
  10. package/vscode/src/vs/platform/mcp/common/nativeMcpDiscoveryHelper.d.ts +1 -0
  11. package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +3 -3
  12. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +2 -2
  13. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.d.ts +10 -3
  14. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +357 -121
  15. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +25 -25
  16. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.d.ts +11 -1
  17. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +409 -145
  18. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.js +4 -4
  19. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.js +8 -8
  20. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +37 -37
  21. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +2 -2
  22. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerIcons.js +5 -5
  23. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +5 -5
  24. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +18 -18
  25. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +12 -0
  26. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +279 -72
  27. package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServersView.css +1 -1
  28. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +6 -5
  29. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +9 -16
  30. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +4 -4
  31. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +7 -3
  32. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +14 -6
  33. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +32 -9
  34. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceDotMcpDiscovery.d.ts +2 -2
  35. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceDotMcpDiscovery.js +20 -6
  36. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +9 -5
  37. package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +4 -4
  38. package/vscode/src/vs/workbench/contrib/mcp/common/mcpEditorAffordanceState.d.ts +13 -0
  39. package/vscode/src/vs/workbench/contrib/mcp/common/mcpEditorAffordanceState.js +36 -0
  40. package/vscode/src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.js +6 -6
  41. package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +2 -0
  42. package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +51 -19
  43. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +1 -1
  44. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +11 -11
  45. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.d.ts +4 -0
  46. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.js +42 -6
  47. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +3 -3
  48. package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +6 -3
  49. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +9 -9
@@ -33,7 +33,9 @@ import { IMcpDevModeDebugging } from './mcpDevMode.service.js';
33
33
  import { McpRegistryInputStorage } from './mcpRegistryInputStorage.js';
34
34
  import { IMcpSandboxService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpSandboxService.service';
35
35
  import { McpServerConnection } from './mcpServerConnection.js';
36
- import { LazyCollectionState, UserInteractionRequiredError, McpServerTrust, McpStartServerInteraction } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
36
+ import { LazyCollectionState, UserInteractionRequiredError, McpServerTrust, McpStartServerInteraction, McpServerLaunch, McpCollectionProvenance } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
37
+ import { COPILOT_STRICT_PLUGIN_ONLY_CUSTOMIZATION_CONFIG } from '@codingame/monaco-vscode-api/vscode/vs/platform/policy/common/copilotManagedSettings';
38
+ import { isStrictPluginOnlyCustomizationEnabled } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/customizationLockdown';
37
39
  import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
38
40
  import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
39
41
  import { autorunSelfDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
@@ -76,7 +78,8 @@ let McpRegistry = class McpRegistry extends Disposable {
76
78
  if (this._mcpAccessValue.read(reader) === McpAccessValue.None) {
77
79
  return [];
78
80
  }
79
- return this._collections.read(reader);
81
+ const strictPluginOnly = this._strictPluginOnlyCustomization.read(reader);
82
+ return this._collections.read(reader).filter(collection => this.isCollectionAllowed(collection, strictPluginOnly));
80
83
  });
81
84
  this._workspaceStorage = ( new Lazy(() => this._register(
82
85
  this._instantiationService.createInstance(McpRegistryInputStorage, StorageScope.WORKSPACE, StorageTarget.USER)
@@ -98,7 +101,8 @@ let McpRegistry = class McpRegistry extends Disposable {
98
101
  collections: []
99
102
  };
100
103
  }
101
- const collections = this._collections.read(reader);
104
+ const strictPluginOnly = this._strictPluginOnlyCustomization.read(reader);
105
+ const collections = this._collections.read(reader).filter(collection => this.isCollectionAllowed(collection, strictPluginOnly));
102
106
  const hasUnknown = ( collections.some(c => c.lazy && c.lazy.isCached === false));
103
107
  return hasUnknown ? {
104
108
  state: LazyCollectionState.HasUnknown,
@@ -111,6 +115,11 @@ let McpRegistry = class McpRegistry extends Disposable {
111
115
  this._onDidChangeInputs = this._register(( new Emitter()));
112
116
  this.onDidChangeInputs = this._onDidChangeInputs.event;
113
117
  this._mcpAccessValue = observableConfigValue(mcpAccessConfig, McpAccessValue.All, configurationService);
118
+ this._strictPluginOnlyCustomization = observableConfigValue(
119
+ COPILOT_STRICT_PLUGIN_ONLY_CUSTOMIZATION_CONFIG,
120
+ undefined,
121
+ configurationService
122
+ );
114
123
  }
115
124
  registerDelegate(delegate) {
116
125
  const delegates = this._delegates.get().slice();
@@ -147,6 +156,12 @@ let McpRegistry = class McpRegistry extends Disposable {
147
156
  getServerDefinition(collectionRef, definitionRef) {
148
157
  const collectionObs = ( this._collections.map(cols => cols.find(c => c.id === collectionRef.id)));
149
158
  return ( collectionObs.map((collection, reader) => {
159
+ if (collection && !this.isCollectionAllowed(collection, this._strictPluginOnlyCustomization.read(reader))) {
160
+ return {
161
+ collection: undefined,
162
+ server: undefined
163
+ };
164
+ }
150
165
  const server = collection?.serverDefinitions.read(reader).find(s => s.id === definitionRef.id);
151
166
  return {
152
167
  collection,
@@ -155,7 +170,10 @@ let McpRegistry = class McpRegistry extends Disposable {
155
170
  }));
156
171
  }
157
172
  async discoverCollections() {
158
- const toDiscover = this._collections.get().filter(c => c.lazy && !c.lazy.isCached);
173
+ const strictPluginOnly = this._strictPluginOnlyCustomization.get();
174
+ const toDiscover = this._collections.get().filter(
175
+ c => this.isCollectionAllowed(c, strictPluginOnly) && c.lazy && !c.lazy.isCached
176
+ );
159
177
  this._ongoingLazyActivations.set(this._ongoingLazyActivations.get() + 1, undefined);
160
178
  await Promise.all(( toDiscover.map(c => c.lazy?.load()))).finally(() => {
161
179
  this._ongoingLazyActivations.set(this._ongoingLazyActivations.get() - 1, undefined);
@@ -227,7 +245,7 @@ let McpRegistry = class McpRegistry extends Disposable {
227
245
  if (errorOnUserInteraction) {
228
246
  throw ( new UserInteractionRequiredError("workspaceTrust"));
229
247
  } else if (!(await this._workspaceTrustRequestService.requestWorkspaceTrust({
230
- message: ( localize(12142, "This MCP server definition is defined in your workspace files."))
248
+ message: ( localize(13903, "This MCP server definition is defined in your workspace files."))
231
249
  }))) {
232
250
  return false;
233
251
  }
@@ -305,7 +323,7 @@ let McpRegistry = class McpRegistry extends Disposable {
305
323
  const originURI = r.definition.presentation?.origin?.uri || r.collection.presentation?.origin;
306
324
  let labelWithOrigin = originURI ? `[\`${r.definition.label}\`](${originURI})` : "`" + r.definition.label + "`";
307
325
  if (r.collection.source instanceof ExtensionIdentifier) {
308
- labelWithOrigin += ` (${( localize(12143, "from {0}", r.collection.source.value))})`;
326
+ labelWithOrigin += ` (${( localize(13904, "from {0}", r.collection.source.value))})`;
309
327
  }
310
328
  return labelWithOrigin;
311
329
  }
@@ -315,12 +333,12 @@ let McpRegistry = class McpRegistry extends Disposable {
315
333
  const {
316
334
  result
317
335
  } = await this._dialogService.prompt({
318
- message: ( localize(12144, "Trust and run MCP server {0}?", def.definition.label)),
336
+ message: ( localize(13905, "Trust and run MCP server {0}?", def.definition.label)),
319
337
  custom: {
320
338
  icon: Codicon.shield,
321
339
  markdownDetails: [{
322
340
  markdown: ( new MarkdownString(( localize(
323
- 12145,
341
+ 13906,
324
342
  "The MCP server {0} was updated. MCP servers may add context to your chat session and lead to unexpected behavior. Do you want to trust and run this server?",
325
343
  labelFor(def)
326
344
  )))),
@@ -333,10 +351,10 @@ let McpRegistry = class McpRegistry extends Disposable {
333
351
  }]
334
352
  },
335
353
  buttons: [{
336
- label: ( localize(12146, "Trust")),
354
+ label: ( localize(13907, "Trust")),
337
355
  run: () => true
338
356
  }, {
339
- label: ( localize(12147, "Do not trust")),
357
+ label: ( localize(13908, "Do not trust")),
340
358
  run: () => false
341
359
  }]
342
360
  });
@@ -346,12 +364,12 @@ let McpRegistry = class McpRegistry extends Disposable {
346
364
  const {
347
365
  result
348
366
  } = await this._dialogService.prompt({
349
- message: ( localize(12148, "Trust and run {0} MCP servers?", definitions.length)),
367
+ message: ( localize(13909, "Trust and run {0} MCP servers?", definitions.length)),
350
368
  custom: {
351
369
  icon: Codicon.shield,
352
370
  markdownDetails: [{
353
371
  markdown: ( new MarkdownString(( localize(
354
- 12149,
372
+ 13910,
355
373
  "Several updated MCP servers were discovered:\n\n{0}\n\n MCP servers may add context to your chat session and lead to unexpected behavior. Do you want to trust and run these server?",
356
374
  list
357
375
  )))),
@@ -364,13 +382,13 @@ let McpRegistry = class McpRegistry extends Disposable {
364
382
  }]
365
383
  },
366
384
  buttons: [{
367
- label: ( localize(12146, "Trust")),
385
+ label: ( localize(13907, "Trust")),
368
386
  run: () => "all"
369
387
  }, {
370
- label: ( localize(12150, "Pick Trusted")),
388
+ label: ( localize(13911, "Pick Trusted")),
371
389
  run: () => "pick"
372
390
  }, {
373
- label: ( localize(12147, "Do not trust")),
391
+ label: ( localize(13908, "Do not trust")),
374
392
  run: () => "none"
375
393
  }]
376
394
  });
@@ -461,7 +479,7 @@ let McpRegistry = class McpRegistry extends Disposable {
461
479
  } = definition.variableReplacement;
462
480
  const inputStorage = this._getInputStorageInConfigTarget(target);
463
481
  const [previouslyStored, withRemoteFilled] = await Promise.all([inputStorage.getMap(), delegate.substituteVariables(definition, launch)]);
464
- const expr = ConfigurationResolverExpression.parse(withRemoteFilled);
482
+ const expr = ConfigurationResolverExpression.parse(McpServerLaunch.toSerialized(withRemoteFilled));
465
483
  for (const replacement of expr.unresolved()) {
466
484
  if (previouslyStored.hasOwnProperty(replacement.id)) {
467
485
  expr.resolve(replacement, previouslyStored[replacement.id]);
@@ -475,7 +493,11 @@ let McpRegistry = class McpRegistry extends Disposable {
475
493
  }
476
494
  await this._configurationResolverService.resolveWithInteraction(folder, expr, section, undefined, target);
477
495
  await this._updateStorageWithExpressionInputs(inputStorage, expr);
478
- return await this._configurationResolverService.resolveAsync(folder, expr);
496
+ const resolved = await this._configurationResolverService.resolveAsync(folder, expr);
497
+ return McpServerLaunch.fromSerialized(resolved);
498
+ }
499
+ isCollectionAllowed(collection, strictPluginOnly) {
500
+ return !isStrictPluginOnlyCustomizationEnabled(strictPluginOnly) || collection.provenance === McpCollectionProvenance.Plugin;
479
501
  }
480
502
  async resolveConnection(opts) {
481
503
  const {
@@ -486,10 +508,20 @@ let McpRegistry = class McpRegistry extends Disposable {
486
508
  debug
487
509
  } = opts;
488
510
  let collection = this._collections.get().find(c => c.id === collectionRef.id);
511
+ if (collection && !this.isCollectionAllowed(collection, this._strictPluginOnlyCustomization.get())) {
512
+ throw ( new Error(
513
+ `MCP collection ${collectionRef.id} is blocked by enterprise customization policy`
514
+ ));
515
+ }
489
516
  if (collection?.lazy) {
490
517
  await collection.lazy.load();
491
518
  collection = this._collections.get().find(c => c.id === collectionRef.id);
492
519
  }
520
+ if (collection && !this.isCollectionAllowed(collection, this._strictPluginOnlyCustomization.get())) {
521
+ throw ( new Error(
522
+ `MCP collection ${collectionRef.id} is blocked by enterprise customization policy`
523
+ ));
524
+ }
493
525
  const definition = collection?.serverDefinitions.get().find(s => s.id === definitionRef.id);
494
526
  if (!collection || !definition) {
495
527
  throw ( new Error(
@@ -533,14 +565,14 @@ let McpRegistry = class McpRegistry extends Disposable {
533
565
  }
534
566
  this._notificationService.notify({
535
567
  severity: Severity.Error,
536
- message: ( localize(12151, "Error starting {0}: {1}", definition.label, String(e))),
568
+ message: ( localize(13912, "Error starting {0}: {1}", definition.label, String(e))),
537
569
  actions: {
538
570
  primary: collection.presentation?.origin && [{
539
571
  id: "mcp.launchError.openConfig",
540
572
  class: undefined,
541
573
  enabled: true,
542
574
  tooltip: "",
543
- label: ( localize(12152, "Open Configuration")),
575
+ label: ( localize(13913, "Open Configuration")),
544
576
  run: () => this._editorService.openEditor({
545
577
  resource: collection.presentation.origin,
546
578
  options: {
@@ -41,7 +41,7 @@ let McpSamplingLog = class McpSamplingLog extends Disposable {
41
41
  }
42
42
  const parts = [];
43
43
  const total = record.bins.reduce((sum, value) => sum + value, 0);
44
- parts.push(( localize(12153, "{0} total requests in the last 7 days.", total)));
44
+ parts.push(( localize(13914, "{0} total requests in the last 7 days.", total)));
45
45
  parts.push(this._formatRecentRequests(record));
46
46
  return parts.join("\n");
47
47
  }
@@ -131,11 +131,11 @@ let McpSamplingService = class McpSamplingService extends Disposable {
131
131
  return this._getMatchingModel(opts);
132
132
  }
133
133
  const retry = await this._showContextual(opts.isDuringToolCall, ( localize(
134
- 12154,
134
+ 13915,
135
135
  "Allow MCP tools from \"{0}\" to make LLM requests?",
136
136
  opts.server.definition.label
137
137
  )), ( localize(
138
- 12155,
138
+ 13916,
139
139
  "The MCP server \"{0}\" has issued a request to make a language model call. Do you want to allow it to make requests during chat?",
140
140
  opts.server.definition.label
141
141
  )), this.allowButtons(opts.server, "allowedDuringChat"));
@@ -149,11 +149,11 @@ let McpSamplingService = class McpSamplingService extends Disposable {
149
149
  return this._getMatchingModel(opts);
150
150
  }
151
151
  const retry = await this._showContextual(opts.isDuringToolCall, ( localize(
152
- 12156,
152
+ 13917,
153
153
  "Allow MCP server \"{0}\" to make LLM requests?",
154
154
  opts.server.definition.label
155
155
  )), ( localize(
156
- 12157,
156
+ 13918,
157
157
  "The MCP server \"{0}\" has issued a request to make a language model call. Do you want to allow it to make requests, outside of tool calls during chat?",
158
158
  opts.server.definition.label
159
159
  )), this.allowButtons(opts.server, "allowedOutsideChat"));
@@ -165,12 +165,12 @@ let McpSamplingService = class McpSamplingService extends Disposable {
165
165
  throw McpError.notAllowed();
166
166
  } else if (model === ModelMatch.NoMatchingModel) {
167
167
  const newlyPickedModels = opts.isDuringToolCall ? await this._commandService.executeCommand(McpCommandIds.ConfigureSamplingModels, opts.server) : await this._notify(( localize(
168
- 12158,
168
+ 13919,
169
169
  "MCP server \"{0}\" triggered a language model request, but it has no allowlisted models.",
170
170
  opts.server.definition.label
171
171
  )), {
172
- [( localize(12159, "Configure"))]: () => this._commandService.executeCommand(McpCommandIds.ConfigureSamplingModels, opts.server),
173
- [( localize(12160, "Cancel"))]: () => Promise.resolve(undefined)
172
+ [( localize(13920, "Configure"))]: () => this._commandService.executeCommand(McpCommandIds.ConfigureSamplingModels, opts.server),
173
+ [( localize(13921, "Cancel"))]: () => Promise.resolve(undefined)
174
174
  });
175
175
  if (newlyPickedModels) {
176
176
  return this._getMatchingModel(opts);
@@ -181,19 +181,19 @@ let McpSamplingService = class McpSamplingService extends Disposable {
181
181
  }
182
182
  allowButtons(server, key) {
183
183
  return {
184
- [( localize(12161, "Allow in this Session"))]: async () => {
184
+ [( localize(13922, "Allow in this Session"))]: async () => {
185
185
  this._sessionSets[key].set(server.definition.id, true);
186
186
  return true;
187
187
  },
188
- [( localize(12162, "Always"))]: async () => {
188
+ [( localize(13923, "Always"))]: async () => {
189
189
  await this.updateConfig(server, c => c[key] = true);
190
190
  return true;
191
191
  },
192
- [( localize(12163, "Not Now"))]: async () => {
192
+ [( localize(13924, "Not Now"))]: async () => {
193
193
  this._sessionSets[key].set(server.definition.id, false);
194
194
  return false;
195
195
  },
196
- [( localize(12164, "Never"))]: async () => {
196
+ [( localize(13925, "Never"))]: async () => {
197
197
  await this.updateConfig(server, c => c[key] = false);
198
198
  return false;
199
199
  }
@@ -1,4 +1,5 @@
1
1
  import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
2
+ import { OperatingSystem } from "@codingame/monaco-vscode-api/vscode/vs/base/common/platform";
2
3
  import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
3
4
  import { ConfigurationTarget } from "@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration";
4
5
  import { IEnvironmentService } from "@codingame/monaco-vscode-api/vscode/vs/platform/environment/common/environment.service";
@@ -13,6 +14,8 @@ export type SandboxConfigSuggestionResult = {
13
14
  message: string;
14
15
  sandboxConfig: IMcpSandboxConfiguration;
15
16
  };
17
+ export declare function mcpDefaultCwdToFsPath(resource: URI, os: OperatingSystem): string;
18
+ export declare function resolveMcpServerSandboxWorkingDirectory(cwd: string | undefined, defaultCwd: URI | undefined, userHome: URI | undefined, os: OperatingSystem): string | undefined;
16
19
  export declare class McpSandboxService extends Disposable implements IMcpSandboxService {
17
20
  private readonly _fileService;
18
21
  private readonly _environmentService;
@@ -37,6 +40,7 @@ export declare class McpSandboxService extends Disposable implements IMcpSandbox
37
40
  private _getSandboxEnvVariables;
38
41
  private _getSandboxCommandArgs;
39
42
  private _getRemoteEnv;
43
+ private _getUserHome;
40
44
  private _getOperatingSystem;
41
45
  private _getAppRoot;
42
46
  private _getTempDir;
@@ -1,8 +1,9 @@
1
1
 
2
2
  import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
3
  import { VSBuffer } from '@codingame/monaco-vscode-api/vscode/vs/base/common/buffer';
4
+ import { untildify } from '@codingame/monaco-vscode-api/vscode/vs/base/common/labels';
4
5
  import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
5
- import { FileAccess } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
6
+ import { Schemas, FileAccess } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
6
7
  import { win32, posix, dirname } from '@codingame/monaco-vscode-api/vscode/vs/base/common/path';
7
8
  import { OperatingSystem, OS } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
8
9
  import { arch } from '@codingame/monaco-vscode-api/vscode/vs/base/common/process';
@@ -17,6 +18,27 @@ import { IMcpResourceScannerService } from '@codingame/monaco-vscode-api/vscode/
17
18
  import { IRemoteAgentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteAgentService.service';
18
19
  import { McpServerTransportType } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
19
20
 
21
+ function mcpDefaultCwdToFsPath(resource, os) {
22
+ let value = resource.scheme === Schemas.file && resource.authority ? `//${resource.authority}${resource.path}` : resource.path;
23
+ if (os === OperatingSystem.Windows) {
24
+ if (/^\/[a-zA-Z]:/.test(value)) {
25
+ value = value.slice(1);
26
+ }
27
+ value = value.replace(/\//g, "\\");
28
+ }
29
+ return value;
30
+ }
31
+ function resolveMcpServerSandboxWorkingDirectory(cwd, defaultCwd, userHome, os) {
32
+ const targetDefaultCwd = defaultCwd ? mcpDefaultCwdToFsPath(defaultCwd, os) : undefined;
33
+ if (!cwd) {
34
+ return targetDefaultCwd;
35
+ }
36
+ const targetUserHome = userHome ? mcpDefaultCwdToFsPath(userHome, os) : undefined;
37
+ const expandedCwd = targetUserHome ? untildify(cwd, targetUserHome) : cwd;
38
+ const path = os === OperatingSystem.Windows ? win32 : posix;
39
+ const base = targetDefaultCwd ?? targetUserHome;
40
+ return base && !path.isAbsolute(expandedCwd) ? path.join(base, expandedCwd) : expandedCwd;
41
+ }
20
42
  let McpSandboxService = class McpSandboxService extends Disposable {
21
43
  constructor(
22
44
  _fileService,
@@ -58,7 +80,13 @@ let McpSandboxService = class McpSandboxService extends Disposable {
58
80
  }
59
81
  if (await this.isEnabled(serverDef, remoteAuthority)) {
60
82
  this._logService.trace(`McpSandboxService: Launching with config target ${configTarget}`);
61
- const launchDetails = await this._resolveSandboxLaunchDetails(configTarget, remoteAuthority, launch.sandbox, launch.cwd);
83
+ const launchCwd = resolveMcpServerSandboxWorkingDirectory(
84
+ launch.cwd,
85
+ serverDef.defaultCwd,
86
+ await this._getUserHome(remoteAuthority),
87
+ await this._getOperatingSystem(remoteAuthority)
88
+ );
89
+ const launchDetails = await this._resolveSandboxLaunchDetails(configTarget, remoteAuthority, launch.sandbox, launchCwd);
62
90
  const quotedCommand = this._quoteShellArgument(launch.command);
63
91
  const quotedArgs = ( launch.args.map(arg => this._quoteShellArgument(arg)));
64
92
  const sandboxArgs = this._getSandboxCommandArgs(quotedCommand, quotedArgs, launchDetails.sandboxConfigPath);
@@ -103,11 +131,11 @@ let McpSandboxService = class McpSandboxService extends Disposable {
103
131
  const suggestionLines = [];
104
132
  if (allowedDomainsList.length) {
105
133
  const shown = ( allowedDomainsList.map(domain => `"${domain}"`)).join(", ");
106
- suggestionLines.push(( localize(12165, "Add to `sandbox.network.allowedDomains`: {0}", shown)));
134
+ suggestionLines.push(( localize(13926, "Add to `sandbox.network.allowedDomains`: {0}", shown)));
107
135
  }
108
136
  if (allowWriteList.length) {
109
137
  const shown = ( allowWriteList.map(path => `"${path}"`)).join(", ");
110
- suggestionLines.push(( localize(12166, "Add to `sandbox.filesystem.allowWrite`: {0}", shown)));
138
+ suggestionLines.push(( localize(13927, "Add to `sandbox.filesystem.allowWrite`: {0}", shown)));
111
139
  }
112
140
  const sandboxConfig = {};
113
141
  if (allowedDomainsList.length) {
@@ -122,7 +150,7 @@ let McpSandboxService = class McpSandboxService extends Disposable {
122
150
  }
123
151
  return {
124
152
  message: ( localize(
125
- 12167,
153
+ 13928,
126
154
  "The MCP server {0} reported potential sandbox blocks. VS Code found possible sandbox configuration updates:\n{1}",
127
155
  serverLabel,
128
156
  suggestionLines.join("\n")
@@ -309,6 +337,14 @@ let McpSandboxService = class McpSandboxService extends Disposable {
309
337
  }
310
338
  return this._remoteEnvDetailsPromise;
311
339
  }
340
+ async _getUserHome(remoteAuthority) {
341
+ const remoteEnv = await this._getRemoteEnv(remoteAuthority);
342
+ if (remoteEnv) {
343
+ return remoteEnv.userHome;
344
+ }
345
+ const nativeEnv = this._environmentService;
346
+ return nativeEnv.userHome;
347
+ }
312
348
  async _getOperatingSystem(remoteAuthority) {
313
349
  const remoteEnv = await this._getRemoteEnv(remoteAuthority);
314
350
  if (remoteEnv) {
@@ -400,4 +436,4 @@ let McpSandboxService = class McpSandboxService extends Disposable {
400
436
  };
401
437
  McpSandboxService = ( __decorate([( __param(0, IFileService)), ( __param(1, IEnvironmentService)), ( __param(2, ILogService)), ( __param(3, IMcpResourceScannerService)), ( __param(4, IRemoteAgentService))], McpSandboxService));
402
438
 
403
- export { McpSandboxService };
439
+ export { McpSandboxService, mcpDefaultCwdToFsPath, resolveMcpServerSandboxWorkingDirectory };
@@ -52,7 +52,7 @@ let McpServerConnection = class McpServerConnection extends Disposable {
52
52
  this._state.set({
53
53
  state: McpConnectionState.Kind.Starting
54
54
  }, undefined);
55
- this._logger.info(( localize(12183, "Starting server {0}", this.definition.label)));
55
+ this._logger.info(( localize(13944, "Starting server {0}", this.definition.label)));
56
56
  try {
57
57
  const launch = this._delegate.start(this._collection, this.definition, this.launchDefinition, {
58
58
  errorOnUserInteraction: this._errorOnUserInteraction
@@ -89,7 +89,7 @@ let McpServerConnection = class McpServerConnection extends Disposable {
89
89
  store.add(autorun(reader => {
90
90
  const state = launch.state.read(reader);
91
91
  this._state.set(state, undefined);
92
- this._logger.info(( localize(12184, "Connection state: {0}", (McpConnectionState.toString(state)))));
92
+ this._logger.info(( localize(13945, "Connection state: {0}", (McpConnectionState.toString(state)))));
93
93
  if (state.state === McpConnectionState.Kind.Running && !didStart) {
94
94
  didStart = true;
95
95
  McpServerRequestHandler.create(this._instantiationService, {
@@ -128,7 +128,7 @@ let McpServerConnection = class McpServerConnection extends Disposable {
128
128
  };
129
129
  }
130
130
  async stop() {
131
- this._logger.info(( localize(12185, "Stopping server {0}", this.definition.label)));
131
+ this._logger.info(( localize(13946, "Stopping server {0}", this.definition.label)));
132
132
  this._launch.value?.object.stop();
133
133
  await this._waitForState(McpConnectionState.Kind.Stopped, McpConnectionState.Kind.Error);
134
134
  }
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
3
  import { RunOnceScheduler } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
4
+ import { equals } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
4
5
  import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
5
6
  import { Disposable, DisposableStore, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
6
7
  import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
@@ -203,9 +204,11 @@ let McpService = class McpService extends Disposable {
203
204
  object
204
205
  });
205
206
  }
206
- transaction(tx => {
207
- this._servers.set(nextServers, tx);
208
- });
207
+ if (!equals(currentServers, nextServers)) {
208
+ transaction(tx => {
209
+ this._servers.set(nextServers, tx);
210
+ });
211
+ }
209
212
  }
210
213
  dispose() {
211
214
  this._servers.get().forEach(s => s.object.dispose());
@@ -120,7 +120,7 @@ let AuthenticationMcpService = class AuthenticationMcpService extends Disposable
120
120
  numberOfRequests += ( Object.keys(accessRequest)).length;
121
121
  });
122
122
  if (numberOfRequests > 0) {
123
- const badge = ( new NumberBadge(numberOfRequests, () => ( localize(17361, "Sign in requested"))));
123
+ const badge = ( new NumberBadge(numberOfRequests, () => ( localize(19114, "Sign in requested"))));
124
124
  this._accountBadgeDisposable.value = this.activityService.showAccountsActivity({
125
125
  badge
126
126
  });
@@ -194,17 +194,17 @@ let AuthenticationMcpService = class AuthenticationMcpService extends Disposable
194
194
  } = await this.dialogService.prompt({
195
195
  type: Severity.Info,
196
196
  message: ( localize(
197
- 17362,
197
+ 19115,
198
198
  "The MCP server '{0}' wants to access the {1} account '{2}'.",
199
199
  mcpServerName,
200
200
  provider.label,
201
201
  accountName
202
202
  )),
203
203
  buttons: [{
204
- label: ( localize(17363, "&&Allow")),
204
+ label: ( localize(19116, "&&Allow")),
205
205
  run: () => SessionPromptChoice.Allow
206
206
  }, {
207
- label: ( localize(17364, "&&Deny")),
207
+ label: ( localize(19117, "&&Deny")),
208
208
  run: () => SessionPromptChoice.Deny
209
209
  }],
210
210
  cancelButton: {
@@ -246,17 +246,17 @@ let AuthenticationMcpService = class AuthenticationMcpService extends Disposable
246
246
  }
247
247
  });
248
248
  items.push({
249
- label: ( localize(17365, "Sign in to another account"))
249
+ label: ( localize(19118, "Sign in to another account"))
250
250
  });
251
251
  quickPick.items = items;
252
252
  quickPick.title = ( localize(
253
- 17366,
253
+ 19119,
254
254
  "The MCP server '{0}' wants to access a {1} account",
255
255
  mcpServerName,
256
256
  this._authenticationService.getProvider(providerId).label
257
257
  ));
258
258
  quickPick.placeholder = ( localize(
259
- 17367,
259
+ 19120,
260
260
  "Select an account for '{0}' to use or Esc to cancel",
261
261
  mcpServerName
262
262
  ));
@@ -336,7 +336,7 @@ let AuthenticationMcpService = class AuthenticationMcpService extends Disposable
336
336
  group: "3_accessRequests",
337
337
  command: {
338
338
  id: `${providerId}${mcpServerId}Access`,
339
- title: ( localize(17368, "Grant access to {0} for {1}... (1)", provider.label, mcpServerName))
339
+ title: ( localize(19121, "Grant access to {0} for {1}... (1)", provider.label, mcpServerName))
340
340
  }
341
341
  }));
342
342
  const accessCommand = CommandsRegistry.registerCommand({
@@ -380,7 +380,7 @@ let AuthenticationMcpService = class AuthenticationMcpService extends Disposable
380
380
  group: "2_signInRequests",
381
381
  command: {
382
382
  id: commandId,
383
- title: ( localize(17369, "Sign in with {0} to use {1} (1)", provider.label, mcpServerName))
383
+ title: ( localize(19122, "Sign in with {0} to use {1} (1)", provider.label, mcpServerName))
384
384
  }
385
385
  }));
386
386
  const signInCommand = CommandsRegistry.registerCommand({