From 0b742d1f6831687ac47d6236d2d8437476c9e440 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Tue, 10 Mar 2026 11:38:57 -0700 Subject: [PATCH] fix(mcp): add missing mock in test, show Approve for rejected, clear submission metadata, drop spurious Content-Type --- .../mcp_management_endpoints.py | 7 ++-- .../test_mcp_management_endpoints.py | 8 +++++ .../mcp_tools/MCPSubmissionsTab.tsx | 36 ++++++++++--------- .../src/components/networking.tsx | 1 - 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/litellm/proxy/management_endpoints/mcp_management_endpoints.py b/litellm/proxy/management_endpoints/mcp_management_endpoints.py index 43dcde535a4..f81c5ff6834 100644 --- a/litellm/proxy/management_endpoints/mcp_management_endpoints.py +++ b/litellm/proxy/management_endpoints/mcp_management_endpoints.py @@ -1026,9 +1026,12 @@ if MCP_AVAILABLE: # TODO: audit log for create - # Admin-created servers are always active regardless of any lifecycle fields - # in the payload — prevents an admin from accidentally creating a pending server. + # Admin-created servers are always active — clear any submission lifecycle + # fields the caller may have provided to prevent fake entries appearing in + # the submissions queue. payload.approval_status = MCPApprovalStatus.active + payload.submitted_by = None + payload.submitted_at = None # Attempt to create the mcp server try: diff --git a/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py index ecc2e08855d..f90205ece6d 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py @@ -1739,6 +1739,9 @@ class TestMCPApprovalWorkflow: now_rejected = generate_mock_mcp_server_db_record() now_rejected.approval_status = MCPApprovalStatus.rejected + mock_manager = MagicMock() + mock_manager.reload_servers_from_database = AsyncMock() + with ( patch( "litellm.proxy.management_endpoints.mcp_management_endpoints.get_prisma_client_or_throw", @@ -1752,6 +1755,10 @@ class TestMCPApprovalWorkflow: "litellm.proxy.management_endpoints.mcp_management_endpoints.reject_mcp_server", AsyncMock(return_value=now_rejected), ), + patch( + "litellm.proxy.management_endpoints.mcp_management_endpoints.global_mcp_server_manager", + mock_manager, + ), ): result = await reject_mcp_server_submission( server_id=active_server.server_id, @@ -1759,3 +1766,4 @@ class TestMCPApprovalWorkflow: user_api_key_dict=admin, ) assert result is not None + mock_manager.reload_servers_from_database.assert_awaited_once() diff --git a/ui/litellm-dashboard/src/components/mcp_tools/MCPSubmissionsTab.tsx b/ui/litellm-dashboard/src/components/mcp_tools/MCPSubmissionsTab.tsx index 50d119134f0..85875b620bb 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/MCPSubmissionsTab.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/MCPSubmissionsTab.tsx @@ -322,7 +322,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe )} {/* Approve/Reject when no checks panel (no rules configured) */} - {checks.length === 0 && approvalStatus === "pending_review" && ( + {checks.length === 0 && (approvalStatus === "pending_review" || approvalStatus === "rejected") && (
- + {approvalStatus === "pending_review" && ( + + )}
)} @@ -375,7 +377,7 @@ function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServe {/* Approve / Reject in header */} - {approvalStatus === "pending_review" && ( + {(approvalStatus === "pending_review" || approvalStatus === "rejected") && (
- + {approvalStatus === "pending_review" && ( + + )}
)} diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 3ad44e343c4..d11442b9ddf 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -6551,7 +6551,6 @@ export const approveMCPServer = async (accessToken: string, serverId: string) => method: HTTP_REQUEST.PUT, headers: { [globalLitellmHeaderName]: `Bearer ${accessToken}`, - "Content-Type": "application/json", }, }); if (!response.ok) {