@@ -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