import { IconPlugConnected, IconAlertTriangle, IconLoader2, IconCheck, IconTestPipe, } from "@tabler/icons-react"; /** * Detail view for a virtual MCP server entry in the Workspace tree. * * Shown when the user clicks an `mcp-servers/.json` entry. Servers * aren't editable in-place — today the server endpoints only support * create + delete, matching the Settings UX they replaced. Users can * delete and recreate if they need to change a URL or headers. */ import React, { useState } from "react"; import { agentNativePath } from "../api-path.js"; import { cn } from "../utils.js"; import { type McpServer, type TestMcpUrlResult } from "./use-mcp-servers.js"; interface McpServerDetailProps { server: McpServer; } export function McpServerDetail({ server }: McpServerDetailProps) { const [testing, setTesting] = useState(false); const [testResult, setTestResult] = useState(null); const headers = server.headers ? Object.keys(server.headers) : []; const runTest = async () => { setTesting(true); setTestResult(null); try { // We don't have the real header values client-side (redacted). The // test-existing endpoint uses the stored headers, but there's no // convenient way to hit it from here without the server id + scope, // which we do have — so wire that up. const res = await fetch( agentNativePath( `/_agent-native/mcp/servers/${encodeURIComponent(server.id)}/test?scope=${server.scope}`, ), { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, }, ); const body = (await res.json().catch(() => ({}))) as TestMcpUrlResult; setTestResult(body.ok ? body : { ok: false, error: body.error }); } catch (err: any) { setTestResult({ ok: false, error: err?.message ?? String(err) }); } finally { setTesting(false); } }; return (

{server.name}

{server.description && (

{server.description}

)}
{server.scope === "user" ? "Personal" : "Organization"}

{server.scope === "user" ? "Only available to you. Best for private or staging connections." : "Shared with the active organization. Best for vetted team connections."}

{server.url} {headers.length > 0 && (
    {headers.map((k) => (
  • {k} (hidden)
  • ))}
)}
{testResult && }

To change the URL, headers, or description, delete this entry and add a new server. Edits in place aren't supported yet.

); } function Field({ label, children, }: { label: string; children: React.ReactNode; }) { return (
{label}
{children}
); } function StatusBadge({ server }: { server: McpServer }) { if (server.status.state === "connected") { return ( Connected ); } if (server.status.state === "error") { return ( Error ); } return ( Connecting… ); } function ToolsSummary({ server }: { server: McpServer }) { if (server.status.state === "connected") { return ( {server.status.toolCount} tool {server.status.toolCount === 1 ? "" : "s"} exposed ); } if (server.status.state === "error") { return ( {server.status.error} ); } return ( Not connected yet — try the Test button. ); } function TestResultLine({ result }: { result: TestMcpUrlResult }) { if (result.ok) { return ( {result.toolCount} tool{result.toolCount === 1 ? "" : "s"} available ); } return ( {result.error ?? "Failed"} ); }