Skip to content

Commit 617da4d

Browse files
authored
1 parent ba15634 commit 617da4d

File tree

9 files changed

+107
-132
lines changed

9 files changed

+107
-132
lines changed

src/vs/platform/mcp/common/mcpManagement.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,10 @@ import { SortBy, SortOrder } from '../../extensionManagement/common/extensionMan
1010
import { createDecorator } from '../../instantiation/common/instantiation.js';
1111
import { IMcpServerConfiguration, IMcpServerVariable } from './mcpPlatformTypes.js';
1212

13-
export interface IScannedMcpServer {
14-
readonly id: string;
15-
readonly name: string;
16-
readonly version?: string;
17-
readonly gallery?: boolean;
18-
readonly config: IMcpServerConfiguration;
19-
}
20-
2113
export interface ILocalMcpServer {
2214
readonly name: string;
2315
readonly config: IMcpServerConfiguration;
24-
readonly version: string;
16+
readonly version?: string;
2517
readonly mcpResource: URI;
2618
readonly location?: URI;
2719
readonly id?: string;
@@ -181,9 +173,9 @@ export type UninstallOptions = {
181173
};
182174

183175
export interface IInstallableMcpServer {
184-
name: string;
185-
config: IMcpServerConfiguration;
186-
inputs?: IMcpServerVariable[];
176+
readonly name: string;
177+
readonly config: IMcpServerConfiguration;
178+
readonly inputs?: IMcpServerVariable[];
187179
}
188180

189181
export const IMcpManagementService = createDecorator<IMcpManagementService>('IMcpManagementService');

src/vs/platform/mcp/common/mcpManagementService.ts

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ import { IInstantiationService } from '../../instantiation/common/instantiation.
1818
import { ILogService } from '../../log/common/log.js';
1919
import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.js';
2020
import { IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.js';
21-
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpGalleryService, IMcpManagementService, IMcpServerInput, IMcpServerManifest, InstallMcpServerEvent, InstallMcpServerResult, PackageType, UninstallMcpServerEvent, IScannedMcpServer, InstallOptions, UninstallOptions, IInstallableMcpServer } from './mcpManagement.js';
22-
import { IMcpServerVariable, McpServerVariableType, IMcpServerConfiguration } from './mcpPlatformTypes.js';
21+
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpGalleryService, IMcpManagementService, IMcpServerInput, IMcpServerManifest, InstallMcpServerEvent, InstallMcpServerResult, PackageType, UninstallMcpServerEvent, InstallOptions, UninstallOptions, IInstallableMcpServer } from './mcpManagement.js';
22+
import { IMcpServerVariable, McpServerVariableType, IMcpServerConfiguration, McpServerType } from './mcpPlatformTypes.js';
2323
import { IMcpResourceScannerService, McpResourceTarget } from './mcpResourceScannerService.js';
2424

2525
export interface ILocalMcpServerInfo {
2626
name: string;
27-
version: string;
27+
version?: string;
2828
id?: string;
2929
displayName?: string;
3030
url?: string;
@@ -95,7 +95,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
9595
const scannedMcpServers = await this.mcpResourceScannerService.scanMcpServers(this.mcpResource, this.target);
9696
if (scannedMcpServers.servers) {
9797
await Promise.allSettled(Object.entries(scannedMcpServers.servers).map(async ([name, scannedServer]) => {
98-
const server = await this.scanServer(scannedServer);
98+
const server = await this.scanLocalServer(name, scannedServer);
9999
local.set(name, server);
100100
}));
101101
}
@@ -115,7 +115,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
115115
}));
116116
}
117117

