@codingame/monaco-vscode-mcp-service-override 18.4.0 → 19.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 +10 -5
- package/package.json +14 -14
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +2 -1
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +34 -11
- package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.d.ts +39 -0
- package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.js +59 -0
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +89 -15
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +393 -182
- package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.d.ts +16 -29
- package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.js +6 -1
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.d.ts +33 -0
- package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +191 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +25 -45
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.d.ts +109 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +826 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommandsAddConfiguration.d.ts +41 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommandsAddConfiguration.js +420 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.d.ts +23 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +305 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.d.ts +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +30 -32
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.d.ts +28 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.js +161 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.d.ts +60 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.js +423 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +60 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +299 -45
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +12 -4
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +237 -37
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +4 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +29 -18
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.d.ts +26 -1
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +182 -28
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +59 -9
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +316 -31
- package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServerEditor.css +73 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServersView.css +35 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.d.ts +4 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.js +18 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.d.ts +17 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +151 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.d.ts +15 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +60 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +8 -8
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.js +12 -12
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +18 -15
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +9 -5
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +77 -34
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +3 -3
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +3 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +6 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +14 -13
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.js +27 -1
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +9 -9
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.d.ts +72 -0
- package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.js +475 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.d.ts +0 -19
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.js +0 -167
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.d.ts +0 -33
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.js +0 -112
|
@@ -1,259 +1,308 @@
|
|
|
1
1
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { RunOnceScheduler } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
3
4
|
import { VSBuffer } from '@codingame/monaco-vscode-api/vscode/vs/base/common/buffer';
|
|
4
5
|
import { CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
5
6
|
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
6
|
-
import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { Disposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
8
|
+
import { ResourceMap } from '@codingame/monaco-vscode-api/vscode/vs/base/common/map';
|
|
9
|
+
import { equals } from '@codingame/monaco-vscode-api/vscode/vs/base/common/objects';
|
|
9
10
|
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
|
|
10
11
|
import { ConfigurationTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration';
|
|
11
|
-
import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
|
|
12
12
|
import { IEnvironmentService } from '@codingame/monaco-vscode-api/vscode/vs/platform/environment/common/environment.service';
|
|
13
13
|
import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
|
|
14
|
+
import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
|
14
15
|
import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
|
|
15
16
|
import { IUriIdentityService } from '@codingame/monaco-vscode-api/vscode/vs/platform/uriIdentity/common/uriIdentity.service';
|
|
16
|
-
import {
|
|
17
|
+
import { IUserDataProfilesService } from '@codingame/monaco-vscode-api/vscode/vs/platform/userDataProfile/common/userDataProfile.service';
|
|
18
|
+
import { PackageType } from '@codingame/monaco-vscode-dc3fa21d-a483-5b99-a7ab-173235644a34-common/vscode/vs/platform/mcp/common/mcpManagement';
|
|
17
19
|
import { IMcpGalleryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpManagement.service';
|
|
18
|
-
import { McpServerVariableType } from './mcpPlatformTypes.js';
|
|
20
|
+
import { McpServerType, McpServerVariableType } from './mcpPlatformTypes.js';
|
|
21
|
+
import { IMcpResourceScannerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/mcp/common/mcpResourceScannerService.service';
|
|
19
22
|
|
|
20
|
-
let
|
|
23
|
+
let AbstractMcpResourceManagementService = class AbstractMcpResourceManagementService extends Disposable {
|
|
21
24
|
get onDidInstallMcpServers() { return this._onDidInstallMcpServers.event; }
|
|
25
|
+
get onDidUpdateMcpServers() { return this._onDidUpdateMcpServers.event; }
|
|
22
26
|
get onUninstallMcpServer() { return this._onUninstallMcpServer.event; }
|
|
23
27
|
get onDidUninstallMcpServer() { return this._onDidUninstallMcpServer.event; }
|
|
24
|
-
constructor(
|
|
28
|
+
constructor(mcpResource, target, mcpGalleryService, fileService, uriIdentityService, logService, mcpResourceScannerService) {
|
|
25
29
|
super();
|
|
26
|
-
this.
|
|
30
|
+
this.mcpResource = mcpResource;
|
|
31
|
+
this.target = target;
|
|
27
32
|
this.mcpGalleryService = mcpGalleryService;
|
|
28
33
|
this.fileService = fileService;
|
|
29
34
|
this.uriIdentityService = uriIdentityService;
|
|
30
35
|
this.logService = logService;
|
|
36
|
+
this.mcpResourceScannerService = mcpResourceScannerService;
|
|
37
|
+
this.local = ( new Map());
|
|
31
38
|
this._onInstallMcpServer = this._register(( new Emitter()));
|
|
32
39
|
this.onInstallMcpServer = this._onInstallMcpServer.event;
|
|
33
40
|
this._onDidInstallMcpServers = this._register(( new Emitter()));
|
|
41
|
+
this._onDidUpdateMcpServers = this._register(( new Emitter()));
|
|
34
42
|
this._onUninstallMcpServer = this._register(( new Emitter()));
|
|
35
43
|
this._onDidUninstallMcpServer = this._register(( new Emitter()));
|
|
36
|
-
this.
|
|
44
|
+
this.reloadConfigurationScheduler = this._register(( new RunOnceScheduler(() => this.updateLocal(), 50)));
|
|
37
45
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
initialize() {
|
|
47
|
+
if (!this.initializePromise) {
|
|
48
|
+
this.initializePromise = (async () => {
|
|
49
|
+
this.local = await this.populateLocalServers();
|
|
50
|
+
this.startWatching();
|
|
51
|
+
})();
|
|
42
52
|
}
|
|
43
|
-
return
|
|
53
|
+
return this.initializePromise;
|
|
44
54
|
}
|
|
45
|
-
async
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
async populateLocalServers() {
|
|
56
|
+
this.logService.trace('AbstractMcpResourceManagementService#populateLocalServers', ( this.mcpResource.toString()));
|
|
57
|
+
const local = ( new Map());
|
|
58
|
+
try {
|
|
59
|
+
const scannedMcpServers = await this.mcpResourceScannerService.scanMcpServers(this.mcpResource, this.target);
|
|
60
|
+
if (scannedMcpServers.servers) {
|
|
61
|
+
await Promise.allSettled(( Object.entries(scannedMcpServers.servers).map(async ([name, scannedServer]) => {
|
|
62
|
+
const server = await this.scanLocalServer(name, scannedServer);
|
|
63
|
+
local.set(name, server);
|
|
64
|
+
})));
|
|
53
65
|
}
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
this.logService.debug('Could not read user MCP servers:', error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return local;
|
|
72
|
+
}
|
|
73
|
+
startWatching() {
|
|
74
|
+
this._register(this.fileService.watch(this.mcpResource));
|
|
75
|
+
this._register(this.fileService.onDidFilesChange(e => {
|
|
76
|
+
if (e.affects(this.mcpResource)) {
|
|
77
|
+
this.reloadConfigurationScheduler.schedule();
|
|
56
78
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
async updateLocal() {
|
|
82
|
+
try {
|
|
83
|
+
const current = await this.populateLocalServers();
|
|
84
|
+
const added = [];
|
|
85
|
+
const updated = [];
|
|
86
|
+
const removed = [...( this.local.keys())].filter(name => !( current.has(name)));
|
|
87
|
+
for (const server of removed) {
|
|
88
|
+
this.local.delete(server);
|
|
60
89
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
for (const [name, server] of current) {
|
|
91
|
+
const previous = this.local.get(name);
|
|
92
|
+
if (previous) {
|
|
93
|
+
if (!equals(previous, server)) {
|
|
94
|
+
updated.push(server);
|
|
95
|
+
this.local.set(name, server);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
added.push(server);
|
|
100
|
+
this.local.set(name, server);
|
|
69
101
|
}
|
|
70
102
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
103
|
+
for (const server of removed) {
|
|
104
|
+
this.local.delete(server);
|
|
105
|
+
this._onDidUninstallMcpServer.fire({ name: server, mcpResource: this.mcpResource });
|
|
106
|
+
}
|
|
107
|
+
if (updated.length) {
|
|
108
|
+
this._onDidUpdateMcpServers.fire(( updated.map(
|
|
109
|
+
server => ({ name: server.name, local: server, mcpResource: this.mcpResource })
|
|
110
|
+
)));
|
|
111
|
+
}
|
|
112
|
+
if (added.length) {
|
|
113
|
+
this._onDidInstallMcpServers.fire(( added.map(
|
|
114
|
+
server => ({ name: server.name, local: server, mcpResource: this.mcpResource })
|
|
115
|
+
)));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
this.logService.error('Failed to load installed MCP servers:', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async getInstalled() {
|
|
123
|
+
await this.initialize();
|
|
124
|
+
return Array.from(( this.local.values()));
|
|
125
|
+
}
|
|
126
|
+
async scanLocalServer(name, config) {
|
|
127
|
+
let mcpServerInfo = await this.getLocalServerInfo(name, config);
|
|
128
|
+
if (!mcpServerInfo) {
|
|
129
|
+
mcpServerInfo = { name, version: config.version };
|
|
77
130
|
}
|
|
78
131
|
return {
|
|
79
132
|
name,
|
|
80
133
|
config,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
134
|
+
mcpResource: this.mcpResource,
|
|
135
|
+
version: mcpServerInfo.version,
|
|
136
|
+
location: mcpServerInfo.location,
|
|
137
|
+
id: mcpServerInfo.id,
|
|
138
|
+
displayName: mcpServerInfo.displayName,
|
|
139
|
+
description: mcpServerInfo.description,
|
|
140
|
+
publisher: mcpServerInfo.publisher,
|
|
141
|
+
publisherDisplayName: mcpServerInfo.publisherDisplayName,
|
|
142
|
+
repositoryUrl: mcpServerInfo.repositoryUrl,
|
|
143
|
+
readmeUrl: mcpServerInfo.readmeUrl,
|
|
144
|
+
icon: mcpServerInfo.icon,
|
|
145
|
+
codicon: mcpServerInfo.codicon,
|
|
146
|
+
manifest: mcpServerInfo.manifest,
|
|
147
|
+
source: config.gallery ? 'gallery' : 'local'
|
|
92
148
|
};
|
|
93
149
|
}
|
|
94
|
-
async
|
|
95
|
-
this.logService.trace('MCP Management Service:
|
|
96
|
-
this._onInstallMcpServer.fire({ name: server.name });
|
|
150
|
+
async install(server, options) {
|
|
151
|
+
this.logService.trace('MCP Management Service: install', server.name);
|
|
152
|
+
this._onInstallMcpServer.fire({ name: server.name, mcpResource: this.mcpResource });
|
|
97
153
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
name: server.name,
|
|
104
|
-
displayName: server.displayName,
|
|
105
|
-
description: server.description,
|
|
106
|
-
version: server.version,
|
|
107
|
-
publisher: server.publisher,
|
|
108
|
-
publisherDisplayName: server.publisherDisplayName,
|
|
109
|
-
repository: server.repositoryUrl,
|
|
110
|
-
licenseUrl: server.licenseUrl,
|
|
111
|
-
...manifest,
|
|
112
|
-
})));
|
|
113
|
-
if (server.readmeUrl) {
|
|
114
|
-
const readme = await this.mcpGalleryService.getReadme(server, CancellationToken.None);
|
|
115
|
-
await this.fileService.writeFile(this.uriIdentityService.extUri.joinPath(location, 'README.md'), VSBuffer.fromString(readme));
|
|
116
|
-
}
|
|
117
|
-
const { userLocal } = this.configurationService.inspect('mcp');
|
|
118
|
-
const value = deepClone(userLocal?.value ?? { servers: {} });
|
|
119
|
-
if (!value.servers) {
|
|
120
|
-
value.servers = {};
|
|
154
|
+
await this.mcpResourceScannerService.addMcpServers([server], this.mcpResource, this.target);
|
|
155
|
+
await this.updateLocal();
|
|
156
|
+
const local = this.local.get(server.name);
|
|
157
|
+
if (!local) {
|
|
158
|
+
throw ( new Error(`Failed to install MCP server: ${server.name}`));
|
|
121
159
|
}
|
|
122
|
-
|
|
123
|
-
value.servers[server.name] = {
|
|
124
|
-
...serverConfig,
|
|
125
|
-
location: location.toJSON(),
|
|
126
|
-
};
|
|
127
|
-
if (serverConfig.inputs) {
|
|
128
|
-
value.inputs = value.inputs ?? [];
|
|
129
|
-
for (const input of serverConfig.inputs) {
|
|
130
|
-
if (!( value.inputs.some(i => i.id === input.id))) {
|
|
131
|
-
value.inputs.push({ ...input, serverName: server.name });
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
await this.configurationService.updateValue('mcp', value, ConfigurationTarget.USER_LOCAL);
|
|
136
|
-
const local = await this.scanServer(server.name, value.servers[server.name]);
|
|
137
|
-
this._onDidInstallMcpServers.fire([{ name: server.name, source: server, local }]);
|
|
160
|
+
return local;
|
|
138
161
|
}
|
|
139
162
|
catch (e) {
|
|
140
|
-
this._onDidInstallMcpServers.fire([{ name: server.name,
|
|
163
|
+
this._onDidInstallMcpServers.fire([{ name: server.name, error: e, mcpResource: this.mcpResource }]);
|
|
141
164
|
throw e;
|
|
142
165
|
}
|
|
143
166
|
}
|
|
144
|
-
async uninstall(server) {
|
|
167
|
+
async uninstall(server, options) {
|
|
145
168
|
this.logService.trace('MCP Management Service: uninstall', server.name);
|
|
146
|
-
this._onUninstallMcpServer.fire({ name: server.name });
|
|
169
|
+
this._onUninstallMcpServer.fire({ name: server.name, mcpResource: this.mcpResource });
|
|
147
170
|
try {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
value.servers = {};
|
|
171
|
+
const currentServers = await this.mcpResourceScannerService.scanMcpServers(this.mcpResource, this.target);
|
|
172
|
+
if (!currentServers.servers) {
|
|
173
|
+
return;
|
|
152
174
|
}
|
|
153
|
-
|
|
154
|
-
if (value.inputs) {
|
|
155
|
-
const index = value.inputs.findIndex(i => i.serverName === server.name);
|
|
156
|
-
if (index !== undefined && index >= 0) {
|
|
157
|
-
value.inputs?.splice(index, 1);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
await this.configurationService.updateValue('mcp', value, ConfigurationTarget.USER_LOCAL);
|
|
175
|
+
await this.mcpResourceScannerService.removeMcpServers([server.name], this.mcpResource, this.target);
|
|
161
176
|
if (server.location) {
|
|
162
177
|
await this.fileService.del(URI.revive(server.location), { recursive: true });
|
|
163
178
|
}
|
|
164
|
-
this.
|
|
179
|
+
await this.updateLocal();
|
|
165
180
|
}
|
|
166
181
|
catch (e) {
|
|
167
|
-
this._onDidUninstallMcpServer.fire({ name: server.name, error: e });
|
|
182
|
+
this._onDidUninstallMcpServer.fire({ name: server.name, error: e, mcpResource: this.mcpResource });
|
|
168
183
|
throw e;
|
|
169
184
|
}
|
|
170
185
|
}
|
|
171
|
-
|
|
186
|
+
toScannedMcpServerAndInputs(manifest, packageType) {
|
|
172
187
|
if (packageType === undefined) {
|
|
173
188
|
packageType = manifest.packages?.[0]?.registry_name ?? PackageType.REMOTE;
|
|
174
189
|
}
|
|
175
|
-
|
|
176
|
-
|
|
190
|
+
let config;
|
|
191
|
+
const inputs = [];
|
|
192
|
+
if (packageType === PackageType.REMOTE && manifest.remotes?.length) {
|
|
177
193
|
const headers = {};
|
|
178
194
|
for (const input of manifest.remotes[0].headers ?? []) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
195
|
+
const variables = input.variables ? this.getVariables(input.variables) : [];
|
|
196
|
+
let value = input.value;
|
|
197
|
+
for (const variable of variables) {
|
|
198
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
199
|
+
}
|
|
200
|
+
headers[input.name] = value;
|
|
201
|
+
if (variables.length) {
|
|
202
|
+
inputs.push(...variables);
|
|
182
203
|
}
|
|
183
204
|
}
|
|
184
|
-
|
|
185
|
-
type:
|
|
205
|
+
config = {
|
|
206
|
+
type: McpServerType.REMOTE,
|
|
186
207
|
url: manifest.remotes[0].url,
|
|
187
208
|
headers: ( Object.keys(headers)).length ? headers : undefined,
|
|
188
|
-
inputs: inputs.length ? inputs : undefined,
|
|
189
209
|
};
|
|
190
210
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (serverPackage.registry_name === PackageType.DOCKER) {
|
|
196
|
-
args.push('run');
|
|
197
|
-
args.push('-i');
|
|
198
|
-
args.push('--rm');
|
|
199
|
-
}
|
|
200
|
-
for (const arg of serverPackage.runtime_arguments ?? []) {
|
|
201
|
-
if (arg.type === 'positional') {
|
|
202
|
-
args.push(arg.value ?? arg.value_hint);
|
|
211
|
+
else {
|
|
212
|
+
const serverPackage = manifest.packages?.find(p => p.registry_name === packageType) ?? manifest.packages?.[0];
|
|
213
|
+
if (!serverPackage) {
|
|
214
|
+
throw ( new Error(`No server package found`));
|
|
203
215
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
216
|
+
const args = [];
|
|
217
|
+
const env = {};
|
|
218
|
+
if (serverPackage.registry_name === PackageType.DOCKER) {
|
|
219
|
+
args.push('run');
|
|
220
|
+
args.push('-i');
|
|
221
|
+
args.push('--rm');
|
|
209
222
|
}
|
|
210
|
-
|
|
211
|
-
|
|
223
|
+
for (const arg of serverPackage.runtime_arguments ?? []) {
|
|
224
|
+
const variables = arg.variables ? this.getVariables(arg.variables) : [];
|
|
225
|
+
if (arg.type === 'positional') {
|
|
226
|
+
let value = arg.value;
|
|
227
|
+
if (value) {
|
|
228
|
+
for (const variable of variables) {
|
|
229
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
args.push(value ?? arg.value_hint);
|
|
233
|
+
}
|
|
234
|
+
else if (arg.type === 'named') {
|
|
235
|
+
args.push(arg.name);
|
|
236
|
+
if (arg.value) {
|
|
237
|
+
let value = arg.value;
|
|
238
|
+
for (const variable of variables) {
|
|
239
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
240
|
+
}
|
|
241
|
+
args.push(value);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (variables.length) {
|
|
245
|
+
inputs.push(...variables);
|
|
246
|
+
}
|
|
212
247
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
248
|
+
for (const input of serverPackage.environment_variables ?? []) {
|
|
249
|
+
const variables = input.variables ? this.getVariables(input.variables) : [];
|
|
250
|
+
let value = input.value;
|
|
251
|
+
for (const variable of variables) {
|
|
252
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
253
|
+
}
|
|
254
|
+
env[input.name] = value;
|
|
255
|
+
if (variables.length) {
|
|
256
|
+
inputs.push(...variables);
|
|
257
|
+
}
|
|
258
|
+
if (serverPackage.registry_name === PackageType.DOCKER) {
|
|
259
|
+
args.push('-e');
|
|
260
|
+
args.push(input.name);
|
|
261
|
+
}
|
|
219
262
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
inputs.push(...variables);
|
|
263
|
+
if (serverPackage.registry_name === PackageType.NODE) {
|
|
264
|
+
args.push(serverPackage.version ? `${serverPackage.name}@${serverPackage.version}` : serverPackage.name);
|
|
223
265
|
}
|
|
224
|
-
if (serverPackage.registry_name === PackageType.
|
|
225
|
-
args.push(
|
|
226
|
-
args.push(input.name);
|
|
266
|
+
else if (serverPackage.registry_name === PackageType.PYTHON) {
|
|
267
|
+
args.push(serverPackage.version ? `${serverPackage.name}==${serverPackage.version}` : serverPackage.name);
|
|
227
268
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
args.push(`${serverPackage.name}@${serverPackage.version}`);
|
|
231
|
-
}
|
|
232
|
-
else if (serverPackage.registry_name === PackageType.PYTHON) {
|
|
233
|
-
args.push(`${serverPackage.name}==${serverPackage.version}`);
|
|
234
|
-
}
|
|
235
|
-
else if (serverPackage.registry_name === PackageType.DOCKER) {
|
|
236
|
-
args.push(`${serverPackage.name}:${serverPackage.version}`);
|
|
237
|
-
}
|
|
238
|
-
for (const arg of serverPackage.package_arguments ?? []) {
|
|
239
|
-
if (arg.type === 'positional') {
|
|
240
|
-
args.push(arg.value ?? arg.value_hint);
|
|
269
|
+
else if (serverPackage.registry_name === PackageType.DOCKER) {
|
|
270
|
+
args.push(serverPackage.version ? `${serverPackage.name}:${serverPackage.version}` : serverPackage.name);
|
|
241
271
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (arg.
|
|
245
|
-
|
|
272
|
+
for (const arg of serverPackage.package_arguments ?? []) {
|
|
273
|
+
const variables = arg.variables ? this.getVariables(arg.variables) : [];
|
|
274
|
+
if (arg.type === 'positional') {
|
|
275
|
+
let value = arg.value;
|
|
276
|
+
if (value) {
|
|
277
|
+
for (const variable of variables) {
|
|
278
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
args.push(value ?? arg.value_hint);
|
|
282
|
+
}
|
|
283
|
+
else if (arg.type === 'named') {
|
|
284
|
+
args.push(arg.name);
|
|
285
|
+
if (arg.value) {
|
|
286
|
+
let value = arg.value;
|
|
287
|
+
for (const variable of variables) {
|
|
288
|
+
value = value.replace(`{${variable.id}}`, `{input:${variable.id}}`);
|
|
289
|
+
}
|
|
290
|
+
args.push(value);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (variables.length) {
|
|
294
|
+
inputs.push(...variables);
|
|
246
295
|
}
|
|
247
296
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
297
|
+
config = {
|
|
298
|
+
type: McpServerType.LOCAL,
|
|
299
|
+
command: this.getCommandName(serverPackage.registry_name),
|
|
300
|
+
args: args.length ? args : undefined,
|
|
301
|
+
env: ( Object.keys(env)).length ? env : undefined,
|
|
302
|
+
};
|
|
251
303
|
}
|
|
252
304
|
return {
|
|
253
|
-
|
|
254
|
-
command: this.getCommandName(serverPackage.registry_name),
|
|
255
|
-
args: args.length ? args : undefined,
|
|
256
|
-
env: ( Object.keys(env)).length ? env : undefined,
|
|
305
|
+
config,
|
|
257
306
|
inputs: inputs.length ? inputs : undefined,
|
|
258
307
|
};
|
|
259
308
|
}
|
|
@@ -280,13 +329,175 @@ let McpManagementService = class McpManagementService extends Disposable {
|
|
|
280
329
|
return variables;
|
|
281
330
|
}
|
|
282
331
|
};
|
|
283
|
-
|
|
284
|
-
( __param(
|
|
332
|
+
AbstractMcpResourceManagementService = ( __decorate([
|
|
333
|
+
( __param(2, IMcpGalleryService)),
|
|
334
|
+
( __param(3, IFileService)),
|
|
335
|
+
( __param(4, IUriIdentityService)),
|
|
336
|
+
( __param(5, ILogService)),
|
|
337
|
+
( __param(6, IMcpResourceScannerService))
|
|
338
|
+
], AbstractMcpResourceManagementService));
|
|
339
|
+
let McpUserResourceManagementService = class McpUserResourceManagementService extends AbstractMcpResourceManagementService {
|
|
340
|
+
constructor(mcpResource, mcpGalleryService, fileService, uriIdentityService, logService, mcpResourceScannerService, environmentService) {
|
|
341
|
+
super(mcpResource, ConfigurationTarget.USER, mcpGalleryService, fileService, uriIdentityService, logService, mcpResourceScannerService);
|
|
342
|
+
this.mcpLocation = uriIdentityService.extUri.joinPath(environmentService.userRoamingDataHome, 'mcp');
|
|
343
|
+
}
|
|
344
|
+
async installFromGallery(server, options) {
|
|
345
|
+
this.logService.trace('MCP Management Service: installGallery', server.url);
|
|
346
|
+
this._onInstallMcpServer.fire({ name: server.name, mcpResource: this.mcpResource });
|
|
347
|
+
try {
|
|
348
|
+
const manifest = await this.updateMetadataFromGallery(server);
|
|
349
|
+
const { config, inputs } = this.toScannedMcpServerAndInputs(manifest, options?.packageType);
|
|
350
|
+
const installable = {
|
|
351
|
+
name: server.name,
|
|
352
|
+
config: {
|
|
353
|
+
...config,
|
|
354
|
+
gallery: true,
|
|
355
|
+
version: server.version
|
|
356
|
+
},
|
|
357
|
+
inputs
|
|
358
|
+
};
|
|
359
|
+
await this.mcpResourceScannerService.addMcpServers([installable], this.mcpResource, this.target);
|
|
360
|
+
await this.updateLocal();
|
|
361
|
+
const local = (await this.getInstalled()).find(s => s.name === server.name);
|
|
362
|
+
if (!local) {
|
|
363
|
+
throw ( new Error(`Failed to install MCP server: ${server.name}`));
|
|
364
|
+
}
|
|
365
|
+
return local;
|
|
366
|
+
}
|
|
367
|
+
catch (e) {
|
|
368
|
+
this._onDidInstallMcpServers.fire([{ name: server.name, source: server, error: e, mcpResource: this.mcpResource }]);
|
|
369
|
+
throw e;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async updateMetadata(local, gallery) {
|
|
373
|
+
await this.updateMetadataFromGallery(gallery);
|
|
374
|
+
await this.updateLocal();
|
|
375
|
+
const updatedLocal = (await this.getInstalled()).find(s => s.name === local.name);
|
|
376
|
+
if (!updatedLocal) {
|
|
377
|
+
throw ( new Error(`Failed to find MCP server: ${local.name}`));
|
|
378
|
+
}
|
|
379
|
+
return updatedLocal;
|
|
380
|
+
}
|
|
381
|
+
async updateMetadataFromGallery(gallery) {
|
|
382
|
+
const manifest = await this.mcpGalleryService.getManifest(gallery, CancellationToken.None);
|
|
383
|
+
const location = this.getLocation(gallery.name, gallery.version);
|
|
384
|
+
const manifestPath = this.uriIdentityService.extUri.joinPath(location, 'manifest.json');
|
|
385
|
+
const local = {
|
|
386
|
+
id: gallery.id,
|
|
387
|
+
name: gallery.name,
|
|
388
|
+
displayName: gallery.displayName,
|
|
389
|
+
description: gallery.description,
|
|
390
|
+
version: gallery.version,
|
|
391
|
+
publisher: gallery.publisher,
|
|
392
|
+
publisherDisplayName: gallery.publisherDisplayName,
|
|
393
|
+
repositoryUrl: gallery.repositoryUrl,
|
|
394
|
+
licenseUrl: gallery.licenseUrl,
|
|
395
|
+
icon: gallery.icon,
|
|
396
|
+
codicon: gallery.codicon,
|
|
397
|
+
manifest,
|
|
398
|
+
};
|
|
399
|
+
await this.fileService.writeFile(manifestPath, VSBuffer.fromString(JSON.stringify(local)));
|
|
400
|
+
if (gallery.readmeUrl) {
|
|
401
|
+
const readme = await this.mcpGalleryService.getReadme(gallery, CancellationToken.None);
|
|
402
|
+
await this.fileService.writeFile(this.uriIdentityService.extUri.joinPath(location, 'README.md'), VSBuffer.fromString(readme));
|
|
403
|
+
}
|
|
404
|
+
return manifest;
|
|
405
|
+
}
|
|
406
|
+
async getLocalServerInfo(name, mcpServerConfig) {
|
|
407
|
+
let storedMcpServerInfo;
|
|
408
|
+
let location;
|
|
409
|
+
let readmeUrl;
|
|
410
|
+
if (mcpServerConfig.gallery) {
|
|
411
|
+
location = this.getLocation(name, mcpServerConfig.version);
|
|
412
|
+
const manifestLocation = this.uriIdentityService.extUri.joinPath(location, 'manifest.json');
|
|
413
|
+
try {
|
|
414
|
+
const content = await this.fileService.readFile(manifestLocation);
|
|
415
|
+
storedMcpServerInfo = JSON.parse(( content.value.toString()));
|
|
416
|
+
storedMcpServerInfo.location = location;
|
|
417
|
+
readmeUrl = this.uriIdentityService.extUri.joinPath(location, 'README.md');
|
|
418
|
+
if (!(await this.fileService.exists(readmeUrl))) {
|
|
419
|
+
readmeUrl = undefined;
|
|
420
|
+
}
|
|
421
|
+
storedMcpServerInfo.readmeUrl = readmeUrl;
|
|
422
|
+
}
|
|
423
|
+
catch (e) {
|
|
424
|
+
this.logService.error('MCP Management Service: failed to read manifest', ( location.toString()), e);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return storedMcpServerInfo;
|
|
428
|
+
}
|
|
429
|
+
getLocation(name, version) {
|
|
430
|
+
name = name.replace('/', '.');
|
|
431
|
+
return this.uriIdentityService.extUri.joinPath(this.mcpLocation, version ? `${name}-${version}` : name);
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
McpUserResourceManagementService = ( __decorate([
|
|
285
435
|
( __param(1, IMcpGalleryService)),
|
|
286
436
|
( __param(2, IFileService)),
|
|
287
|
-
( __param(3,
|
|
288
|
-
( __param(4,
|
|
289
|
-
( __param(5,
|
|
437
|
+
( __param(3, IUriIdentityService)),
|
|
438
|
+
( __param(4, ILogService)),
|
|
439
|
+
( __param(5, IMcpResourceScannerService)),
|
|
440
|
+
( __param(6, IEnvironmentService))
|
|
441
|
+
], McpUserResourceManagementService));
|
|
442
|
+
let McpManagementService = class McpManagementService extends Disposable {
|
|
443
|
+
constructor(userDataProfilesService, instantiationService) {
|
|
444
|
+
super();
|
|
445
|
+
this.userDataProfilesService = userDataProfilesService;
|
|
446
|
+
this.instantiationService = instantiationService;
|
|
447
|
+
this._onInstallMcpServer = this._register(( new Emitter()));
|
|
448
|
+
this.onInstallMcpServer = this._onInstallMcpServer.event;
|
|
449
|
+
this._onDidInstallMcpServers = this._register(( new Emitter()));
|
|
450
|
+
this.onDidInstallMcpServers = this._onDidInstallMcpServers.event;
|
|
451
|
+
this._onDidUpdateMcpServers = this._register(( new Emitter()));
|
|
452
|
+
this.onDidUpdateMcpServers = this._onDidUpdateMcpServers.event;
|
|
453
|
+
this._onUninstallMcpServer = this._register(( new Emitter()));
|
|
454
|
+
this.onUninstallMcpServer = this._onUninstallMcpServer.event;
|
|
455
|
+
this._onDidUninstallMcpServer = this._register(( new Emitter()));
|
|
456
|
+
this.onDidUninstallMcpServer = this._onDidUninstallMcpServer.event;
|
|
457
|
+
this.mcpResourceManagementServices = ( new ResourceMap());
|
|
458
|
+
}
|
|
459
|
+
getMcpResourceManagementService(mcpResource) {
|
|
460
|
+
let mcpResourceManagementService = this.mcpResourceManagementServices.get(mcpResource);
|
|
461
|
+
if (!mcpResourceManagementService) {
|
|
462
|
+
const disposables = ( new DisposableStore());
|
|
463
|
+
const service = disposables.add(this.instantiationService.createInstance(McpUserResourceManagementService, mcpResource));
|
|
464
|
+
disposables.add(service.onInstallMcpServer(e => this._onInstallMcpServer.fire(e)));
|
|
465
|
+
disposables.add(service.onDidInstallMcpServers(e => this._onDidInstallMcpServers.fire(e)));
|
|
466
|
+
disposables.add(service.onDidUpdateMcpServers(e => this._onDidUpdateMcpServers.fire(e)));
|
|
467
|
+
disposables.add(service.onUninstallMcpServer(e => this._onUninstallMcpServer.fire(e)));
|
|
468
|
+
disposables.add(service.onDidUninstallMcpServer(e => this._onDidUninstallMcpServer.fire(e)));
|
|
469
|
+
this.mcpResourceManagementServices.set(mcpResource, mcpResourceManagementService = { service, dispose: () => disposables.dispose() });
|
|
470
|
+
}
|
|
471
|
+
return mcpResourceManagementService.service;
|
|
472
|
+
}
|
|
473
|
+
async getInstalled(mcpResource) {
|
|
474
|
+
const mcpResourceUri = mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
|
|
475
|
+
return this.getMcpResourceManagementService(mcpResourceUri).getInstalled();
|
|
476
|
+
}
|
|
477
|
+
async install(server, options) {
|
|
478
|
+
const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
|
|
479
|
+
return this.getMcpResourceManagementService(mcpResourceUri).install(server, options);
|
|
480
|
+
}
|
|
481
|
+
async uninstall(server, options) {
|
|
482
|
+
const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
|
|
483
|
+
return this.getMcpResourceManagementService(mcpResourceUri).uninstall(server, options);
|
|
484
|
+
}
|
|
485
|
+
async installFromGallery(server, options) {
|
|
486
|
+
const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
|
|
487
|
+
return this.getMcpResourceManagementService(mcpResourceUri).installFromGallery(server, options);
|
|
488
|
+
}
|
|
489
|
+
async updateMetadata(local, gallery, mcpResource) {
|
|
490
|
+
return this.getMcpResourceManagementService(mcpResource || this.userDataProfilesService.defaultProfile.mcpResource).updateMetadata(local, gallery);
|
|
491
|
+
}
|
|
492
|
+
dispose() {
|
|
493
|
+
this.mcpResourceManagementServices.forEach(service => service.dispose());
|
|
494
|
+
this.mcpResourceManagementServices.clear();
|
|
495
|
+
super.dispose();
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
McpManagementService = ( __decorate([
|
|
499
|
+
( __param(0, IUserDataProfilesService)),
|
|
500
|
+
( __param(1, IInstantiationService))
|
|
290
501
|
], McpManagementService));
|
|
291
502
|
|
|
292
|
-
export { McpManagementService };
|
|
503
|
+
export { AbstractMcpResourceManagementService, McpManagementService, McpUserResourceManagementService };
|