diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/IdJagFormFields.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/IdJagFormFields.tsx
new file mode 100644
index 00000000000..0d95c5b426d
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/IdJagFormFields.tsx
@@ -0,0 +1,105 @@
+import React from "react";
+import { Form, Input, Select, Tooltip } from "antd";
+import { InfoCircleOutlined } from "@ant-design/icons";
+
+interface IdJagFormFieldsProps {
+ isEditing?: boolean;
+}
+
+const fieldClassName = "rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500";
+
+const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, tooltip }) => (
+
+ {label}
+
+
+
+
+);
+
+const IdJagFormFields: React.FC = ({ isEditing = false }) => {
+ const placeholderSuffix = isEditing ? " (leave blank to keep existing)" : "";
+
+ return (
+ <>
+
+ }
+ name="token_exchange_endpoint"
+ rules={[{ required: !isEditing, message: "The IdP token endpoint is required for ID-JAG" }]}
+ >
+
+
+
+ }
+ name={["credentials", "id_jag_resource_token_endpoint"]}
+ rules={[{ required: !isEditing, message: "The resource token endpoint is required for ID-JAG" }]}
+ >
+
+
+
+ }
+ name={["credentials", "client_id"]}
+ rules={[{ required: !isEditing, message: "Client ID is required for ID-JAG" }]}
+ >
+
+
+
+ }
+ name={["credentials", "client_secret"]}
+ rules={[{ required: !isEditing, message: "Client Secret is required for ID-JAG" }]}
+ >
+
+
+
+ }
+ name="audience"
+ >
+
+
+
+ }
+ name={["credentials", "id_jag_resource"]}
+ >
+
+
+ }
+ name={["credentials", "scopes"]}
+ >
+
+
+ >
+ );
+};
+
+export default IdJagFormFields;
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..c285172633a 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
@@ -1058,6 +1058,73 @@ describe("CreateMCPServer", () => {
});
});
+ it("routes ID-JAG (Okta Cross App Access) config to the backend payload", async () => {
+ await selectHttpTransport();
+
+ fireEvent.change(getServerNameInput(), { target: { value: "IdJag_Server" } });
+ fireEvent.change(screen.getByPlaceholderText("https://your-mcp-server.com"), {
+ target: { value: "https://upstream.example.com/mcp" },
+ });
+
+ await selectAntOption("Authentication", "ID-JAG (Okta Cross App Access)");
+
+ await waitFor(() => {
+ expect(screen.getByPlaceholderText("https://your-okta-domain.okta.com/oauth2/v1/token")).toBeInTheDocument();
+ });
+
+ fireEvent.change(screen.getByPlaceholderText("https://your-okta-domain.okta.com/oauth2/v1/token"), {
+ target: { value: "https://acme.okta.com/oauth2/v1/token" },
+ });
+ fireEvent.change(screen.getByPlaceholderText("api://your-mcp-resource"), {
+ target: { value: "api://mcp-resource" },
+ });
+ fireEvent.change(screen.getByPlaceholderText("https://mcp.example.com/oauth2/token"), {
+ target: { value: "https://mcp.example.com/oauth2/token" },
+ });
+ fireEvent.change(screen.getByPlaceholderText("https://mcp.example.com"), {
+ target: { value: "https://mcp.example.com" },
+ });
+ fireEvent.change(screen.getByPlaceholderText("Enter OAuth client ID"), {
+ target: { value: "idjag-client-id" },
+ });
+ fireEvent.change(screen.getByPlaceholderText("Enter OAuth client secret"), {
+ target: { value: "idjag-client-secret" },
+ });
+
+ vi.mocked(networking.createMCPServer).mockResolvedValue({
+ server_id: "new-server-idjag",
+ server_name: "IdJag_Server",
+ alias: "IdJag_Server",
+ url: "https://upstream.example.com/mcp",
+ transport: "http",
+ auth_type: "oauth2_id_jag",
+ created_at: "2024-01-01T00:00:00Z",
+ created_by: "user-1",
+ updated_at: "2024-01-01T00:00:00Z",
+ updated_by: "user-1",
+ });
+
+ const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
+ await act(async () => {
+ fireEvent.click(submitButton);
+ });
+
+ await waitFor(() => {
+ expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
+ });
+
+ const [, payload] = vi.mocked(networking.createMCPServer).mock.calls[0];
+ expect(payload.auth_type).toBe("oauth2_id_jag");
+ expect(payload.token_exchange_endpoint).toBe("https://acme.okta.com/oauth2/v1/token");
+ expect(payload.audience).toBe("api://mcp-resource");
+ expect(payload.credentials).toMatchObject({
+ client_id: "idjag-client-id",
+ client_secret: "idjag-client-secret",
+ id_jag_resource_token_endpoint: "https://mcp.example.com/oauth2/token",
+ id_jag_resource: "https://mcp.example.com",
+ });
+ });
+
it("makes scope required when the Entra OBO profile is selected", 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 9f7639d00c7..52ed7b0411c 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
@@ -25,6 +25,7 @@ import OAuthFormFields from "./OAuthFormFields";
import TruePassthroughWarning from "./TruePassthroughWarning";
import PassthroughAuthorizeSection from "./PassthroughAuthorizeSection";
import TokenExchangeFormFields from "./TokenExchangeFormFields";
+import IdJagFormFields from "./IdJagFormFields";
import MCPServerCostConfig from "./mcp_server_cost_config";
import MCPConnectionStatus from "./mcp_connection_status";
import MCPToolConfiguration from "./mcp_tool_configuration";
@@ -61,6 +62,7 @@ const AUTH_TYPES_REQUIRING_CREDENTIALS = [
...AUTH_TYPES_REQUIRING_AUTH_VALUE,
AUTH_TYPE.OAUTH2,
AUTH_TYPE.OAUTH2_TOKEN_EXCHANGE,
+ AUTH_TYPE.OAUTH2_ID_JAG,
AUTH_TYPE.AWS_SIGV4,
AUTH_TYPE.TRUE_PASSTHROUGH,
AUTH_TYPE.OAUTH_DELEGATE,
@@ -140,6 +142,7 @@ const CreateMCPServer: React.FC = ({
const shouldShowAuthValueField = authType ? AUTH_TYPES_REQUIRING_AUTH_VALUE.includes(authType) : false;
const isOAuthAuthType = authType === AUTH_TYPE.OAUTH2;
const isTokenExchangeAuthType = authType === AUTH_TYPE.OAUTH2_TOKEN_EXCHANGE;
+ const isIdJagAuthType = authType === AUTH_TYPE.OAUTH2_ID_JAG;
const isAwsSigV4AuthType = authType === AUTH_TYPE.AWS_SIGV4;
const isM2MFlow = isOAuthAuthType && formValues.oauth_flow_type === OAUTH_FLOW.M2M;
@@ -1071,7 +1074,7 @@ const CreateMCPServer: React.FC = ({
children: (
<>
-