diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx index 2de324499e..8c85fb3bb2 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx @@ -218,4 +218,56 @@ describe("ChatUI", () => { expect(options[0]).toHaveTextContent("Enter custom model"); }); }); + + it("should enable the MCP tools selector for chat completions", async () => { + render( + , + ); + + await waitFor(() => { + expect(screen.getByText("Test Key")).toBeInTheDocument(); + }); + + const endpointTypeText = screen.getByText("Endpoint Type"); + const endpointSelect = endpointTypeText.parentElement?.querySelector(".ant-select-selector") as HTMLElement | null; + expect(endpointSelect).not.toBeNull(); + + const selectEndpointOption = async (label: string) => { + act(() => { + fireEvent.mouseDown(endpointSelect!); + }); + + await waitFor(() => { + expect(screen.getByText(label)).toBeInTheDocument(); + }); + + act(() => { + fireEvent.click(screen.getByText(label)); + }); + }; + + const getMcpSelect = () => + screen.getByText("MCP Tool").closest("div")?.querySelector(".ant-select") as HTMLElement | null; + + await selectEndpointOption("/v1/embeddings"); + + const mcpSelect = getMcpSelect(); + expect(mcpSelect).not.toBeNull(); + + await waitFor(() => { + expect(mcpSelect).toHaveClass("ant-select-disabled"); + }); + + await selectEndpointOption("/v1/chat/completions"); + + await waitFor(() => { + expect(mcpSelect).not.toHaveClass("ant-select-disabled"); + }); + }); }); diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.tsx index a963aa706b..1cf9c7eb8d 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.tsx @@ -84,6 +84,11 @@ interface ChatUIProps { }; } +const MCP_SUPPORTED_ENDPOINTS = new Set([ + EndpointType.CHAT, + EndpointType.RESPONSES, +]); + const ChatUI: React.FC = ({ accessToken, token, @@ -743,8 +748,19 @@ const ChatUI: React.FC = ({ return; } - // Require model selection for Responses API - if (endpointType === EndpointType.RESPONSES && !selectedModel) { + // Require model selection for all model-based endpoints + const modelRequiredEndpoints = [ + EndpointType.CHAT, + EndpointType.IMAGE, + EndpointType.SPEECH, + EndpointType.IMAGE_EDITS, + EndpointType.RESPONSES, + EndpointType.ANTHROPIC_MESSAGES, + EndpointType.EMBEDDINGS, + EndpointType.TRANSCRIPTION, + ]; + + if (modelRequiredEndpoints.includes(endpointType as EndpointType) && !selectedModel) { NotificationsManager.fromBackend("Please select a model before sending a request"); return; } @@ -1319,7 +1335,7 @@ const ChatUI: React.FC = ({ MCP Tool @@ -1334,7 +1350,7 @@ const ChatUI: React.FC = ({ className="mb-4" allowClear optionLabelProp="label" - disabled={!(endpointType === EndpointType.RESPONSES)} + disabled={!MCP_SUPPORTED_ENDPOINTS.has(endpointType as EndpointType)} maxTagCount="responsive" > {Array.isArray(mcpTools) && diff --git a/ui/litellm-dashboard/src/components/playground/llm_calls/chat_completion.tsx b/ui/litellm-dashboard/src/components/playground/llm_calls/chat_completion.tsx index 799f050fc8..8bdaa94ec6 100644 --- a/ui/litellm-dashboard/src/components/playground/llm_calls/chat_completion.tsx +++ b/ui/litellm-dashboard/src/components/playground/llm_calls/chat_completion.tsx @@ -60,7 +60,7 @@ export async function makeOpenAIChatCompletionRequest( { type: "mcp", server_label: "litellm", - server_url: `${proxyBaseUrl}/mcp`, + server_url: 'litellm_proxy/mcp', require_approval: "never", allowed_tools: selectedMCPTools, headers: {