Loomal

Roots (MCP)

Roots are an MCP mechanism by which a client tells a server which directories or URIs it is allowed to operate within.

Also known as: MCP roots, filesystem roots

What are roots in MCP?

Roots are the Model Context Protocol's way for a client to declare the boundaries a server should work within. Each root is a URI — most commonly a file:// path to a directory — and the set of roots tells the server: these locations are relevant and permitted; stay inside them.

The canonical example is a filesystem server. Without roots, a server capable of reading files has no protocol-level signal about which files the user intended to expose. With roots, the client can scope it to the current project folder and nothing else.

How the roots exchange works

Roots are a client-side capability, declared during the initial capability negotiation. A server that wants to know its boundaries sends a roots/list request, and the client responds with the current set of root URIs, each with an optional human-readable name. If the user changes scope — opening a different project, say — the client emits a roots/list_changed notification so the server can re-query.

This inverts the usual MCP direction: most requests flow client-to-server, but roots (like sampling) flow server-to-client, letting the server ask the environment about its own constraints.

Why roots matter for security

Servers that read or write local files are among the most powerful and most dangerous things an agent can touch. Roots provide the basic sandboxing primitive: least privilege expressed at the protocol level. An IDE-style client can grant a code-analysis server the repository directory while keeping the user's home directory, credentials, and SSH keys out of scope.

Roots also improve behavior, not just safety. A server that knows the project boundary can index the right tree, resolve relative paths sensibly, and avoid wandering into node_modules or system directories.

What roots do not guarantee

Roots are a contract, not a cage. The protocol communicates boundaries, but enforcement depends on the server honoring them — a malicious or buggy local server running with your OS user's permissions can still read whatever your account can read. Treat roots as a necessary signal and pair them with real isolation (containers, OS sandboxes, restricted accounts) when running untrusted code.

This is one reason provenance matters when choosing servers. A listing whose maintainer has claimed it through GitHub ownership verification — as on the Loomal Index — tells you who stands behind the code that your roots are trusting.

Roots vs resources

Roots and resources both involve URIs but answer opposite questions. Resources are content the server offers to the client — documents, records, files it can serve. Roots are constraints the client imposes on the server — where it may legitimately operate. A filesystem server might expose the files under its roots as resources; the roots came first and defined what could be offered. If you remember one direction, remember this one: resources flow outward from the server, roots flow inward from the client.