From 816e878019aab32fe05e5abcdd5161a2b89cce12 Mon Sep 17 00:00:00 2001 From: Pratham-Mishra04 Date: Wed, 27 May 2026 13:39:28 +0530 Subject: [PATCH] fix: mcp ui fixes --- .../mcp-registry/views/mcpClientForm.tsx | 420 ++++++++++-------- .../mcp-registry/views/mcpClientSheet.tsx | 54 ++- .../mcp-registry/views/mcpClientsTable.tsx | 87 ++-- 3 files changed, 339 insertions(+), 222 deletions(-) diff --git a/ui/app/workspace/mcp-registry/views/mcpClientForm.tsx b/ui/app/workspace/mcp-registry/views/mcpClientForm.tsx index 6b22cffe1e4..836ce0f90b3 100644 --- a/ui/app/workspace/mcp-registry/views/mcpClientForm.tsx +++ b/ui/app/workspace/mcp-registry/views/mcpClientForm.tsx @@ -5,13 +5,14 @@ import { HeadersTable } from "@/components/ui/headersTable"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { useToast } from "@/hooks/use-toast"; import { getErrorMessage, useCreateMCPClientMutation } from "@/lib/store"; -import { CreateMCPClientRequest, EnvVar, MCPAuthType, MCPConnectionType, MCPStdioConfig } from "@/lib/types/mcp"; +import { CreateMCPClientRequest, EnvVar, MCPConnectionType, MCPStdioConfig } from "@/lib/types/mcp"; import { parseArrayFromText } from "@/lib/utils/array"; import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib"; import { Info } from "lucide-react"; @@ -70,6 +71,14 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { const [newHeaderKeyInput, setNewHeaderKeyInput] = useState(""); const [headersFlow, setHeadersFlow] = useState<{ payload: CreateMCPClientRequest } | null>(null); + // UI splits the canonical `auth_type` into two dropdowns: + // - authKind: none | headers | oauth + // - authScope: shared | per_user (hidden when authKind = none) + // They recombine into the wire `auth_type` ("oauth", "per_user_oauth", + // "headers", "per_user_headers", "none") so the backend contract is + // unchanged. + const [authScope, setAuthScope] = useState<"shared" | "per_user">("shared"); + const methods = useForm({ defaultValues: emptyForm }); const { control, handleSubmit, setValue, watch, reset, setError, clearErrors } = methods; @@ -77,6 +86,34 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { const authType = watch("auth_type"); const headers = watch("headers"); + const authKind: "none" | "headers" | "oauth" = + authType === "oauth" || authType === "per_user_oauth" + ? "oauth" + : authType === "headers" || authType === "per_user_headers" + ? "headers" + : "none"; + + const applyAuthKind = (kind: "none" | "headers" | "oauth") => { + if (kind === "none") { + setValue("auth_type", "none"); + return; + } + if (kind === "oauth") { + setValue("auth_type", authScope === "per_user" ? "per_user_oauth" : "oauth"); + return; + } + setValue("auth_type", authScope === "per_user" ? "per_user_headers" : "headers"); + }; + + const applyAuthScope = (scope: "shared" | "per_user") => { + setAuthScope(scope); + if (authKind === "oauth") { + setValue("auth_type", scope === "per_user" ? "per_user_oauth" : "oauth"); + } else if (authKind === "headers") { + setValue("auth_type", scope === "per_user" ? "per_user_headers" : "headers"); + } + }; + // Inline header validation (shown live as user edits headers). // Both "headers" and "per_user_headers" auth types persist the static // headers map via the submit path (see "headers" property of payload @@ -109,6 +146,7 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { setHeadersFlow(null); setPerUserHeaderKeys([]); setNewHeaderKeyInput(""); + setAuthScope("shared"); setIsLoading(false); } }, [open, reset]); @@ -311,6 +349,7 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { +

Connection type and authentication settings cannot be changed later.

)} @@ -389,24 +428,7 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { name="connection_string" render={({ field }) => ( -
- Connection URL - - - - - - - - -

- Use env.<VAR> to read - the value from an environment variable. -

-
-
-
-
+ Connection URL { @@ -422,40 +444,49 @@ const ClientForm: React.FC = ({ open, onClose, onSaved }) => { /> {/* Auth Type */} - ( - - Authentication Type - - - - )} - /> + + Authentication Type + + + + {/* Auth Scope — only meaningful when there's an auth flow */} + {authKind !== "none" && ( + + Auth Scope + + + )} {authType === "headers" && ( = ({ open, onClose, onSaved }) => {

Comma-separated list of header names each caller must supply when they first use this server (e.g.{" "} - X-API-Key, X-Tenant-ID). Values are submitted per user — never stored on this server config. + X-API-Key, X-Tenant-ID). Values are submitted per user - never stored on this server config.