diff --git a/examples/servers/simple-prompt/mcp_simple_prompt/server.py b/examples/servers/simple-prompt/mcp_simple_prompt/server.py index b562cc932..634ac43dc 100644 --- a/examples/servers/simple-prompt/mcp_simple_prompt/server.py +++ b/examples/servers/simple-prompt/mcp_simple_prompt/server.py @@ -89,9 +89,9 @@ async def get_prompt( ) if transport == "sse": + from mcp.server.fastmcp.server import SilentResponse from mcp.server.sse import SseServerTransport from starlette.applications import Starlette - from starlette.responses import Response from starlette.routing import Mount, Route sse = SseServerTransport("/messages/") @@ -103,7 +103,7 @@ async def handle_sse(request): await app.run( streams[0], streams[1], app.create_initialization_options() ) - return Response() + return SilentResponse() starlette_app = Starlette( debug=True, diff --git a/examples/servers/simple-resource/mcp_simple_resource/server.py b/examples/servers/simple-resource/mcp_simple_resource/server.py index cef29b851..80fc51521 100644 --- a/examples/servers/simple-resource/mcp_simple_resource/server.py +++ b/examples/servers/simple-resource/mcp_simple_resource/server.py @@ -56,9 +56,9 @@ async def read_resource(uri: AnyUrl) -> str | bytes: return SAMPLE_RESOURCES[name]["content"] if transport == "sse": + from mcp.server.fastmcp.server import SilentResponse from mcp.server.sse import SseServerTransport from starlette.applications import Starlette - from starlette.responses import Response from starlette.routing import Mount, Route sse = SseServerTransport("/messages/") @@ -70,7 +70,7 @@ async def handle_sse(request): await app.run( streams[0], streams[1], app.create_initialization_options() ) - return Response() + return SilentResponse() starlette_app = Starlette( debug=True, diff --git a/examples/servers/simple-tool/mcp_simple_tool/server.py b/examples/servers/simple-tool/mcp_simple_tool/server.py index bf3683c9e..8e30aa59b 100644 --- a/examples/servers/simple-tool/mcp_simple_tool/server.py +++ b/examples/servers/simple-tool/mcp_simple_tool/server.py @@ -57,9 +57,9 @@ async def list_tools() -> list[types.Tool]: ] if transport == "sse": + from mcp.server.fastmcp.server import SilentResponse from mcp.server.sse import SseServerTransport from starlette.applications import Starlette - from starlette.responses import Response from starlette.routing import Mount, Route sse = SseServerTransport("/messages/") @@ -71,7 +71,7 @@ async def handle_sse(request): await app.run( streams[0], streams[1], app.create_initialization_options() ) - return Response() + return SilentResponse() starlette_app = Starlette( debug=True, diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 924baaa9b..00e028fd8 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -52,6 +52,16 @@ logger = get_logger(__name__) +class SilentResponse(Response): + """A response that does not send any HTTP response back to the client.""" + + def __init__(self) -> None: + super().__init__() + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + return + + class Settings(BaseSettings, Generic[LifespanResultT]): """FastMCP server settings. @@ -748,7 +758,7 @@ async def handle_sse(scope: Scope, receive: Receive, send: Send): streams[1], self._mcp_server.create_initialization_options(), ) - return Response() + return SilentResponse() # Create routes routes: list[Route | Mount] = [] diff --git a/src/mcp/server/sse.py b/src/mcp/server/sse.py index b7ff33280..bcd2b547c 100644 --- a/src/mcp/server/sse.py +++ b/src/mcp/server/sse.py @@ -23,7 +23,7 @@ async def handle_sse(request): streams[0], streams[1], app.create_initialization_options() ) # Return empty response to avoid NoneType error - return Response() + return SilentResponse() # Create and run Starlette app starlette_app = Starlette(routes=routes) diff --git a/tests/server/test_sse_security.py b/tests/server/test_sse_security.py index 43af35061..dd0be811e 100644 --- a/tests/server/test_sse_security.py +++ b/tests/server/test_sse_security.py @@ -10,10 +10,10 @@ import uvicorn from starlette.applications import Starlette from starlette.requests import Request -from starlette.responses import Response from starlette.routing import Mount, Route from mcp.server import Server +from mcp.server.fastmcp.server import SilentResponse from mcp.server.sse import SseServerTransport from mcp.server.transport_security import TransportSecuritySettings from mcp.types import Tool @@ -55,7 +55,7 @@ async def handle_sse(request: Request): except ValueError as e: # Validation error was already handled inside connect_sse logger.debug(f"SSE connection failed validation: {e}") - return Response() + return SilentResponse() routes = [ Route("/sse", endpoint=handle_sse), diff --git a/tests/shared/test_sse.py b/tests/shared/test_sse.py index 39ae13524..2751c88fa 100644 --- a/tests/shared/test_sse.py +++ b/tests/shared/test_sse.py @@ -19,6 +19,7 @@ from mcp.client.session import ClientSession from mcp.client.sse import sse_client from mcp.server import Server +from mcp.server.fastmcp.server import SilentResponse from mcp.server.sse import SseServerTransport from mcp.server.transport_security import TransportSecuritySettings from mcp.shared.exceptions import McpError @@ -91,7 +92,7 @@ def make_server_app() -> Starlette: async def handle_sse(request: Request) -> Response: async with sse.connect_sse(request.scope, request.receive, request._send) as streams: await server.run(streams[0], streams[1], server.create_initialization_options()) - return Response() + return SilentResponse() app = Starlette( routes=[ @@ -354,7 +355,7 @@ def run_context_server(server_port: int) -> None: async def handle_sse(request: Request) -> Response: async with sse.connect_sse(request.scope, request.receive, request._send) as streams: await context_server.run(streams[0], streams[1], context_server.create_initialization_options()) - return Response() + return SilentResponse() app = Starlette( routes=[