Roots allow clients to expose directories or files that MCP servers can access or operate on.
Overview
Roots represent directories or files that the client wants to make available to the server. This is useful for file-based operations where the server needs to know which paths are accessible. The server can request the list of roots at any time using ctx.list_roots().
Configuration
To expose roots to MCP servers, provide a roots list when initializing the MCPClient:
from mcp.types import Root
from mcp_use.client import MCPClient
# Define roots to expose to servers
roots = [
Root(uri="file:///home/user/projects", name="Projects"),
Root(uri="file:///home/user/documents", name="Documents"),
]
# Initialize client with roots
client = MCPClient(
config="config.json",
roots=roots
)
Dynamic Roots Updates
You can update the roots dynamically after connecting to a server. The client will automatically notify the server when roots change:
from mcp.types import Root
from mcp_use.client import MCPClient
client = MCPClient(config="config.json")
await client.create_all_sessions()
session = client.get_session("my-server")
# Update roots dynamically
new_roots = [
Root(uri="file:///home/user/new-project", name="New Project"),
]
await session.connector.set_roots(new_roots)
# Get current roots
current_roots = session.connector.get_roots()
Custom Roots Callback
For advanced use cases, you can provide a custom callback that dynamically determines which roots to expose:
from mcp.types import ListRootsResult, Root
from mcp_use.client import MCPClient
async def custom_roots_callback(context):
"""Dynamically determine roots based on context."""
# You could check user permissions, load from config, etc.
return ListRootsResult(roots=[
Root(uri="file:///dynamic/path", name="Dynamic Root"),
])
client = MCPClient(
config="config.json",
list_roots_callback=custom_roots_callback
)
When a custom list_roots_callback is provided, it takes precedence over the static roots list.
Root Structure
Each Root object has the following fields:
| Field | Type | Required | Description |
|---|
uri | AnyUrl | Yes | A file:// URI pointing to the root directory or file |
name | str | No | A human-readable name for the root |
Example: File Manager Server
Here’s a complete example showing a client exposing roots to a file management server:
import asyncio
from mcp.types import Root
from mcp_use.client import MCPClient
async def main():
# Expose workspace directories to the server
roots = [
Root(uri="file:///home/user/workspace", name="Workspace"),
Root(uri="file:///home/user/config", name="Config Files"),
]
config = {
"mcpServers": {
"file-manager": {"url": "http://localhost:8000/mcp"}
}
}
client = MCPClient(config, roots=roots)
try:
await client.create_all_sessions()
session = client.get_session("file-manager")
# The server can now query available roots
# and operate on files within them
result = await session.call_tool("list_files", {})
print(result.content[0].text)
finally:
await client.close_all_sessions()
if __name__ == "__main__":
asyncio.run(main())
Next Steps