docs: update README with lifespan examples and usage
Add comprehensive documentation for lifespan support: - Add usage examples for both Server and FastMPC classes - Document startup/shutdown patterns - Show context access in tools and handlers - Clean up spacing in test files
This commit is contained in:
parent
e598750cba
commit
e5815bd162
2 changed files with 66 additions and 12 deletions
56
README.md
56
README.md
|
|
@ -135,6 +135,28 @@ mcp = FastMCP("My App")
|
||||||
|
|
||||||
# Specify dependencies for deployment and development
|
# Specify dependencies for deployment and development
|
||||||
mcp = FastMCP("My App", dependencies=["pandas", "numpy"])
|
mcp = FastMCP("My App", dependencies=["pandas", "numpy"])
|
||||||
|
|
||||||
|
# Add lifespan support for startup/shutdown
|
||||||
|
@asynccontextmanager
|
||||||
|
async def app_lifespan(server: FastMCP) -> AsyncIterator[dict]:
|
||||||
|
"""Manage application lifecycle"""
|
||||||
|
try:
|
||||||
|
# Initialize on startup
|
||||||
|
await db.connect()
|
||||||
|
yield {"db": db}
|
||||||
|
finally:
|
||||||
|
# Cleanup on shutdown
|
||||||
|
await db.disconnect()
|
||||||
|
|
||||||
|
# Pass lifespan to server
|
||||||
|
mcp = FastMCP("My App", lifespan=app_lifespan)
|
||||||
|
|
||||||
|
# Access lifespan context in tools
|
||||||
|
@mcp.tool()
|
||||||
|
def query_db(ctx: Context) -> str:
|
||||||
|
"""Tool that uses initialized resources"""
|
||||||
|
db = ctx.request_context.lifespan_context["db"]
|
||||||
|
return db.query()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
@ -334,7 +356,39 @@ def query_data(sql: str) -> str:
|
||||||
|
|
||||||
### Low-Level Server
|
### Low-Level Server
|
||||||
|
|
||||||
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:
|
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:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import AsyncIterator
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def server_lifespan(server: Server) -> AsyncIterator[dict]:
|
||||||
|
"""Manage server startup and shutdown lifecycle."""
|
||||||
|
try:
|
||||||
|
# Initialize resources on startup
|
||||||
|
await db.connect()
|
||||||
|
yield {"db": db}
|
||||||
|
finally:
|
||||||
|
# Clean up on shutdown
|
||||||
|
await db.disconnect()
|
||||||
|
|
||||||
|
# Pass lifespan to server
|
||||||
|
server = Server("example-server", lifespan=server_lifespan)
|
||||||
|
|
||||||
|
# Access lifespan context in handlers
|
||||||
|
@server.call_tool()
|
||||||
|
async def query_db(name: str, arguments: dict) -> list:
|
||||||
|
ctx = server.request_context
|
||||||
|
db = ctx.lifespan_context["db"]
|
||||||
|
return await db.query(arguments["query"])
|
||||||
|
```
|
||||||
|
|
||||||
|
The lifespan API provides:
|
||||||
|
- A way to initialize resources when the server starts and clean them up when it stops
|
||||||
|
- Access to initialized resources through the request context in handlers
|
||||||
|
- Support for both low-level Server and FastMCP classes
|
||||||
|
- Type-safe context passing between lifespan and request handlers
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from mcp.server.lowlevel import Server, NotificationOptions
|
from mcp.server.lowlevel import Server, NotificationOptions
|
||||||
|
|
|
||||||
|
|
@ -267,10 +267,10 @@ def test_complex_function_json_schema():
|
||||||
normalized_schema = actual_schema.copy()
|
normalized_schema = actual_schema.copy()
|
||||||
|
|
||||||
# Normalize the my_model_a_with_default field to handle both pydantic formats
|
# Normalize the my_model_a_with_default field to handle both pydantic formats
|
||||||
if 'allOf' in actual_schema['properties']['my_model_a_with_default']:
|
if "allOf" in actual_schema["properties"]["my_model_a_with_default"]:
|
||||||
normalized_schema['properties']['my_model_a_with_default'] = {
|
normalized_schema["properties"]["my_model_a_with_default"] = {
|
||||||
'$ref': '#/$defs/SomeInputModelA',
|
"$ref": "#/$defs/SomeInputModelA",
|
||||||
'default': {}
|
"default": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert normalized_schema == {
|
assert normalized_schema == {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue