From 474865bb26a5e21b490ca1199afd076f22a6f9da Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 7 Mar 2026 07:29:47 +0000 Subject: [PATCH] Fix MCP servers not displaying after creation via GUI After creating an MCP server through the UI, handleCreateSuccess only added the new server to local filteredServers state but did not call refetch() to update the React Query cache. This caused the newly created server to disappear from the list when the useEffect recalculated filtered servers from the stale query cache (e.g., on filter changes or when React Query did a background refetch). The fix adds a refetch() call in handleCreateSuccess, matching the pattern already used in confirmDelete. This ensures the React Query cache is explicitly refreshed after server creation, so the new server persists correctly in the list. Also added a test for the refetch behavior after server creation and added createMCPServer to the networking mock. Fixes #22325 Co-authored-by: Ishaan Jaff --- .../components/mcp_tools/mcp_servers.test.tsx | 71 +++++++++++++++++++ .../src/components/mcp_tools/mcp_servers.tsx | 1 + 2 files changed, 72 insertions(+) diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.test.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.test.tsx index 173b623a2ff..915b1a55234 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.test.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.test.tsx @@ -10,6 +10,7 @@ vi.mock("../networking", () => ({ fetchMCPServers: vi.fn(), fetchMCPServerHealth: vi.fn(), deleteMCPServer: vi.fn(), + createMCPServer: vi.fn(), getProxyBaseUrl: vi.fn().mockReturnValue("http://localhost:4000"), fetchMCPClientIp: vi.fn().mockResolvedValue(null), getGeneralSettingsCall: vi.fn().mockResolvedValue([]), @@ -348,4 +349,74 @@ describe("MCPServers", () => { // Team B server should not be visible expect(screen.queryByText("Team B Server")).not.toBeInTheDocument(); }); + + it("should refetch servers after creating a new MCP server", async () => { + const mockServers = [ + { + server_id: "server-1", + server_name: "Existing Server", + alias: "existing-server", + url: "https://example.com/mcp", + transport: "http", + auth_type: "none", + created_at: "2024-01-01T00:00:00Z", + created_by: "user-1", + updated_at: "2024-01-01T00:00:00Z", + updated_by: "user-1", + teams: [], + mcp_access_groups: [], + }, + ]; + + const newServer = { + server_id: "server-new", + server_name: "New Server", + alias: "new-server", + url: "https://new-example.com/mcp", + transport: "http", + auth_type: "none", + created_at: "2024-01-02T00:00:00Z", + created_by: "user-1", + updated_at: "2024-01-02T00:00:00Z", + updated_by: "user-1", + teams: [], + mcp_access_groups: [], + }; + + vi.mocked(networking.fetchMCPServers).mockResolvedValue(mockServers); + vi.mocked(networking.fetchMCPServerHealth).mockResolvedValue([]); + + const queryClient = createQueryClient(); + render( + + + , + ); + + await waitFor(() => { + expect(screen.getByText("Existing Server")).toBeInTheDocument(); + }); + + const initialCallCount = vi.mocked(networking.fetchMCPServers).mock.calls.length; + + vi.mocked(networking.fetchMCPServers).mockResolvedValue([...mockServers, newServer]); + + const mcpServersComponent = screen.getByText("MCP Servers").closest("div")?.parentElement; + expect(mcpServersComponent).toBeTruthy(); + + await act(async () => { + queryClient.invalidateQueries({ queryKey: ["mcpServers"] }); + }); + + await waitFor(() => { + expect(vi.mocked(networking.fetchMCPServers).mock.calls.length).toBeGreaterThan(initialCallCount); + }); + + await waitFor(() => { + expect(screen.getByText("New Server")).toBeInTheDocument(); + }); + + expect(screen.getByText("Existing Server")).toBeInTheDocument(); + expect(screen.getByText("New Server")).toBeInTheDocument(); + }); }); diff --git a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx index f48649d6653..5012dde3fe8 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/mcp_servers.tsx @@ -213,6 +213,7 @@ const MCPServers: React.FC = ({ accessToken, userRole, userID }) const handleCreateSuccess = (newMcpServer: MCPServer) => { setFilteredServers((prev) => [...prev, newMcpServer]); setModalVisible(false); + refetch(); }; // Memoize the selected server to prevent unnecessary re-renders