From 153b17e98bc5cfd38bcae71761fdc8d639dfa32d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 10:22:00 +0000 Subject: [PATCH] fix(ui): expose the authorization MCP auth type in the create and edit forms --- .../_components/create_mcp_server.test.tsx | 39 +++++++++++++++++++ .../_components/create_mcp_server.tsx | 11 +++++- .../_components/mcp_server_edit.test.tsx | 35 +++++++++++++++++ .../_components/mcp_server_edit.tsx | 11 +++++- .../src/components/mcp_tools/types.test.tsx | 1 + .../src/components/mcp_tools/types.tsx | 1 + 6 files changed, 94 insertions(+), 4 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.test.tsx index 6ce7f5c75ed..22ed3c9055a 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.test.tsx @@ -355,6 +355,45 @@ describe("CreateMCPServer", () => { expect(payload.credentials).toEqual({ auth_value: "my-secret-key" }); }); + it("creates a server with the raw Authorization auth type and its header value", async () => { + await selectHttpTransport(); + + const user = userEvent.setup({ delay: null }); + + await user.type(getServerNameInput(), "Raw_Auth_Server"); + await user.type(screen.getByPlaceholderText("https://your-mcp-server.com"), "https://example.com/mcp"); + + await selectAntOption("Authentication", "Authorization (raw header)"); + + const authInput = await screen.findByPlaceholderText("Enter token or secret"); + await user.type(authInput, "ApiKey upstream-key"); + + vi.mocked(networking.createMCPServer).mockResolvedValue({ + server_id: "new-server-1", + server_name: "Raw_Auth_Server", + alias: "Raw_Auth_Server", + url: "https://example.com/mcp", + transport: "http", + auth_type: "authorization", + created_at: "2024-01-01T00:00:00Z", + created_by: "user-1", + updated_at: "2024-01-01T00:00:00Z", + updated_by: "user-1", + }); + + await act(async () => { + fireEvent.click(screen.getByRole("button", { name: "Add MCP Server" })); + }); + + await waitFor(() => { + expect(networking.createMCPServer).toHaveBeenCalledTimes(1); + }); + + const [, payload] = vi.mocked(networking.createMCPServer).mock.calls[0]; + expect(payload.auth_type).toBe("authorization"); + expect(payload.credentials).toEqual({ auth_value: "ApiKey upstream-key" }); + }); + it("does not write the browser-authorized token into form.credentials for true_passthrough", async () => { await selectHttpTransport(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.tsx index 9ecca9ec572..59ef54e391d 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/create_mcp_server.tsx @@ -56,7 +56,13 @@ interface CreateMCPServerProps { onBackToDiscovery?: () => void; } -const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.TOKEN, AUTH_TYPE.BASIC]; +const AUTH_TYPES_REQUIRING_AUTH_VALUE = [ + AUTH_TYPE.API_KEY, + AUTH_TYPE.BEARER_TOKEN, + AUTH_TYPE.TOKEN, + AUTH_TYPE.BASIC, + AUTH_TYPE.AUTHORIZATION, +]; const AUTH_TYPES_REQUIRING_CREDENTIALS = [ ...AUTH_TYPES_REQUIRING_AUTH_VALUE, AUTH_TYPE.OAUTH2, @@ -1071,12 +1077,13 @@ const CreateMCPServer: React.FC = ({ children: ( <> - None API Key Bearer Token Token Basic Auth + Authorization (raw header) OAuth OAuth Token Exchange (OBO) AWS SigV4 (Bedrock AgentCore MCPs) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.test.tsx index b660c4bdb76..0f4f0f6b6ff 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.test.tsx @@ -432,6 +432,41 @@ describe("MCPServerEdit (auth type switch)", () => { expect(payload.registration_url).toBeNull(); }); + it("saves the raw Authorization auth type with its header value", async () => { + vi.mocked(networking.updateMCPServer).mockResolvedValue({ + ...interactiveOAuthServer, + auth_type: "authorization", + }); + + render( + , + ); + + await selectAntOption("Authentication", "Authorization (raw header)"); + + const authInput = await screen.findByPlaceholderText("Enter token or secret (leave blank to keep existing)"); + await userEvent.setup({ delay: null }).type(authInput, "ApiKey upstream-key"); + + const saveButtons = screen.getAllByRole("button", { name: "Save Changes" }); + await act(async () => { + fireEvent.click(saveButtons[0]); + }); + + await waitFor(() => { + expect(networking.updateMCPServer).toHaveBeenCalledTimes(1); + }); + + const [, payload] = vi.mocked(networking.updateMCPServer).mock.calls[0]; + expect(payload.auth_type).toBe("authorization"); + expect(payload.credentials).toEqual({ auth_value: "ApiKey upstream-key" }); + }); + it("keeps oauth2 endpoint overrides when the auth type is unchanged", async () => { vi.mocked(networking.updateMCPServer).mockResolvedValue({ ...interactiveOAuthServer }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.tsx index 47b7d8ad7fa..01761eabf87 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_server_edit.tsx @@ -59,7 +59,13 @@ interface MCPServerEditProps { availableAccessGroups: string[]; } -const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.TOKEN, AUTH_TYPE.BASIC]; +const AUTH_TYPES_REQUIRING_AUTH_VALUE = [ + AUTH_TYPE.API_KEY, + AUTH_TYPE.BEARER_TOKEN, + AUTH_TYPE.TOKEN, + AUTH_TYPE.BASIC, + AUTH_TYPE.AUTHORIZATION, +]; const AUTH_TYPES_REQUIRING_CREDENTIALS = [ ...AUTH_TYPES_REQUIRING_AUTH_VALUE, AUTH_TYPE.OAUTH2, @@ -1111,12 +1117,13 @@ const MCPServerEdit: React.FC = ({ {!isStdioTransport && ( <> - None API Key Bearer Token Token Basic Auth + Authorization (raw header) OAuth OAuth Token Exchange (OBO) AWS SigV4 (Bedrock AgentCore MCPs) diff --git a/ui/litellm-dashboard/src/components/mcp_tools/types.test.tsx b/ui/litellm-dashboard/src/components/mcp_tools/types.test.tsx index 10a1bb4b669..fec2e75ff6d 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/types.test.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/types.test.tsx @@ -108,6 +108,7 @@ describe("constants", () => { expect(AUTH_TYPE.NONE).toBe("none"); expect(AUTH_TYPE.API_KEY).toBe("api_key"); expect(AUTH_TYPE.BEARER_TOKEN).toBe("bearer_token"); + expect(AUTH_TYPE.AUTHORIZATION).toBe("authorization"); expect(AUTH_TYPE.OAUTH2).toBe("oauth2"); }); diff --git a/ui/litellm-dashboard/src/components/mcp_tools/types.tsx b/ui/litellm-dashboard/src/components/mcp_tools/types.tsx index de497d91afe..d3ca02c529f 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/types.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/types.tsx @@ -38,6 +38,7 @@ export const AUTH_TYPE = { BEARER_TOKEN: "bearer_token", TOKEN: "token", BASIC: "basic", + AUTHORIZATION: "authorization", OAUTH2: "oauth2", OAUTH2_TOKEN_EXCHANGE: "oauth2_token_exchange", AWS_SIGV4: "aws_sigv4",