Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -601,13 +601,6 @@ export class McpServerItemRenderer extends Disposable implements IListRenderer<I
}

if (!presentation?.icon) {
const compatibility = getMcpCompatibilityPresentation(compatibilityKind);
if (compatibility) {
const icon = DOM.append(templateData.actions, $('.mcp-server-status.mcp-server-state-icon'));
updateMcpCompatibilityIcon(icon, compatibilityKind, undefined);
icon.setAttribute('aria-hidden', 'true');
templateData.actionDisposables.add(this.hoverService.setupManagedHover(getDefaultHoverDelegate('element'), icon, compatibility.label));
}
this._renderManagementActions(getEntry, templateData.actions, templateData.actionDisposables, () => this.updateActionsTabbability(templateData));
this.updateActionsTabbability(templateData);
return;
Expand Down Expand Up @@ -935,6 +928,11 @@ export function updateMcpCompatibilityMessage(message: HTMLElement, kind: Custom
},
}, message);
const migrationLink = message.firstElementChild as HTMLAnchorElement | null;
const iconTheme = kind === 'unsupported' ? Codicon.error : Codicon.warning;
Comment thread
hawkticehurst marked this conversation as resolved.
const icon = $('span.mcp-server-compatibility-icon');
icon.classList.add(...ThemeIcon.asClassNameArray(iconTheme));
icon.setAttribute('aria-hidden', 'true');
message.insertBefore(icon, message.firstChild);
if (migrationLink) {
migrationLink.href = '#';
migrationLink.tabIndex = -1;
Expand All @@ -944,17 +942,6 @@ export function updateMcpCompatibilityMessage(message: HTMLElement, kind: Custom
return migrationLink ?? undefined;
}

function updateMcpCompatibilityIcon(icon: HTMLElement, kind: CustomizationMcpServerCompatibilityKind | undefined, runtimeIcon: ThemeIcon | undefined): void {
const compatibility = getMcpCompatibilityPresentation(kind);
if (runtimeIcon || !compatibility) {
return;
}
const iconTheme = kind === 'unsupported' ? Codicon.error : Codicon.warning;
icon.className = `mcp-server-state-icon ${ThemeIcon.asClassNameArray(iconTheme).join(' ')} compatibility ${compatibility.className}`;
icon.style.display = '';
icon.setAttribute('aria-label', compatibility.label);
}

export function getMcpStatusPresentation(state: McpStatusKind | undefined, disabledReason?: CustomizationDisabledReason): IMcpStatusPresentation | undefined {
if (state === undefined) {
return undefined;
Expand Down Expand Up @@ -2775,7 +2762,6 @@ export class McpListWidget extends Disposable {
getMcpEntryAriaLabel(entry, this.workspaceService.isSessionsWindow, compatibilityKind, this.labelService, this.agentPluginService, this.extensionsWorkbenchService),
this.getInstalledEntryDescription(entry),
);
updateMcpCompatibilityIcon(statusIcon, compatibilityKind, getMcpStatusPresentation(getMcpStatusKind(entry, this.workspaceService.isSessionsWindow))?.icon);
start.update();
showOutput.update();
}));
Expand All @@ -2796,7 +2782,6 @@ export class McpListWidget extends Disposable {
getMcpEntryAriaLabel(entry, this.workspaceService.isSessionsWindow, compatibilityKind, this.labelService, this.agentPluginService, this.extensionsWorkbenchService),
this.getInstalledEntryDescription(entry),
);
updateMcpCompatibilityIcon(statusIcon, compatibilityKind, getMcpStatusPresentation(getMcpStatusKind(entry, this.workspaceService.isSessionsWindow))?.icon);
signIn?.update();
start.update();
showOutput.update();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2669,6 +2669,15 @@ per-word capitalization does not survive translation. */
color: var(--vscode-errorForeground);
}

.ai-customization-management-editor .mcp-server-compatibility-message > .mcp-server-compatibility-icon.codicon {
margin-right: var(--vscode-spacing-size40);
font-size: var(--vscode-codiconFontSize-compact);
color: inherit;
position: relative;
top: -1px;
vertical-align: text-bottom;
}

.mcp-server-item .mcp-server-source-path.source-link + .mcp-server-compatibility-message::before {
content: "· ";
color: var(--vscode-descriptionForeground);
Expand Down Expand Up @@ -2791,14 +2800,6 @@ per-word capitalization does not survive translation. */
color: var(--vscode-errorForeground);
}

.plugin-list-widget .mcp-server-state-icon.compatibility {
color: var(--vscode-chat-mcpCompatibilityWarningForeground);
}

.plugin-list-widget .mcp-server-state-icon.compatibility.unsupported {
color: var(--vscode-errorForeground);
}

.plugin-list-widget .mcp-server-state-icon.starting {
color: var(--vscode-progressBar-background, var(--vscode-icon-foreground));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,8 @@ suite('mcpListWidget', () => {
],
messageClass: message.className,
messageText: message.textContent,
messageIcon: message.querySelector('.mcp-server-compatibility-icon')?.className,
messageIconAriaHidden: message.querySelector('.mcp-server-compatibility-icon')?.getAttribute('aria-hidden'),
messageDisplay: message.style.display,
linkHref: message.querySelector<HTMLAnchorElement>('.mcp-server-compatibility-link')?.getAttribute('href'),
migrationRequests,
Expand All @@ -790,6 +792,8 @@ suite('mcpListWidget', () => {
],
messageClass: 'mcp-server-compatibility-message partially-supported',
messageText: 'Partially supported. See Migrations for details.',
messageIcon: 'mcp-server-compatibility-icon codicon codicon-warning',
messageIconAriaHidden: 'true',
messageDisplay: '',
linkHref: '#',
migrationRequests: 1,
Expand Down Expand Up @@ -2199,7 +2203,7 @@ suite('mcpListWidget', () => {
assert.strictEqual(ctx.templateData.container.style.minHeight, '44px');
});

test('compatibility issues use severity-specific icons without runtime status', () => {
test('compatibility issues use severity-specific icons at the beginning of their messages', () => {
const render = (kind: 'unsupported' | 'partiallySupported') => {
const ctx = createRenderer(createAgentHostServer(), true, false, undefined, kind);
disposables.add(ctx.store);
Expand All @@ -2210,7 +2214,8 @@ suite('mcpListWidget', () => {
ctx.notifyUnchanged();
return {
message: ctx.templateData.compatibilityMessage.textContent,
icon: ctx.templateData.actions.querySelector('.mcp-server-state-icon.compatibility')?.className,
messageIcon: ctx.templateData.compatibilityMessage.querySelector('.mcp-server-compatibility-icon')?.className,
Comment thread
hawkticehurst marked this conversation as resolved.
actionIcon: ctx.templateData.actions.querySelector('.mcp-server-state-icon.compatibility')?.className,
badges: ctx.templateData.container.querySelectorAll('.plugin-list-item-status').length,
focusedLinkTabIndex,
unfocusedLinkTabIndex: ctx.templateData.compatibilityLink?.tabIndex,
Expand All @@ -2224,15 +2229,17 @@ suite('mcpListWidget', () => {
}, {
unsupported: {
message: 'Unsupported. See Migrations for details.',
icon: 'mcp-server-state-icon codicon codicon-error compatibility unsupported',
messageIcon: 'mcp-server-compatibility-icon codicon codicon-error',
actionIcon: undefined,
badges: 0,
focusedLinkTabIndex: 0,
unfocusedLinkTabIndex: -1,
migrationRequests: 1,
},
partiallySupported: {
message: 'Partially supported. See Migrations for details.',
icon: 'mcp-server-state-icon codicon codicon-warning compatibility partially-supported',
messageIcon: 'mcp-server-compatibility-icon codicon codicon-warning',
actionIcon: undefined,
badges: 0,
focusedLinkTabIndex: 0,
unfocusedLinkTabIndex: -1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2931,21 +2931,21 @@ export default defineThemedFixtureGroup({ path: 'chat/aiCustomizations/' }, {
McpServersTabCopilotCompatibility: defineComponentFixture({
labels: { kind: 'screenshot', blocksCi: false },
additionalThemes: ['light2026', 'lightHighContrast'],
expectedVisualDescriptions: ['With the Copilot harness selected, Unsupported uses a red error icon and red message while Partially supported uses a yellow warning icon and yellow message. Both messages include a Migrations link; configuration file paths and compatibility badges do not appear.'],
expectedVisualDescriptions: ['With the Copilot harness selected, Unsupported begins its red message with a compact red error icon while Partially supported begins its yellow message with a compact yellow warning icon. Both messages include a Migrations link; compatibility icons do not appear beside the row actions, and configuration file paths and compatibility badges do not appear.'],
render: ctx => renderEditor(ctx, {
sessionResource: agentHostCopilotSessionResource,
selectedSection: AICustomizationManagementSection.McpServers,
mcpServerCompatibility: [
{ id: 'component-explorer', kind: 'partiallySupported' },
{ id: 'mcp-postgres', kind: 'unsupported' },
{ id: 'mcp-github', kind: 'unsupported' },
],
}),
}),

McpServersAllStates: defineComponentFixture({
labels: { kind: 'screenshot', blocksCi: false },
additionalThemes: ['light2026', 'darkHighContrast', 'lightHighContrast'],
expectedVisualDescriptions: ['Every installed MCP row has the same height as the default running row. The tree presents all states without configuration file paths: running has no indicator, starting has a spinner, authentication shows Sign In without an auth icon, error retains the ordinary description and shows a red error icon plus Show Output before the switch, stopped shows a Start button styled like Sign In, disabled rows are dimmed with switches off and labels for Globally, Workspace, and Session scopes, Unsupported uses a red error treatment, and Partially supported uses a yellow warning treatment. Compatibility messages include a Migrations link; no state badges or inline error snippets appear.'],
expectedVisualDescriptions: ['Every installed MCP row has the same height as the default running row. The tree presents all states without configuration file paths: running has no indicator, starting has a spinner, authentication shows Sign In without an auth icon, error retains the ordinary description and shows a red error icon plus Show Output before the switch, stopped shows a Start button styled like Sign In, disabled rows are dimmed with switches off and labels for Globally, Workspace, and Session scopes, Unsupported begins its red message with a compact error icon, and Partially supported begins its yellow message with a compact warning icon. Compatibility messages include a Migrations link; compatibility icons do not appear beside row actions, and no state badges or inline error snippets appear.'],
render: async ctx => {
await renderEditor(ctx, {
sessionResource: agentHostCopilotSessionResource,
Expand Down
Loading