feat: add default clickhouse logo to MCPSelect

This commit is contained in:
Dustin Healy 2026-01-05 20:42:03 -08:00 committed by Danny Avila
parent 74a1a874d5
commit c336cd886c
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
3 changed files with 65 additions and 26 deletions

View file

@ -2,6 +2,7 @@ import { useMemo } from 'react';
import { MCPIcon } from '@librechat/client';
import type { MCPServerDefinition } from '~/hooks/MCP/useMCPServerManager';
import { getSelectedServerIcons } from './mcpServerUtils';
import ClickHouseIcon from './ClickHouseIcon';
import { cn } from '~/utils';
interface StackedMCPIconsProps {
@ -58,8 +59,31 @@ export default function StackedMCPIcons({
const sizes = sizeConfig[iconSize];
const colors = variantConfig[variant];
const renderIcon = (icon: { iconPath: string | null; displayName: string }) => {
if (icon.iconPath === 'clickhouse') {
return (
<ClickHouseIcon
className={cn('rounded-full object-cover', sizes.icon)}
alt={icon.displayName}
/>
);
}
if (icon.iconPath) {
return (
<img
src={icon.iconPath}
alt={icon.displayName}
className={cn('rounded-full object-cover', sizes.icon)}
/>
);
}
return <MCPIcon className={cn('text-text-primary', sizes.icon)} />;
};
return (
<div className="flex items-center" aria-hidden="true">
<div className="flex items-center">
{icons.map((icon, index) => (
<div
key={icon.key}
@ -73,15 +97,7 @@ export default function StackedMCPIcons({
)}
style={{ zIndex: icons.length - index }}
>
{icon.iconPath ? (
<img
src={icon.iconPath}
alt={icon.displayName}
className={cn('rounded-full object-cover', sizes.icon)}
/>
) : (
<MCPIcon className={cn('text-text-primary', sizes.icon)} />
)}
{renderIcon(icon)}
</div>
))}
{overflowCount > 0 && (

View file

@ -24,6 +24,7 @@ export function getSelectedServerIcons(
maxIcons: number = 3,
): { icons: SelectedIconInfo[]; overflowCount: number; defaultServerNames: string[] } {
const customIcons: SelectedIconInfo[] = [];
const clickhouseServers: SelectedIconInfo[] = [];
const defaultServerNames: string[] = [];
for (const server of selectedServers) {
@ -35,17 +36,25 @@ export function getSelectedServerIcons(
iconPath: server.config.iconPath,
displayName,
});
} else if (server.serverName.toLowerCase().includes('clickhouse')) {
clickhouseServers.push({
key: server.serverName,
serverName: server.serverName,
iconPath: 'clickhouse',
displayName,
});
} else {
defaultServerNames.push(server.serverName);
}
}
// Add one default icon entry if any server uses default icon
// Custom icons are prioritized first, default icon comes last
const allIcons: SelectedIconInfo[] =
defaultServerNames.length > 0
// Custom icons are prioritized first, ClickHouse icons second, default icon comes last
const allIcons: SelectedIconInfo[] = [
...customIcons,
...clickhouseServers,
...(defaultServerNames.length > 0
? [
...customIcons,
{
key: '_default_',
serverName: defaultServerNames[0],
@ -53,7 +62,8 @@ export function getSelectedServerIcons(
displayName: 'MCP',
},
]
: customIcons;
: []),
];
const visibleIcons = allIcons.slice(0, maxIcons);
const overflowCount = Math.max(0, allIcons.length - maxIcons);

View file

@ -1,5 +1,6 @@
import { XCircle, PlusCircleIcon, Wrench } from 'lucide-react';
import type { AgentToolType } from 'librechat-data-provider';
import ClickHouseIcon from '~/components/MCP/ClickHouseIcon';
import { useLocalize } from '~/hooks';
type MCPToolItemProps = {
@ -71,22 +72,34 @@ function MCPToolItem({
const buttonState = getButtonState();
const renderIcon = () => {
if (icon) {
return (
<img
src={icon}
alt={localize('com_ui_logo', { 0: name })}
className="h-full w-full rounded-[5px] bg-white"
/>
);
}
if (name.toLowerCase().includes('clickhouse')) {
return <ClickHouseIcon className="h-full w-full rounded-[5px] object-cover" alt={name} />;
}
return (
<div className="flex h-full w-full items-center justify-center rounded-[5px] border border-border-medium bg-transparent">
<Wrench className="h-8 w-8 text-text-secondary" />
</div>
);
};
return (
<div className="flex flex-col gap-4 rounded border border-border-medium bg-transparent p-6">
<div className="flex gap-4">
<div className="h-[70px] w-[70px] shrink-0">
<div className="relative h-full w-full">
{icon ? (
<img
src={icon}
alt={localize('com_ui_logo', { 0: name })}
className="h-full w-full rounded-[5px] bg-white"
/>
) : (
<div className="flex h-full w-full items-center justify-center rounded-[5px] border border-border-medium bg-transparent">
<Wrench className="h-8 w-8 text-text-secondary" />
</div>
)}
{renderIcon()}
<div className="absolute inset-0 rounded-[5px] ring-1 ring-inset ring-black/10"></div>
</div>
</div>