Skip to content

Commit 4bb9808

Browse files
chughtapanclaude
andcommitted
Add SEP: Allow Non-File URI Schemes for Roots
Transfers SEP-1573 to the new PR-based SEP workflow per SEP-1850. This SEP proposes removing the restriction that root URIs must begin with file://, allowing servers to work with remote resources through any URI scheme. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 500cc2d commit 4bb9808

22 files changed

Lines changed: 5778 additions & 0 deletions

#SEP-Non-File-URI-Roots.md#

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# SEP: Allow Non-File URI Schemes for Roots
2+
3+
## Preamble
4+
5+
**Title:** Allow Non-File URI Schemes for Roots
6+
**Status:** Proposal
7+
**Authors:** Tapan Chugh (@chughtapan), (original proposal by @noctonic in [PR #507](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/507))
8+
**Type:** Standards Track
9+
**Created:** 2025-09-23
10+
11+
## Abstract
12+
13+
This SEP proposes removing the restriction that root URIs must begin with `file://`, allowing servers to work with remote resources through any URI scheme.
14+
15+
## Motivation
16+
17+
Consider the following MCP servers, where scoping access to specific resources using roots is highly desirable:
18+
19+
1. **Cloud Storage**: Restricting access to specific S3 buckets or prefixes using `s3://bucket-name/prefix/` roots allows operating only within designated storage areas while preventing access to other buckets or sensitive data paths.
20+
21+
2. **Version Control Repository**: Limiting operations to specific repositories using `https://github.com/owner/repo/` roots limits actions within the current project context without inadvertently affecting other repositories.
22+
23+
3. **Databases**: Restricting databases to `postgres://host/database/schema/` roots enables fine-grained control over which schemas, tables, or collections a server can query or modify. No more accidentally deleting the production database.
24+
25+
26+
## Specification
27+
28+
This change was originally proposed in [PR #507](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/507).
29+
30+
### Schema Changes
31+
32+
Update the `Root` interface in all schema versions to remove the file:// restriction:
33+
34+
```typescript
35+
export interface Root {
36+
/**
37+
* The URI identifying the root. This can be any valid URI scheme.
38+
* Common schemes include file://, https://, github://, s3://, etc.
39+
* Servers should document which URI schemes they support.
40+
*
41+
* @format uri
42+
*/
43+
uri: string;
44+
45+
/**
46+
* An optional human-readable name for this root.
47+
*/
48+
name?: string;
49+
50+
/**
51+
* Optional metadata for this root.
52+
*/
53+
_meta?: { [key: string]: unknown };
54+
}
55+
```
56+
57+
The specification should include guidance that servers must document their supported URI schemes and validate them. Clients may provide roots with any URI scheme, and servers must gracefully handle unsupported schemes by returning clear error messages rather than failing silently.
58+
59+
## Rationale
60+
61+
The decision to simply remove the file:// restriction rather than creating a more complex schema stems from several considerations. The URI field in the current schema already accepts any valid URI as a string; the file:// requirement is purely a documentation constraint rather than a technical limitation. Resources in MCP already support any URI scheme, and maintaining consistency between resources and roots simplifies the mental model for developers.
62+
63+
Alternative approaches were considered but rejected for adding unnecessary complexity: creating separate mechanisms for local and remote servers does not provide any clear benefits and fragmenents the ecosystem. A more flexible configuration scheme beyond URIs might be helpful, but we defer backward incompatible changes to the future, depending upon if there is any demand in the community.
64+
65+
Thr simple approach of allowing any URI maintains complete backward compatibility. Existing clients continue sending file:// roots unchanged, existing servers continue accepting them, and the ecosystem can gradually adopt support for additional schemes as needed. This evolutionary approach allows the community to discover optimal patterns through real-world usage rather than attempting to predict all future needs upfront.
66+
67+
## Backward Compatibility
68+
69+
This change is fully backward compatible with existing implementations.
70+
71+
## Reference Implementation
72+
73+
A complete reference implementation is available in [github.com/chughtapan/wags](https://github.com/chughtapan/wags/blob/main/src/wags/middleware/roots.py), demonstrating root validation across multiple URI schemes with practical examples of enforcement patterns.
74+
75+
The library provides a helpful decorator for server tools to declare which roots they would consume:
76+
```python
77+
@mcp.tool
78+
@requires_root("https://github.com/{owner}/{repo}")
79+
async def create_issue(self, owner: str, repo: str, title: str, body: str):
80+
# Proceed with search operation
81+
```
82+
and the `call_tool` tool handlers check that provides a root which satisfies this requirement before proceeding.
83+
84+
**Python SDK Changes:** https://github.com/modelcontextprotocol/python-sdk/pull/1390
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# SEP: Resource List Prefix Filter
2+
3+
## Preamble
4+
5+
**Title:** Resource List Prefix Filter
6+
**Status:** Proposal
7+
**Author:** Tapan Chugh (@chughtapan)
8+
**Type:** Standards Track
9+
**Created:** 2025-07-31
10+
11+
## Abstract
12+
13+
This SEP proposes adding an optional `prefix` parameter to the `resources/list` and `resources/templates/list` requests to enable servers to efficiently filter resources and resource templates by URI prefix, to improve discoverability of resources for clients when servers expose thousands of resources (or more).
14+
15+
## Motivation
16+
17+
While the protocol already supports pagination for handling large resource lists, this alone is insufficient when servers expose thousands of resources. Clients must retrieve multiple pages and implement local filtering to find specific resources, which becomes complex when combined with pagination as they must track filtered results across page boundaries. This leads to inefficiency as the same filtering logic is reimplemented in every client, with redundant data transfer for resources that will be discarded. Since resources already use URI format, prefix-based filtering is a natural solution that offloads this common operation to the server.
18+
19+
## Specification
20+
21+
### Schema Changes
22+
23+
Update `ListResourcesRequest` and `ListResourceTemplatesRequest` interfaces to include an optional `prefix` parameter:
24+
25+
```typescript
26+
export interface ListResourcesRequest extends PaginatedRequest {
27+
method: "resources/list";
28+
params?: {
29+
/**
30+
* Optional URI prefix to filter resources.
31+
* Only resources whose URI starts with this prefix will be returned.
32+
*/
33+
prefix?: string;
34+
} & PaginatedRequest["params"];
35+
}
36+
37+
export interface ListResourceTemplatesRequest extends PaginatedRequest {
38+
method: "resources/templates/list";
39+
params?: {
40+
/**
41+
* Optional URI prefix to filter resource templates.
42+
* Only templates whose URI template starts with this prefix will be returned.
43+
*/
44+
prefix?: string;
45+
} & PaginatedRequest["params"];
46+
}
47+
```
48+
49+
### Behavior
50+
51+
1. **Prefix matching**: The server returns only resources whose URI (or URI template) starts with the prefix
52+
2. **Pagination compatibility**: Prefix filtering works with pagination - the cursor represents position within the filtered results
53+
54+
### Examples
55+
56+
Request with prefix filter:
57+
58+
```json
59+
{
60+
"jsonrpc": "2.0",
61+
"id": 1,
62+
"method": "resources/list",
63+
"params": {
64+
"prefix": "file:///project/src/"
65+
}
66+
}
67+
```
68+
69+
Response:
70+
71+
```json
72+
{
73+
"jsonrpc": "2.0",
74+
"id": 1,
75+
"result": {
76+
"resources": [
77+
{
78+
"uri": "file:///project/src/main.py",
79+
"name": "main.py"
80+
},
81+
{
82+
"uri": "file:///project/src/config.json",
83+
"name": "config.json"
84+
}
85+
]
86+
}
87+
}
88+
```
89+
90+
Combining with pagination:
91+
92+
```json
93+
{
94+
"jsonrpc": "2.0",
95+
"id": 2,
96+
"method": "resources/list",
97+
"params": {
98+
"prefix": "https://api.example.com/users/",
99+
"cursor": "cursor-123"
100+
}
101+
}
102+
```
103+
104+
Resource templates with prefix filter:
105+
106+
```json
107+
{
108+
"jsonrpc": "2.0",
109+
"id": 3,
110+
"method": "resources/templates/list",
111+
"params": {
112+
"prefix": "https://api.example.com/"
113+
}
114+
}
115+
```
116+
117+
Response:
118+
119+
```json
120+
{
121+
"jsonrpc": "2.0",
122+
"id": 3,
123+
"result": {
124+
"resourceTemplates": [
125+
{
126+
"uriTemplate": "https://api.example.com/users/{id}",
127+
"name": "User Details"
128+
},
129+
{
130+
"uriTemplate": "https://api.example.com/posts/{postId}",
131+
"name": "Blog Post"
132+
}
133+
]
134+
}
135+
}
136+
```
137+
138+
## Rationale
139+
140+
Resources are a powerful abstraction in MCP that limit the scope of information available to LLMs. Efficient discoverability of these resources is crucial for effective context management. As the number of resources exposed by servers increases into thousands or millions, naively returning all resources becomes inefficient and convoluted for clients to handle. Given the hierarchical structure inherent in URIs, prefix-based filtering provides the simplest approach to improve resource discoverability.
141+
142+
### Alternatives Considered
143+
144+
1. **Glob patterns**: Although more flexible than simple prefixes, the value from the additional implementation complexity does not seem clear given the hierarchical nature of URIs.
145+
146+
2. **Client-side filtering**: Implementation complexity with pagination; inefficient for large resource sets.
147+
148+
3. **Separate method**: Adds unnecessary protocol complexity and duplicates logic.
149+
150+
## Backward Compatibility
151+
152+
While the `prefix` parameter is optional in the schema, this feature requires updates to SDKs to expose the prefix parameter. Existing clients continue to work as it is since the parameter is optional.
153+
154+
## Reference Implementation
155+
156+
TBD
157+
158+
## Security Implications
159+
160+
Prefix filtering doesn't grant access to resources that wouldn't already be accessible through pagination. It only provides a more efficient way to retrieve subsets of already-accessible resources.
161+
162+
## Open Questions
163+
164+
1. Should we consider path-based prefix matching versus string-based prefix matching? For example, should the prefix `uri://a` match `uri://abc/def` or not? Assuming the prefix to be path prefix seems like the easiest to implement especially with templates in mix.
165+
166+
2. For resource templates with embedded variables (e.g., `https://api.example.com/users/{id}/operations/{action}`), should we resolve partial parameters and try to match them against templates? This seems a little tricky to get right: While resolving template parameters makes sense from an improving discoverability perspective, it's unclear if returning something like: `https://api.example.com/users/123/operations/{action}` is in line with semantics that we want list_templates to offer.

.LICENSE.~undo-tree~

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(undo-tree-save-format-version . 1)
2+
"62ea415015c2b81baec7e7383d2723c15d2d2fb5"
3+
[nil current nil nil (27010 22883 841971 0) 0 nil]
4+
nil

0 commit comments

Comments
 (0)