@@ -128,13 +128,41 @@ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you bui
128
128
The FastMCP server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
129
129
130
130
``` python
131
+ # Add lifespan support for startup/shutdown with strong typing
132
+ from dataclasses import dataclass
133
+ from typing import AsyncIterator
131
134
from mcp.server.fastmcp import FastMCP
132
135
133
136
# Create a named server
134
137
mcp = FastMCP(" My App" )
135
138
136
139
# Specify dependencies for deployment and development
137
140
mcp = FastMCP(" My App" , dependencies = [" pandas" , " numpy" ])
141
+
142
+ @dataclass
143
+ class AppContext :
144
+ db: Database # Replace with your actual DB type
145
+
146
+ @asynccontextmanager
147
+ async def app_lifespan (server : FastMCP) -> AsyncIterator[AppContext]:
148
+ """ Manage application lifecycle with type-safe context"""
149
+ try :
150
+ # Initialize on startup
151
+ await db.connect()
152
+ yield AppContext(db = db)
153
+ finally :
154
+ # Cleanup on shutdown
155
+ await db.disconnect()
156
+
157
+ # Pass lifespan to server
158
+ mcp = FastMCP(" My App" , lifespan = app_lifespan)
159
+
160
+ # Access type-safe lifespan context in tools
161
+ @mcp.tool ()
162
+ def query_db (ctx : Context) -> str :
163
+ """ Tool that uses initialized resources"""
164
+ db = ctx.request_context.lifespan_context[" db" ]
165
+ return db.query()
138
166
```
139
167
140
168
### Resources
@@ -334,7 +362,38 @@ def query_data(sql: str) -> str:
334
362
335
363
### Low-Level Server
336
364
337
- For more control, you can use the low-level server implementation directly. This gives you full access to the protocol and allows you to customize every aspect of your server:
365
+ For more control, you can use the low-level server implementation directly. This gives you full access to the protocol and allows you to customize every aspect of your server, including lifecycle management through the lifespan API:
366
+
367
+ ``` python
368
+ from contextlib import asynccontextmanager
369
+ from typing import AsyncIterator
370
+
371
+ @asynccontextmanager
372
+ async def server_lifespan (server : Server) -> AsyncIterator[dict ]:
373
+ """ Manage server startup and shutdown lifecycle."""
374
+ try :
375
+ # Initialize resources on startup
376
+ await db.connect()
377
+ yield {" db" : db}
378
+ finally :
379
+ # Clean up on shutdown
380
+ await db.disconnect()
381
+
382
+ # Pass lifespan to server
383
+ server = Server(" example-server" , lifespan = server_lifespan)
384
+
385
+ # Access lifespan context in handlers
386
+ @server.call_tool ()
387
+ async def query_db (name : str , arguments : dict ) -> list :
388
+ ctx = server.request_context
389
+ db = ctx.lifespan_context[" db" ]
390
+ return await db.query(arguments[" query" ])
391
+ ```
392
+
393
+ The lifespan API provides:
394
+ - A way to initialize resources when the server starts and clean them up when it stops
395
+ - Access to initialized resources through the request context in handlers
396
+ - Type-safe context passing between lifespan and request handlers
338
397
339
398
``` python
340
399
from mcp.server.lowlevel import Server, NotificationOptions
@@ -417,9 +476,21 @@ server_params = StdioServerParameters(
417
476
env = None # Optional environment variables
418
477
)
419
478
479
+ # Optional: create a sampling callback
480
+ async def handle_sampling_message (message : types.CreateMessageRequestParams) -> types.CreateMessageResult:
481
+ return types.CreateMessageResult(
482
+ role = " assistant" ,
483
+ content = types.TextContent(
484
+ type = " text" ,
485
+ text = " Hello, world! from model" ,
486
+ ),
487
+ model = " gpt-3.5-turbo" ,
488
+ stopReason = " endTurn" ,
489
+ )
490
+
420
491
async def run ():
421
492
async with stdio_client(server_params) as (read, write):
422
- async with ClientSession(read, write) as session:
493
+ async with ClientSession(read, write, sampling_callback = handle_sampling_message ) as session:
423
494
# Initialize the connection
424
495
await session.initialize()
425
496
0 commit comments