mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix: add OAuth headers to call_tool_rest_api, fix stale accessToken closure, fix group toggle on filtered subset
This commit is contained in:
parent
7259d4f6b4
commit
4e2f18ba49
4 changed files with 37 additions and 14 deletions
|
|
@ -557,6 +557,16 @@ if MCP_AVAILABLE:
|
|||
request, user_api_key_dict, server_id
|
||||
)
|
||||
|
||||
# Look up per-user OAuth headers for this server (mirrors list_tool_rest_api).
|
||||
user_oauth_extra_headers: Optional[Dict[str, str]] = None
|
||||
target_server = next(
|
||||
(s for s in allowed_mcp_servers if s.server_id == server_id), None
|
||||
)
|
||||
if target_server is not None:
|
||||
user_oauth_extra_headers = await _get_user_oauth_extra_headers(
|
||||
target_server, user_api_key_dict
|
||||
)
|
||||
|
||||
# Call execute_mcp_tool directly (permission checks already done)
|
||||
result = await execute_mcp_tool(
|
||||
name=tool_name,
|
||||
|
|
@ -566,7 +576,7 @@ if MCP_AVAILABLE:
|
|||
user_api_key_auth=data.get("user_api_key_auth"),
|
||||
mcp_auth_header=data.get("mcp_auth_header"),
|
||||
mcp_server_auth_headers=data.get("mcp_server_auth_headers"),
|
||||
oauth2_headers=data.get("oauth2_headers"),
|
||||
oauth2_headers=user_oauth_extra_headers or data.get("oauth2_headers"),
|
||||
raw_headers=data.get("raw_headers"),
|
||||
litellm_logging_obj=data.get("litellm_logging_obj"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -43,12 +43,13 @@ const MCPToolPermissions: React.FC<MCPToolPermissionsProps> = ({
|
|||
}, [allServers, selectedServers]);
|
||||
|
||||
// Fetch tools for a specific server; applies delete-blocked-by-default for new servers.
|
||||
const fetchToolsForServer = async (serverId: string) => {
|
||||
// `token` is passed explicitly so the closure never captures a stale accessToken.
|
||||
const fetchToolsForServer = async (serverId: string, token: string) => {
|
||||
setLoadingTools((prev) => ({ ...prev, [serverId]: true }));
|
||||
setToolErrors((prev) => ({ ...prev, [serverId]: "" }));
|
||||
|
||||
try {
|
||||
const response = await listMCPTools(accessToken, serverId);
|
||||
const response = await listMCPTools(token, serverId);
|
||||
|
||||
if (response.error) {
|
||||
setToolErrors((prev) => ({ ...prev, [serverId]: response.message || "Failed to fetch tools" }));
|
||||
|
|
@ -76,14 +77,17 @@ const MCPToolPermissions: React.FC<MCPToolPermissionsProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
// Auto-fetch tools when servers change
|
||||
// Auto-fetch tools when servers or accessToken change
|
||||
useEffect(() => {
|
||||
servers.forEach((server) => {
|
||||
if (!serverTools[server.server_id] && !loadingTools[server.server_id]) {
|
||||
fetchToolsForServer(server.server_id);
|
||||
fetchToolsForServer(server.server_id, accessToken);
|
||||
}
|
||||
});
|
||||
}, [servers]);
|
||||
// fetchToolsForServer is defined in this render scope but receives `accessToken`
|
||||
// as an explicit argument, so it is safe to omit from deps here.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [servers, accessToken]);
|
||||
|
||||
const handleCrudPanelChange = (serverId: string, allowed: string[]) => {
|
||||
onChange({ ...toolPermissions, [serverId]: allowed });
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ interface McpCrudPermissionPanelProps {
|
|||
/** Called whenever the allowed set changes. Always emits a concrete string[]. */
|
||||
onChange: (allowed: string[]) => void;
|
||||
readOnly?: boolean;
|
||||
/**
|
||||
* Optional search filter string. When set, only tools whose name or description
|
||||
* contain this string (case-insensitive) are shown. Group-level toggles still
|
||||
* operate on the complete group — not just the visible (filtered) subset.
|
||||
*/
|
||||
searchFilter?: string;
|
||||
}
|
||||
|
||||
const CRUD_ORDER: CrudOp[] = ["read", "create", "update", "delete", "unknown"];
|
||||
|
|
@ -67,6 +73,7 @@ const McpCrudPermissionPanel: React.FC<McpCrudPermissionPanelProps> = ({
|
|||
value,
|
||||
onChange,
|
||||
readOnly = false,
|
||||
searchFilter = "",
|
||||
}) => {
|
||||
const [collapsed, setCollapsed] = useState<Record<CrudOp, boolean>>({
|
||||
read: false,
|
||||
|
|
@ -197,10 +204,16 @@ const McpCrudPermissionPanel: React.FC<McpCrudPermissionPanelProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Tool list */}
|
||||
{/* Tool list — searchFilter narrows display only; group toggles still cover all tools */}
|
||||
{!isCollapsed && (
|
||||
<div className="bg-white divide-y divide-gray-50">
|
||||
{group.map((tool) => {
|
||||
{group
|
||||
.filter((t) =>
|
||||
!searchFilter ||
|
||||
t.name.toLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||
(t.description ?? "").toLowerCase().includes(searchFilter.toLowerCase())
|
||||
)
|
||||
.map((tool) => {
|
||||
const allowed = isToolAllowed(tool.name);
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -464,12 +464,8 @@ const MCPToolConfiguration: React.FC<MCPToolConfigurationProps> = ({
|
|||
size="large"
|
||||
/>
|
||||
<McpCrudPermissionPanel
|
||||
tools={tools.filter(
|
||||
(t) =>
|
||||
!toolSearchTerm ||
|
||||
t.name.toLowerCase().includes(toolSearchTerm.toLowerCase()) ||
|
||||
(t.description ?? "").toLowerCase().includes(toolSearchTerm.toLowerCase())
|
||||
)}
|
||||
tools={tools}
|
||||
searchFilter={toolSearchTerm}
|
||||
value={allowedTools}
|
||||
onChange={(allowed) => onAllowedToolsChange(allowed)}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue