🔍 feat: Add Filter to MCP Builder Panel (#10885)

Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
This commit is contained in:
Atef Bellaaj 2025-12-10 16:36:41 +01:00 committed by GitHub
parent 1940b13679
commit ba74c5c8b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 7 deletions

View file

@ -1,7 +1,7 @@
import { useState, useRef } from 'react';
import { Plus } from 'lucide-react';
import { useState, useRef, useMemo } from 'react';
import { Plus, Search } from 'lucide-react';
import { PermissionTypes, Permissions } from 'librechat-data-provider';
import { Button, Spinner, OGDialogTrigger } from '@librechat/client';
import { Button, Spinner, OGDialogTrigger, Input } from '@librechat/client';
import { useLocalize, useMCPServerManager, useHasAccess } from '~/hooks';
import MCPServerList from './MCPServerList';
import MCPServerDialog from './MCPServerDialog';
@ -18,15 +18,41 @@ export default function MCPBuilderPanel() {
permission: Permissions.CREATE,
});
const [showDialog, setShowDialog] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const addButtonRef = useRef<HTMLButtonElement | null>(null);
const configDialogProps = getConfigDialogProps();
const filteredServers = useMemo(() => {
if (!searchQuery.trim()) {
return availableMCPServers;
}
const query = searchQuery.toLowerCase();
return availableMCPServers.filter((server) => {
const displayName = server.config?.title || server.serverName;
return (
displayName.toLowerCase().includes(query) || server.serverName.toLowerCase().includes(query)
);
});
}, [availableMCPServers, searchQuery]);
return (
<div className="flex h-full w-full flex-col overflow-visible">
<div role="region" aria-label="MCP Builder" className="mt-2 space-y-2">
{/* Admin Settings Button */}
<MCPAdminSettings />
{/* Search Input */}
<div className="relative">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" />
<Input
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder={localize('com_ui_filter_mcp_servers')}
className="pl-9"
aria-label={localize('com_ui_filter_mcp_servers')}
/>
</div>
{hasCreateAccess && (
<MCPServerDialog open={showDialog} onOpenChange={setShowDialog} triggerRef={addButtonRef}>
<OGDialogTrigger asChild>
@ -52,8 +78,9 @@ export default function MCPBuilderPanel() {
</div>
) : (
<MCPServerList
servers={availableMCPServers}
servers={filteredServers}
getServerStatusIconProps={getServerStatusIconProps}
isFiltered={searchQuery.trim().length > 0}
/>
)}
{configDialogProps && <MCPConfigDialog {...configDialogProps} />}

View file

@ -15,6 +15,7 @@ interface MCPServerListProps {
getServerStatusIconProps: (
serverName: string,
) => React.ComponentProps<typeof MCPServerStatusIcon>;
isFiltered?: boolean;
}
// Self-contained edit button component (follows MemoryViewer pattern)
@ -39,7 +40,11 @@ const EditMCPServerButton = ({ server }: { server: MCPServerDefinition }) => {
);
};
export default function MCPServerList({ servers, getServerStatusIconProps }: MCPServerListProps) {
export default function MCPServerList({
servers,
getServerStatusIconProps,
isFiltered = false,
}: MCPServerListProps) {
const canCreateEditMCPs = useHasAccess({
permissionType: PermissionTypes.MCP_SERVERS,
permission: Permissions.CREATE,
@ -49,8 +54,16 @@ export default function MCPServerList({ servers, getServerStatusIconProps }: MCP
if (servers.length === 0) {
return (
<div className="rounded-lg border border-border-light bg-transparent p-8 text-center shadow-sm">
<p className="text-sm text-text-secondary">{localize('com_ui_no_mcp_servers')}</p>
<p className="mt-1 text-xs text-text-tertiary">{localize('com_ui_add_first_mcp_server')}</p>
{isFiltered ? (
<p className="text-sm text-text-secondary">{localize('com_ui_no_mcp_servers_match')}</p>
) : (
<>
<p className="text-sm text-text-secondary">{localize('com_ui_no_mcp_servers')}</p>
<p className="mt-1 text-xs text-text-tertiary">
{localize('com_ui_add_first_mcp_server')}
</p>
</>
)}
</div>
);
}

View file

@ -634,6 +634,8 @@
"com_ui_mcp_server_created": "MCP server created successfully",
"com_ui_mcp_server_updated": "MCP server updated successfully",
"com_ui_mcp_server_connection_failed": "Connection attempt to the provided MCP server failed. Please make sure the URL, the server type, and any authentication configuration are correct, then try again. Also ensure the URL is reachable.",
"com_ui_filter_mcp_servers": "Filter MCP servers by name",
"com_ui_no_mcp_servers_match": "No MCP servers match your filter",
"com_ui_add_model_preset": "Add a model or preset for an additional response",
"com_ui_add_multi_conversation": "Add multi-conversation",
"com_ui_add_special_variables": "Add Special Variables",