Files
mcp-use__mcp-use/docs/python/client/roots.mdx
Luigi Pederzani b45d9663ec feat(python): introduce roots support in MCPClient and Server (#751)
* fix(python): expose client capabilities to MCP servers

Add list_roots_callback support to Python connectors to properly
advertise the roots capability during MCP initialization handshake.

Previously, the Python library was not exposing any client capabilities
because the list_roots_callback was not being passed to ClientSession.
This fix ensures the roots capability is always advertised, bringing
the Python library in line with the TypeScript implementation.

Changes:
- Add roots and list_roots_callback params to BaseConnector
- Add get_roots() and set_roots() methods for managing roots
- Pass list_roots_callback to ClientSession in all connectors
- Export Root type from connectors module
- Update unit tests to expect list_roots_callback parameter

Closes MCP-1063

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(python): add roots and list_roots_callback params to connectors

- Add roots and list_roots_callback parameters to StdioConnector,
  HttpConnector, and SandboxConnector constructors
- Add comprehensive unit tests for client capabilities exposure
- Tests verify roots capability, get_roots(), set_roots(), and
  that all callbacks are correctly passed to ClientSession

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: fix import sorting and update API documentation

- Fix import sorting in test_client_capabilities.py (ruff)
- Regenerate API documentation for updated connector classes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(python): add list_roots() method to server Context

Allow MCP servers to request the list of roots from connected clients
via ctx.list_roots(). This follows the same pattern as ctx.sample()
and ctx.elicit() for server-to-client requests.

* feat(python): add roots params to MCPClient and config

- Add roots and list_roots_callback parameters to MCPClient.__init__,
  from_dict(), and from_config_file() methods
- Update create_connector_from_config() to pass roots params to all
  connector types (Stdio, HTTP, Sandbox)
- Allows clients to configure roots at the MCPClient level and have
  them propagate to all sessions

* test(python): add get_client_roots tool to primitive server

Add a tool that demonstrates the roots capability by requesting and
returning the list of roots from the connected client. Used for
integration testing of the roots feature.

* test(python): add integration tests for roots capability

Add comprehensive integration tests for the roots feature:
- test_roots_capability: Verify server can request/receive roots
- test_roots_empty_by_default: Verify empty roots when not provided
- test_roots_with_custom_callback: Verify custom callback precedence
- test_set_roots_updates_server_view: Verify dynamic root updates

* test(python): update unit tests for roots parameters

Update mock assertions in test_client.py to expect the new roots
and list_roots_callback parameters in create_connector_from_config
calls.

* ci(python): add roots to primitive tests and README badge

- Add roots to CI workflow primitive test matrix
- Add roots to PR comment report primitives list
- Add Roots badge to README Primitives row

* feat(docs): enhance MCP client and server documentation for roots feature

- Added `roots` and `list_roots_callback` parameters to MCP client initialization documentation.
- Updated `create_connector_from_config` documentation to include new parameters.
- Introduced `list_roots` method documentation in server context, detailing its usage and return values.
- Improved overall clarity and completeness of API reference for better developer guidance.

* feat(python): add get_client_roots tool to context example

- Introduced a new tool, `get_client_roots`, to the context example, demonstrating how to retrieve and display the list of roots exposed by the client.
- Updated documentation to include the new tool and its functionality, enhancing the example's coverage of context features.

* feat(docs): add roots documentation for client and server

- Introduced new documentation for the `roots` feature, detailing how clients can expose file system roots to MCP servers and how servers can access these roots.
- Added examples for configuring roots in the MCP client and using the `list_roots()` method in the server context.
- Enhanced overall clarity and usability of the documentation to support developers in implementing the roots functionality.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: pietrozullo <pietro.zullo@gmail.com>
2026-01-12 11:16:09 +01:00

140 lines
3.7 KiB
Plaintext

---
title: "Roots"
description: "Expose file system roots to MCP servers"
icon: "folder-tree"
---
<Info>
Roots allow clients to expose directories or files that MCP servers can access or operate on.
</Info>
## 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:
<CodeGroup>
```python Python
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
)
```
</CodeGroup>
## Dynamic Roots Updates
You can update the roots dynamically after connecting to a server. The client will automatically notify the server when roots change:
```python
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:
```python
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
)
```
<Note>
When a custom `list_roots_callback` is provided, it takes precedence over the static `roots` list.
</Note>
## 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:
```python
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
- See [Server Roots](/python/server/roots) for how servers can request and use roots
- Learn about [Sampling](/python/client/sampling) for enabling LLM capabilities
- Explore [Elicitation](/python/client/elicitation) for user input requests