fix: change Resource URI fields from AnyUrl to str (#1863)

This commit is contained in:
Felix Weinberger 2026-01-16 08:58:57 +00:00 • committed by GitHub
commit cfb2909631
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 343 additions and 179 deletions

View file

@ -1,14 +1,12 @@
"""Base classes and interfaces for FastMCP resources."""
import abc
from typing import Annotated, Any
from typing import Any
from pydantic import (
AnyUrl,
BaseModel,
ConfigDict,
Field,
UrlConstraints,
ValidationInfo,
field_validator,
)
@ -21,7 +19,7 @@ class Resource(BaseModel, abc.ABC):
model_config = ConfigDict(validate_default=True)
uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] = Field(default=..., description="URI of the resource")
uri: str = Field(default=..., description="URI of the resource")
name: str | None = Field(description="Name of the resource", default=None)
title: str | None = Field(description="Human-readable title of the resource", default=None)
description: str | None = Field(description="Description of the resource", default=None)

View file

@ -11,7 +11,7 @@ import anyio.to_thread
import httpx
import pydantic
import pydantic_core
from pydantic import AnyUrl, Field, ValidationInfo, validate_call
from pydantic import Field, ValidationInfo, validate_call
from mcp.server.fastmcp.resources.base import Resource
from mcp.types import Annotations, Icon
@ -94,7 +94,7 @@ class FunctionResource(Resource):
fn = validate_call(fn)
return cls(
uri=AnyUrl(uri),
uri=uri,
name=func_name,
title=title,
description=description or fn.__doc__ or "",

View file

@ -79,7 +79,6 @@ from typing import Any, Generic, TypeAlias, cast
import anyio
import jsonschema
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
from pydantic import AnyUrl
from typing_extensions import TypeVar
import mcp.types as types
@ -337,7 +336,7 @@ class Server(Generic[LifespanResultT, RequestT]):
def read_resource(self):
def decorator(
func: Callable[[AnyUrl], Awaitable[str | bytes | Iterable[ReadResourceContents]]],
func: Callable[[str], Awaitable[str | bytes | Iterable[ReadResourceContents]]],
):
logger.debug("Registering handler for ReadResourceRequest")
@ -412,7 +411,7 @@ class Server(Generic[LifespanResultT, RequestT]):
return decorator
def subscribe_resource(self): # pragma: no cover
def decorator(func: Callable[[AnyUrl], Awaitable[None]]):
def decorator(func: Callable[[str], Awaitable[None]]):
logger.debug("Registering handler for SubscribeRequest")
async def handler(req: types.SubscribeRequest):
@ -425,7 +424,7 @@ class Server(Generic[LifespanResultT, RequestT]):
return decorator
def unsubscribe_resource(self): # pragma: no cover
def decorator(func: Callable[[AnyUrl], Awaitable[None]]):
def decorator(func: Callable[[str], Awaitable[None]]):
logger.debug("Registering handler for UnsubscribeRequest")
async def handler(req: types.UnsubscribeRequest):

View file

@ -227,12 +227,12 @@ class ServerSession(
related_request_id,
)
async def send_resource_updated(self, uri: AnyUrl) -> None: # pragma: no cover
async def send_resource_updated(self, uri: str | AnyUrl) -> None: # pragma: no cover
"""Send a resource updated notification."""
await self.send_notification(
types.ServerNotification(
types.ResourceUpdatedNotification(
params=types.ResourceUpdatedNotificationParams(uri=uri),
params=types.ResourceUpdatedNotificationParams(uri=str(uri)),
)
)
)