mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-15 23:31:29 +00:00
fix(ui): expose the authorization MCP auth type in the create and edit forms
This commit is contained in:
parent
24123269cc
commit
153b17e98b
6 changed files with 94 additions and 4 deletions
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<CreateMCPServerProps> = ({
|
|||
children: (
|
||||
<>
|
||||
<Form.Item name="auth_type" rules={[{ required: true, message: "Please select an auth type" }]}>
|
||||
<Select placeholder="Select auth type" className="rounded-lg" size="large">
|
||||
<Select placeholder="Select auth type" className="rounded-lg" size="large" virtual={false}>
|
||||
<Select.Option value="none">None</Select.Option>
|
||||
<Select.Option value="api_key">API Key</Select.Option>
|
||||
<Select.Option value="bearer_token">Bearer Token</Select.Option>
|
||||
<Select.Option value="token">Token</Select.Option>
|
||||
<Select.Option value="basic">Basic Auth</Select.Option>
|
||||
<Select.Option value="authorization">Authorization (raw header)</Select.Option>
|
||||
<Select.Option value="oauth2">OAuth</Select.Option>
|
||||
<Select.Option value="oauth2_token_exchange">OAuth Token Exchange (OBO)</Select.Option>
|
||||
<Select.Option value="aws_sigv4">AWS SigV4 (Bedrock AgentCore MCPs)</Select.Option>
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
<MCPServerEdit
|
||||
mcpServer={{ ...interactiveOAuthServer, auth_type: "api_key" }}
|
||||
accessToken="access-token"
|
||||
onCancel={vi.fn()}
|
||||
onSuccess={vi.fn()}
|
||||
availableAccessGroups={[]}
|
||||
/>,
|
||||
);
|
||||
|
||||
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 });
|
||||
|
||||
|
|
|
|||
|
|
@ -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<MCPServerEditProps> = ({
|
|||
{!isStdioTransport && (
|
||||
<>
|
||||
<Form.Item label="Authentication" name="auth_type" rules={[{ required: true }]}>
|
||||
<Select>
|
||||
<Select virtual={false}>
|
||||
<Select.Option value="none">None</Select.Option>
|
||||
<Select.Option value="api_key">API Key</Select.Option>
|
||||
<Select.Option value="bearer_token">Bearer Token</Select.Option>
|
||||
<Select.Option value="token">Token</Select.Option>
|
||||
<Select.Option value="basic">Basic Auth</Select.Option>
|
||||
<Select.Option value="authorization">Authorization (raw header)</Select.Option>
|
||||
<Select.Option value="oauth2">OAuth</Select.Option>
|
||||
<Select.Option value="oauth2_token_exchange">OAuth Token Exchange (OBO)</Select.Option>
|
||||
<Select.Option value="aws_sigv4">AWS SigV4 (Bedrock AgentCore MCPs)</Select.Option>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue