@codingame/monaco-vscode-mcp-service-override 26.2.2 → 28.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/index.js +8 -2
- package/package.json +2 -2
- package/vscode/src/vs/base/common/jsonRpcProtocol.d.ts +66 -0
- package/vscode/src/vs/base/common/jsonRpcProtocol.js +216 -0
- package/vscode/src/vs/platform/mcp/common/allowedMcpServersService.js +1 -1
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpGateway.d.ts +39 -0
- package/vscode/src/vs/platform/mcp/common/mcpGateway.js +6 -0
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.d.ts +3 -1
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +12 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +15 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +58 -58
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +27 -28
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpGatewayService.d.ts +20 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpGatewayService.js +51 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpGatewayToolBrokerContribution.d.ts +7 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpGatewayToolBrokerContribution.js +16 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +18 -18
- 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/mcpServersView.d.ts +4 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +42 -24
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +13 -12
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +3 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +2 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/pluginMcpDiscovery.d.ts +15 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/pluginMcpDiscovery.js +106 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpGatewayToolBrokerChannel.d.ts +39 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpGatewayToolBrokerChannel.js +302 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.js +25 -17
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +3 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +27 -18
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +1 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +28 -18
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.d.ts +47 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSandboxService.js +385 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.d.ts +6 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +61 -3
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +4 -20
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +95 -145
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +9 -9
- package/vscode/src/vs/workbench/services/mcp/browser/mcpWorkbenchManagementService.d.ts +1 -1
- package/vscode/src/vs/workbench/services/mcp/browser/mcpWorkbenchManagementService.js +2 -2
- package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.d.ts +0 -42
- package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.js +0 -105
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +0 -130
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +0 -665
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +0 -259
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +0 -1225
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +0 -72
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +0 -996
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.d.ts +0 -17
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +0 -49
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerIcons.d.ts +0 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerIcons.js +0 -12
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +0 -88
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +0 -464
- package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServerEditor.css +0 -94
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.d.ts +0 -87
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.js +0 -702
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
|
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { VSBuffer } from '@codingame/monaco-vscode-api/vscode/vs/base/common/buffer';
|
|
4
|
+
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 { win32, posix, dirname } from '@codingame/monaco-vscode-api/vscode/vs/base/common/path';
|
|
7
|
+
import { OperatingSystem, OS } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
|
|
8
|
+
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
|
|
9
|
+
import { generateUuid } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uuid';
|
|
10
|
+
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
11
|
+
import { ConfigurationTarget, ConfigurationTargetToString } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration';
|
|
12
|
+
import { IEnvironmentService } from '@codingame/monaco-vscode-api/vscode/vs/platform/environment/common/environment.service';
|
|
13
|
+
import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
|
|
14
|
+
import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
|
|
15
|
+
import { IMcpResourceScannerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpResourceScannerService.service';
|
|
16
|
+
import { IRemoteAgentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteAgentService.service';
|
|
17
|
+
import { McpServerTransportType } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
|
|
18
|
+
|
|
19
|
+
let McpSandboxService = class McpSandboxService extends Disposable {
|
|
20
|
+
constructor(
|
|
21
|
+
_fileService,
|
|
22
|
+
_environmentService,
|
|
23
|
+
_logService,
|
|
24
|
+
_mcpResourceScannerService,
|
|
25
|
+
_remoteAgentService
|
|
26
|
+
) {
|
|
27
|
+
super();
|
|
28
|
+
this._fileService = _fileService;
|
|
29
|
+
this._environmentService = _environmentService;
|
|
30
|
+
this._logService = _logService;
|
|
31
|
+
this._mcpResourceScannerService = _mcpResourceScannerService;
|
|
32
|
+
this._remoteAgentService = _remoteAgentService;
|
|
33
|
+
this._defaultAllowedDomains = ["registry.npmjs.org"];
|
|
34
|
+
this._sandboxConfigPerConfigurationTarget = ( new Map());
|
|
35
|
+
this._pathJoin = (os, ...segments) => {
|
|
36
|
+
const path = os === OperatingSystem.Windows ? win32 : posix;
|
|
37
|
+
return path.join(...segments);
|
|
38
|
+
};
|
|
39
|
+
this._getPathDelimiter = async remoteAuthority => {
|
|
40
|
+
const os = await this._getOperatingSystem(remoteAuthority);
|
|
41
|
+
return os === OperatingSystem.Windows ? win32.delimiter : posix.delimiter;
|
|
42
|
+
};
|
|
43
|
+
this._sandboxSettingsId = generateUuid();
|
|
44
|
+
this._remoteEnvDetailsPromise = this._remoteAgentService.getEnvironment();
|
|
45
|
+
}
|
|
46
|
+
async isEnabled(serverDef, remoteAuthority) {
|
|
47
|
+
const os = await this._getOperatingSystem(remoteAuthority);
|
|
48
|
+
if (os === OperatingSystem.Windows) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return !!serverDef.sandboxEnabled;
|
|
52
|
+
}
|
|
53
|
+
async launchInSandboxIfEnabled(serverDef, launch, remoteAuthority, configTarget) {
|
|
54
|
+
if (launch.type !== McpServerTransportType.Stdio) {
|
|
55
|
+
return launch;
|
|
56
|
+
}
|
|
57
|
+
if (await this.isEnabled(serverDef, remoteAuthority)) {
|
|
58
|
+
this._logService.trace(`McpSandboxService: Launching with config target ${configTarget}`);
|
|
59
|
+
const launchDetails = await this._resolveSandboxLaunchDetails(configTarget, remoteAuthority, launch.sandbox, launch.cwd);
|
|
60
|
+
const sandboxArgs = this._getSandboxCommandArgs(launch.command, launch.args, launchDetails.sandboxConfigPath);
|
|
61
|
+
const sandboxEnv = await this._getSandboxEnvVariables(launch.env, launchDetails.tempDir, launchDetails.rgPath, remoteAuthority);
|
|
62
|
+
if (launchDetails.srtPath) {
|
|
63
|
+
if (launchDetails.execPath) {
|
|
64
|
+
return {
|
|
65
|
+
...launch,
|
|
66
|
+
command: launchDetails.execPath,
|
|
67
|
+
args: [launchDetails.srtPath, ...sandboxArgs],
|
|
68
|
+
env: sandboxEnv,
|
|
69
|
+
type: McpServerTransportType.Stdio
|
|
70
|
+
};
|
|
71
|
+
} else {
|
|
72
|
+
return {
|
|
73
|
+
...launch,
|
|
74
|
+
command: launchDetails.srtPath,
|
|
75
|
+
args: sandboxArgs,
|
|
76
|
+
env: sandboxEnv,
|
|
77
|
+
type: McpServerTransportType.Stdio
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!launchDetails.execPath) {
|
|
82
|
+
this._logService.warn(
|
|
83
|
+
"McpSandboxService: execPath is unavailable, launching without sandbox runtime wrapper"
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
this._logService.debug(
|
|
87
|
+
`McpSandboxService: launch details for server ${serverDef.label} - command: ${launch.command}, args: ${launch.args.join(" ")}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return launch;
|
|
91
|
+
}
|
|
92
|
+
getSandboxConfigSuggestionMessage(serverLabel, potentialBlocks, existingSandboxConfig) {
|
|
93
|
+
const suggestions = this._getSandboxConfigSuggestions(potentialBlocks, existingSandboxConfig);
|
|
94
|
+
if (!suggestions) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const allowWriteList = suggestions.allowWrite;
|
|
98
|
+
const allowedDomainsList = suggestions.allowedDomains;
|
|
99
|
+
const suggestionLines = [];
|
|
100
|
+
if (allowedDomainsList.length) {
|
|
101
|
+
const shown = ( allowedDomainsList.map(domain => `"${domain}"`)).join(", ");
|
|
102
|
+
suggestionLines.push(( localize(10452, "Add to `sandbox.network.allowedDomains`: {0}", shown)));
|
|
103
|
+
}
|
|
104
|
+
if (allowWriteList.length) {
|
|
105
|
+
const shown = ( allowWriteList.map(path => `"${path}"`)).join(", ");
|
|
106
|
+
suggestionLines.push(( localize(10453, "Add to `sandbox.filesystem.allowWrite`: {0}", shown)));
|
|
107
|
+
}
|
|
108
|
+
const sandboxConfig = {};
|
|
109
|
+
if (allowedDomainsList.length) {
|
|
110
|
+
sandboxConfig.network = {
|
|
111
|
+
allowedDomains: [...allowedDomainsList]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (allowWriteList.length) {
|
|
115
|
+
sandboxConfig.filesystem = {
|
|
116
|
+
allowWrite: [...allowWriteList]
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
message: ( localize(
|
|
121
|
+
10454,
|
|
122
|
+
"The MCP server {0} reported potential sandbox blocks. VS Code found possible sandbox configuration updates:\n{1}",
|
|
123
|
+
serverLabel,
|
|
124
|
+
suggestionLines.join("\n")
|
|
125
|
+
)),
|
|
126
|
+
sandboxConfig
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async applySandboxConfigSuggestion(
|
|
130
|
+
serverDef,
|
|
131
|
+
mcpResource,
|
|
132
|
+
configTarget,
|
|
133
|
+
potentialBlocks,
|
|
134
|
+
suggestedSandboxConfig
|
|
135
|
+
) {
|
|
136
|
+
const scanTarget = this._toMcpResourceTarget(configTarget);
|
|
137
|
+
let didChange = false;
|
|
138
|
+
await this._mcpResourceScannerService.updateSandboxConfig(data => {
|
|
139
|
+
const existingSandbox = data.sandbox;
|
|
140
|
+
const suggestedAllowedDomains = suggestedSandboxConfig?.network?.allowedDomains ?? [];
|
|
141
|
+
const suggestedAllowWrite = suggestedSandboxConfig?.filesystem?.allowWrite ?? [];
|
|
142
|
+
const currentAllowedDomains = ( new Set(existingSandbox?.network?.allowedDomains ?? []));
|
|
143
|
+
for (const domain of suggestedAllowedDomains) {
|
|
144
|
+
if (domain && !( currentAllowedDomains.has(domain))) {
|
|
145
|
+
currentAllowedDomains.add(domain);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const currentAllowWrite = ( new Set(existingSandbox?.filesystem?.allowWrite ?? []));
|
|
149
|
+
for (const path of suggestedAllowWrite) {
|
|
150
|
+
if (path && !( currentAllowWrite.has(path))) {
|
|
151
|
+
currentAllowWrite.add(path);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (suggestedAllowedDomains.length === 0 && suggestedAllowWrite.length === 0) {
|
|
155
|
+
return data;
|
|
156
|
+
}
|
|
157
|
+
didChange = true;
|
|
158
|
+
const nextSandboxConfig = {};
|
|
159
|
+
if (currentAllowedDomains.size > 0) {
|
|
160
|
+
nextSandboxConfig.network = {
|
|
161
|
+
...existingSandbox?.network,
|
|
162
|
+
allowedDomains: [...currentAllowedDomains]
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (currentAllowWrite.size > 0) {
|
|
166
|
+
nextSandboxConfig.filesystem = {
|
|
167
|
+
...existingSandbox?.filesystem,
|
|
168
|
+
allowWrite: [...currentAllowWrite]
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
...data,
|
|
173
|
+
sandbox: nextSandboxConfig
|
|
174
|
+
};
|
|
175
|
+
}, mcpResource, scanTarget);
|
|
176
|
+
return didChange;
|
|
177
|
+
}
|
|
178
|
+
_getSandboxConfigSuggestions(potentialBlocks, existingSandboxConfig) {
|
|
179
|
+
if (!potentialBlocks.length) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
const allowWrite = ( new Set());
|
|
183
|
+
const allowedDomains = ( new Set());
|
|
184
|
+
const existingAllowWrite = ( new Set(existingSandboxConfig?.filesystem?.allowWrite ?? []));
|
|
185
|
+
const existingAllowedDomains = ( new Set(existingSandboxConfig?.network?.allowedDomains ?? []));
|
|
186
|
+
for (const block of potentialBlocks) {
|
|
187
|
+
if (block.kind === "network" && block.host && !( existingAllowedDomains.has(block.host))) {
|
|
188
|
+
allowedDomains.add(block.host);
|
|
189
|
+
}
|
|
190
|
+
if (block.kind === "filesystem" && block.path && !( existingAllowWrite.has(block.path))) {
|
|
191
|
+
allowWrite.add(block.path);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (!allowWrite.size && !allowedDomains.size) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
allowWrite: [...allowWrite],
|
|
199
|
+
allowedDomains: [...allowedDomains]
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
_toMcpResourceTarget(configTarget) {
|
|
203
|
+
switch (configTarget) {
|
|
204
|
+
case ConfigurationTarget.USER:
|
|
205
|
+
case ConfigurationTarget.USER_LOCAL:
|
|
206
|
+
case ConfigurationTarget.USER_REMOTE:
|
|
207
|
+
return ConfigurationTarget.USER;
|
|
208
|
+
case ConfigurationTarget.WORKSPACE:
|
|
209
|
+
return ConfigurationTarget.WORKSPACE;
|
|
210
|
+
case ConfigurationTarget.WORKSPACE_FOLDER:
|
|
211
|
+
return ConfigurationTarget.WORKSPACE_FOLDER;
|
|
212
|
+
default:
|
|
213
|
+
return ConfigurationTarget.USER;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async _resolveSandboxLaunchDetails(configTarget, remoteAuthority, sandboxConfig, launchCwd) {
|
|
217
|
+
const os = await this._getOperatingSystem(remoteAuthority);
|
|
218
|
+
if (os === OperatingSystem.Windows) {
|
|
219
|
+
return {
|
|
220
|
+
execPath: undefined,
|
|
221
|
+
srtPath: undefined,
|
|
222
|
+
rgPath: undefined,
|
|
223
|
+
sandboxConfigPath: undefined,
|
|
224
|
+
tempDir: undefined
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const appRoot = await this._getAppRoot(remoteAuthority);
|
|
228
|
+
const execPath = await this._getExecPath(os, appRoot, remoteAuthority);
|
|
229
|
+
const tempDir = await this._getTempDir(remoteAuthority);
|
|
230
|
+
const srtPath = this._pathJoin(
|
|
231
|
+
os,
|
|
232
|
+
appRoot,
|
|
233
|
+
"node_modules",
|
|
234
|
+
"@anthropic-ai",
|
|
235
|
+
"sandbox-runtime",
|
|
236
|
+
"dist",
|
|
237
|
+
"cli.js"
|
|
238
|
+
);
|
|
239
|
+
const rgPath = this._pathJoin(os, appRoot, "node_modules", "@vscode", "ripgrep", "bin", "rg");
|
|
240
|
+
const sandboxConfigPath = tempDir ? await this._updateSandboxConfig(tempDir, configTarget, sandboxConfig, launchCwd) : undefined;
|
|
241
|
+
this._logService.debug(`McpSandboxService: Updated sandbox config path: ${sandboxConfigPath}`);
|
|
242
|
+
return {
|
|
243
|
+
execPath,
|
|
244
|
+
srtPath,
|
|
245
|
+
rgPath,
|
|
246
|
+
sandboxConfigPath,
|
|
247
|
+
tempDir
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async _getExecPath(os, appRoot, remoteAuthority) {
|
|
251
|
+
if (remoteAuthority) {
|
|
252
|
+
return this._pathJoin(os, appRoot, "node");
|
|
253
|
+
}
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
async _getSandboxEnvVariables(baseEnv, tempDir, rgPath, remoteAuthority) {
|
|
257
|
+
let env = {
|
|
258
|
+
...baseEnv
|
|
259
|
+
};
|
|
260
|
+
if (tempDir) {
|
|
261
|
+
env = {
|
|
262
|
+
...env,
|
|
263
|
+
TMPDIR: tempDir.path,
|
|
264
|
+
SRT_DEBUG: "true"
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (rgPath) {
|
|
268
|
+
env = {
|
|
269
|
+
...env,
|
|
270
|
+
PATH: env["PATH"] ? `${env["PATH"]}${await this._getPathDelimiter(remoteAuthority)}${dirname(rgPath)}` : dirname(rgPath)
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if (!remoteAuthority) {
|
|
274
|
+
env = {
|
|
275
|
+
...env,
|
|
276
|
+
ELECTRON_RUN_AS_NODE: "1"
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
env["VSCODE_INSPECTOR_OPTIONS"] = null;
|
|
280
|
+
return env;
|
|
281
|
+
}
|
|
282
|
+
_getSandboxCommandArgs(command, args, sandboxConfigPath) {
|
|
283
|
+
const result = [];
|
|
284
|
+
if (sandboxConfigPath) {
|
|
285
|
+
result.push("--settings", sandboxConfigPath);
|
|
286
|
+
}
|
|
287
|
+
result.push(command, ...args);
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
async _getRemoteEnv(remoteAuthority) {
|
|
291
|
+
if (!remoteAuthority) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return this._remoteEnvDetailsPromise;
|
|
295
|
+
}
|
|
296
|
+
async _getOperatingSystem(remoteAuthority) {
|
|
297
|
+
const remoteEnv = await this._getRemoteEnv(remoteAuthority);
|
|
298
|
+
if (remoteEnv) {
|
|
299
|
+
return remoteEnv.os;
|
|
300
|
+
}
|
|
301
|
+
return OS;
|
|
302
|
+
}
|
|
303
|
+
async _getAppRoot(remoteAuthority) {
|
|
304
|
+
const remoteEnv = await this._getRemoteEnv(remoteAuthority);
|
|
305
|
+
if (remoteEnv) {
|
|
306
|
+
return remoteEnv.appRoot.path;
|
|
307
|
+
}
|
|
308
|
+
return dirname(( FileAccess.asFileUri("")).path);
|
|
309
|
+
}
|
|
310
|
+
async _getTempDir(remoteAuthority) {
|
|
311
|
+
const remoteEnv = await this._getRemoteEnv(remoteAuthority);
|
|
312
|
+
if (remoteEnv) {
|
|
313
|
+
return remoteEnv.tmpDir;
|
|
314
|
+
}
|
|
315
|
+
const environmentService = this._environmentService;
|
|
316
|
+
const tempDir = environmentService.tmpDir;
|
|
317
|
+
if (!tempDir) {
|
|
318
|
+
this._logService.warn(
|
|
319
|
+
"McpSandboxService: Cannot create sandbox settings file because no tmpDir is available in this environment"
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
return tempDir;
|
|
323
|
+
}
|
|
324
|
+
async _updateSandboxConfig(tempDir, configTarget, sandboxConfig, launchCwd) {
|
|
325
|
+
const normalizedSandboxConfig = this._withDefaultSandboxConfig(sandboxConfig, launchCwd);
|
|
326
|
+
let configFileUri;
|
|
327
|
+
const configTargetKey = ConfigurationTargetToString(configTarget);
|
|
328
|
+
if (( this._sandboxConfigPerConfigurationTarget.has(configTargetKey))) {
|
|
329
|
+
configFileUri = ( URI.parse(this._sandboxConfigPerConfigurationTarget.get(configTargetKey)));
|
|
330
|
+
} else {
|
|
331
|
+
configFileUri = URI.joinPath(
|
|
332
|
+
tempDir,
|
|
333
|
+
`vscode-${configTargetKey}-mcp-sandbox-settings-${this._sandboxSettingsId}.json`
|
|
334
|
+
);
|
|
335
|
+
this._sandboxConfigPerConfigurationTarget.set(configTargetKey, ( configFileUri.toString()));
|
|
336
|
+
}
|
|
337
|
+
await this._fileService.createFile(
|
|
338
|
+
configFileUri,
|
|
339
|
+
VSBuffer.fromString(JSON.stringify(normalizedSandboxConfig, null, "\t")),
|
|
340
|
+
{
|
|
341
|
+
overwrite: true
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
return configFileUri.path;
|
|
345
|
+
}
|
|
346
|
+
_withDefaultSandboxConfig(sandboxConfig, launchCwd) {
|
|
347
|
+
const mergedAllowWrite = ( new Set(sandboxConfig?.filesystem?.allowWrite ?? []));
|
|
348
|
+
for (const defaultAllowWrite of this._getDefaultAllowWrite(launchCwd ? [launchCwd] : undefined)) {
|
|
349
|
+
if (defaultAllowWrite) {
|
|
350
|
+
mergedAllowWrite.add(defaultAllowWrite);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const mergedAllowedDomains = ( new Set(sandboxConfig?.network?.allowedDomains ?? []));
|
|
354
|
+
for (const defaultAllowedDomain of this._defaultAllowedDomains) {
|
|
355
|
+
if (defaultAllowedDomain) {
|
|
356
|
+
mergedAllowedDomains.add(defaultAllowedDomain);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
...sandboxConfig,
|
|
361
|
+
network: {
|
|
362
|
+
allowedDomains: [...mergedAllowedDomains],
|
|
363
|
+
deniedDomains: sandboxConfig?.network?.deniedDomains ?? []
|
|
364
|
+
},
|
|
365
|
+
filesystem: {
|
|
366
|
+
allowWrite: [...mergedAllowWrite],
|
|
367
|
+
denyRead: sandboxConfig?.filesystem?.denyRead ?? [],
|
|
368
|
+
denyWrite: sandboxConfig?.filesystem?.denyWrite ?? []
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
_getDefaultAllowWrite(directories) {
|
|
373
|
+
const defaultAllowWrite = ["~/.npm"];
|
|
374
|
+
for (const launchCwd of directories ?? []) {
|
|
375
|
+
const trimmed = launchCwd.trim();
|
|
376
|
+
if (trimmed) {
|
|
377
|
+
defaultAllowWrite.push(trimmed);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return defaultAllowWrite;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
McpSandboxService = ( __decorate([( __param(0, IFileService)), ( __param(1, IEnvironmentService)), ( __param(2, ILogService)), ( __param(3, IMcpResourceScannerService)), ( __param(4, IRemoteAgentService))], McpSandboxService));
|
|
384
|
+
|
|
385
|
+
export { McpSandboxService };
|
|
@@ -5,7 +5,7 @@ import { ILogger } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/com
|
|
|
5
5
|
import { IMcpHostDelegate } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes";
|
|
6
6
|
import { McpServerRequestHandler } from "./mcpServerRequestHandler.js";
|
|
7
7
|
import { McpTaskManager } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTaskManager";
|
|
8
|
-
import { IMcpClientMethods, IMcpServerConnection, McpCollectionDefinition, McpConnectionState, McpServerDefinition, McpServerLaunch } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
8
|
+
import { IMcpClientMethods, IMcpPotentialSandboxBlock, IMcpServerConnection, McpCollectionDefinition, McpConnectionState, McpServerDefinition, McpServerLaunch } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
9
9
|
export declare class McpServerConnection extends Disposable implements IMcpServerConnection {
|
|
10
10
|
private readonly _collection;
|
|
11
11
|
readonly definition: McpServerDefinition;
|
|
@@ -18,8 +18,10 @@ export declare class McpServerConnection extends Disposable implements IMcpServe
|
|
|
18
18
|
private readonly _launch;
|
|
19
19
|
private readonly _state;
|
|
20
20
|
private readonly _requestHandler;
|
|
21
|
+
private readonly _onPotentialSandboxBlock;
|
|
21
22
|
readonly state: IObservable<McpConnectionState>;
|
|
22
23
|
readonly handler: IObservable<McpServerRequestHandler | undefined>;
|
|
24
|
+
readonly onPotentialSandboxBlock: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<IMcpPotentialSandboxBlock>;
|
|
23
25
|
constructor(_collection: McpCollectionDefinition, definition: McpServerDefinition, _delegate: IMcpHostDelegate, launchDefinition: McpServerLaunch, _logger: ILogger, _errorOnUserInteraction: boolean | undefined, _taskManager: McpTaskManager, _instantiationService: IInstantiationService);
|
|
24
26
|
/** @inheritdoc */
|
|
25
27
|
start(methods: IMcpClientMethods): Promise<McpConnectionState>;
|
|
@@ -27,4 +29,7 @@ export declare class McpServerConnection extends Disposable implements IMcpServe
|
|
|
27
29
|
stop(): Promise<void>;
|
|
28
30
|
dispose(): void;
|
|
29
31
|
private _waitForState;
|
|
32
|
+
private _toPotentialSandboxBlock;
|
|
33
|
+
private _extractSandboxPath;
|
|
34
|
+
private _extractSandboxHost;
|
|
30
35
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
3
|
import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
4
4
|
import { CancellationError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
|
|
5
|
+
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
5
6
|
import { Disposable, MutableDisposable, 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';
|
|
7
8
|
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
@@ -37,8 +38,10 @@ let McpServerConnection = class McpServerConnection extends Disposable {
|
|
|
37
38
|
state: McpConnectionState.Kind.Stopped
|
|
38
39
|
});
|
|
39
40
|
this._requestHandler = observableValue("mcpServerRequestHandler", undefined);
|
|
41
|
+
this._onPotentialSandboxBlock = this._register(( new Emitter()));
|
|
40
42
|
this.state = this._state;
|
|
41
43
|
this.handler = this._requestHandler;
|
|
44
|
+
this.onPotentialSandboxBlock = this._onPotentialSandboxBlock.event;
|
|
42
45
|
}
|
|
43
46
|
async start(methods) {
|
|
44
47
|
const currentState = this._state.get();
|
|
@@ -49,7 +52,7 @@ let McpServerConnection = class McpServerConnection extends Disposable {
|
|
|
49
52
|
this._state.set({
|
|
50
53
|
state: McpConnectionState.Kind.Starting
|
|
51
54
|
}, undefined);
|
|
52
|
-
this._logger.info(( localize(
|
|
55
|
+
this._logger.info(( localize(10470, "Starting server {0}", this.definition.label)));
|
|
53
56
|
try {
|
|
54
57
|
const launch = this._delegate.start(this._collection, this.definition, this.launchDefinition, {
|
|
55
58
|
errorOnUserInteraction: this._errorOnUserInteraction
|
|
@@ -77,12 +80,16 @@ let McpServerConnection = class McpServerConnection extends Disposable {
|
|
|
77
80
|
}
|
|
78
81
|
) => {
|
|
79
82
|
log(this._logger, level, message);
|
|
83
|
+
const potentialBlock = this._toPotentialSandboxBlock(message);
|
|
84
|
+
if (potentialBlock) {
|
|
85
|
+
this._onPotentialSandboxBlock.fire(potentialBlock);
|
|
86
|
+
}
|
|
80
87
|
}));
|
|
81
88
|
let didStart = false;
|
|
82
89
|
store.add(autorun(reader => {
|
|
83
90
|
const state = launch.state.read(reader);
|
|
84
91
|
this._state.set(state, undefined);
|
|
85
|
-
this._logger.info(( localize(
|
|
92
|
+
this._logger.info(( localize(10471, "Connection state: {0}", (McpConnectionState.toString(state)))));
|
|
86
93
|
if (state.state === McpConnectionState.Kind.Running && !didStart) {
|
|
87
94
|
didStart = true;
|
|
88
95
|
McpServerRequestHandler.create(this._instantiationService, {
|
|
@@ -121,7 +128,7 @@ let McpServerConnection = class McpServerConnection extends Disposable {
|
|
|
121
128
|
};
|
|
122
129
|
}
|
|
123
130
|
async stop() {
|
|
124
|
-
this._logger.info(( localize(
|
|
131
|
+
this._logger.info(( localize(10472, "Stopping server {0}", this.definition.label)));
|
|
125
132
|
this._launch.value?.object.stop();
|
|
126
133
|
await this._waitForState(McpConnectionState.Kind.Stopped, McpConnectionState.Kind.Error);
|
|
127
134
|
}
|
|
@@ -147,6 +154,57 @@ let McpServerConnection = class McpServerConnection extends Disposable {
|
|
|
147
154
|
});
|
|
148
155
|
}));
|
|
149
156
|
}
|
|
157
|
+
_toPotentialSandboxBlock(message) {
|
|
158
|
+
if (!this.definition.sandboxEnabled) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
if (/No matching config rule, denying:/i.test(message)) {
|
|
162
|
+
return {
|
|
163
|
+
kind: "network",
|
|
164
|
+
message,
|
|
165
|
+
host: this._extractSandboxHost(message)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (/\b(?:EAI_AGAIN|ENOTFOUND)\b/i.test(message)) {
|
|
169
|
+
return {
|
|
170
|
+
kind: "network",
|
|
171
|
+
message,
|
|
172
|
+
host: this._extractSandboxHost(message)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (/(?:\b(?:EACCES|EPERM|ENOENT|fail(?:ed|ure)?)\b|not accessible)/i.test(message)) {
|
|
176
|
+
return {
|
|
177
|
+
kind: "filesystem",
|
|
178
|
+
message,
|
|
179
|
+
path: this._extractSandboxPath(message)
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
_extractSandboxPath(line) {
|
|
185
|
+
const bracketedPath = line.match(/\[(\/[^\]\r\n]+)\]/);
|
|
186
|
+
if (bracketedPath?.[1]) {
|
|
187
|
+
return bracketedPath[1].trim();
|
|
188
|
+
}
|
|
189
|
+
const quotedPath = line.match(/["'](\/[^"']+)["']/);
|
|
190
|
+
if (quotedPath?.[1]) {
|
|
191
|
+
return quotedPath[1];
|
|
192
|
+
}
|
|
193
|
+
const trailingPath = line.match(/(\/[\w.\-~/ ]+)$/);
|
|
194
|
+
return trailingPath?.[1]?.trim();
|
|
195
|
+
}
|
|
196
|
+
_extractSandboxHost(value) {
|
|
197
|
+
const deniedMatch = value.match(/No matching config rule, denying:\s+(.+)$/i);
|
|
198
|
+
const matchTarget = deniedMatch?.[1] ?? value;
|
|
199
|
+
const trimmed = matchTarget.trim().replace(/^["'`]+|["'`,.;]+$/g, "");
|
|
200
|
+
if (!trimmed) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const withoutProtocol = trimmed.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "");
|
|
204
|
+
const firstToken = withoutProtocol.split(/[\s/]/, 1)[0] ?? "";
|
|
205
|
+
const host = firstToken.replace(/:\d+$/, "");
|
|
206
|
+
return host || undefined;
|
|
207
|
+
}
|
|
150
208
|
};
|
|
151
209
|
McpServerConnection = ( __decorate([( __param(7, IInstantiationService))], McpServerConnection));
|
|
152
210
|
|
|
@@ -27,8 +27,7 @@ export interface IMcpServerRequestHandlerOptions extends IMcpClientMethods {
|
|
|
27
27
|
* handling of ping requests and typed client request methods.
|
|
28
28
|
*/
|
|
29
29
|
export declare class McpServerRequestHandler extends Disposable {
|
|
30
|
-
private
|
|
31
|
-
private readonly _pendingRequests;
|
|
30
|
+
private readonly _rpc;
|
|
32
31
|
private _hasAnnouncedRoots;
|
|
33
32
|
private _roots;
|
|
34
33
|
set roots(roots: MCP.Root[]);
|
|
@@ -83,18 +82,6 @@ export declare class McpServerRequestHandler extends Disposable {
|
|
|
83
82
|
*/
|
|
84
83
|
private sendRequestPaginated;
|
|
85
84
|
private sendNotification;
|
|
86
|
-
/**
|
|
87
|
-
* Handle incoming messages from the server
|
|
88
|
-
*/
|
|
89
|
-
private handleMessage;
|
|
90
|
-
/**
|
|
91
|
-
* Handle successful responses
|
|
92
|
-
*/
|
|
93
|
-
private handleResult;
|
|
94
|
-
/**
|
|
95
|
-
* Handle error responses
|
|
96
|
-
*/
|
|
97
|
-
private handleError;
|
|
98
85
|
/**
|
|
99
86
|
* Handle incoming server requests
|
|
100
87
|
*/
|
|
@@ -105,10 +92,6 @@ export declare class McpServerRequestHandler extends Disposable {
|
|
|
105
92
|
private handleServerNotification;
|
|
106
93
|
private handleCancelledNotification;
|
|
107
94
|
private handleLoggingNotification;
|
|
108
|
-
/**
|
|
109
|
-
* Send a generic response to a request
|
|
110
|
-
*/
|
|
111
|
-
private respondToRequest;
|
|
112
95
|
/**
|
|
113
96
|
* Send a response to a ping request
|
|
114
97
|
*/
|
|
@@ -166,7 +149,7 @@ export declare class McpServerRequestHandler extends Disposable {
|
|
|
166
149
|
/**
|
|
167
150
|
* Call a specific tool. Supports tasks automatically if `task` is set on the request.
|
|
168
151
|
*/
|
|
169
|
-
callTool(params: MCP.CallToolRequest["params"] & MCP.Request["params"], token?: CancellationToken): Promise<MCP.CallToolResult>;
|
|
152
|
+
callTool(params: MCP.CallToolRequest["params"] & MCP.Request["params"], token?: CancellationToken, onStatusMessage?: (message: string) => void): Promise<MCP.CallToolResult>;
|
|
170
153
|
/**
|
|
171
154
|
* Set the logging level
|
|
172
155
|
*/
|
|
@@ -206,12 +189,13 @@ export declare class McpServerRequestHandler extends Disposable {
|
|
|
206
189
|
*/
|
|
207
190
|
export declare class McpTask<T extends MCP.Result> extends Disposable implements IMcpTaskInternal {
|
|
208
191
|
private readonly _task;
|
|
192
|
+
private readonly _onStatusMessage?;
|
|
209
193
|
private readonly promise;
|
|
210
194
|
get result(): Promise<T>;
|
|
211
195
|
get id(): string;
|
|
212
196
|
private _lastTaskState;
|
|
213
197
|
private _handler;
|
|
214
|
-
constructor(_task: MCP.Task, _token?: CancellationToken);
|
|
198
|
+
constructor(_task: MCP.Task, _token?: CancellationToken, _onStatusMessage?: ((message: string) => void) | undefined);
|
|
215
199
|
onDidUpdateState(task: MCP.Task): void;
|
|
216
200
|
setHandler(handler: McpServerRequestHandler | undefined): void;
|
|
217
201
|
}
|