diff --git a/src/fastmcp/server/middleware/middleware.py b/src/fastmcp/server/middleware/middleware.py index 0b78e4866..38b99b316 100644 --- a/src/fastmcp/server/middleware/middleware.py +++ b/src/fastmcp/server/middleware/middleware.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from collections.abc import Awaitable +from collections.abc import Awaitable, Sequence from dataclasses import dataclass, field, replace from datetime import datetime, timezone from functools import partial @@ -135,15 +135,15 @@ class Middleware: async def on_request( self, - context: MiddlewareContext[mt.Request], - call_next: CallNext[mt.Request, Any], + context: MiddlewareContext[mt.Request[Any, Any]], + call_next: CallNext[mt.Request[Any, Any], Any], ) -> Any: return await call_next(context) async def on_notification( self, - context: MiddlewareContext[mt.Notification], - call_next: CallNext[mt.Notification, Any], + context: MiddlewareContext[mt.Notification[Any, Any]], + call_next: CallNext[mt.Notification[Any, Any], Any], ) -> Any: return await call_next(context) @@ -164,8 +164,10 @@ class Middleware: async def on_read_resource( self, context: MiddlewareContext[mt.ReadResourceRequestParams], - call_next: CallNext[mt.ReadResourceRequestParams, list[ReadResourceContents]], - ) -> list[ReadResourceContents]: + call_next: CallNext[ + mt.ReadResourceRequestParams, Sequence[ReadResourceContents] + ], + ) -> Sequence[ReadResourceContents]: return await call_next(context) async def on_get_prompt( @@ -178,27 +180,29 @@ class Middleware: async def on_list_tools( self, context: MiddlewareContext[mt.ListToolsRequest], - call_next: CallNext[mt.ListToolsRequest, list[Tool]], - ) -> list[Tool]: + call_next: CallNext[mt.ListToolsRequest, Sequence[Tool]], + ) -> Sequence[Tool]: return await call_next(context) async def on_list_resources( self, context: MiddlewareContext[mt.ListResourcesRequest], - call_next: CallNext[mt.ListResourcesRequest, list[Resource]], - ) -> list[Resource]: + call_next: CallNext[mt.ListResourcesRequest, Sequence[Resource]], + ) -> Sequence[Resource]: return await call_next(context) async def on_list_resource_templates( self, context: MiddlewareContext[mt.ListResourceTemplatesRequest], - call_next: CallNext[mt.ListResourceTemplatesRequest, list[ResourceTemplate]], - ) -> list[ResourceTemplate]: + call_next: CallNext[ + mt.ListResourceTemplatesRequest, Sequence[ResourceTemplate] + ], + ) -> Sequence[ResourceTemplate]: return await call_next(context) async def on_list_prompts( self, context: MiddlewareContext[mt.ListPromptsRequest], - call_next: CallNext[mt.ListPromptsRequest, list[Prompt]], - ) -> list[Prompt]: + call_next: CallNext[mt.ListPromptsRequest, Sequence[Prompt]], + ) -> Sequence[Prompt]: return await call_next(context) diff --git a/src/fastmcp/server/server.py b/src/fastmcp/server/server.py index 81290e5cd..25db16cd1 100644 --- a/src/fastmcp/server/server.py +++ b/src/fastmcp/server/server.py @@ -641,7 +641,11 @@ class FastMCP(Generic[LifespanResultT]): ) # Apply the middleware chain. - return await self._apply_middleware(mw_context, self._list_tools) + return list( + await self._apply_middleware( + context=mw_context, call_next=self._list_tools + ) + ) async def _list_tools( self, @@ -721,7 +725,11 @@ class FastMCP(Generic[LifespanResultT]): ) # Apply the middleware chain. - return await self._apply_middleware(mw_context, self._list_resources) + return list( + await self._apply_middleware( + context=mw_context, call_next=self._list_resources + ) + ) async def _list_resources( self, @@ -811,8 +819,10 @@ class FastMCP(Generic[LifespanResultT]): ) # Apply the middleware chain. - return await self._apply_middleware( - mw_context, self._list_resource_templates + return list( + await self._apply_middleware( + context=mw_context, call_next=self._list_resource_templates + ) ) async def _list_resource_templates( @@ -907,7 +917,11 @@ class FastMCP(Generic[LifespanResultT]): ) # Apply the middleware chain. - return await self._apply_middleware(mw_context, self._list_prompts) + return list( + await self._apply_middleware( + context=mw_context, call_next=self._list_prompts + ) + ) async def _list_prompts( self, @@ -1002,7 +1016,9 @@ class FastMCP(Generic[LifespanResultT]): method="tools/call", fastmcp_context=fastmcp.server.dependencies.get_context(), ) - return await self._apply_middleware(mw_context, self._call_tool) + return await self._apply_middleware( + context=mw_context, call_next=self._call_tool + ) async def _call_tool( self, @@ -1056,7 +1072,9 @@ class FastMCP(Generic[LifespanResultT]): async with fastmcp.server.context.Context(fastmcp=self): try: - return await self._read_resource_middleware(uri) + return list[ReadResourceContents]( + await self._read_resource_middleware(uri) + ) except DisabledError: # convert to NotFoundError to avoid leaking resource presence raise NotFoundError(f"Unknown resource: {str(uri)!r}") @@ -1085,7 +1103,11 @@ class FastMCP(Generic[LifespanResultT]): method="resources/read", fastmcp_context=fastmcp.server.dependencies.get_context(), ) - return await self._apply_middleware(mw_context, self._read_resource) + return list( + await self._apply_middleware( + context=mw_context, call_next=self._read_resource + ) + ) async def _read_resource( self, @@ -1114,7 +1136,7 @@ class FastMCP(Generic[LifespanResultT]): if not self._should_enable_component(resource): # Parent filter blocks this resource, continue searching continue - result = await mounted.server._read_resource_middleware(key) + result = list(await mounted.server._read_resource_middleware(key)) return result except NotFoundError: continue @@ -1173,7 +1195,9 @@ class FastMCP(Generic[LifespanResultT]): method="prompts/get", fastmcp_context=fastmcp.server.dependencies.get_context(), ) - return await self._apply_middleware(mw_context, self._get_prompt) + return await self._apply_middleware( + context=mw_context, call_next=self._get_prompt + ) async def _get_prompt( self,