diff --git a/docs/mcp/auth/overview.mdx b/docs/mcp/auth/overview.mdx index 7322a3cfef0..a1cffdbcc76 100644 --- a/docs/mcp/auth/overview.mdx +++ b/docs/mcp/auth/overview.mdx @@ -50,6 +50,8 @@ Per-user auth applies to the **HTTP** and **SSE** connection types. STDIO connec Per-user auth requires every request to carry an identity. See [Identity modes](#identity-modes) below. +Connection-state semantics (`connected`, `disconnected`, `error`, `needs_reauth`, etc., shown on the MCP client list) describe a persistent upstream connection, so they only apply to server-level clients. Per-user clients are stateless by design: each tool call resolves and uses the caller's credential on its own, with nothing held open between calls, so the dashboard links a per-user client to its [MCP Sessions](../sessions) rows instead of showing a connection state for it. + --- ## Pick your auth type diff --git a/ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx b/ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx index fe623a4002d..75b7175b44f 100644 --- a/ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx +++ b/ui/app/workspace/mcp-registry/views/mcpClientSheet.tsx @@ -458,7 +458,9 @@ export default function MCPClientSheet({ ? mcpClient.config.auth_type === "per_user_oauth" ? "This client was declared in config.json. A one-time admin test login is needed to verify the OAuth setup and discover tools — each user will authenticate individually afterward." : "This client was declared in config.json and needs a one-time OAuth authorization before it can be used." - : "MCP server configuration and available tools"} + : mcpClient.state === "needs_reauth" + ? "This connection's credentials have expired and need to be re-authorized. Re-authorization from the dashboard isn't available yet: recreating this client is the current workaround." + : "MCP server configuration and available tools"} { e.preventDefault(); onReconnect(client); @@ -644,8 +644,22 @@ export default function MCPClientsTable({ "-" )} - - {c.state} + e.stopPropagation()}> + {isPerUserAuth ? ( + // Per-user clients never hold a shared upstream connection, so a + // connection-state badge here would be misleading: point to the + // per-user sessions this client actually has instead. + + View sessions + + ) : ( + {c.state} + )} e.stopPropagation()}> = { pending_tools: "bg-yellow-100 text-yellow-800", pending_verification: "bg-yellow-100 text-yellow-800", disabled: "bg-orange-100 text-orange-800", + // Same red as `error`: the client's credential has died and it can't be + // used until a human reauthorizes it, mirroring the "destructive" treatment + // this status already gets on the MCP sessions table. + needs_reauth: "bg-red-100 text-red-800", }; // Mapping of what IS supported by each base provider diff --git a/ui/lib/types/mcp.ts b/ui/lib/types/mcp.ts index dcd372ab658..b8b6f2e9d66 100644 --- a/ui/lib/types/mcp.ts +++ b/ui/lib/types/mcp.ts @@ -3,7 +3,7 @@ import { SecretVar } from "./schemas"; export type MCPConnectionType = "http" | "stdio" | "sse"; -export type MCPConnectionState = "connected" | "disconnected" | "error" | "pending_tools" | "pending_verification" | "disabled"; +export type MCPConnectionState = "connected" | "disconnected" | "error" | "pending_tools" | "pending_verification" | "disabled" | "needs_reauth"; export type MCPAuthType = "none" | "headers" | "oauth" | "per_user_oauth" | "per_user_headers";