fix: unify MCP server label logic with simplified fallback
This commit is contained in:
parent
bdd9bcfb75
commit
fdd67f45e6
|
|
@ -8,7 +8,7 @@
|
||||||
import McpLogo from '$lib/components/app/misc/McpLogo.svelte';
|
import McpLogo from '$lib/components/app/misc/McpLogo.svelte';
|
||||||
import { settingsStore } from '$lib/stores/settings.svelte';
|
import { settingsStore } from '$lib/stores/settings.svelte';
|
||||||
import { conversationsStore } from '$lib/stores/conversations.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 type { MCPServerSettingsEntry } from '$lib/types';
|
||||||
import { HealthCheckStatus } from '$lib/enums';
|
import { HealthCheckStatus } from '$lib/enums';
|
||||||
import { mcpStore } from '$lib/stores/mcp.svelte';
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||||
|
|
@ -44,6 +44,10 @@
|
||||||
return conversationsStore.getMcpServerOverride(serverId) !== undefined;
|
return conversationsStore.getMcpServerOverride(serverId) !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getServerLabel(server: MCPServerSettingsEntry): string {
|
||||||
|
return getMcpServerLabel(server, mcpStore.getHealthCheckState(server.id));
|
||||||
|
}
|
||||||
|
|
||||||
let enabledMcpServersForChat = $derived(
|
let enabledMcpServersForChat = $derived(
|
||||||
mcpServers.filter((s) => isServerEnabledForChat(s) && s.url.trim())
|
mcpServers.filter((s) => isServerEnabledForChat(s) && s.url.trim())
|
||||||
);
|
);
|
||||||
|
|
@ -68,7 +72,7 @@
|
||||||
if (usageB !== usageA) return usageB - usageA;
|
if (usageB !== usageA) return usageB - usageA;
|
||||||
|
|
||||||
// Then alphabetically by name
|
// 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();
|
const query = searchQuery.toLowerCase().trim();
|
||||||
if (query) {
|
if (query) {
|
||||||
return sortedMcpServers.filter((s) => {
|
return sortedMcpServers.filter((s) => {
|
||||||
const name = getServerDisplayName(s).toLowerCase();
|
const name = getServerLabel(s).toLowerCase();
|
||||||
const url = s.url.toLowerCase();
|
const url = s.url.toLowerCase();
|
||||||
return name.includes(query) || url.includes(query);
|
return name.includes(query) || url.includes(query);
|
||||||
});
|
});
|
||||||
|
|
@ -173,7 +177,7 @@
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="truncate text-sm">{getServerDisplayName(server)}</span>
|
<span class="truncate text-sm">{getServerLabel(server)}</span>
|
||||||
{#if hasError}
|
{#if hasError}
|
||||||
<span class="shrink-0 rounded bg-destructive/15 px-1.5 py-0.5 text-xs text-destructive"
|
<span class="shrink-0 rounded bg-destructive/15 px-1.5 py-0.5 text-xs text-destructive"
|
||||||
>Error</span
|
>Error</span
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
import type { MCPServerSettingsEntry, HealthCheckState } from '$lib/types';
|
import type { MCPServerSettingsEntry, HealthCheckState } from '$lib/types';
|
||||||
|
import { getMcpServerLabel } from '$lib/utils/mcp';
|
||||||
import { HealthCheckStatus } from '$lib/enums';
|
import { HealthCheckStatus } from '$lib/enums';
|
||||||
import { mcpStore } from '$lib/stores/mcp.svelte';
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||||
import { mcpClient } from '$lib/clients/mcp.client';
|
import { mcpClient } from '$lib/clients/mcp.client';
|
||||||
|
|
@ -15,16 +16,16 @@
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
server: MCPServerSettingsEntry;
|
server: MCPServerSettingsEntry;
|
||||||
displayName: string;
|
|
||||||
faviconUrl: string | null;
|
faviconUrl: string | null;
|
||||||
onToggle: (enabled: boolean) => void;
|
onToggle: (enabled: boolean) => void;
|
||||||
onUpdate: (updates: Partial<MCPServerSettingsEntry>) => void;
|
onUpdate: (updates: Partial<MCPServerSettingsEntry>) => void;
|
||||||
onDelete: () => 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 healthState = $derived<HealthCheckState>(mcpStore.getHealthCheckState(server.id));
|
||||||
|
let displayName = $derived(getMcpServerLabel(server, healthState));
|
||||||
let isHealthChecking = $derived(healthState.status === HealthCheckStatus.Connecting);
|
let isHealthChecking = $derived(healthState.status === HealthCheckStatus.Connecting);
|
||||||
let isConnected = $derived(healthState.status === HealthCheckStatus.Success);
|
let isConnected = $derived(healthState.status === HealthCheckStatus.Success);
|
||||||
let isError = $derived(healthState.status === HealthCheckStatus.Error);
|
let isError = $derived(healthState.status === HealthCheckStatus.Error);
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<p class="truncate leading-none font-medium">
|
<p class="truncate leading-none font-medium">{displayName}</p>
|
||||||
{serverInfo?.title || serverInfo?.name || displayName}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{#if serverInfo?.version}
|
{#if serverInfo?.version}
|
||||||
<Badge variant="secondary" class="h-4 shrink-0 px-1 text-[10px]">
|
<Badge variant="secondary" class="h-4 shrink-0 px-1 text-[10px]">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { Plus, X } from '@lucide/svelte';
|
import { Plus, X } from '@lucide/svelte';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import * as Card from '$lib/components/ui/card';
|
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 type { MCPServerSettingsEntry } from '$lib/types';
|
||||||
import { mcpStore } from '$lib/stores/mcp.svelte';
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||||
import { McpServerCard } from '$lib/components/app/mcp/McpServerCard';
|
import { McpServerCard } from '$lib/components/app/mcp/McpServerCard';
|
||||||
|
|
@ -117,7 +117,6 @@
|
||||||
{#each servers as server (server.id)}
|
{#each servers as server (server.id)}
|
||||||
<McpServerCard
|
<McpServerCard
|
||||||
{server}
|
{server}
|
||||||
displayName={getServerDisplayName(server)}
|
|
||||||
faviconUrl={getFaviconUrl(server.url)}
|
faviconUrl={getFaviconUrl(server.url)}
|
||||||
onToggle={(enabled) => mcpStore.updateServer(server.id, { enabled })}
|
onToggle={(enabled) => mcpStore.updateServer(server.id, { enabled })}
|
||||||
onUpdate={(updates) => mcpStore.updateServer(server.id, updates)}
|
onUpdate={(updates) => mcpStore.updateServer(server.id, updates)}
|
||||||
|
|
|
||||||
|
|
@ -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 { SettingsConfigType } from '$lib/types/settings';
|
||||||
import type { McpServerOverride } from '$lib/types/database';
|
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 { DEFAULT_MCP_CONFIG } from '$lib/constants/mcp';
|
||||||
import { normalizePositiveNumber } from '$lib/utils/number';
|
import { normalizePositiveNumber } from '$lib/utils/number';
|
||||||
import { Info, AlertTriangle, XCircle } from '@lucide/svelte';
|
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.
|
* Gets a display label for an MCP server based on health state.
|
||||||
* Strips common prefixes like 'www.' and 'mcp.' and capitalizes the result.
|
|
||||||
*/
|
*/
|
||||||
export function extractServerNameFromUrl(url: string): string {
|
export function getMcpServerLabel(
|
||||||
try {
|
server: MCPServerSettingsEntry,
|
||||||
const parsedUrl = new URL(url);
|
healthState?: HealthCheckState
|
||||||
const host = parsedUrl.hostname.replace(/^(www\.|mcp\.)/, '');
|
): string {
|
||||||
const name = host.split('.')[0] || 'Unknown';
|
if (healthState?.status === HealthCheckStatus.Success) {
|
||||||
|
return (
|
||||||
return name.charAt(0).toUpperCase() + name.slice(1);
|
healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
|
||||||
} catch {
|
);
|
||||||
return 'New Server';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue