fix: change Resource URI fields from AnyUrl to str (#1863)
This commit is contained in:
parent
f2abefffaf
commit
cfb2909631
5 changed files with 343 additions and 179 deletions
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue