mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-08 22:21:35 +00:00
fix: double-add race, conditional bulk query, narrow DELETE_RE, hoist search input
This commit is contained in:
parent
5010b2b0cd
commit
9e767ce77f
4 changed files with 29 additions and 35 deletions
|
|
@ -369,11 +369,6 @@ if MCP_AVAILABLE:
|
|||
list_tools_result = []
|
||||
error_message = None
|
||||
|
||||
# Bulk-fetch all OAuth credentials for this user in a single DB query
|
||||
# so per-server calls below can use a dict lookup (O(1)) instead of
|
||||
# issuing one DB query per server (N+1 pattern).
|
||||
bulk_oauth_headers = await _get_bulk_user_oauth_headers(user_api_key_dict)
|
||||
|
||||
# If server_id is specified, only query that specific server
|
||||
if server_id:
|
||||
# Resolve a server name to its UUID if needed (MCPConnectPicker passes
|
||||
|
|
@ -422,7 +417,8 @@ if MCP_AVAILABLE:
|
|||
server_auth_header = _get_server_auth_header(
|
||||
server, mcp_server_auth_headers, mcp_auth_header
|
||||
)
|
||||
user_oauth_extra_headers = bulk_oauth_headers.get(server.server_id)
|
||||
# Single-server request: targeted lookup is more efficient than a bulk fetch.
|
||||
user_oauth_extra_headers = await _get_user_oauth_extra_headers(server, user_api_key_dict)
|
||||
|
||||
try:
|
||||
list_tools_result = await _get_tools_for_single_server(
|
||||
|
|
@ -464,7 +460,10 @@ if MCP_AVAILABLE:
|
|||
},
|
||||
)
|
||||
|
||||
# Query all servers the user has access to
|
||||
# Query all servers the user has access to.
|
||||
# Bulk-fetch OAuth creds once so each per-server call below can
|
||||
# do an O(1) dict lookup instead of N individual DB queries.
|
||||
bulk_oauth_headers = await _get_bulk_user_oauth_headers(user_api_key_dict)
|
||||
errors = []
|
||||
for allowed_server_id in allowed_server_ids:
|
||||
server = global_mcp_server_manager.get_mcp_server_by_id(
|
||||
|
|
|
|||
|
|
@ -193,7 +193,11 @@ const MCPAppsPanel: React.FC<Props> = ({ accessToken, selectedServers, onChange
|
|||
message.warning(`Could not load tools for ${serverName}`);
|
||||
return;
|
||||
}
|
||||
onChange([...selectedServers, serverName]);
|
||||
// Use the ref so we read the most up-to-date list; guard against duplicates
|
||||
// that the oauthConnected effect may have already added while we awaited.
|
||||
if (!selectedServersRef.current.includes(serverName)) {
|
||||
onChange([...selectedServersRef.current, serverName]);
|
||||
}
|
||||
} catch {
|
||||
message.warning(`Could not load tools for ${serverName}`);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -451,39 +451,30 @@ const MCPToolConfiguration: React.FC<MCPToolConfigurationProps> = ({
|
|||
</Text>
|
||||
</div>
|
||||
|
||||
{/* Search box shared by both views */}
|
||||
<Input
|
||||
placeholder="Search tools by name or description..."
|
||||
prefix={<SearchOutlined className="text-gray-400" />}
|
||||
value={toolSearchTerm}
|
||||
onChange={(e) => setToolSearchTerm(e.target.value)}
|
||||
allowClear
|
||||
className="rounded-lg"
|
||||
size="large"
|
||||
/>
|
||||
|
||||
{/* CRUD grouped view */}
|
||||
{viewMode === "crud" && (
|
||||
<>
|
||||
<Input
|
||||
placeholder="Search tools by name or description..."
|
||||
prefix={<SearchOutlined className="text-gray-400" />}
|
||||
value={toolSearchTerm}
|
||||
onChange={(e) => setToolSearchTerm(e.target.value)}
|
||||
allowClear
|
||||
className="rounded-lg"
|
||||
size="large"
|
||||
/>
|
||||
<McpCrudPermissionPanel
|
||||
tools={tools}
|
||||
searchFilter={toolSearchTerm}
|
||||
value={allowedTools}
|
||||
onChange={(allowed) => onAllowedToolsChange(allowed)}
|
||||
/>
|
||||
</>
|
||||
<McpCrudPermissionPanel
|
||||
tools={tools}
|
||||
searchFilter={toolSearchTerm}
|
||||
value={allowedTools}
|
||||
onChange={(allowed) => onAllowedToolsChange(allowed)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Flat list view */}
|
||||
{viewMode === "flat" && (
|
||||
<>
|
||||
<Input
|
||||
placeholder="Search tools by name or description..."
|
||||
prefix={<SearchOutlined className="text-gray-400" />}
|
||||
value={toolSearchTerm}
|
||||
onChange={(e) => setToolSearchTerm(e.target.value)}
|
||||
allowClear
|
||||
className="rounded-lg"
|
||||
size="large"
|
||||
/>
|
||||
{filteredTools.length === 0 ? (
|
||||
<div className="text-center py-6 text-gray-400 border rounded-lg border-dashed">
|
||||
<SearchOutlined className="text-2xl mb-2" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export type CrudOp = "read" | "create" | "update" | "delete" | "unknown";
|
||||
|
||||
const DELETE_RE = /\b(delete|remove|destroy|purge|drop|clear|erase|unlink|disconnect)\b/i;
|
||||
const DELETE_RE = /\b(delete|remove|destroy|purge|drop|erase|unlink)\b/i;
|
||||
const CREATE_RE = /\b(create|add|insert|new|post|submit|register|make|generate|write|upload)\b/i;
|
||||
const UPDATE_RE = /\b(update|edit|modify|change|patch|put|set|rename|move|transform)\b/i;
|
||||
const READ_RE = /\b(get|read|list|fetch|search|find|query|retrieve|show|view|check|describe|info)\b/i;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue