mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 09:50:15 +01:00
🔍 feat: Add Filter to MCP Builder Panel (#10885)
Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
This commit is contained in:
parent
6fc6471010
commit
da9b5196aa
3 changed files with 49 additions and 7 deletions
|
|
@ -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} />}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue