@codingame/monaco-vscode-mcp-service-override 18.3.1 → 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.
Files changed (71) hide show
  1. package/index.js +10 -5
  2. package/package.json +14 -14
  3. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +2 -1
  4. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +34 -11
  5. package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.d.ts +39 -0
  6. package/vscode/src/vs/platform/mcp/common/mcpManagementIpc.js +59 -0
  7. package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +89 -15
  8. package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +393 -182
  9. package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.d.ts +16 -29
  10. package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.js +6 -1
  11. package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.d.ts +33 -0
  12. package/vscode/src/vs/platform/mcp/common/mcpResourceScannerService.js +191 -0
  13. package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +25 -45
  14. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +3 -3
  15. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.d.ts +109 -0
  16. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommands.js +826 -0
  17. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommandsAddConfiguration.d.ts +41 -0
  18. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpCommandsAddConfiguration.js +420 -0
  19. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +1 -1
  20. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.d.ts +23 -0
  21. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpElicitationService.js +305 -0
  22. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.d.ts +3 -3
  23. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +30 -32
  24. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.d.ts +28 -0
  25. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpMigration.js +161 -0
  26. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.d.ts +60 -0
  27. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.js +423 -0
  28. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +60 -5
  29. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +299 -45
  30. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +12 -4
  31. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +237 -37
  32. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +3 -3
  33. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +4 -2
  34. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +29 -18
  35. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.d.ts +26 -1
  36. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +182 -28
  37. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +59 -9
  38. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +316 -31
  39. package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServerEditor.css +73 -0
  40. package/vscode/src/vs/workbench/contrib/mcp/browser/media/mcpServersView.css +35 -0
  41. package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.d.ts +4 -0
  42. package/vscode/src/vs/workbench/contrib/mcp/browser/openPanelChatAndGetWidget.js +18 -0
  43. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +4 -4
  44. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.d.ts +17 -0
  45. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/installedMcpServersDiscovery.js +151 -0
  46. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +1 -1
  47. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +2 -2
  48. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +1 -1
  49. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +1 -1
  50. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +1 -1
  51. package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.d.ts +15 -0
  52. package/vscode/src/vs/workbench/contrib/mcp/common/mcpContextKeys.js +60 -0
  53. package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +8 -8
  54. package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.js +12 -12
  55. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +2 -2
  56. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +1 -1
  57. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +18 -15
  58. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +9 -5
  59. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +77 -34
  60. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +3 -3
  61. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +3 -2
  62. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +6 -1
  63. package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +14 -13
  64. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.js +27 -1
  65. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +9 -9
  66. package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.d.ts +72 -0
  67. package/vscode/src/vs/workbench/services/mcp/common/mcpWorkbenchManagementService.js +475 -0
  68. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.d.ts +0 -19
  69. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.js +0 -167
  70. package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.d.ts +0 -33
  71. 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 { deepClone } from '@codingame/monaco-vscode-api/vscode/vs/base/common/objects';
