@@ -175,6 +175,7 @@ def __init__(
175175 self ._event_store = event_store
176176 self ._custom_starlette_routes : list [Route ] = []
177177 self .dependencies = self .settings .dependencies
178+ self ._session_manager : StreamableHTTPSessionManager | None = None
178179
179180 # Set up MCP protocol handlers
180181 self ._setup_handlers ()
@@ -190,6 +191,25 @@ def name(self) -> str:
190191 def instructions (self ) -> str | None :
191192 return self ._mcp_server .instructions
192193
194+ @property
195+ def session_manager (self ) -> StreamableHTTPSessionManager :
196+ """Get the StreamableHTTP session manager.
197+
198+ This is exposed to enable advanced use cases like mounting multiple
199+ FastMCP servers in a single FastAPI application.
200+
201+ Raises:
202+ RuntimeError: If called before streamable_http_app() has been called.
203+ """
204+ if self ._session_manager is None :
205+ raise RuntimeError (
206+ "Session manager can only be accessed after"
207+ "calling streamable_http_app()."
208+ "The session manager is created lazily"
209+ "to avoid unnecessary initialization."
210+ )
211+ return self ._session_manager
212+
193213 def run (
194214 self ,
195215 transport : Literal ["stdio" , "sse" , "streamable-http" ] = "stdio" ,
@@ -746,19 +766,20 @@ def streamable_http_app(self) -> Starlette:
746766 from starlette .middleware import Middleware
747767 from starlette .routing import Mount
748768
749- # Create session manager using the provided event store
750- session_manager = StreamableHTTPSessionManager (
751- app = self ._mcp_server ,
752- event_store = self ._event_store ,
753- json_response = self .settings .json_response ,
754- stateless = self .settings .stateless_http , # Use the stateless setting
755- )
769+ # Create session manager on first call (lazy initialization)
770+ if self ._session_manager is None :
771+ self ._session_manager = StreamableHTTPSessionManager (
772+ app = self ._mcp_server ,
773+ event_store = self ._event_store ,
774+ json_response = self .settings .json_response ,
775+ stateless = self .settings .stateless_http , # Use the stateless setting
776+ )
756777
757778 # Create the ASGI handler
758779 async def handle_streamable_http (
759780 scope : Scope , receive : Receive , send : Send
760781 ) -> None :
761- await session_manager .handle_request (scope , receive , send )
782+ await self . session_manager .handle_request (scope , receive , send )
762783
763784 # Create routes
764785 routes : list [Route | Mount ] = []
@@ -807,12 +828,11 @@ async def handle_streamable_http(
807828
808829 routes .extend (self ._custom_starlette_routes )
809830
810- # Create Starlette app with routes and middleware
811831 return Starlette (
812832 debug = self .settings .debug ,
813833 routes = routes ,
814834 middleware = middleware ,
815- lifespan = lambda app : session_manager .run (),
835+ lifespan = lambda app : self . session_manager .run (),
816836 )
817837
818838 async def list_prompts (self ) -> list [MCPPrompt ]:
0 commit comments