MCP Roots

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.

src/components/ui/mcp-roots.tsx

About

From the component's own source, where it was written.

The roots a client has granted its MCP servers.

Roots are how an MCP client says "you may look here and nowhere else", and they are the closest thing the protocol has to a permission boundary. They are also invisible in most clients, which means nobody notices when one is a great deal wider than intended.

So this leans on making a wide grant *look* wide. A root at /, ~ or a home directory covers everything a person owns, and it is rendered as a warning rather than as another grey row — the same reasoning as SandboxPolicy, applied to the protocol's own mechanism.

Per-server scoping is shown when present. A root granted to every server is a different fact from one granted to a single trusted server, and a flat list of paths cannot tell them apart.

Install

npx astralyx-ui add mcp-roots

Usage

import { McpRoots } from '@/components/ui/mcp-roots'

<McpRoots roots={roots} onAdd={add} onRemove={remove} />

Composer

Change the props and the source below follows.

Roots

  • astralyx

    file:///Users/ada/work/astralyx

    filesystem, git
  • Scratch

    file:///tmp/agent-scratch

    all servers
  • Home

    file:///Users/ada

    filesystem

    Covers everything you own

Props
tsx
<McpRoots
  roots={roots}
  onAdd={add}
  onRemove={remove}
/>

Examples

One root wider than intended

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

McpRoots

The roots a client has granted its MCP servers.

Extends Omit<ComponentProps<'div'>, 'children'>.

PropTypeDefaultDescription
rootsMcpRoot[]requiredRendered as “servers can see nothing”, rather than as an empty box that could mean either thing.
onAdd() => void——
onRemove(uri: string) => void——
addLabelstring'Add a root'—
removeLabelstring'Remove'—
allServersLabelstring'all servers'—
readOnlyLabelstring'read-only'—
broadLabelstring'Covers everything you own'—
emptyLabelstring'No roots granted — servers can see nothing on this machine.'—
labelstring'Roots'—

Functions

FunctionSignatureDescription
isBroadRoot(uri: string) => boolean—

Types

McpRoot

FieldTypeDescription
uristringA file:// URI, as the protocol specifies.
name?string—
servers?string[]Server ids this root is exposed to. Empty or absent means all of them.
readOnly?booleanRead-only grant.

Behaviour

TopicDetailDescription
broad detectionisBroadRoot/, a bare ~, and /Users/<name> or /home/<name> cover everything a person owns. Exported so a save handler can check before granting.
scopingshown per rootA root granted to every server is a different fact from one granted to a single trusted server, and a flat path list cannot tell them apart.