From 28d8e8a4c94c4df5deb8c7519086b80ee5f102c9 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sat, 20 Sep 2025 14:46:51 -0700 Subject: [PATCH] Allow non-file URI schemes for Root resources Changed Root.uri from FileUrl to AnyUrl to support various URI schemes (https://, git://, s3://, etc.) in addition to file:// URLs. --- src/mcp/types.py | 9 ++++----- tests/client/test_list_roots_callback.py | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mcp/types.py b/src/mcp/types.py index 62feda87a..3869cd83c 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -1,7 +1,7 @@ from collections.abc import Callable from typing import Annotated, Any, Generic, Literal, TypeAlias, TypeVar -from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel +from pydantic import BaseModel, ConfigDict, Field, RootModel from pydantic.networks import AnyUrl, UrlConstraints from typing_extensions import deprecated @@ -1151,11 +1151,10 @@ class ListRootsRequest(Request[RequestParams | None, Literal["roots/list"]]): class Root(BaseModel): """Represents a root directory or file that the server can operate on.""" - uri: FileUrl + uri: AnyUrl """ - The URI identifying the root. This *must* start with file:// for now. - This restriction may be relaxed in future versions of the protocol to allow - other URI schemes. + The URI identifying the root. Can be any valid URI scheme (e.g., file://, https://, + git://, s3://, etc.). Servers should document which URI schemes they support. """ name: str | None = None """ diff --git a/tests/client/test_list_roots_callback.py b/tests/client/test_list_roots_callback.py index 0da0fff07..ecfce33bc 100644 --- a/tests/client/test_list_roots_callback.py +++ b/tests/client/test_list_roots_callback.py @@ -1,5 +1,5 @@ import pytest -from pydantic import FileUrl +from pydantic import AnyUrl from mcp.client.session import ClientSession from mcp.server.fastmcp.server import Context @@ -20,11 +20,11 @@ async def test_list_roots_callback(): callback_return = ListRootsResult( roots=[ Root( - uri=FileUrl("file://users/fake/test"), + uri=AnyUrl("file://users/fake/test"), name="Test Root 1", ), Root( - uri=FileUrl("file://users/fake/test/2"), + uri=AnyUrl("https://github.com/user/repo"), # Non-file URL also works name="Test Root 2", ), ]