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
5 changed files with 343 additions and 179 deletions

View file

@ -29,7 +29,7 @@ from mcp.types import (
TextContent,
TextResourceContents,
)
from pydantic import AnyUrl, BaseModel, Field
from pydantic import BaseModel, Field
logger = logging.getLogger(__name__)
@ -114,7 +114,7 @@ def test_embedded_resource() -> list[EmbeddedResource]:
EmbeddedResource(
type="resource",
resource=TextResourceContents(
uri=AnyUrl("test://embedded-resource"),
uri="test://embedded-resource",
mimeType="text/plain",
text="This is an embedded resource content.",
),
@ -131,7 +131,7 @@ def test_multiple_content_types() -> list[TextContent | ImageContent | EmbeddedR
EmbeddedResource(
type="resource",
resource=TextResourceContents(
uri=AnyUrl("test://mixed-content-resource"),
uri="test://mixed-content-resource",
mimeType="application/json",
text='{"test": "data", "value": 123}',
),
@ -372,7 +372,7 @@ def test_prompt_with_embedded_resource(resourceUri: str) -> list[UserMessage]:
content=EmbeddedResource(
type="resource",
resource=TextResourceContents(
uri=AnyUrl(resourceUri),
uri=resourceUri,
mimeType="text/plain",
text="Embedded resource content for testing.",
),
@ -402,13 +402,13 @@ async def handle_set_logging_level(level: str) -> None:
# For conformance testing, we just acknowledge the request
async def handle_subscribe(uri: AnyUrl) -> None:
async def handle_subscribe(uri: str) -> None:
"""Handle resource subscription"""
resource_subscriptions.add(str(uri))
logger.info(f"Subscribed to resource: {uri}")
async def handle_unsubscribe(uri: AnyUrl) -> None:
async def handle_unsubscribe(uri: str) -> None:
"""Handle resource unsubscription"""
resource_subscriptions.discard(str(uri))
logger.info(f"Unsubscribed from resource: {uri}")

View file

@ -11,7 +11,6 @@ import anyio
import click
import mcp.types as types
from mcp.server.lowlevel import Server
from pydantic import AnyUrl
from starlette.requests import Request
# Sample data - in real scenarios, this might come from a database
@ -27,7 +26,7 @@ SAMPLE_TOOLS = [
SAMPLE_RESOURCES = [
types.Resource(
uri=AnyUrl(f"file:///path/to/resource_{i}.txt"),
uri=f"file:///path/to/resource_{i}.txt",
name=f"resource_{i}",
description=f"This is sample resource number {i}",
)
@ -160,7 +159,7 @@ def main(port: int, transport: str) -> int:
# Implement read_resource handler
@app.read_resource()
async def read_resource(uri: AnyUrl) -> str:
async def read_resource(uri: str) -> str:
# Find the resource in our sample data
resource = next((r for r in SAMPLE_RESOURCES if r.uri == uri), None)
if not resource:

View file

@ -3,7 +3,6 @@ import click
import mcp.types as types
from mcp.server.lowlevel import Server
from mcp.server.lowlevel.helper_types import ReadResourceContents
from pydantic import AnyUrl, FileUrl
from starlette.requests import Request
SAMPLE_RESOURCES = {
@ -37,7 +36,7 @@ def main(port: int, transport: str) -> int:
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri=FileUrl(f"file:///{name}.txt"),
uri=f"file:///{name}.txt",
name=name,
title=SAMPLE_RESOURCES[name]["title"],
description=f"A sample text resource named {name}",
@ -47,10 +46,13 @@ def main(port: int, transport: str) -> int:
]
@app.read_resource()
async def read_resource(uri: AnyUrl):
if uri.path is None:
async def read_resource(uri: str):
from urllib.parse import urlparse
parsed = urlparse(uri)
if not parsed.path:
raise ValueError(f"Invalid resource path: {uri}")
name = uri.path.replace(".txt", "").lstrip("/")
name = parsed.path.replace(".txt", "").lstrip("/")
if name not in SAMPLE_RESOURCES:
raise ValueError(f"Unknown resource: {uri}")

View file

@ -8,7 +8,6 @@ import click
import mcp.types as types
from mcp.server.lowlevel import Server
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
from pydantic import AnyUrl
from starlette.applications import Starlette
from starlette.middleware.cors import CORSMiddleware
from starlette.routing import Mount
@ -74,7 +73,7 @@ def main(
# This will send a resource notificaiton though standalone SSE
# established by GET request
await ctx.session.send_resource_updated(uri=AnyUrl("http:///test_resource"))
await ctx.session.send_resource_updated(uri="http:///test_resource")
return [
types.TextContent(
type="text",

View file

@ -2,8 +2,6 @@
Example of implementing pagination with MCP server decorators.
"""
from pydantic import AnyUrl
import mcp.types as types
from mcp.server.lowlevel import Server
@ -28,7 +26,7 @@ async def list_resources_paginated(request: types.ListResourcesRequest) -> types
# Get page of resources
page_items = [
types.Resource(uri=AnyUrl(f"resource://items/{item}"), name=item, description=f"Description for {item}")
types.Resource(uri=f"resource://items/{item}", name=item, description=f"Description for {item}")
for item in ITEMS[start:end]
]