8
- import { uppercaseFirstLetter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/strings';
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 { PackageType } from '@codingame/monaco-vscode-aa9ead53-dfd3-59da-b9e7-f163d201de8d-common/vscode/vs/platform/mcp/common/mcpManagement';
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 McpManagementService = class McpManagementService extends Disposable {
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(configurationService, mcpGalleryService, fileService, environmentService, uriIdentityService, logService) {
28
+ constructor(mcpResource, target, mcpGalleryService, fileService, uriIdentityService, logService, mcpResourceScannerService) {
25
29
  super();
26
- this.configurationService = configurationService;
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.mcpLocation = uriIdentityService.extUri.joinPath(environmentService.userRoamingDataHome, 'mcp');
44
+ this.reloadConfigurationScheduler = this._register(( new RunOnceScheduler(() => this.updateLocal(), 50)));
37
45
  }
38
- async getInstalled() {
39
- const { userLocal } = this.configurationService.inspect('mcp');
40
- if (!userLocal?.value?.servers) {
41
- return [];
46
+ initialize() {
47
+ if (!this.initializePromise) {
48
+ this.initializePromise = (async () => {
49
+ this.local = await this.populateLocalServers();
50
+ this.startWatching();
51
+ })();
42
52
  }
43
- return Promise.all(( Object.entries(userLocal.value.servers).map(([name, config]) => this.scanServer(name, config))));
53
+ return this.initializePromise;
44
54
  }
45
- async scanServer(name, config) {
46
- let scanned;
47
- let readmeUrl;
48
- if (config.location) {
49
- const manifestLocation = this.uriIdentityService.extUri.joinPath(URI.revive(config.location), 'manifest.json');
50
- try {
51
- const content = await this.fileService.readFile(manifestLocation);
52
- scanned = JSON.parse(( content.value.toString()));
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
- catch (e) {
55
- this.logService.error('MCP Management Service: failed to read manifest', ( config.location.toString()), e);
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
- readmeUrl = this.uriIdentityService.extUri.joinPath(URI.revive(config.location), 'README.md');
58
- if (!(await this.fileService.exists(readmeUrl))) {
59
- readmeUrl = undefined;
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
- if (!scanned) {
63
- let publisher = '';
64
- const nameParts = name.split('/');
65
- if (nameParts.length > 0) {
66
- const domainParts = nameParts[0].split('.');
67
- if (domainParts.length > 0) {
68
- publisher = domainParts[domainParts.length - 1];
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
- scanned = {
72
- name,
73
- version: '1.0.0',
74
- displayName: ( nameParts[nameParts.length - 1].split('-').map(s => uppercaseFirstLetter(s))).join(' '),
75
- publisher
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
- version: scanned.version,
82
- location: URI.revive(config.location),
83
- id: scanned.id,
84
- displayName: scanned.displayName,
85
- description: scanned.description,
86
- publisher: scanned.publisher,
87
- publisherDisplayName: scanned.publisherDisplayName,
88
- repositoryUrl: scanned.repositoryUrl,
89
- readmeUrl,
90
- iconUrl: scanned.iconUrl,
91
- manifest: scanned.manifest
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 installFromGallery(server, packageType) {
95
- this.logService.trace('MCP Management Service: installGallery', server.url);
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
- const manifest = await this.mcpGalleryService.getManifest(server, CancellationToken.None);
99
- const location = this.uriIdentityService.extUri.joinPath(this.mcpLocation, `${server.name.replace('/', '.')}-${server.version}`);
100
- const manifestPath = this.uriIdentityService.extUri.joinPath(location, 'manifest.json');
101
- await this.fileService.writeFile(manifestPath, VSBuffer.fromString(JSON.stringify({
102
- id: server.id,
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
- const serverConfig = this.getServerConfig(manifest, packageType);
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, source: server, error: e }]);
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 { userLocal } = this.configurationService.inspect('mcp');
149
- const value = deepClone(userLocal?.value ?? { servers: {} });
150
- if (!value.servers) {
151
- value.servers = {};
171
+ const currentServers = await this.mcpResourceScannerService.scanMcpServers(this.mcpResource, this.target);
172
+ if (!currentServers.servers) {
173
+ return;
152
174
  }
153
- delete value.servers[server.name];
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._onDidUninstallMcpServer.fire({ name: server.name });
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
- getServerConfig(manifest, packageType) {
186
+ toScannedMcpServerAndInputs(manifest, packageType) {
172
187
  if (packageType === undefined) {
173
188
  packageType = manifest.packages?.[0]?.registry_name ?? PackageType.REMOTE;
174
189
  }
175
- if (packageType === PackageType.REMOTE) {
176
- const inputs = [];
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
- headers[input.name] = input.value;
180
- if (input.variables) {
181
- inputs.push(...this.getVariables(input.variables));
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
- return {
185
- type: 'http',
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
- const serverPackage = manifest.packages.find(p => p.registry_name === packageType) ?? manifest.packages[0];
192
- const inputs = [];
193
- const args = [];
194
- const env = {};
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
- else if (arg.type === 'named') {
205
- args.push(arg.name);
206
- if (arg.value) {
207
- args.push(arg.value);
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
- if (arg.variables) {
211
- inputs.push(...this.getVariables(arg.variables));
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
- for (const input of serverPackage.environment_variables ?? []) {
215
- const variables = input.variables ? this.getVariables(input.variables) : [];
216
- let value = input.value;
217
- for (const variable of variables) {
218
- value = value.replace(`{${variable.id}}`, `\${input:${variable.id}}`);
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
- env[input.name] = value;
221
- if (variables.length) {
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.DOCKER) {
225
- args.push('-e');
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
- if (serverPackage.registry_name === PackageType.NODE) {
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
- else if (arg.type === 'named') {
243
- args.push(arg.name);
244
- if (arg.value) {
245
- args.push(arg.value);
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
- if (arg.variables) {
249
- inputs.push(...this.getVariables(arg.variables));
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
- type: 'stdio',
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
- McpManagementService = ( __decorate([
284
- ( __param(0, IConfigurationService)),
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, IEnvironmentService)),
288
- ( __param(4, IUriIdentityService)),
289
- ( __param(5, ILogService))
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 };