Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 217 additions & 0 deletions docs/spec/roots.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
---
title: Roots
type: docs
weight: 8
description: "MCP protocol specification for root directory and file access"
draft: false
params:
author: Anthropic
keywords: ["mcp", "roots", "directories", "files", "protocols"]
---

Roots enable clients to provide a list of root directories or files that servers can operate on. This allows servers to understand which parts of the filesystem they have access to and should work with. Servers can request the list of roots from clients that support this capability, and clients can notify servers when the list of available roots changes.

## Capabilities

To indicate support for roots, clients MUST include a `roots` capability in their `ClientCapabilities` during initialization:

{{<tabs items="Basic,With Notifications">}}
{{<tab>}}
```json
{
"capabilities": {
"roots": { }
}
}
```
{{</tab>}}
{{<tab>}}
```json
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
```
{{</tab>}}
{{</tabs>}}

The optional `listChanged` property indicates whether the client will send notifications when the root list changes.

Servers SHOULD check for this capability before attempting to use any roots functionality.

## Concepts

### Root

A Root in the Model Context Protocol (MCP) represents a directory or file that a server is allowed to operate on. Each Root is uniquely identified by a URI (currently restricted to file:// URIs) and may have an optional human-readable name. Roots define the boundaries of where servers can work within the filesystem.

{{< callout type="info" >}}
Only URI's starting with **file://** are accepted.
{{< /callout >}}

## Use Cases

Common use cases for roots include defining workspace directories, project repositories, or specific files that a server should analyze or modify. Here are some examples:

### Project Directory

A root representing a project workspace:

```json
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```

### Multiple Repositories

Multiple roots for different Git repositories:

```json
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```

## Diagram

The following diagram visualizes the interaction between client and server for roots:

```mermaid
sequenceDiagram
participant Server
participant Client

Note over Server,Client: Server requests roots list
Server->>Client: roots/list
Client-->>Server: ListRootsResult

Note over Server,Client: Client updates roots
opt Roots Changed
Client-)Server: notifications/roots/list_changed
Server->>Client: roots/list
Client-->>Server: ListRootsResult
end
```

## Messages

This section defines the protocol messages for root management in the Model Context Protocol (MCP).

### Listing Roots

#### Request

To retrieve a list of available roots from the client, the server MUST send a `roots/list` request.

Method: `roots/list`
Params: None

Example:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
```

#### Response

The client MUST respond with a `ListRootsResult` containing:

- `roots`: An array of `Root` objects

A `Root` object consists of:
- `uri`: A URI string identifying the root location. Currently only `file://` URIs are supported. This field is required.
- `name`: An optional string providing a human-readable name for the root.

Example:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
}
}
```

### Root List Changed Notification

If the client supports the `listChanged` capability for roots, it MUST send a `notifications/roots/list_changed` notification when the list of available roots changes.

#### Notification

Method: `notifications/roots/list_changed`
Params: None

Example:
```json
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
```

Upon receiving this notification, servers SHOULD request an updated root list using the `roots/list` method to ensure they have the most up-to-date information.

## Error Handling

Servers MUST be prepared to handle cases where:
- The client does not support roots
- Listed roots become unavailable
- Access to roots is denied

The client SHOULD return appropriate error responses in these cases.

Example error response:
```json
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
```

## Security Considerations

Implementations MUST carefully consider:

- Access control for root directories and files
- Validation of root URIs to prevent path traversal attacks
- Scope limitations to prevent unauthorized access
- Permission checks before exposing roots
- Regular validation that roots remain accessible

Clients SHOULD:
- Only expose roots that the server has permission to access
- Validate all root URIs before returning them
- Implement proper filesystem permission checks
- Monitor for changes in root accessibility
112 changes: 112 additions & 0 deletions schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@
"description": "Experimental, non-standard capabilities that the client supports.",
"type": "object"
},
"roots": {
"description": "Present if the client supports listing roots.",
"properties": {
"listChanged": {
"description": "Whether the client supports notifications for changes to the roots list.",
"type": "boolean"
}
},
"type": "object"
},
"sampling": {
"additionalProperties": true,
"description": "Present if the client supports sampling from an LLM.",
Expand All @@ -96,6 +106,9 @@
},
{
"$ref": "#/definitions/ProgressNotification"
},
{
"$ref": "#/definitions/RootsListChangedNotification"
}
]
},
Expand Down Expand Up @@ -136,6 +149,9 @@
},
{
"$ref": "#/definitions/CompleteRequest"
},
{
"$ref": "#/definitions/ListRootsRequest"
}
]
},
Expand All @@ -146,6 +162,9 @@
},
{
"$ref": "#/definitions/CreateMessageResult"
},
{
"$ref": "#/definitions/ListRootsResult"
}
]
},
Expand Down Expand Up @@ -810,6 +829,54 @@
],
"type": "object"
},
"ListRootsRequest": {
"description": "Sent from the server to request a list of root URIs from the client. Roots allow\nservers to ask for specific directories or files to operate on. A common example\nfor roots is providing a set of repositories or directories a server should operate\non.\n\nThis request is typically used when the server needs to understand the file system\nstructure or access specific locations that the client has permission to read from.",
"properties": {
"method": {
"const": "roots/list",
"type": "string"
},
"params": {
"additionalProperties": {},
"properties": {
"_meta": {
"properties": {
"progressToken": {
"$ref": "#/definitions/ProgressToken",
"description": "If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications."
}
},
"type": "object"
}
},
"type": "object"
}
},
"required": [
"method"
],
"type": "object"
},
"ListRootsResult": {
"description": "The client's response to a roots/list request from the server.\nThis result contains an array of Root objects, each representing a root directory\nor file that the server can operate on.",
"properties": {
"_meta": {
"additionalProperties": {},
"description": "This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.",
"type": "object"
},
"roots": {
"items": {
"$ref": "#/definitions/Root"
},
"type": "array"
}
},
"required": [
"roots"
],
"type": "object"
},
"ListToolsRequest": {
"description": "Sent from the client to request a list of tools the server has.",
"properties": {
Expand Down Expand Up @@ -1353,6 +1420,48 @@
},
"type": "object"
},
"Root": {
"description": "Represents a root directory or file that the server can operate on.",
"properties": {
"name": {
"description": "An optional name for the root. This can be used to provide a human-readable\nidentifier for the root, which may be useful for display purposes or for\nreferencing the root in other parts of the application.",
"type": "string"
},
"uri": {
"description": "The URI identifying the root. This *must* start with file:// for now.\nThis restriction may be relaxed in future versions of the protocol to allow\nother URI schemes.",
"format": "uri-template",
"type": "string"
}
},
"required": [
"uri"
],
"type": "object"
},
"RootsListChangedNotification": {
"description": "A notification from the client to the server, informing it that the list of roots has changed.\nThis notification should be sent whenever the client adds, removes, or modifies any root.\nThe server should then request an updated list of roots using the ListRootsRequest.",
"properties": {
"method": {
"const": "notifications/roots/list_changed",
"type": "string"
},
"params": {
"additionalProperties": {},
"properties": {
"_meta": {
"additionalProperties": {},
"description": "This parameter name is reserved by MCP to allow clients and servers to attach additional metadata to their notifications.",
"type": "object"
}
},
"type": "object"
}
},
"required": [
"method"
],
"type": "object"
},
"SamplingMessage": {
"description": "Describes a message issued to or received from an LLM API.",
"properties": {
Expand Down Expand Up @@ -1464,6 +1573,9 @@
},
{
"$ref": "#/definitions/CreateMessageRequest"
},
{
"$ref": "#/definitions/ListRootsRequest"
}
]
},
Expand Down
Loading