Skip to content

Commit 8f8efd5

Browse files
authored
Fix mcp server uri handling (#252350)
* Fix mcp server uri handling * feedback and some fixes
1 parent 7fdfadf commit 8f8efd5

File tree

12 files changed

+132
-182
lines changed

12 files changed

+132
-182
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export type UninstallOptions = {
176176
mcpResource?: URI;
177177
};
178178

179-
export interface IMcpServer {
179+
export interface IInstallableMcpServer {
180180
name: string;
181181
config: IMcpServerConfiguration;
182182
inputs?: IMcpServerVariable[];
@@ -190,7 +190,7 @@ export interface IMcpManagementService {
190190
readonly onUninstallMcpServer: Event<UninstallMcpServerEvent>;
191191
readonly onDidUninstallMcpServer: Event<DidUninstallMcpServerEvent>;
192192
getInstalled(mcpResource?: URI): Promise<ILocalMcpServer[]>;
193-
install(server: IMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
193+
install(server: IInstallableMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
194194
installFromGallery(server: IGalleryMcpServer, options?: InstallOptions): Promise<ILocalMcpServer>;
195195
uninstall(server: ILocalMcpServer, options?: UninstallOptions): Promise<void>;
196196
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { cloneAndChange } from '../../../base/common/objects.js';
99
import { URI, UriComponents } from '../../../base/common/uri.js';
1010
import { DefaultURITransformer, IURITransformer, transformAndReviveIncomingURIs } from '../../../base/common/uriIpc.js';
1111
import { IChannel, IServerChannel } from '../../../base/parts/ipc/common/ipc.js';
12-
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpManagementService, IMcpServer, InstallMcpServerEvent, InstallMcpServerResult, InstallOptions, UninstallMcpServerEvent, UninstallOptions } from './mcpManagement.js';
12+
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpManagementService, IInstallableMcpServer, InstallMcpServerEvent, InstallMcpServerResult, InstallOptions, UninstallMcpServerEvent, UninstallOptions } from './mcpManagement.js';
1313

1414
function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI;
1515
function transformIncomingURI(uri: UriComponents | undefined, transformer: IURITransformer | null): URI | undefined;
@@ -126,7 +126,7 @@ export class McpManagementChannelClient extends Disposable implements IMcpManage
126126
this._register(this.channel.listen<DidUninstallMcpServerEvent>('onDidUninstallMcpServer')(e => this._onDidUninstallMcpServer.fire(({ ...e, mcpResource: transformIncomingURI(e.mcpResource, null) }))));
127127
}
128128

129-
install(server: IMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
129+
install(server: IInstallableMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
130130
return Promise.resolve(this.channel.call<ILocalMcpServer>('install', [server, options])).then(local => transformIncomingServer(local, null));
131131
}
132132

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ import { VSBuffer } from '../../../base/common/buffer.js';
77
import { CancellationToken } from '../../../base/common/cancellation.js';
88
import { Emitter } from '../../../base/common/event.js';
99
import { Disposable } from '../../../base/common/lifecycle.js';
10-
import { uppercaseFirstLetter } from '../../../base/common/strings.js';
1110
import { URI } from '../../../base/common/uri.js';
1211
import { ConfigurationTarget } from '../../configuration/common/configuration.js';
1312
import { IEnvironmentService } from '../../environment/common/environment.js';
1413
import { IFileService } from '../../files/common/files.js';
1514
import { ILogService } from '../../log/common/log.js';
1615
import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.js';
1716
import { IUserDataProfilesService } from '../../userDataProfile/common/userDataProfile.js';
18-
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpGalleryService, IMcpManagementService, IMcpServerInput, IMcpServerManifest, InstallMcpServerEvent, InstallMcpServerResult, PackageType, UninstallMcpServerEvent, IScannedMcpServer, InstallOptions, UninstallOptions, IMcpServer } from './mcpManagement.js';
17+
import { DidUninstallMcpServerEvent, IGalleryMcpServer, ILocalMcpServer, IMcpGalleryService, IMcpManagementService, IMcpServerInput, IMcpServerManifest, InstallMcpServerEvent, InstallMcpServerResult, PackageType, UninstallMcpServerEvent, IScannedMcpServer, InstallOptions, UninstallOptions, IInstallableMcpServer } from './mcpManagement.js';
1918
import { IMcpServerVariable, McpServerVariableType, IMcpServerConfiguration } from './mcpPlatformTypes.js';
2019
import { IMcpResourceScannerService, McpResourceTarget } from './mcpResourceScannerService.js';
2120

@@ -83,19 +82,9 @@ export abstract class AbstractMcpManagementService extends Disposable implements
8382
protected async scanServer(scannedMcpServer: IScannedMcpServer, mcpResource: URI): Promise<ILocalMcpServer> {
8483
let mcpServerInfo = await this.getLocalMcpServerInfo(scannedMcpServer);
8584
if (!mcpServerInfo) {
86-
let publisher = '';
87-
const nameParts = scannedMcpServer.name.split('/');
88-
if (nameParts.length > 0) {
89-
const domainParts = nameParts[0].split('.');
90-
if (domainParts.length > 0) {
91-
publisher = domainParts[domainParts.length - 1]; // Always take the last part as owner
92-
}
93-
}
9485
mcpServerInfo = {
9586
name: scannedMcpServer.name,
9687
version: '1.0.0',
97-
displayName: nameParts[nameParts.length - 1].split('-').map(s => uppercaseFirstLetter(s)).join(' '),
98-
publisher
9988
};
10089
}
10190

@@ -117,7 +106,7 @@ export abstract class AbstractMcpManagementService extends Disposable implements
117106
};
118107
}
119108

120-
async install(server: IMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
109+
async install(server: IInstallableMcpServer, options?: InstallOptions): Promise<ILocalMcpServer> {
121110
this.logService.trace('MCP Management Service: install', server.name);
122111

123112
const mcpResource = options?.mcpResource ?? this.getDefaultMcpResource();

src/vs/workbench/contrib/mcp/browser/mcp.contribution.ts

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { localize, localize2 } from '../../../../nls.js';
6+
import { localize } from '../../../../nls.js';
77
import { registerAction2 } from '../../../../platform/actions/common/actions.js';
8-
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
98
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
109
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
1110
import * as jsonContributionRegistry from '../../../../platform/jsonschemas/common/jsonContributionRegistry.js';
@@ -14,10 +13,7 @@ import { Registry } from '../../../../platform/registry/common/platform.js';
1413
import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';
1514
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
1615
import { EditorExtensions } from '../../../common/editor.js';
17-
import { IViewsRegistry, Extensions as ViewExtensions } from '../../../common/views.js';
1816
import { mcpSchemaId } from '../../../services/configuration/common/configuration.js';
19-
import { VIEW_CONTAINER } from '../../extensions/browser/extensions.contribution.js';
20-
import { DefaultViewsContext, SearchMcpServersContext } from '../../extensions/common/extensions.js';
2117
import { ExtensionMcpDiscovery } from '../common/discovery/extensionMcpDiscovery.js';
2218
import { InstalledMcpServersDiscovery } from '../common/discovery/installedMcpServersDiscovery.js';
2319
import { mcpDiscoveryRegistry } from '../common/discovery/mcpDiscovery.js';
@@ -32,18 +28,17 @@ import { IMcpRegistry } from '../common/mcpRegistryTypes.js';
3228
import { McpResourceFilesystem } from '../common/mcpResourceFilesystem.js';
3329
import { McpSamplingService } from '../common/mcpSamplingService.js';
3430
import { McpService } from '../common/mcpService.js';
35-
import { HasInstalledMcpServersContext, IMcpElicitationService, IMcpSamplingService, IMcpService, IMcpWorkbenchService, InstalledMcpServersViewId } from '../common/mcpTypes.js';
31+
import { IMcpElicitationService, IMcpSamplingService, IMcpService, IMcpWorkbenchService } from '../common/mcpTypes.js';
3632
import { McpAddContextContribution } from './mcpAddContextContribution.js';
37-
import { AddConfigurationAction, EditStoredInput, InstallFromActivation, ListMcpServerCommand, McpBrowseCommand, McpBrowseResourcesCommand, McpConfigureSamplingModels, MCPServerActionRendering, McpServerOptionsCommand, McpStartPromptingServerCommand, RemoveStoredInput, ResetMcpCachedTools, ResetMcpTrustCommand, RestartServer, ShowConfiguration, ShowInstalledMcpServersCommand, ShowOutput, StartServer, StopServer } from './mcpCommands.js';
33+
import { AddConfigurationAction, EditStoredInput, ListMcpServerCommand, McpBrowseCommand, McpBrowseResourcesCommand, McpConfigureSamplingModels, MCPServerActionRendering, McpServerOptionsCommand, McpStartPromptingServerCommand, RemoveStoredInput, ResetMcpCachedTools, ResetMcpTrustCommand, RestartServer, ShowConfiguration, ShowInstalledMcpServersCommand, ShowOutput, StartServer, StopServer } from './mcpCommands.js';
3834
import { McpDiscovery } from './mcpDiscovery.js';
3935
import { McpElicitationService } from './mcpElicitationService.js';
4036
import { McpLanguageFeatures } from './mcpLanguageFeatures.js';
4137
import { McpConfigMigrationContribution } from './mcpMigration.js';
4238
import { McpResourceQuickAccess } from './mcpResourceQuickAccess.js';
4339
import { McpServerEditor } from './mcpServerEditor.js';
4440
import { McpServerEditorInput } from './mcpServerEditorInput.js';
45-
import { DefaultBrowseMcpServersView, McpServersListView } from './mcpServersView.js';
46-
import { McpUrlHandler } from './mcpUrlHandler.js';
41+
import { McpServersViewsContribution } from './mcpServersView.js';
4742
import { MCPContextsInitialisation, McpWorkbenchService } from './mcpWorkbenchService.js';
4843

4944
registerSingleton(IMcpRegistry, McpRegistry, InstantiationType.Delayed);
@@ -61,7 +56,6 @@ mcpDiscoveryRegistry.register(new SyncDescriptor(CursorWorkspaceMcpDiscoveryAdap
6156
registerWorkbenchContribution2('mcpDiscovery', McpDiscovery, WorkbenchPhase.AfterRestored);
6257
registerWorkbenchContribution2('mcpContextKeys', McpContextKeysController, WorkbenchPhase.BlockRestore);
6358
registerWorkbenchContribution2('mcpLanguageFeatures', McpLanguageFeatures, WorkbenchPhase.Eventually);
64-
registerWorkbenchContribution2('mcpUrlHandler', McpUrlHandler, WorkbenchPhase.BlockRestore);
6559
registerWorkbenchContribution2('mcpResourceFilesystem', McpResourceFilesystem, WorkbenchPhase.BlockRestore);
6660

6761
registerAction2(ListMcpServerCommand);
@@ -74,7 +68,6 @@ registerAction2(EditStoredInput);
7468
registerAction2(StartServer);
7569
registerAction2(StopServer);
7670
registerAction2(ShowOutput);
77-
registerAction2(InstallFromActivation);
7871
registerAction2(RestartServer);
7972
registerAction2(ShowConfiguration);
8073
registerAction2(McpBrowseCommand);
@@ -87,37 +80,11 @@ registerWorkbenchContribution2('mcpActionRendering', MCPServerActionRendering, W
8780
registerWorkbenchContribution2('mcpAddContext', McpAddContextContribution, WorkbenchPhase.Eventually);
8881
registerWorkbenchContribution2(MCPContextsInitialisation.ID, MCPContextsInitialisation, WorkbenchPhase.AfterRestored);
8982
registerWorkbenchContribution2(McpConfigMigrationContribution.ID, McpConfigMigrationContribution, WorkbenchPhase.Eventually);
83+
registerWorkbenchContribution2(McpServersViewsContribution.ID, McpServersViewsContribution, WorkbenchPhase.AfterRestored);
9084

9185
const jsonRegistry = <jsonContributionRegistry.IJSONContributionRegistry>Registry.as(jsonContributionRegistry.Extensions.JSONContribution);
9286
jsonRegistry.registerSchema(mcpSchemaId, mcpServerSchema);
9387

94-
Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([
95-
{
96-
id: InstalledMcpServersViewId,
97-
name: localize2('mcp-installed', "MCP Servers - Installed"),
98-
ctorDescriptor: new SyncDescriptor(McpServersListView, [{ showWelcomeOnEmpty: false }]),
99-
when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext),
100-
weight: 40,
101-
order: 4,
102-
canToggleVisibility: true
103-
},
104-
{
105-
id: 'workbench.views.mcp.default.marketplace',
106-
name: localize2('mcp', "MCP Servers"),
107-
ctorDescriptor: new SyncDescriptor(DefaultBrowseMcpServersView, [{ showWelcomeOnEmpty: true }]),
108-
when: ContextKeyExpr.and(DefaultViewsContext, HasInstalledMcpServersContext.toNegated()),
109-
weight: 40,
110-
order: 4,
111-
canToggleVisibility: true
112-
},
113-
{
114-
id: 'workbench.views.mcp.marketplace',
115-
name: localize2('mcp', "MCP Servers"),
116-
ctorDescriptor: new SyncDescriptor(McpServersListView, [{ showWelcomeOnEmpty: true }]),
117-
when: ContextKeyExpr.and(SearchMcpServersContext),
118-
}
119-
], VIEW_CONTAINER);
120-
12188
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
12289
EditorPaneDescriptor.create(
12390
McpServerEditor,

src/vs/workbench/contrib/mcp/browser/mcpCommands.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ import { IMcpRegistry } from '../common/mcpRegistryTypes.js';
4848
import { HasInstalledMcpServersContext, IMcpSamplingService, IMcpServer, IMcpServerStartOpts, IMcpService, InstalledMcpServersViewId, LazyCollectionState, McpCapability, McpConnectionState, mcpPromptPrefix, McpServerCacheState } from '../common/mcpTypes.js';
4949
import { McpAddConfigurationCommand } from './mcpCommandsAddConfiguration.js';
5050
import { McpResourceQuickAccess, McpResourceQuickPick } from './mcpResourceQuickAccess.js';
51-
import { McpUrlHandler } from './mcpUrlHandler.js';
5251
import { openPanelChatAndGetWidget } from './openPanelChatAndGetWidget.js';
5352

5453
// acroynms do not get localized
@@ -737,26 +736,6 @@ export class StopServer extends Action2 {
737736
}
738737
}
739738

740-
export class InstallFromActivation extends Action2 {
741-
constructor() {
742-
super({
743-
id: McpCommandIds.InstallFromActivation,
744-
title: localize2('mcp.command.installFromActivation', "Install..."),
745-
category,
746-
f1: false,
747-
menu: {
748-
id: MenuId.EditorContent,
749-
when: ContextKeyExpr.equals('resourceScheme', McpUrlHandler.scheme)
750-
}
751-
});
752-
}
753-
754-
async run(accessor: ServicesAccessor, uri: URI) {
755-
const addConfigHelper = accessor.get(IInstantiationService).createInstance(McpAddConfigurationCommand, undefined);
756-
addConfigHelper.pickForUrlHandler(uri);
757-
}
758-
}
759-
760739
export class McpBrowseCommand extends Action2 {
761740
constructor() {
762741
super({

src/vs/workbench/contrib/mcp/browser/mcpServerActions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ export class InstallAction extends McpServerAction {
107107
update(): void {
108108
this.enabled = false;
109109
this.class = InstallAction.HIDE;
110-
if (!this.mcpServer?.gallery) {
110+
if (this.mcpServer?.local) {
111111
return;
112112
}
113-
if (this.mcpServer.local) {
113+
if (!this.mcpServer?.gallery && !this.mcpServer?.installable) {
114114
return;
115115
}
116116
this.class = InstallAction.CLASS;
@@ -122,7 +122,7 @@ export class InstallAction extends McpServerAction {
122122
if (!this.mcpServer) {
123123
return;
124124
}
125-
await this.mcpWorkbenchService.installFromGallery(this.mcpServer);
125+
await this.mcpWorkbenchService.install(this.mcpServer);
126126
}
127127
}
128128

src/vs/workbench/contrib/mcp/browser/mcpServerEditor.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,11 @@ export class McpServerEditor extends EditorPane {
317317
this.currentIdentifier = extension.id;
318318
}
319319

320-
template.navbar.push(McpServerEditorTab.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
320+
if (extension.hasReadme()) {
321+
template.navbar.push(McpServerEditorTab.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
322+
}
321323

322-
if (extension.local) {
324+
if (extension.config) {
323325
template.navbar.push(McpServerEditorTab.Configuration, localize('configuration', "Configuration"), localize('configurationtooltip', "Server configuration details"));
324326
}
325327

@@ -562,20 +564,20 @@ export class McpServerEditor extends EditorPane {
562564
private renderConfigurationDetails(container: HTMLElement, mcpServer: IWorkbenchMcpServer): void {
563565
container.remove();
564566

565-
if (!mcpServer.local) {
567+
const config = mcpServer.config;
568+
569+
if (!config) {
566570
const noConfigMessage = append(container, $('.no-config'));
567571
noConfigMessage.textContent = localize('noConfig', "No configuration available for this MCP server.");
568572
return;
569573
}
570574

571-
const config = mcpServer.local.config;
572-
573575
// Server Name
574576
const nameSection = append(container, $('.config-section'));
575577
const nameLabel = append(nameSection, $('.config-label'));
576578
nameLabel.textContent = localize('serverName', "Name:");
577579
const nameValue = append(nameSection, $('.config-value'));
578-
nameValue.textContent = mcpServer.local.name;
580+
nameValue.textContent = mcpServer.name;
579581

580582
// Server Type
581583
const typeSection = append(container, $('.config-section'));

0 commit comments

Comments
 (0)