Understanding Roots

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

When you give an AI agent access to your file system, you face a significant security risk. You might want the agent to read documentation in /home/knight/docs, but you definitely do not want it reading your SSH keys in ~/.ssh or deleting system files.

In MCP, Roots are the solution to this problem.

Roots define the boundaries of where a server is allowed to operate. They act as a “sandbox,” telling the server: “You can go berserk inside this specific directory, but you cannot touch anything outside of it.”

The Concept of Roots

Roots serve two main purposes: Context Scoping and Security Boundaries.

1. Context Scoping (The “Where”)

Roots tell the server which directories are currently relevant to the user.

2. Security Boundaries (The “Fence”)

This is the most critical aspect.

Implementing a Secure Server in Python

To understand how to enforce this, you will build a Secure File Reader.

What You Are Building

You are building a server that only reads files inside client-approved directories. The client defines the allowed roots, and the server enforces them for every file request.

Key Security Logic

  1. ctx.session.list_roots(): The server dynamically queries the client for permission.
  2. extract_path_from_uri: MCP uses file:// URIs (like browsers do), but Python uses OS paths. This helper bridges the gap.
  3. target_path.is_relative_to(root): This is the firewall. It ensures the requested file is physically located inside one of the authorized folders.

How the Server Script Works

  • ctx.session.list_roots() asks the client which directories are allowed.
  • extract_path_from_uri(...) converts file:// URIs into OS paths you can compare.
  • is_relative_to(...) enforces the boundary check for every request.
  • If no roots are provided, the server falls back to a local sandbox directory.

Implementing the Client with Roots

Now, create the client. This client represents the “Host Application” (like VS Code). It acts as the authority, telling the server: “You are only allowed to touch the sandbox folder.”

How the Client Script Works

  • list_roots_handler(...) is the callback the server asks for when it needs roots.
  • It returns a list of file:// URIs that define the allowed directories.
  • list_roots_callback=... is what makes the client “roots-aware.”

Run It

  1. In one terminal, start the server:
See forum comments
Download course materials from Github
Previous: Handling Elicitation with a Custom Client Next: Enforcing Roots