118-
private async updateLocal(): Promise<void> {
118+
protected async updateLocal(): Promise<void> {
119119
try {
120120
const current = await this.populateLocalServer();
121121

@@ -163,20 +163,17 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
163163
return Array.from(this.local.values());
164164
}
165165

166-
protected async scanServer(scannedMcpServer: IScannedMcpServer): Promise<ILocalMcpServer> {
167-
let mcpServerInfo = await this.getLocalMcpServerInfo(scannedMcpServer);
166+
protected async scanLocalServer(name: string, config: IMcpServerConfiguration): Promise<ILocalMcpServer> {
167+
let mcpServerInfo = await this.getLocalServerInfo(name, config);
168168
if (!mcpServerInfo) {
169-
mcpServerInfo = {
170-
name: scannedMcpServer.name,
171-
version: '1.0.0',
172-
};
169+
mcpServerInfo = { name, version: config.version };
173170
}
174171

175172
return {
176-
name: scannedMcpServer.name,
177-
config: scannedMcpServer.config,
178-
version: mcpServerInfo.version,
173+
name,
174+
config,
179175
mcpResource: this.mcpResource,
176+
version: mcpServerInfo.version,
180177
location: mcpServerInfo.location,
181178
id: mcpServerInfo.id,
182179
displayName: mcpServerInfo.displayName,
@@ -196,17 +193,12 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
196193

197194
this._onInstallMcpServer.fire({ name: server.name, mcpResource: this.mcpResource });
198195
try {
199-
const scannedServer: IScannedMcpServer = {
200-
id: server.name,
201-
name: server.name,
202-
version: '0.0.1',
203-
config: server.config
204-
};
205-
206-
await this.mcpResourceScannerService.addMcpServers([{ server: scannedServer, inputs: server.inputs }], this.mcpResource, this.target);
207-
208-
const local = await this.scanServer(scannedServer);
209-
this.reloadConfigurationScheduler.schedule();
196+
await this.mcpResourceScannerService.addMcpServers([server], this.mcpResource, this.target);
197+
await this.updateLocal();
198+
const local = this.local.get(server.name);
199+
if (!local) {
200+
throw new Error(`Failed to install MCP server: ${server.name}`);
201+
}
210202
return local;
211203
} catch (e) {
212204
this._onDidInstallMcpServers.fire([{ name: server.name, error: e, mcpResource: this.mcpResource }]);
@@ -227,7 +219,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
227219
if (server.location) {
228220
await this.fileService.del(URI.revive(server.location), { recursive: true });
229221
}
230-
this.reloadConfigurationScheduler.schedule();
222+
await this.updateLocal();
231223
} catch (e) {
232224
this._onDidUninstallMcpServer.fire({ name: server.name, error: e, mcpResource: this.mcpResource });
233225
throw e;
@@ -256,7 +248,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
256248
}
257249
}
258250
config = {
259-
type: 'http',
251+
type: McpServerType.REMOTE,
260252
url: manifest.remotes[0].url,
261253
headers: Object.keys(headers).length ? headers : undefined,
262254
};
@@ -352,7 +344,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
352344
}
353345

354346
config = {
355-
type: 'stdio',
347+
type: McpServerType.LOCAL,
356348
command: this.getCommandName(serverPackage.registry_name),
357349
args: args.length ? args : undefined,
358350
env: Object.keys(env).length ? env : undefined,
@@ -390,7 +382,7 @@ export abstract class AbstractMcpResourceManagementService extends Disposable im
390382
}
391383

392384
abstract installFromGallery(server: IGalleryMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
393-
protected abstract getLocalMcpServerInfo(scannedMcpServer: IScannedMcpServer): Promise<ILocalMcpServerInfo | undefined>;
385+
protected abstract getLocalServerInfo(name: string, mcpServerConfig: IMcpServerConfiguration): Promise<ILocalMcpServerInfo | undefined>;
394386
}
395387

396388
export class McpUserResourceManagementService extends AbstractMcpResourceManagementService implements IMcpManagementService {
@@ -440,30 +432,36 @@ export class McpUserResourceManagementService extends AbstractMcpResourceManagem
440432
}
441433
const { config, inputs } = this.toScannedMcpServerAndInputs(manifest, options?.packageType);
442434

443-
const scannedServer: IScannedMcpServer = {
444-
id: server.id,
435+
const installable: IInstallableMcpServer = {
445436
name: server.name,
446-
version: server.version,
447-
gallery: true,
448-
config
437+
config: {
438+
...config,
439+
gallery: true,
440+
version: server.version
441+
},
442+
inputs
449443
};
450444

451-
await this.mcpResourceScannerService.addMcpServers([{ server: scannedServer, inputs }], this.mcpResource, this.target);
445+
await this.mcpResourceScannerService.addMcpServers([installable], this.mcpResource, this.target);
452446

453-
const local = await this.scanServer(scannedServer);
447+
await this.updateLocal();
448+
const local = (await this.getInstalled()).find(s => s.name === server.name);
449+
if (!local) {
450+
throw new Error(`Failed to install MCP server: ${server.name}`);
451+
}
454452
return local;
455453
} catch (e) {
456454
this._onDidInstallMcpServers.fire([{ name: server.name, source: server, error: e, mcpResource: this.mcpResource }]);
457455
throw e;
458456
}
459457
}
460458

461-
protected async getLocalMcpServerInfo(scannedMcpServer: IScannedMcpServer): Promise<ILocalMcpServerInfo | undefined> {
459+
protected async getLocalServerInfo(name: string, mcpServerConfig: IMcpServerConfiguration): Promise<ILocalMcpServerInfo | undefined> {
462460
let storedMcpServerInfo: ILocalMcpServerInfo | undefined;
463461
let location: URI | undefined;
464462
let readmeUrl: URI | undefined;
465-
if (scannedMcpServer.gallery) {
466-
location = this.getLocation(scannedMcpServer.name, scannedMcpServer.version);
463+
if (mcpServerConfig.gallery) {
464+
location = this.getLocation(name, mcpServerConfig.version);
467465
const manifestLocation = this.uriIdentityService.extUri.joinPath(location, 'manifest.json');
468466
try {
469467
const content = await this.fileService.readFile(manifestLocation);

src/vs/platform/mcp/common/mcpPlatformTypes.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,19 @@ export interface IMcpServerVariable {
2727
readonly serverName?: string;
2828
}
2929

30-
export interface IMcpStdioServerConfiguration {
31-
readonly type: 'stdio';
30+
export const enum McpServerType {
31+
LOCAL = 'stdio',
32+
REMOTE = 'http',
33+
}
34+
35+
export interface ICommonMcpServerConfiguration {
36+
readonly type: McpServerType;
37+
readonly version?: string;
38+
readonly gallery?: boolean;
39+
}
40+
41+
export interface IMcpStdioServerConfiguration extends ICommonMcpServerConfiguration {
42+
readonly type: McpServerType.LOCAL;
3243
readonly command: string;
3344
readonly args?: readonly string[];
3445
readonly env?: Record<string, string | number | null>;
@@ -37,8 +48,8 @@ export interface IMcpStdioServerConfiguration {
3748
readonly dev?: IMcpDevModeConfig;
3849
}
3950

40-
export interface IMcpRemoteServerConfiguration {
41-
readonly type: 'http';
51+
export interface IMcpRemoteServerConfiguration extends ICommonMcpServerConfiguration {
52+
readonly type: McpServerType.REMOTE;
4253
readonly url: string;
4354
readonly headers?: Record<string, string>;
4455
readonly dev?: IMcpDevModeConfig;

0 commit comments

Comments
 (0)