@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.
- package/package.json +2 -2
- package/vscode/src/vs/base/common/jsonRpcProtocol.d.ts +2 -2
- package/vscode/src/vs/platform/mcp/common/allowedMcpServers.d.ts +52 -0
- package/vscode/src/vs/platform/mcp/common/allowedMcpServers.js +180 -0
- package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.d.ts +4 -0
- package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.js +68 -12
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +5 -1
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +200 -92
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +3 -2
- package/vscode/src/vs/platform/mcp/common/nativeMcpDiscoveryHelper.d.ts +1 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.d.ts +10 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +357 -121
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +25 -25
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.d.ts +11 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +409 -145
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.js +8 -8
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +37 -37
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerIcons.js +5 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +5 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +18 -18
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +12 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +279 -72
- package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServersView.css +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +6 -5
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +9 -16
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +7 -3
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +14 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +32 -9
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceDotMcpDiscovery.d.ts +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceDotMcpDiscovery.js +20 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +9 -5
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpEditorAffordanceState.d.ts +13 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpEditorAffordanceState.js +36 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.js +6 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +2 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +51 -19
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +11 -11
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.d.ts +4 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.js +42 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +6 -3
- 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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
354
|
+
label: ( localize(13907, "Trust")),
|
|
337
355
|
run: () => true
|
|
338
356
|
}, {
|
|
339
|
-
label: ( localize(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
385
|
+
label: ( localize(13907, "Trust")),
|
|
368
386
|
run: () => "all"
|
|
369
387
|
}, {
|
|
370
|
-
label: ( localize(
|
|
388
|
+
label: ( localize(13911, "Pick Trusted")),
|
|
371
389
|
run: () => "pick"
|
|
372
390
|
}, {
|
|
373
|
-
label: ( localize(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
134
|
+
13915,
|
|
135
135
|
"Allow MCP tools from \"{0}\" to make LLM requests?",
|
|
136
136
|
opts.server.definition.label
|
|
137
137
|
)), ( localize(
|
|
138
|
-
|
|
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
|
-
|
|
152
|
+
13917,
|
|
153
153
|
"Allow MCP server \"{0}\" to make LLM requests?",
|
|
154
154
|
opts.server.definition.label
|
|
155
155
|
)), ( localize(
|
|
156
|
-
|
|
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
|
-
|
|
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(
|
|
173
|
-
[( localize(
|
|
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(
|
|
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(
|
|
188
|
+
[( localize(13923, "Always"))]: async () => {
|
|
189
189
|
await this.updateConfig(server, c => c[key] = true);
|
|
190
190
|
return true;
|
|
191
191
|
},
|
|
192
|
-
[( localize(
|
|
192
|
+
[( localize(13924, "Not Now"))]: async () => {
|
|
193
193
|
this._sessionSets[key].set(server.definition.id, false);
|
|
194
194
|
return false;
|
|
195
195
|
},
|
|
196
|
-
[( localize(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
207
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
204
|
+
label: ( localize(19116, "&&Allow")),
|
|
205
205
|
run: () => SessionPromptChoice.Allow
|
|
206
206
|
}, {
|
|
207
|
-
label: ( localize(
|
|
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(
|
|
249
|
+
label: ( localize(19118, "Sign in to another account"))
|
|
250
250
|
});
|
|
251
251
|
quickPick.items = items;
|
|
252
252
|
quickPick.title = ( localize(
|
|
253
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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({
|