Skip to content

feat: add reusable roots enforcement utilities to MCPServer#2425

Closed
NeelakandanNC wants to merge 2 commits intomodelcontextprotocol:mainfrom
NeelakandanNC:feat/roots-utility
Closed

feat: add reusable roots enforcement utilities to MCPServer#2425
NeelakandanNC wants to merge 2 commits intomodelcontextprotocol:mainfrom
NeelakandanNC:feat/roots-utility

Conversation

@NeelakandanNC
Copy link
Copy Markdown

@NeelakandanNC NeelakandanNC commented Apr 12, 2026

MCP Roots let clients declare filesystem boundaries to servers, but the SDK provides no helpers to enforce them — every server author has to write the same boundary-check logic by hand. This adds a small utility module so authors can drop in enforcement without reinventing it.

  • get_roots(ctx): fetch root URIs declared by the client
  • assert_within_roots(path, ctx): raise PermissionError if path is outside roots
  • within_roots_check: decorator that auto-enforces roots on path parameters

Both sides of the comparison go through Path.resolve() so that platform firmlinks (e.g. macOS /tmp -> /private/tmp, /home -> /System/Volumes/Data/home) don't produce spurious denials.

Motivation and Context

I learned about MCP Roots in an advanced MCP course. When I actually tried implementing it in my own servers, I realised you have to write the same enforcement logic every single time you build a new server — the course teaches the concept but the SDK gives you no utility to actually apply it without repeating yourself.
So I built one.

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

MCP Roots let clients declare filesystem boundaries to servers, but the
SDK provides no helpers to enforce them — every server author has to
write the same boundary-check logic by hand. This adds a small utility
module so authors can drop in enforcement without reinventing it.

- get_roots(ctx): fetch root URIs declared by the client
- assert_within_roots(path, ctx): raise PermissionError if path is outside roots
- within_roots_check: decorator that auto-enforces roots on path parameters

Both sides of the comparison go through Path.resolve() so that platform
firmlinks (e.g. macOS /tmp -> /private/tmp, /home -> /System/Volumes/Data/home)
don't produce spurious denials.
- Add a test for a decorated tool that takes a non-path string
  parameter alongside a path parameter. Covers the previously
  unexercised loop-continue branch in within_roots_check when a
  str/Path argument is found whose name isn't `path` / `*_path`.

- Replace placeholder return bodies in the "decorator denies"
  tests with `raise AssertionError(...)  # pragma: no cover`,
  so the unreachable tool bodies don't drop project coverage
  below CI's fail_under=100 threshold while still documenting
  that they must not run.
@Kludex
Copy link
Copy Markdown
Member

Kludex commented Apr 12, 2026

Please create an issue about it, with what you want to achieve. I don't think the proposed API is easy to use.

@Kludex Kludex closed this Apr 12, 2026
@NeelakandanNC
Copy link
Copy Markdown
Author

Sure, will create a issue and add proper docs to understand it and make it easier to use

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants