mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-24 06:24:18 +02:00
Preserve component metadata in response cache (#4521)
This commit is contained in:
parent
00cab8ba8f
commit
16383a64d6
2 changed files with 68 additions and 43 deletions
|
|
@ -42,6 +42,7 @@ from fastmcp.server.middleware.caching import (
|
|||
)
|
||||
from fastmcp.server.middleware.middleware import CallNext, MiddlewareContext
|
||||
from fastmcp.tools.base import Tool, ToolResult
|
||||
from fastmcp.utilities.tasks import TaskConfig
|
||||
|
||||
TEST_URI = AnyUrl("https://test_uri")
|
||||
|
||||
|
|
@ -352,6 +353,47 @@ class TestResponseCachingMiddlewareIntegration:
|
|||
|
||||
assert pre_tool_list == post_tool_list
|
||||
|
||||
async def test_list_operations_preserve_component_metadata(self):
|
||||
"""Base component fields should survive conversion through the cache."""
|
||||
icon = mcp_types.Icon(src="https://example.com/component.png")
|
||||
mcp = FastMCP("MetadataServer")
|
||||
mcp.add_middleware(ResponseCachingMiddleware())
|
||||
|
||||
@mcp.tool(icons=[icon], task=TaskConfig(mode="optional"))
|
||||
async def greet() -> str:
|
||||
return "hello"
|
||||
|
||||
@mcp.resource("resource://metadata", icons=[icon])
|
||||
def metadata_resource() -> str:
|
||||
return "resource"
|
||||
|
||||
@mcp.prompt(icons=[icon])
|
||||
def metadata_prompt() -> str:
|
||||
return "prompt"
|
||||
|
||||
cached_tools = await mcp.list_tools()
|
||||
cached_resources = await mcp.list_resources()
|
||||
cached_prompts = await mcp.list_prompts()
|
||||
assert type(cached_tools[0]) is Tool
|
||||
assert type(cached_resources[0]) is Resource
|
||||
assert type(cached_prompts[0]) is Prompt
|
||||
assert not hasattr(cached_tools[0], "fn")
|
||||
assert not hasattr(cached_resources[0], "fn")
|
||||
assert not hasattr(cached_prompts[0], "fn")
|
||||
|
||||
async with Client(mcp) as client:
|
||||
for _ in range(2):
|
||||
tools = await client.list_tools()
|
||||
resources = await client.list_resources()
|
||||
prompts = await client.list_prompts()
|
||||
|
||||
assert tools[0].icons == [icon]
|
||||
assert tools[0].execution == mcp_types.ToolExecution(
|
||||
task_support="optional"
|
||||
)
|
||||
assert resources[0].icons == [icon]
|
||||
assert prompts[0].icons == [icon]
|
||||
|
||||
async def test_call_tool(
|
||||
self,
|
||||
caching_server: FastMCP,
|
||||
|
|
@ -595,13 +637,16 @@ class TestCachingWithImportedServerPrefixes:
|
|||
):
|
||||
"""Resource URIs should retain prefix after being served from cache."""
|
||||
async with Client(parent_with_imported_child) as client:
|
||||
# First call populates cache
|
||||
resources_first = await client.list_resources()
|
||||
resource_uris_first = [str(r.uri) for r in resources_first]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", UserWarning)
|
||||
|
||||
# Second call should come from cache
|
||||
resources_cached = await client.list_resources()
|
||||
resource_uris_cached = [str(r.uri) for r in resources_cached]
|
||||
# First call populates cache
|
||||
resources_first = await client.list_resources()
|
||||
resource_uris_first = [str(r.uri) for r in resources_first]
|
||||
|
||||
# Second call should come from cache
|
||||
resources_cached = await client.list_resources()
|
||||
resource_uris_cached = [str(r.uri) for r in resources_cached]
|
||||
|
||||
# All resources should have prefix in URI path in both calls
|
||||
# Resources get path-style prefix: resource://child/path
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue