fix: unify MCP server label logic with simplified fallback

This commit is contained in:
Pascal 2026-01-18 13:09:43 +01:00
parent 16a03eea36
commit d92b621346
5 changed files with 30 additions and 33 deletions

View File

@ -8,7 +8,7 @@
import McpLogo from '$lib/components/app/misc/McpLogo.svelte';
import { settingsStore } from '$lib/stores/settings.svelte';
import { conversationsStore } from '$lib/stores/conversations.svelte';
import { parseMcpServerSettings, getServerDisplayName, getFaviconUrl } from '$lib/utils/mcp';
import { parseMcpServerSettings, getMcpServerLabel, getFaviconUrl } from '$lib/utils/mcp';
import type { MCPServerSettingsEntry } from '$lib/types';
import { HealthCheckStatus } from '$lib/enums';
import { mcpStore } from '$lib/stores/mcp.svelte';
@ -44,6 +44,10 @@
return conversationsStore.getMcpServerOverride(serverId) !== undefined;
}
function getServerLabel(server: MCPServerSettingsEntry): string {
return getMcpServerLabel(server, mcpStore.getHealthCheckState(server.id));
}
let enabledMcpServersForChat = $derived(
mcpServers.filter((s) => isServerEnabledForChat(s) && s.url.trim())
);
@ -68,7 +72,7 @@
if (usageB !== usageA) return usageB - usageA;
// Then alphabetically by name
return getServerDisplayName(a).localeCompare(getServerDisplayName(b));
return getServerLabel(a).localeCompare(getServerLabel(b));
})
);
@ -76,7 +80,7 @@
const query = searchQuery.toLowerCase().trim();
if (query) {
return sortedMcpServers.filter((s) => {
const name = getServerDisplayName(s).toLowerCase();
const name = getServerLabel(s).toLowerCase();
const url = s.url.toLowerCase();
return name.includes(query) || url.includes(query);
});
@ -173,7 +177,7 @@
}}
/>
{/if}
<span class="truncate text-sm">{getServerDisplayName(server)}</span>
<span class="truncate text-sm">{getServerLabel(server)}</span>
{#if hasError}
<span class="shrink-0 rounded bg-destructive/15 px-1.5 py-0.5 text-xs text-destructive"
>Error</span

View File

@ -2,6 +2,7 @@
import { onMount, tick } from 'svelte';
import * as Card from '$lib/components/ui/card';
import type { MCPServerSettingsEntry, HealthCheckState } from '$lib/types';
import { getMcpServerLabel } from '$lib/utils/mcp';
import { HealthCheckStatus } from '$lib/enums';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { mcpClient } from '$lib/clients/mcp.client';
@ -15,16 +16,16 @@
interface Props {
server: MCPServerSettingsEntry;
displayName: string;
faviconUrl: string | null;
onToggle: (enabled: boolean) => void;
onUpdate: (updates: Partial<MCPServerSettingsEntry>) => void;
onDelete: () => void;
}
let { server, displayName, faviconUrl, onToggle, onUpdate, onDelete }: Props = $props();
let { server, faviconUrl, onToggle, onUpdate, onDelete }: Props = $props();
let healthState = $derived<HealthCheckState>(mcpStore.getHealthCheckState(server.id));
let displayName = $derived(getMcpServerLabel(server, healthState));
let isHealthChecking = $derived(healthState.status === HealthCheckStatus.Connecting);
let isConnected = $derived(healthState.status === HealthCheckStatus.Success);
let isError = $derived(healthState.status === HealthCheckStatus.Error);

View File

@ -58,9 +58,7 @@
</div>
{/if}
<p class="truncate leading-none font-medium">
{serverInfo?.title || serverInfo?.name || displayName}
</p>
<p class="truncate leading-none font-medium">{displayName}</p>
{#if serverInfo?.version}
<Badge variant="secondary" class="h-4 shrink-0 px-1 text-[10px]">

View File

@ -2,7 +2,7 @@
import { Plus, X } from '@lucide/svelte';
import { Button } from '$lib/components/ui/button';
import * as Card from '$lib/components/ui/card';
import { getServerDisplayName, getFaviconUrl } from '$lib/utils/mcp';
import { getFaviconUrl } from '$lib/utils/mcp';
import type { MCPServerSettingsEntry } from '$lib/types';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { McpServerCard } from '$lib/components/app/mcp/McpServerCard';
@ -117,7 +117,6 @@
{#each servers as server (server.id)}
<McpServerCard
{server}
displayName={getServerDisplayName(server)}
faviconUrl={getFaviconUrl(server.url)}
onToggle={(enabled) => mcpStore.updateServer(server.id, { enabled })}
onUpdate={(updates) => mcpStore.updateServer(server.id, updates)}

View File

@ -1,7 +1,12 @@
import type { MCPClientConfig, MCPServerConfig, MCPServerSettingsEntry } from '$lib/types';
import type {
HealthCheckState,
MCPClientConfig,
MCPServerConfig,
MCPServerSettingsEntry
} from '$lib/types';
import type { SettingsConfigType } from '$lib/types/settings';
import type { McpServerOverride } from '$lib/types/database';
import { MCPTransportType, MCPLogLevel } from '$lib/enums';
import { MCPTransportType, MCPLogLevel, HealthCheckStatus } from '$lib/enums';
import { DEFAULT_MCP_CONFIG } from '$lib/constants/mcp';
import { normalizePositiveNumber } from '$lib/utils/number';
import { Info, AlertTriangle, XCircle } from '@lucide/svelte';
@ -32,29 +37,19 @@ export function generateMcpServerId(id: unknown, index: number): string {
}
/**
* Extracts a human-readable server name from a URL.
* Strips common prefixes like 'www.' and 'mcp.' and capitalizes the result.
* Gets a display label for an MCP server based on health state.
*/
export function extractServerNameFromUrl(url: string): string {
try {
const parsedUrl = new URL(url);
const host = parsedUrl.hostname.replace(/^(www\.|mcp\.)/, '');
const name = host.split('.')[0] || 'Unknown';
return name.charAt(0).toUpperCase() + name.slice(1);
} catch {
return 'New Server';
export function getMcpServerLabel(
server: MCPServerSettingsEntry,
healthState?: HealthCheckState
): string {
if (healthState?.status === HealthCheckStatus.Success) {
return (
healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
);
}
}
/**
* Gets a display name for an MCP server.
* Returns server.name if set, otherwise extracts name from URL.
*/
export function getServerDisplayName(server: MCPServerSettingsEntry): string {
if (server.name) return server.name;
return extractServerNameFromUrl(server.url);
return server.url;
}
/**