{ "name": "mcp-roots", "type": "registry:ui", "title": "MCP Roots", "description": "The roots a client has granted its servers — the closest thing MCP has to a permission boundary, and invisible in most clients. A root covering a whole home directory is drawn as a warning rather than as another grey row.", "category": "MCP", "dependencies": [ "lucide-react@^1.39.0" ], "registryDependencies": [ "badge", "button", "lib-motion", "lib-styles", "lib-utils" ], "files": [ { "path": "components/ui/mcp-roots.tsx", "type": "registry:ui", "content": "import type { ComponentProps } from 'react'\nimport { FolderOpen, Plus, TriangleAlert, X } from 'lucide-react'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { enterFade } from '@/lib/motion'\nimport { radius, surface } from '@/lib/styles'\nimport { cn } from '@/lib/utils'\n\n/**\n * The roots a client has granted its MCP servers.\n *\n * Roots are how an MCP client says \"you may look here and nowhere else\", and\n * they are the closest thing the protocol has to a permission boundary. They\n * are also invisible in most clients, which means nobody notices when one is\n * a great deal wider than intended.\n *\n * So this leans on making a wide grant *look* wide. A root at `/`, `~` or a\n * home directory covers everything a person owns, and it is rendered as a\n * warning rather than as another grey row — the same reasoning as\n * `SandboxPolicy`, applied to the protocol's own mechanism.\n *\n * Per-server scoping is shown when present. A root granted to every server is a\n * different fact from one granted to a single trusted server, and a flat list\n * of paths cannot tell them apart.\n */\nexport type McpRoot = {\n /** A `file://` URI, as the protocol specifies. */\n uri: string\n name?: string\n /** Server ids this root is exposed to. Empty or absent means all of them. */\n servers?: string[]\n /** Read-only grant. */\n readOnly?: boolean\n}\n\n/** Paths that are \"everything\" in practice. */\nconst BROAD = [/^file:\\/\\/\\/?$/, /^file:\\/\\/\\/Users\\/[^/]+\\/?$/, /^file:\\/\\/\\/home\\/[^/]+\\/?$/, /^~\\/?$/]\n\nexport function isBroadRoot(uri: string) {\n return BROAD.some((pattern) => pattern.test(uri.trim()))\n}\n\ntype McpRootsProps = Omit, 'children'> & {\n roots: McpRoot[]\n onAdd?: () => void\n onRemove?: (uri: string) => void\n addLabel?: string\n removeLabel?: string\n allServersLabel?: string\n readOnlyLabel?: string\n broadLabel?: string\n emptyLabel?: string\n label?: string\n}\n\nfunction McpRoots({\n roots,\n onAdd,\n onRemove,\n addLabel = 'Add a root',\n removeLabel = 'Remove',\n allServersLabel = 'all servers',\n readOnlyLabel = 'read-only',\n broadLabel = 'Covers everything you own',\n emptyLabel = 'No roots granted — servers can see nothing on this machine.',\n label = 'Roots',\n className,\n ...props\n}: McpRootsProps) {\n return (\n \n
\n

\n {label}\n

\n {onAdd && (\n \n )}\n
\n\n {roots.length === 0 ? (\n

{emptyLabel}

\n ) : (\n \n )}\n \n )\n}\n\nexport { McpRoots }\nexport type { McpRootsProps }\n" } ] }