@codingame/monaco-vscode-mcp-service-override 36.2.7 → 37.1.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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-mcp-service-override",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "37.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "VSCode public API plugged on the monaco editor - mcp service-override",
|
|
6
6
|
"keywords": [],
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"type": "module",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@codingame/monaco-vscode-api": "
|
|
18
|
+
"@codingame/monaco-vscode-api": "37.1.0"
|
|
19
19
|
},
|
|
20
20
|
"main": "index.js",
|
|
21
21
|
"module": "index.js",
|
|
@@ -35,8 +35,8 @@ export interface IJsonRpcProtocolHandlers {
|
|
|
35
35
|
}
|
|
36
36
|
export declare class JsonRpcError extends Error {
|
|
37
37
|
readonly code: number;
|
|
38
|
-
readonly data?: unknown
|
|
39
|
-
constructor(code: number, message: string, data?: unknown
|
|
38
|
+
readonly data?: unknown;
|
|
39
|
+
constructor(code: number, message: string, data?: unknown);
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Generic JSON-RPC 2.0 protocol helper.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single entry in the `chat.mcp.allowedServers` allowlist. Identifies an MCP server by exactly
|
|
3
|
+
* one strategy: its configured name, a remote server URL pattern (supporting `*` wildcards), or a
|
|
4
|
+
* local stdio command invocation (matched as an ordered argument list). Delivered as JSON via user
|
|
5
|
+
* settings or enterprise managed settings and validated at match time, so only the field matching
|
|
6
|
+
* the intended strategy is meaningful.
|
|
7
|
+
*/
|
|
8
|
+
export interface IMcpServerMatcher {
|
|
9
|
+
readonly serverName?: string;
|
|
10
|
+
readonly serverUrl?: string;
|
|
11
|
+
readonly serverCommand?: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Normalized identity of an MCP server used for allowlist matching. Both the install-time and the
|
|
15
|
+
* runtime enforcement paths reduce their server representation to this shape: `url` is set for
|
|
16
|
+
* remote (HTTP/SSE) servers and `command` (the full `[command, ...args]` invocation) for local
|
|
17
|
+
* stdio servers.
|
|
18
|
+
*/
|
|
19
|
+
export interface IMcpServerIdentity {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly url?: string;
|
|
22
|
+
readonly command?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The result of evaluating an MCP server against the allow/deny lists.
|
|
26
|
+
*/
|
|
27
|
+
export declare enum McpServerAllowResult {
|
|
28
|
+
/** Permitted: not denied, and either no allowlist is configured or it matches one. */
|
|
29
|
+
Allowed = 0,
|
|
30
|
+
/** Blocked because it matches a deny entry (deny always wins). */
|
|
31
|
+
Denied = 1,
|
|
32
|
+
/** Blocked because an allowlist is configured and it matches no entry. */
|
|
33
|
+
NotAllowed = 2
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Coerces a resolved `chat.mcp.allowedServers` / `chat.mcp.deniedServers` configuration value into a
|
|
37
|
+
* list of matchers. Returns `undefined` (meaning "not configured") when the value is not an array —
|
|
38
|
+
* which is also how an unset setting surfaces (the registered `null` default). Malformed matcher
|
|
39
|
+
* entries (non-objects, or entries that do not carry exactly one valid matching field) are dropped
|
|
40
|
+
* so a bad payload degrades to "no match" rather than throwing during matching.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMcpServerMatchers(value: unknown): readonly IMcpServerMatcher[] | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the server identity matches at least one of the given matchers. A `undefined` or empty
|
|
45
|
+
* matcher list matches nothing.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isMcpServerMatched(matchers: readonly IMcpServerMatcher[] | undefined, identity: IMcpServerIdentity): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Evaluates an MCP server against the allow and deny lists. Deny always takes precedence; an unset
|
|
50
|
+
* (`undefined`) allowlist imposes no restriction, while a configured allowlist requires a match.
|
|
51
|
+
*/
|
|
52
|
+
export declare function checkMcpServerAllowed(allowlist: readonly IMcpServerMatcher[] | undefined, denylist: readonly IMcpServerMatcher[] | undefined, identity: IMcpServerIdentity): McpServerAllowResult;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
|
|
2
|
+
import { equals } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
|
|
3
|
+
import { escapeRegExpCharacters } from '@codingame/monaco-vscode-api/vscode/vs/base/common/strings';
|
|
4
|
+
import { isObject, isString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
|
|
5
|
+
|
|
6
|
+
var McpServerAllowResult;
|
|
7
|
+
(function(McpServerAllowResult) {
|
|
8
|
+
McpServerAllowResult[McpServerAllowResult["Allowed"] = 0] = "Allowed";
|
|
9
|
+
McpServerAllowResult[McpServerAllowResult["Denied"] = 1] = "Denied";
|
|
10
|
+
McpServerAllowResult[McpServerAllowResult["NotAllowed"] = 2] = "NotAllowed";
|
|
11
|
+
})(McpServerAllowResult || (McpServerAllowResult = {}));
|
|
12
|
+
function getMcpServerMatchers(value) {
|
|
13
|
+
if (!Array.isArray(value)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return value.filter(isValidMatcher);
|
|
17
|
+
}
|
|
18
|
+
function isValidMatcher(entry) {
|
|
19
|
+
if (!isObject(entry)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const {
|
|
23
|
+
serverName,
|
|
24
|
+
serverUrl,
|
|
25
|
+
serverCommand
|
|
26
|
+
} = entry;
|
|
27
|
+
const hasName = isString(serverName) && serverName.length > 0;
|
|
28
|
+
const hasUrl = isString(serverUrl) && serverUrl.length > 0;
|
|
29
|
+
const hasCommand = Array.isArray(serverCommand) && serverCommand.length > 0 && serverCommand.every(isString);
|
|
30
|
+
return (hasName ? 1 : 0) + (hasUrl ? 1 : 0) + (hasCommand ? 1 : 0) === 1;
|
|
31
|
+
}
|
|
32
|
+
function isMcpServerMatched(matchers, identity) {
|
|
33
|
+
return !!matchers && ( matchers.some(matcher => matchesMatcher(matcher, identity)));
|
|
34
|
+
}
|
|
35
|
+
function checkMcpServerAllowed(allowlist, denylist, identity) {
|
|
36
|
+
if (isMcpServerMatched(denylist, identity)) {
|
|
37
|
+
return McpServerAllowResult.Denied;
|
|
38
|
+
}
|
|
39
|
+
if (allowlist !== undefined && !isMcpServerMatched(allowlist, identity)) {
|
|
40
|
+
return McpServerAllowResult.NotAllowed;
|
|
41
|
+
}
|
|
42
|
+
return McpServerAllowResult.Allowed;
|
|
43
|
+
}
|
|
44
|
+
function matchesMatcher(matcher, identity) {
|
|
45
|
+
if (isString(matcher.serverName)) {
|
|
46
|
+
return matcher.serverName === identity.name;
|
|
47
|
+
}
|
|
48
|
+
if (isString(matcher.serverUrl)) {
|
|
49
|
+
return identity.url !== undefined && matchesUrlPattern(matcher.serverUrl, identity.url);
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(matcher.serverCommand)) {
|
|
52
|
+
return identity.command !== undefined && equals(matcher.serverCommand, identity.command);
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
function matchesUrlPattern(pattern, url) {
|
|
57
|
+
const destination = toNetworkDestinationUrl(url);
|
|
58
|
+
if (destination === undefined) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (!pattern.includes("*")) {
|
|
62
|
+
const expected = toNetworkDestinationUrl(pattern);
|
|
63
|
+
return expected !== undefined && expected.toLowerCase() === destination.toLowerCase();
|
|
64
|
+
}
|
|
65
|
+
const normalizedPattern = toNetworkDestinationPattern(pattern);
|
|
66
|
+
if (normalizedPattern === undefined) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return ( new RegExp(buildUrlPatternRegexSource(normalizedPattern), "i")).test(destination);
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function toNetworkDestinationUrl(url) {
|
|
76
|
+
try {
|
|
77
|
+
const parsed = ( new URL(url));
|
|
78
|
+
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
|
|
79
|
+
return parsed.origin + parsed.pathname + parsed.search;
|
|
80
|
+
}
|
|
81
|
+
return url;
|
|
82
|
+
} catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function toNetworkDestinationPattern(pattern) {
|
|
87
|
+
const schemeSeparator = pattern.indexOf("://");
|
|
88
|
+
if (schemeSeparator < 0) {
|
|
89
|
+
return pattern;
|
|
90
|
+
}
|
|
91
|
+
const scheme = pattern.slice(0, schemeSeparator).toLowerCase();
|
|
92
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
93
|
+
return pattern;
|
|
94
|
+
}
|
|
95
|
+
const rest = pattern.slice(schemeSeparator + 3);
|
|
96
|
+
const authorityEnd = findAuthorityEnd(rest, 0);
|
|
97
|
+
let authority = rest.slice(0, authorityEnd);
|
|
98
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
99
|
+
if (userinfoEnd >= 0) {
|
|
100
|
+
authority = authority.slice(userinfoEnd + 1);
|
|
101
|
+
}
|
|
102
|
+
const hostAndPort = splitHostAndPort(authority);
|
|
103
|
+
if (hostAndPort === undefined) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const defaultPort = scheme === "https" ? "443" : "80";
|
|
107
|
+
const port = hostAndPort.port === defaultPort ? undefined : hostAndPort.port;
|
|
108
|
+
let afterAuthority = rest.slice(authorityEnd).replace(/\\/g, "/");
|
|
109
|
+
const hash = afterAuthority.indexOf("#");
|
|
110
|
+
if (hash >= 0) {
|
|
111
|
+
afterAuthority = afterAuthority.slice(0, hash);
|
|
112
|
+
}
|
|
113
|
+
if (!afterAuthority) {
|
|
114
|
+
afterAuthority = "/";
|
|
115
|
+
} else if (afterAuthority.startsWith("?")) {
|
|
116
|
+
afterAuthority = `/${afterAuthority}`;
|
|
117
|
+
}
|
|
118
|
+
return `${scheme}://${hostAndPort.host}${port !== undefined ? `:${port}` : ""}${afterAuthority}`;
|
|
119
|
+
}
|
|
120
|
+
function splitHostAndPort(authority) {
|
|
121
|
+
if (authority.startsWith("[")) {
|
|
122
|
+
const close = authority.indexOf("]");
|
|
123
|
+
if (close === -1) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
if (authority[close + 1] === ":") {
|
|
127
|
+
return {
|
|
128
|
+
host: authority.slice(0, close + 1),
|
|
129
|
+
port: authority.slice(close + 2)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (close + 1 < authority.length) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
host: authority,
|
|
137
|
+
port: undefined
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const colon = authority.lastIndexOf(":");
|
|
141
|
+
if (colon >= 0) {
|
|
142
|
+
return {
|
|
143
|
+
host: authority.slice(0, colon),
|
|
144
|
+
port: authority.slice(colon + 1)
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return authority ? {
|
|
148
|
+
host: authority,
|
|
149
|
+
port: undefined
|
|
150
|
+
} : undefined;
|
|
151
|
+
}
|
|
152
|
+
function buildUrlPatternRegexSource(pattern) {
|
|
153
|
+
const schemeSeparator = pattern.indexOf("://");
|
|
154
|
+
const authorityStart = schemeSeparator >= 0 ? schemeSeparator + 3 : 0;
|
|
155
|
+
const authorityEnd = findAuthorityEnd(pattern, authorityStart);
|
|
156
|
+
let source = "^";
|
|
157
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
158
|
+
const char = pattern[i];
|
|
159
|
+
if (i < authorityEnd && char === ":" && pattern[i + 1] === "*") {
|
|
160
|
+
source += "(:[^/@\\\\?#]*)?";
|
|
161
|
+
i++;
|
|
162
|
+
} else if (char === "*") {
|
|
163
|
+
source += i < authorityEnd ? "[^/@\\\\?#]*" : ".*";
|
|
164
|
+
} else {
|
|
165
|
+
source += escapeRegExpCharacters(char);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return source + "$";
|
|
169
|
+
}
|
|
170
|
+
function findAuthorityEnd(pattern, authorityStart) {
|
|
171
|
+
for (let i = authorityStart; i < pattern.length; i++) {
|
|
172
|
+
const char = pattern[i];
|
|
173
|
+
if (char === "/" || char === "\\" || char === "?" || char === "#") {
|
|
174
|
+
return i;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return pattern.length;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { McpServerAllowResult, checkMcpServerAllowed, getMcpServerMatchers, isMcpServerMatched };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
2
2
|
import { IMarkdownString } from "@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent";
|
|
3
3
|
import { IConfigurationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service";
|
|
4
|
+
import { IMcpServerIdentity } from "./allowedMcpServers.js";
|
|
4
5
|
import { IGalleryMcpServer, IInstallableMcpServer, ILocalMcpServer } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement";
|
|
5
6
|
import { IAllowedMcpServersService } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement.service";
|
|
6
7
|
export declare class AllowedMcpServersService extends Disposable implements IAllowedMcpServersService {
|
|
@@ -10,4 +11,7 @@ export declare class AllowedMcpServersService extends Disposable implements IAll
|
|
|
10
11
|
readonly onDidChangeAllowedMcpServers: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<void>;
|
|
11
12
|
constructor(configurationService: IConfigurationService);
|
|
12
13
|
isAllowed(mcpServer: IGalleryMcpServer | ILocalMcpServer | IInstallableMcpServer): true | IMarkdownString;
|
|
14
|
+
isServerAllowed(identity: IMcpServerIdentity): true | IMarkdownString;
|
|
15
|
+
private getAllConfiguredMatchers;
|
|
16
|
+
private toIdentity;
|
|
13
17
|
}
|
|
@@ -5,7 +5,11 @@ import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
|
5
5
|
import { createCommandUri, MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent';
|
|
6
6
|
import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
|
|
7
7
|
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
8
|
-
import {
|
|
8
|
+
import { hasKey } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
|
|
9
|
+
import { getMcpServerMatchers, checkMcpServerAllowed, McpServerAllowResult } from './allowedMcpServers.js';
|
|
10
|
+
import { mcpAccessConfig, mcpAllowedServersConfig, mcpDeniedServersConfig, McpAccessValue } from '@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement';
|
|
11
|
+
import { McpServerType } from '@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpPlatformTypes';
|
|
12
|
+
import { COPILOT_ALLOW_MANAGED_MCP_SERVERS_ONLY_CONFIG } from '@codingame/monaco-vscode-api/vscode/vs/platform/policy/common/copilotManagedSettings';
|
|
9
13
|
|
|
10
14
|
let AllowedMcpServersService = class AllowedMcpServersService extends Disposable {
|
|
11
15
|
constructor(configurationService) {
|
|
@@ -14,23 +18,75 @@ let AllowedMcpServersService = class AllowedMcpServersService extends Disposable
|
|
|
14
18
|
this._onDidChangeAllowedMcpServers = this._register(( new Emitter()));
|
|
15
19
|
this.onDidChangeAllowedMcpServers = this._onDidChangeAllowedMcpServers.event;
|
|
16
20
|
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
|
17
|
-
if (e.affectsConfiguration(mcpAccessConfig)) {
|
|
21
|
+
if (e.affectsConfiguration(mcpAccessConfig) || e.affectsConfiguration(mcpAllowedServersConfig) || e.affectsConfiguration(mcpDeniedServersConfig) || e.affectsConfiguration(COPILOT_ALLOW_MANAGED_MCP_SERVERS_ONLY_CONFIG)) {
|
|
18
22
|
this._onDidChangeAllowedMcpServers.fire();
|
|
19
23
|
}
|
|
20
24
|
}));
|
|
21
25
|
}
|
|
22
26
|
isAllowed(mcpServer) {
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
return this.isServerAllowed(this.toIdentity(mcpServer));
|
|
28
|
+
}
|
|
29
|
+
isServerAllowed(identity) {
|
|
30
|
+
if (this.configurationService.getValue(mcpAccessConfig) === McpAccessValue.None) {
|
|
31
|
+
const settingsCommandLink = ( createCommandUri("workbench.action.openSettings", {
|
|
32
|
+
query: `@id:${mcpAccessConfig}`
|
|
33
|
+
}).toString());
|
|
34
|
+
return (new MarkdownString(localize(
|
|
35
|
+
2398,
|
|
36
|
+
"Model Context Protocol servers are disabled in the Editor. Please check your [settings]({0}).",
|
|
37
|
+
settingsCommandLink
|
|
38
|
+
)));
|
|
39
|
+
}
|
|
40
|
+
const managedOnly = this.configurationService.getValue(COPILOT_ALLOW_MANAGED_MCP_SERVERS_ONLY_CONFIG) === true;
|
|
41
|
+
const allowlist = managedOnly ? getMcpServerMatchers(this.configurationService.inspect(mcpAllowedServersConfig).policyValue) ?? [] : getMcpServerMatchers(this.configurationService.getValue(mcpAllowedServersConfig));
|
|
42
|
+
const denylist = managedOnly ? this.getAllConfiguredMatchers(mcpDeniedServersConfig) : getMcpServerMatchers(this.configurationService.getValue(mcpDeniedServersConfig));
|
|
43
|
+
switch (checkMcpServerAllowed(allowlist, denylist, identity)) {
|
|
44
|
+
case McpServerAllowResult.Denied:
|
|
45
|
+
return (new MarkdownString(localize(
|
|
46
|
+
2399,
|
|
47
|
+
"This Model Context Protocol server is blocked by your organization's policy. Please contact your administrator for more information."
|
|
48
|
+
)));
|
|
49
|
+
case McpServerAllowResult.NotAllowed:
|
|
50
|
+
return (new MarkdownString(localize(
|
|
51
|
+
2400,
|
|
52
|
+
"This Model Context Protocol server is not in the list of servers allowed by your organization. Please contact your administrator for more information."
|
|
53
|
+
)));
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
getAllConfiguredMatchers(key) {
|
|
58
|
+
const inspected = this.configurationService.inspect(key);
|
|
59
|
+
return [
|
|
60
|
+
inspected.applicationValue,
|
|
61
|
+
inspected.userValue,
|
|
62
|
+
inspected.userLocalValue,
|
|
63
|
+
inspected.userRemoteValue,
|
|
64
|
+
inspected.workspaceValue,
|
|
65
|
+
inspected.workspaceFolderValue,
|
|
66
|
+
inspected.memoryValue,
|
|
67
|
+
inspected.policyValue
|
|
68
|
+
].flatMap(value => getMcpServerMatchers(value) ?? []);
|
|
69
|
+
}
|
|
70
|
+
toIdentity(mcpServer) {
|
|
71
|
+
if (hasKey(mcpServer, {
|
|
72
|
+
config: true
|
|
73
|
+
})) {
|
|
74
|
+
const config = mcpServer.config;
|
|
75
|
+
if (config.type === McpServerType.REMOTE) {
|
|
76
|
+
return {
|
|
77
|
+
name: mcpServer.name,
|
|
78
|
+
url: config.url
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
name: mcpServer.name,
|
|
83
|
+
command: [config.command, ...(config.args ?? [])]
|
|
84
|
+
};
|
|
25
85
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
2180,
|
|
31
|
-
"Model Context Protocol servers are disabled in the Editor. Please check your [settings]({0}).",
|
|
32
|
-
settingsCommandLink
|
|
33
|
-
)));
|
|
86
|
+
return {
|
|
87
|
+
name: mcpServer.name,
|
|
88
|
+
url: mcpServer.configuration.remotes?.[0]?.url
|
|
89
|
+
};
|
|
34
90
|
}
|
|
35
91
|
};
|
|
36
92
|
AllowedMcpServersService = ( __decorate([( __param(0, IConfigurationService))], AllowedMcpServersService));
|
|
@@ -3,7 +3,7 @@ import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/l
|
|
|
3
3
|
import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
|
|
4
4
|
import { ILogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service";
|
|
5
5
|
import { IRequestService } from "@codingame/monaco-vscode-api/vscode/vs/platform/request/common/request.service";
|
|
6
|
-
import { IGalleryMcpServer, IQueryOptions } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement";
|
|
6
|
+
import { IGalleryMcpServer, IMcpGalleryServerResolveResult, IQueryOptions } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement";
|
|
7
7
|
import { IMcpGalleryService } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement.service";
|
|
8
8
|
import { IMcpGalleryManifest } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpGalleryManifest";
|
|
9
9
|
import { IMcpGalleryManifestService } from "@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpGalleryManifest.service";
|
|
@@ -22,6 +22,10 @@ export declare class McpGalleryService extends Disposable implements IMcpGallery
|
|
|
22
22
|
name: string;
|
|
23
23
|
id?: string;
|
|
24
24
|
}[]): Promise<IGalleryMcpServer[]>;
|
|
25
|
+
resolveMcpServersFromGallery(infos: {
|
|
26
|
+
name: string;
|
|
27
|
+
id?: string;
|
|
28
|
+
}[]): Promise<Map<string, IMcpGalleryServerResolveResult>>;
|
|
25
29
|
private getMcpServerByName;
|
|
26
30
|
getReadme(gallery: IGalleryMcpServer, token: CancellationToken): Promise<string>;
|
|
27
31
|
private toGalleryMcpServer;
|