From ca71c6166d467a68397771808d4c3c736687b307 Mon Sep 17 00:00:00 2001 From: Tin Chi Lo Date: Tue, 23 Jun 2026 22:51:25 -0700 Subject: [PATCH] feat(ui/mcp): clarify base64 format for BYOK Basic auth keys The Basic auth hint described the wire header (Authorization: Basic {key}) but did not tell users the value must be a base64-encoded user:password string, so a user pasting a raw token in the Connect modal could produce a header the upstream silently rejects. Add a Basic-only note to the BYOK hint. --- .../src/components/mcp_tools/ByokFields.tsx | 9 ++++++++ .../mcp_tools/create_mcp_server.test.tsx | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ui/litellm-dashboard/src/components/mcp_tools/ByokFields.tsx b/ui/litellm-dashboard/src/components/mcp_tools/ByokFields.tsx index 17f40645b2a..77536351ec3 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/ByokFields.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/ByokFields.tsx @@ -20,6 +20,7 @@ const ByokFields: React.FC = ({ form }) => { const isByok = Form.useWatch("is_byok", form); const authType = Form.useWatch("auth_type", form) as string | undefined; const formatHint = authType ? BYOK_AUTH_FORMAT_HINT[authType] : undefined; + const isBasicAuth = authType === AUTH_TYPE.BASIC; return ( <> @@ -45,6 +46,14 @@ const ByokFields: React.FC = ({ form }) => { User keys will be sent as: {formatHint} + {isBasicAuth && ( + <> + {" "} + Each user's key must be a base64-encoded{" "} + user:password string, or a raw token if + the server accepts one. + + )} )} diff --git a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx index 581cbed8c7f..18217f7c968 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx @@ -868,6 +868,27 @@ describe("CreateMCPServer BYOK toggle", () => { expect(payload.credentials).toBeUndefined(); }); + it("shows a base64 clarification in the BYOK hint for Basic auth only", async () => { + await selectHttpTransport(); + await selectAntOption("Authentication", "Basic Auth"); + await waitFor(() => expect(screen.getByText(BYOK_LABEL)).toBeInTheDocument()); + await act(async () => { + fireEvent.click(getByokSwitch()!); + }); + await waitFor(() => expect(screen.getByText(/base64-encoded/)).toBeInTheDocument()); + + cleanup(); + + await selectHttpTransport(); + await selectAntOption("Authentication", "Bearer Token"); + await waitFor(() => expect(screen.getByText(BYOK_LABEL)).toBeInTheDocument()); + await act(async () => { + fireEvent.click(getByokSwitch()!); + }); + await waitFor(() => expect(screen.getByText("Access Description")).toBeInTheDocument()); + expect(screen.queryByText(/base64-encoded/)).not.toBeInTheDocument(); + }); + it("blocks submit when the API Key Help URL is not a valid URL", async () => { await selectHttpTransport();