From aadbd769df5e181f6f183ed12778e6f3eb041da7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 29 Sep 2025 12:28:23 +0200 Subject: [PATCH] Enable GH Mcp registry in stable behind a preview setting (#268830) * Enable GH Mcp registry in stable behind a preview setting * add icon --- src/vs/platform/mcp/common/mcpManagement.ts | 1 + .../contrib/chat/browser/chat.contribution.ts | 9 ++- .../contrib/mcp/browser/mcp.contribution.ts | 3 +- .../contrib/mcp/browser/mcpCommands.ts | 34 +++-------- .../contrib/mcp/browser/mcpServersView.ts | 58 +++++++++++++------ 5 files changed, 57 insertions(+), 48 deletions(-) diff --git a/src/vs/platform/mcp/common/mcpManagement.ts b/src/vs/platform/mcp/common/mcpManagement.ts index 2e236c4b6a2..76cd674a410 100644 --- a/src/vs/platform/mcp/common/mcpManagement.ts +++ b/src/vs/platform/mcp/common/mcpManagement.ts @@ -244,6 +244,7 @@ export interface IAllowedMcpServersService { export const mcpAccessConfig = 'chat.mcp.access'; export const mcpGalleryServiceUrlConfig = 'chat.mcp.gallery.serviceUrl'; +export const mcpGalleryServiceEnablementConfig = 'chat.mcp.gallery.enabled'; export const mcpAutoStartConfig = 'chat.mcp.autostart'; export const enum McpAutoStartValue { diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index e5126112eca..7aec3cb801b 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -20,7 +20,7 @@ import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurati import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; -import { McpAccessValue, McpAutoStartValue, mcpAccessConfig, mcpAutoStartConfig, mcpGalleryServiceUrlConfig } from '../../../../platform/mcp/common/mcpManagement.js'; +import { McpAccessValue, McpAutoStartValue, mcpAccessConfig, mcpAutoStartConfig, mcpGalleryServiceEnablementConfig, mcpGalleryServiceUrlConfig } from '../../../../platform/mcp/common/mcpManagement.js'; import { Registry } from '../../../../platform/registry/common/platform.js'; import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js'; import { Extensions, IConfigurationMigrationRegistry } from '../../../common/configuration.js'; @@ -456,6 +456,13 @@ configurationRegistry.registerConfiguration({ default: Object.fromEntries(allDiscoverySources.map(k => [k, false])), markdownDescription: nls.localize('mcp.discovery.enabled', "Configures discovery of Model Context Protocol servers from configuration from various other applications."), }, + [mcpGalleryServiceEnablementConfig]: { + type: 'boolean', + default: false, + tags: ['preview'], + description: nls.localize('chat.mcp.gallery.enabled', "Enables the default Marketplace for Model Context Protocol (MCP) servers."), + included: product.quality === 'stable' + }, [mcpGalleryServiceUrlConfig]: { type: 'string', description: nls.localize('mcp.gallery.serviceUrl', "Configure the MCP Gallery service URL to connect to"), diff --git a/src/vs/workbench/contrib/mcp/browser/mcp.contribution.ts b/src/vs/workbench/contrib/mcp/browser/mcp.contribution.ts index 64183700265..4bbd3637b70 100644 --- a/src/vs/workbench/contrib/mcp/browser/mcp.contribution.ts +++ b/src/vs/workbench/contrib/mcp/browser/mcp.contribution.ts @@ -33,7 +33,7 @@ import { McpSamplingService } from '../common/mcpSamplingService.js'; import { McpService } from '../common/mcpService.js'; import { IMcpElicitationService, IMcpSamplingService, IMcpService, IMcpWorkbenchService } from '../common/mcpTypes.js'; import { McpAddContextContribution } from './mcpAddContextContribution.js'; -import { AddConfigurationAction, BrowseMcpServersPageCommand, EditStoredInput, ListMcpServerCommand, McpBrowseCommand, McpBrowseResourcesCommand, McpConfigureSamplingModels, McpConfirmationServerOptionsCommand, MCPServerActionRendering, McpServerOptionsCommand, McpStartPromptingServerCommand, OpenRemoteUserMcpResourceCommand, OpenUserMcpResourceCommand, OpenWorkspaceFolderMcpResourceCommand, OpenWorkspaceMcpResourceCommand, RemoveStoredInput, ResetMcpCachedTools, ResetMcpTrustCommand, RestartServer, ShowConfiguration, ShowInstalledMcpServersCommand, ShowOutput, StartServer, StopServer } from './mcpCommands.js'; +import { AddConfigurationAction, EditStoredInput, ListMcpServerCommand, McpBrowseCommand, McpBrowseResourcesCommand, McpConfigureSamplingModels, McpConfirmationServerOptionsCommand, MCPServerActionRendering, McpServerOptionsCommand, McpStartPromptingServerCommand, OpenRemoteUserMcpResourceCommand, OpenUserMcpResourceCommand, OpenWorkspaceFolderMcpResourceCommand, OpenWorkspaceMcpResourceCommand, RemoveStoredInput, ResetMcpCachedTools, ResetMcpTrustCommand, RestartServer, ShowConfiguration, ShowInstalledMcpServersCommand, ShowOutput, StartServer, StopServer } from './mcpCommands.js'; import { McpDiscovery } from './mcpDiscovery.js'; import { McpElicitationService } from './mcpElicitationService.js'; import { McpLanguageFeatures } from './mcpLanguageFeatures.js'; @@ -76,7 +76,6 @@ registerAction2(ShowOutput); registerAction2(RestartServer); registerAction2(ShowConfiguration); registerAction2(McpBrowseCommand); -registerAction2(BrowseMcpServersPageCommand); registerAction2(OpenUserMcpResourceCommand); registerAction2(OpenRemoteUserMcpResourceCommand); registerAction2(OpenWorkspaceMcpResourceCommand); diff --git a/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts b/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts index 0aa549a8258..9d3ff8dcede 100644 --- a/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts +++ b/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts @@ -32,11 +32,8 @@ import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextke import { IFileService } from '../../../../platform/files/common/files.js'; import { nativeHoverDelegate } from '../../../../platform/hover/browser/hover.js'; import { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js'; -import { McpGalleryManifestStatus } from '../../../../platform/mcp/common/mcpGalleryManifest.js'; import { mcpAutoStartConfig, McpAutoStartValue } from '../../../../platform/mcp/common/mcpManagement.js'; import { observableConfigValue } from '../../../../platform/observable/common/platformObservableUtils.js'; -import { IOpenerService } from '../../../../platform/opener/common/opener.js'; -import { IProductService } from '../../../../platform/product/common/productService.js'; import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../platform/quickinput/common/quickInput.js'; import { StorageScope } from '../../../../platform/storage/common/storage.js'; import { defaultCheckboxStyles } from '../../../../platform/theme/browser/defaultStyles.js'; @@ -65,7 +62,7 @@ import { TEXT_FILE_EDITOR_ID } from '../../files/common/files.js'; import { McpCommandIds } from '../common/mcpCommandIds.js'; import { McpContextKeys } from '../common/mcpContextKeys.js'; import { IMcpRegistry } from '../common/mcpRegistryTypes.js'; -import { HasInstalledMcpServersContext, IMcpSamplingService, IMcpServer, IMcpServerStartOpts, IMcpService, InstalledMcpServersViewId, LazyCollectionState, McpCapability, McpCollectionDefinition, McpConnectionState, McpDefinitionReference, mcpPromptPrefix, McpServerCacheState, McpServersGalleryStatusContext, McpStartServerInteraction } from '../common/mcpTypes.js'; +import { HasInstalledMcpServersContext, IMcpSamplingService, IMcpServer, IMcpServerStartOpts, IMcpService, InstalledMcpServersViewId, LazyCollectionState, McpCapability, McpCollectionDefinition, McpConnectionState, McpDefinitionReference, mcpPromptPrefix, McpServerCacheState, McpStartServerInteraction } from '../common/mcpTypes.js'; import { McpAddConfigurationCommand } from './mcpCommandsAddConfiguration.js'; import { McpResourceQuickAccess, McpResourceQuickPick } from './mcpResourceQuickAccess.js'; import './media/mcpServerAction.css'; @@ -848,11 +845,17 @@ export class McpBrowseCommand extends Action2 { super({ id: McpCommandIds.Browse, title: localize2('mcp.command.browse', "MCP Servers"), + tooltip: localize2('mcp.command.browse.tooltip', "Browse MCP Servers"), category, + icon: Codicon.globe, menu: [{ id: extensionsFilterSubMenu, group: '1_predefined', order: 1, + }, { + id: MenuId.ViewTitle, + when: ContextKeyExpr.and(ContextKeyExpr.equals('view', InstalledMcpServersViewId)), + group: 'navigation', }], }); } @@ -865,32 +868,11 @@ export class McpBrowseCommand extends Action2 { MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: McpCommandIds.Browse, - title: localize2('mcp.command.browse.mcp', "Browse Servers"), + title: localize2('mcp.command.browse.mcp', "Browse MCP Servers"), category }, }); -export class BrowseMcpServersPageCommand extends Action2 { - constructor() { - super({ - id: McpCommandIds.BrowsePage, - title: localize2('mcp.command.open', "Browse MCP Servers"), - icon: Codicon.globe, - menu: [{ - id: MenuId.ViewTitle, - when: ContextKeyExpr.and(ContextKeyExpr.equals('view', InstalledMcpServersViewId), McpServersGalleryStatusContext.isEqualTo(McpGalleryManifestStatus.Unavailable)), - group: 'navigation', - }], - }); - } - - async run(accessor: ServicesAccessor) { - const productService = accessor.get(IProductService); - const openerService = accessor.get(IOpenerService); - return openerService.open(productService.quality === 'insider' ? 'https://code.visualstudio.com/insider/mcp' : 'https://code.visualstudio.com/mcp'); - } -} - export class ShowInstalledMcpServersCommand extends Action2 { constructor() { super({ diff --git a/src/vs/workbench/contrib/mcp/browser/mcpServersView.ts b/src/vs/workbench/contrib/mcp/browser/mcpServersView.ts index 1c60845f078..364c0a86e91 100644 --- a/src/vs/workbench/contrib/mcp/browser/mcpServersView.ts +++ b/src/vs/workbench/contrib/mcp/browser/mcpServersView.ts @@ -12,7 +12,7 @@ import { combinedDisposable, Disposable, DisposableStore, dispose, IDisposable, import { DelayedPagedModel, IPagedModel, PagedModel } from '../../../../base/common/paging.js'; import { localize, localize2 } from '../../../../nls.js'; import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; -import { ContextKeyExpr, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; +import { ContextKeyDefinedExpr, ContextKeyExpr, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js'; import { IHoverService } from '../../../../platform/hover/browser/hover.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; @@ -24,15 +24,15 @@ import { IThemeService } from '../../../../platform/theme/common/themeService.js import { getLocationBasedViewColors } from '../../../browser/parts/views/viewPane.js'; import { IViewletViewOptions } from '../../../browser/parts/views/viewsViewlet.js'; import { IViewDescriptorService, IViewsRegistry, ViewContainerLocation, Extensions as ViewExtensions } from '../../../common/views.js'; -import { HasInstalledMcpServersContext, IMcpWorkbenchService, InstalledMcpServersViewId, IWorkbenchMcpServer, McpServerContainers, McpServerEnablementState, McpServerInstallState } from '../common/mcpTypes.js'; +import { HasInstalledMcpServersContext, IMcpWorkbenchService, InstalledMcpServersViewId, IWorkbenchMcpServer, McpServerContainers, McpServerEnablementState, McpServerInstallState, McpServersGalleryStatusContext } from '../common/mcpTypes.js'; import { DropDownAction, InstallAction, InstallingLabelAction, ManageMcpServerAction, McpServerStatusAction } from './mcpServerActions.js'; import { PublisherWidget, StarredWidget, McpServerIconWidget, McpServerHoverWidget, McpServerScopeBadgeWidget } from './mcpServerWidgets.js'; import { ActionRunner, IAction, Separator } from '../../../../base/common/actions.js'; import { IActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js'; -import { IAllowedMcpServersService } from '../../../../platform/mcp/common/mcpManagement.js'; +import { IAllowedMcpServersService, mcpGalleryServiceEnablementConfig, mcpGalleryServiceUrlConfig } from '../../../../platform/mcp/common/mcpManagement.js'; import { URI } from '../../../../base/common/uri.js'; import { ThemeIcon } from '../../../../base/common/themables.js'; -import { IProductService } from '../../../../platform/product/common/productService.js'; + import { Registry } from '../../../../platform/registry/common/platform.js'; import { IWorkbenchContribution } from '../../../common/contributions.js'; import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js'; @@ -50,9 +50,11 @@ import { IWorkbenchLayoutService, Position } from '../../../services/layout/brow import { mcpServerIcon } from './mcpServerIcons.js'; import { IPagedRenderer } from '../../../../base/browser/ui/list/listPaging.js'; import { IMcpGalleryManifestService, McpGalleryManifestStatus } from '../../../../platform/mcp/common/mcpGalleryManifest.js'; +import { IPreferencesService } from '../../../services/preferences/common/preferences.js'; +import { ProductQualityContext } from '../../../../platform/contextkey/common/contextkeys.js'; export interface McpServerListViewOptions { - showWelcomeOnEmpty?: boolean; + showWelcome?: boolean; } interface IQueryResult { @@ -82,9 +84,9 @@ export class McpServersListView extends AbstractExtensionsListView { @@ -241,15 +245,16 @@ export class McpServersListView extends AbstractExtensionsListView this.openerService.open(URI.parse(this.productService.quality === 'insider' ? 'https://code.visualstudio.com/insider/mcp' : 'https://code.visualstudio.com/mcp')))); + this._register(button.onDidClick(() => this.preferencesService.openSettings({ + query: `@id:${mcpGalleryServiceEnablementConfig}`, + }))); } private async query(query: string): Promise { @@ -443,7 +448,7 @@ export class McpServersViewsContribution extends Disposable implements IWorkbenc { id: InstalledMcpServersViewId, name: localize2('mcp-installed', "MCP Servers - Installed"), - ctorDescriptor: new SyncDescriptor(McpServersListView, [{ showWelcomeOnEmpty: false }]), + ctorDescriptor: new SyncDescriptor(McpServersListView, [{}]), when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext), weight: 40, order: 4, @@ -452,8 +457,8 @@ export class McpServersViewsContribution extends Disposable implements IWorkbenc { id: 'workbench.views.mcp.default.marketplace', name: localize2('mcp', "MCP Servers"), - ctorDescriptor: new SyncDescriptor(DefaultBrowseMcpServersView, [{ showWelcomeOnEmpty: true }]), - when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext.toNegated(), ChatContextKeys.Setup.hidden.negate()), + ctorDescriptor: new SyncDescriptor(DefaultBrowseMcpServersView, [{}]), + when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext.toNegated(), ChatContextKeys.Setup.hidden.negate(), McpServersGalleryStatusContext.isEqualTo(McpGalleryManifestStatus.Available), ContextKeyExpr.or(ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceUrlConfig}`), ProductQualityContext.notEqualsTo('stable'), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceEnablementConfig}`))), weight: 40, order: 4, canToggleVisibility: true @@ -461,8 +466,23 @@ export class McpServersViewsContribution extends Disposable implements IWorkbenc { id: 'workbench.views.mcp.marketplace', name: localize2('mcp', "MCP Servers"), - ctorDescriptor: new SyncDescriptor(McpServersListView, [{ showWelcomeOnEmpty: true }]), - when: ContextKeyExpr.and(SearchMcpServersContext), + ctorDescriptor: new SyncDescriptor(McpServersListView, [{}]), + when: ContextKeyExpr.and(SearchMcpServersContext, McpServersGalleryStatusContext.isEqualTo(McpGalleryManifestStatus.Available), ContextKeyExpr.or(ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceUrlConfig}`), ProductQualityContext.notEqualsTo('stable'), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceEnablementConfig}`))), + }, + { + id: 'workbench.views.mcp.default.welcomeView', + name: localize2('mcp', "MCP Servers"), + ctorDescriptor: new SyncDescriptor(DefaultBrowseMcpServersView, [{ showWelcome: true }]), + when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext.toNegated(), ChatContextKeys.Setup.hidden.negate(), McpServersGalleryStatusContext.isEqualTo(McpGalleryManifestStatus.Available), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceUrlConfig}`).negate(), ProductQualityContext.isEqualTo('stable'), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceEnablementConfig}`).negate()), + weight: 40, + order: 4, + canToggleVisibility: false + }, + { + id: 'workbench.views.mcp.welcomeView', + name: localize2('mcp', "MCP Servers"), + ctorDescriptor: new SyncDescriptor(McpServersListView, [{ showWelcome: true }]), + when: ContextKeyExpr.and(SearchMcpServersContext, McpServersGalleryStatusContext.isEqualTo(McpGalleryManifestStatus.Available), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceUrlConfig}`).negate(), ProductQualityContext.isEqualTo('stable'), ContextKeyDefinedExpr.create(`config.${mcpGalleryServiceEnablementConfig}`).negate()), } ], VIEW_CONTAINER); }