mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30: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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue