mcpManagementService.ts ×36

Frontier kind: Code frontier

unlabeled · c_92832c61f920

331 tests · 14563 LOC · 65 files · introduces 0 tests · 284 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
50 ranges284 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1825 ranges14563 lines · 65 files · Browse complete extent
All tests (intent)
331 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 284 introduced LOC across 50 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/mcp/common/mcpManagementService.ts 198 introduced LOC · 36 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- mcpManagementService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { RunOnceScheduler } from '../../../base/common/async.js';
7 > import { VSBuffer } from '../../../base/common/buffer.js';
8 > import { CancellationToken } from '../../../base/common/cancellation.js';
9 > import { Emitter, Event } from '../../../base/common/event.js';
10 > import { IMarkdownString, MarkdownString } from '../../../base/common/htmlContent.js';
11 > import { Disposable, DisposableStore, IDisposable } from '../../../base/common/lifecycle.js';
12 > import { ResourceMap } from '../../../base/common/map.js';
13 > import { equals } from '../../../base/common/objects.js';
14 > import { isString } from '../../../base/common/types.js';
15 > import { URI } from '../../../base/common/uri.js';
16 > import { localize } from '../../../nls.js';
17 > import { ConfigurationTarget } from '../../configuration/common/configuration.js';
18 > import { IEnvironmentService } from '../../environment/common/environment.js';
19 > import { IFileService } from '../../files/common/files.js';
20 > import { IInstantiationService } from '../../instantiation/common/instantiation.js';
21 > import { ILogService } from '../../log/common/log.js';
22 > import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.js';
23 > import { IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.js';
24 > import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpGalleryService, IMcpManagementService, IMcpServerInput, IGalleryMcpServerConfiguration, InstallMcpServerEvent, InstallMcpServerResult, RegistryType, UninstallMcpServerEvent, InstallOptions, UninstallOptions, IInstallableMcpServer, IAllowedMcpServersService, IMcpServerArgument, IMcpServerKeyValueInput, McpServerConfigurationParseResult } from './mcpManagement.js';
25 > import { IMcpSandboxConfiguration, IMcpServerVariable, McpServerVariableType, IMcpServerConfiguration, McpServerType } from './mcpPlatformTypes.js';
26 > import { IMcpResourceScannerService, McpResourceTarget } from './mcpResourceScannerService.js';
27 >
28 > export interface ILocalMcpServerInfo {
29 > name: string;
30 > version?: string;
31 > displayName?: string;
32 > galleryId?: string;
33 > galleryUrl?: string;
34 > description?: string;
35 > repositoryUrl?: string;
36 > publisher?: string;
37 > publisherDisplayName?: string;
38 > icon?: {
39 > dark: string;
40 > light: string;
41 > };
42 > codicon?: string;
43 > manifest?: IGalleryMcpServerConfiguration;
44 > readmeUrl?: URI;
45 > location?: URI;
46 > licenseUrl?: string;
47 > }
48 >
49 > export abstract class AbstractCommonMcpManagementService extends Disposable implements IMcpManagementService {
50 >
51 > _serviceBrand: undefined;
52 >
53 > abstract onInstallMcpServer: Event<InstallMcpServerEvent>;
54 > abstract onDidInstallMcpServers: Event<readonly InstallMcpServerResult[]>;
55 > abstract onDidUpdateMcpServers: Event<readonly InstallMcpServerResult[]>;
56 > abstract onUninstallMcpServer: Event<UninstallMcpServerEvent>;
57 > abstract onDidUninstallMcpServer: Event<DidUninstallMcpServerEvent>;
58 >
59 > abstract getInstalled(mcpResource?: URI): Promise<ILocalMcpServer[]>;
60 > abstract install(server: IInstallableMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
61 > abstract installFromGallery(server: IGalleryMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
62 > abstract updateMetadata(local: ILocalMcpServer, server: IGalleryMcpServer, profileLocation?: URI): Promise<ILocalMcpServer>;
63 > abstract uninstall(server: ILocalMcpServer, options?: UninstallOptions): Promise<void>;
64 > abstract canInstall(server: IGalleryMcpServer | IInstallableMcpServer): true | IMarkdownString;
65 >
66 > constructor(
67 @ILogService protected readonly logService: ILogService
68 ) {
69 super();
70 }
72 > getMcpServerConfigurationFromManifest(manifest: IGalleryMcpServerConfiguration, packageType: RegistryType): McpServerConfigurationParseResult {
73
74 // remote
180 };
181 }
183 > protected getCommandName(packageType: RegistryType): string {
184 switch (packageType) {
185 case RegistryType.NODE: return 'npx';
190 return packageType;
191 }
193 > protected getVariables(variableInputs: Record<string, IMcpServerInput>): IMcpServerVariable[] {
194 const variables: IMcpServerVariable[] = [];
195 for (const [key, value] of Object.entries(variableInputs)) {
205 return variables;
206 }
208 > private processKeyValueInputs(keyValueInputs: ReadonlyArray<IMcpServerKeyValueInput>): { inputs: Record<string, string>; variables: IMcpServerVariable[]; notices: string[] } {
209 const notices: string[] = [];
210 const inputs: Record<string, string> = {};
239 return { inputs, variables, notices };
240 }
242 > private processArguments(argumentsList: readonly IMcpServerArgument[]): { args: string[]; variables: IMcpServerVariable[]; notices: string[] } {
243 const args: string[] = [];
244 const variables: IMcpServerVariable[] = [];
302 return { args, variables, notices };
303 }
305 > }
306 >
307 > export abstract class AbstractMcpResourceManagementService extends AbstractCommonMcpManagementService {
308 >
309 > private initializePromise: Promise<void> | undefined;
310 > private readonly reloadConfigurationScheduler: RunOnceScheduler;
311 > private local = new Map<string, ILocalMcpServer>();
312 >
313 > protected readonly _onInstallMcpServer = this._register(new Emitter<InstallMcpServerEvent>());
314 > readonly onInstallMcpServer = this._onInstallMcpServer.event;
315 >
316 > protected readonly _onDidInstallMcpServers = this._register(new Emitter<InstallMcpServerResult[]>());
317 > get onDidInstallMcpServers() { return this._onDidInstallMcpServers.event; }
318 >
319 > protected readonly _onDidUpdateMcpServers = this._register(new Emitter<InstallMcpServerResult[]>());
320 > get onDidUpdateMcpServers() { return this._onDidUpdateMcpServers.event; }
321 >
322 > protected readonly _onUninstallMcpServer = this._register(new Emitter<UninstallMcpServerEvent>());
323 > get onUninstallMcpServer() { return this._onUninstallMcpServer.event; }
324 >
325 > protected _onDidUninstallMcpServer = this._register(new Emitter<DidUninstallMcpServerEvent>());
326 > get onDidUninstallMcpServer() { return this._onDidUninstallMcpServer.event; }
327 >
328 > constructor(
329 protected readonly mcpResource: URI,
330 protected readonly target: McpResourceTarget,
339 this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.updateLocal(), 50));
340 }
342 > /**
343 > * Enforces the enterprise allow/deny policy at the point of persistence. Called by every
344 > * install path (installable and each gallery override) against the fully resolved server
345 > * configuration, so a caller that goes straight to the management API cannot bypass the
346 > * `canInstall` UI check, and a gallery entry cannot slip through if its resolved command/URL
347 > * differs from the pre-resolution metadata.
348 > */
349 > protected ensureServerAllowed(server: IGalleryMcpServer | IInstallableMcpServer): void {
350 const result = this.allowedMcpServersService.isAllowed(server);
351 if (result !== true) {
353 }
354 }
356 > private initialize(): Promise<void> {
357 if (!this.initializePromise) {
358 this.initializePromise = (async () => {
366 return this.initializePromise;
367 }
369 > private async populateLocalServers(): Promise<Map<string, ILocalMcpServer>> {
370 this.logService.trace('AbstractMcpResourceManagementService#populateLocalServers', this.mcpResource.toString());
371 const local = new Map<string, ILocalMcpServer>();
384 return local;
385 }
387 > private startWatching(): void {
388 this._register(this.fileService.watch(this.mcpResource));
389 this._register(this.fileService.onDidFilesChange(e => {
393 }));
394 }
396 > protected async updateLocal(): Promise<void> {
397 try {
398 const current = await this.populateLocalServers();
436 }
437 }
439 > async getInstalled(): Promise<ILocalMcpServer[]> {
440 await this.initialize();
441 return Array.from(this.local.values());
442 }
444 > protected async scanLocalServer(name: string, config: IMcpServerConfiguration, rootSandbox?: IMcpSandboxConfiguration): Promise<ILocalMcpServer> {
445 let mcpServerInfo = await this.getLocalServerInfo(name, config);
446 if (!mcpServerInfo) {
469 };
470 }
472 > async install(server: IInstallableMcpServer, options?: Omit<InstallOptions, 'mcpResource'>): Promise<ILocalMcpServer> {
473 this.logService.trace('MCP Management Service: install', server.name);
474 this.ensureServerAllowed(server);
488 }
489 }
491 > async uninstall(server: ILocalMcpServer, options?: Omit<UninstallOptions, 'mcpResource'>): Promise<void> {
492 this.logService.trace('MCP Management Service: uninstall', server.name);
493 this._onUninstallMcpServer.fire({ name: server.name, mcpResource: this.mcpResource });
508 }
509 }
511 > protected abstract getLocalServerInfo(name: string, mcpServerConfig: IMcpServerConfiguration): Promise<ILocalMcpServerInfo | undefined>;
512 > protected abstract installFromUri(uri: URI, options?: Omit<InstallOptions, 'mcpResource'>): Promise<ILocalMcpServer>;
513 > }
514 >
515 > export class McpUserResourceManagementService extends AbstractMcpResourceManagementService {
516 >
517 > protected readonly mcpLocation: URI;
518 >
519 > constructor(
520 mcpResource: URI,
521 @IMcpGalleryService mcpGalleryService: IMcpGalleryService,
530 this.mcpLocation = uriIdentityService.extUri.joinPath(environmentService.userRoamingDataHome, 'mcp');
531 }
533 > async installFromGallery(server: IGalleryMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
534 throw new Error('Not supported');
535 }
537 > async updateMetadata(local: ILocalMcpServer, gallery: IGalleryMcpServer): Promise<ILocalMcpServer> {
538 await this.updateMetadataFromGallery(gallery);
539 await this.updateLocal();
544 return updatedLocal;
545 }
547 > protected async updateMetadataFromGallery(gallery: IGalleryMcpServer): Promise<IGalleryMcpServerConfiguration> {
548 const manifest = gallery.configuration;
549 const location = this.getLocation(gallery.name, gallery.version);
573 return manifest;
574 }
576 > protected async getLocalServerInfo(name: string, mcpServerConfig: IMcpServerConfiguration): Promise<ILocalMcpServerInfo | undefined> {
577 let storedMcpServerInfo: ILocalMcpServerInfo | undefined;
578 let location: URI | undefined;
603 return storedMcpServerInfo;
604 }
606 > protected getLocation(name: string, version?: string): URI {
607 name = name.replace('/', '.');
608 return this.uriIdentityService.extUri.joinPath(this.mcpLocation, version ? `${name}-${version}` : name);
609 }
611 > protected override installFromUri(uri: URI, options?: Omit<InstallOptions, 'mcpResource'>): Promise<ILocalMcpServer> {
612 throw new Error('Method not supported.');
613 }
615 > override canInstall(): true | IMarkdownString {
616 throw new Error('Not supported');
617 }
619 > }
620 >
621 > export abstract class AbstractMcpManagementService extends AbstractCommonMcpManagementService implements IMcpManagementService {
622 >
623 > constructor(
624 @IAllowedMcpServersService protected readonly allowedMcpServersService: IAllowedMcpServersService,
625 @ILogService logService: ILogService,
627 super(logService);
628 }
630 > canInstall(server: IGalleryMcpServer | IInstallableMcpServer): true | IMarkdownString {
631 const allowedToInstall = this.allowedMcpServersService.isAllowed(server);
632 if (allowedToInstall !== true) {
635 return true;
636 }
638 >
639 > export class McpManagementService extends AbstractMcpManagementService implements IMcpManagementService {
640 >
641 > private readonly _onInstallMcpServer = this._register(new Emitter<InstallMcpServerEvent>());
642 > readonly onInstallMcpServer = this._onInstallMcpServer.event;
643 >
644 > private readonly _onDidInstallMcpServers = this._register(new Emitter<readonly InstallMcpServerResult[]>());
645 > readonly onDidInstallMcpServers = this._onDidInstallMcpServers.event;
646 >
647 > private readonly _onDidUpdateMcpServers = this._register(new Emitter<readonly InstallMcpServerResult[]>());
648 > readonly onDidUpdateMcpServers = this._onDidUpdateMcpServers.event;
649 >
650 > private readonly _onUninstallMcpServer = this._register(new Emitter<UninstallMcpServerEvent>());
651 > readonly onUninstallMcpServer = this._onUninstallMcpServer.event;
652 >
653 > private readonly _onDidUninstallMcpServer = this._register(new Emitter<DidUninstallMcpServerEvent>());
654 > readonly onDidUninstallMcpServer = this._onDidUninstallMcpServer.event;
655 >
656 > private readonly mcpResourceManagementServices = new ResourceMap<{ service: McpUserResourceManagementService } & IDisposable>();
657 >
658 > constructor(
659 @IAllowedMcpServersService allowedMcpServersService: IAllowedMcpServersService,
660 @ILogService logService: ILogService,
664 super(allowedMcpServersService, logService);
665 }
667 > private getMcpResourceManagementService(mcpResource: URI): McpUserResourceManagementService {
668 let mcpResourceManagementService = this.mcpResourceManagementServices.get(mcpResource);
669 if (!mcpResourceManagementService) {
679 return mcpResourceManagementService.service;
680 }
682 > async getInstalled(mcpResource?: URI): Promise<ILocalMcpServer[]> {
683 const mcpResourceUri = mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
684 return this.getMcpResourceManagementService(mcpResourceUri).getInstalled();
685 }
687 > async install(server: IInstallableMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
688 const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
689 return this.getMcpResourceManagementService(mcpResourceUri).install(server, options);
690 }
692 > async uninstall(server: ILocalMcpServer, options?: UninstallOptions): Promise<void> {
693 const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
694 return this.getMcpResourceManagementService(mcpResourceUri).uninstall(server, options);
695 }
697 > async installFromGallery(server: IGalleryMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
698 const mcpResourceUri = options?.mcpResource || this.userDataProfilesService.defaultProfile.mcpResource;
699 return this.getMcpResourceManagementService(mcpResourceUri).installFromGallery(server, options);
700 }
702 > async updateMetadata(local: ILocalMcpServer, gallery: IGalleryMcpServer, mcpResource?: URI): Promise<ILocalMcpServer> {
703 return this.getMcpResourceManagementService(mcpResource || this.userDataProfilesService.defaultProfile.mcpResource).updateMetadata(local, gallery);
704 }
706 > override dispose(): void {
707 this.mcpResourceManagementServices.forEach(service => service.dispose());
708 this.mcpResourceManagementServices.clear();
709 super.dispose();
710 }
712 > protected createMcpResourceManagementService(mcpResource: URI): McpUserResourceManagementService {
713 return this.instantiationService.createInstance(McpUserResourceManagementService, mcpResource);
714 }
716 > }
src/vs/platform/mcp/common/mcpResourceScannerService.ts 86 introduced LOC · 14 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- mcpResourceScannerService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { assertNever } from '../../../base/common/assert.js';
7 > import { Queue } from '../../../base/common/async.js';
8 > import { VSBuffer } from '../../../base/common/buffer.js';
9 > import { IStringDictionary } from '../../../base/common/collections.js';
10 > import { parse, ParseError } from '../../../base/common/json.js';
11 > import { Disposable } from '../../../base/common/lifecycle.js';
12 > import { ResourceMap } from '../../../base/common/map.js';
13 > import { Mutable } from '../../../base/common/types.js';
14 > import { URI } from '../../../base/common/uri.js';
15 > import { ConfigurationTarget, ConfigurationTargetToString } from '../../configuration/common/configuration.js';
16 > import { FileOperationResult, IFileService, toFileOperationResult } from '../../files/common/files.js';
17 > import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js';
18 > import { createDecorator } from '../../instantiation/common/instantiation.js';
19 > import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.js';
20 > import { IInstallableMcpServer } from './mcpManagement.js';
21 > import { ICommonMcpServerConfiguration, IMcpSandboxConfiguration, IMcpServerConfiguration, IMcpServerVariable, IMcpStdioServerConfiguration, McpServerType } from './mcpPlatformTypes.js';
22 >
23 > interface IScannedMcpServers {
24 > servers?: IStringDictionary<Mutable<IMcpServerConfiguration>>;
25 > inputs?: IMcpServerVariable[];
26 > sandbox?: IMcpSandboxConfiguration;
27 > }
28 >
29 > interface IOldScannedMcpServer {
30 > id: string;
31 > name: string;
32 > version?: string;
33 > gallery?: boolean;
34 > config: Mutable<IMcpServerConfiguration>;
35 > }
36 >
37 > interface IScannedWorkspaceMcpServers {
38 > settings?: {
39 > mcp?: IScannedMcpServers;
40 > };
41 > }
42 >
43 > export type McpResourceTarget = ConfigurationTarget.USER | ConfigurationTarget.WORKSPACE | ConfigurationTarget.WORKSPACE_FOLDER;
44 >
45 > export const IMcpResourceScannerService = createDecorator<IMcpResourceScannerService>('IMcpResourceScannerService');
46 > export interface IMcpResourceScannerService {
47 > readonly _serviceBrand: undefined;
48 > scanMcpServers(mcpResource: URI, target?: McpResourceTarget): Promise<IScannedMcpServers>;
49 > addMcpServers(servers: IInstallableMcpServer[], mcpResource: URI, target?: McpResourceTarget): Promise<void>;
50 > updateSandboxConfig(updateFn: (data: IScannedMcpServers) => IScannedMcpServers, mcpResource: URI, target?: McpResourceTarget): Promise<void>;
51 > removeMcpServers(serverNames: string[], mcpResource: URI, target?: McpResourceTarget): Promise<void>;
52 > }
53 >
54 > export class McpResourceScannerService extends Disposable implements IMcpResourceScannerService {
55 > readonly _serviceBrand: undefined;
56 >
57 > private readonly resourcesAccessQueueMap = new ResourceMap<Queue<IScannedMcpServers>>();
58 >
59 > constructor(
60 @IFileService private readonly fileService: IFileService,
61 @IUriIdentityService protected readonly uriIdentityService: IUriIdentityService,
63 super();
64 }
66 > async scanMcpServers(mcpResource: URI, target?: McpResourceTarget): Promise<IScannedMcpServers> {
67 return this.withProfileMcpServers(mcpResource, target);
68 }
70 > async addMcpServers(servers: IInstallableMcpServer[], mcpResource: URI, target?: McpResourceTarget): Promise<void> {
71 await this.withProfileMcpServers(mcpResource, target, scannedMcpServers => {
72 let updatedInputs = scannedMcpServers.inputs ?? [];
83 });
84 }
86 > async updateSandboxConfig(updateFn: (data: IScannedMcpServers) => IScannedMcpServers, mcpResource: URI, target?: McpResourceTarget): Promise<void> {
87 await this.withProfileMcpServers(mcpResource, target, updateFn);
88 }
90 > async removeMcpServers(serverNames: string[], mcpResource: URI, target?: McpResourceTarget): Promise<void> {
91 await this.withProfileMcpServers(mcpResource, target, scannedMcpServers => {
92 for (const serverName of serverNames) {
98 });
99 }
101 > private async withProfileMcpServers(mcpResource: URI, target?: McpResourceTarget, updateFn?: (data: IScannedMcpServers) => IScannedMcpServers): Promise<IScannedMcpServers> {
102 return this.getResourceAccessQueue(mcpResource)
103 .queue(async (): Promise<IScannedMcpServers> => {
143 });
144 }
146 > private async writeScannedMcpServers(mcpResource: URI, scannedMcpServers: IScannedMcpServers): Promise<void> {
147 if ((scannedMcpServers.servers && Object.keys(scannedMcpServers.servers).length > 0)
148 || (scannedMcpServers.inputs && scannedMcpServers.inputs.length > 0)
153 }
154 }
156 > private async writeScannedMcpServersToWorkspaceFolder(mcpResource: URI, scannedMcpServers: IScannedMcpServers): Promise<void> {
157 await this.fileService.writeFile(mcpResource, VSBuffer.fromString(JSON.stringify(scannedMcpServers, null, '\t')));
158 }
160 > private async writeScannedMcpServersToWorkspace(mcpResource: URI, scannedMcpServers: IScannedMcpServers): Promise<void> {
161 let scannedWorkspaceMcpServers: IScannedWorkspaceMcpServers | undefined;
162 try {
179 await this.fileService.writeFile(mcpResource, VSBuffer.fromString(JSON.stringify(scannedWorkspaceMcpServers, null, '\t')));
180 }
182 > private fromUserMcpServers(scannedMcpServers: IScannedMcpServers): IScannedMcpServers {
183 const userMcpServers: IScannedMcpServers = {
184 inputs: scannedMcpServers.inputs,
194 return userMcpServers;
195 }
197 > private fromWorkspaceFolderMcpServers(scannedWorkspaceFolderMcpServers: IScannedMcpServers): IScannedMcpServers {
198 const scannedMcpServers: IScannedMcpServers = {
199 inputs: scannedWorkspaceFolderMcpServers.inputs,
210 return scannedMcpServers;
211 }
213 > private sanitizeServer(serverOrConfig: IOldScannedMcpServer | Mutable<IMcpServerConfiguration>): IMcpServerConfiguration {
214 let server: IMcpServerConfiguration;
215 if ((<IOldScannedMcpServer>serverOrConfig).config) {
229 return server;
230 }
232 > private getResourceAccessQueue(file: URI): Queue<IScannedMcpServers> {
233 let resourceQueue = this.resourcesAccessQueueMap.get(file);
234 if (!resourceQueue) {
238 return resourceQueue;
239 }
241 >
242 > registerSingleton(IMcpResourceScannerService, McpResourceScannerService, InstantiationType.Delayed);