如何用 lifespan 在 FastMCP 服务器启动和停止时运行一次性初始化与清理代码?

如何用 lifespan 在 FastMCP 服务器启动和停止时运行一次性初始化与清理代码? 如何用 lifespan 在 FastMCP 服务器启动和停止时运行一次性初始化与清理代码【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp如果你的 FastMCP 服务器需要一段只在进程生命周期内执行一次的代码——比如启动时建立数据库连接、停止时关闭它——lifespan就是官方提供的机制。它与按会话触发的处理逻辑不同无论多少客户端连接lifespan 只在服务器启动时执行一次初始化在服务器停止时执行一次清理。该特性在 FastMCP 3.0.0 及之后的版本可用参考 docs/servers/lifespan.mdx。用lifespan装饰器定义一次性初始化与清理从fastmcp.server.lifespan导入lifespan装饰器装饰一个接收服务器实例的异步生成器函数。yield之前的代码在服务器启动时执行yield之后的代码在服务器停止时执行from fastmcp import FastMCP from fastmcp.server.lifespan import lifespan lifespan async def app_lifespan(server): # Setup: runs once when server starts print(Starting up...) try: yield {started_at: 2024-01-01} finally: # Teardown: runs when server stops print(Shutting down...) mcp FastMCP(MyServer, lifespanapp_lifespan)yield出去的 dict 会合并为lifespan context可供工具读取。文档明确提醒清理代码要放在try/finally中确保即使服务器被取消也能执行。启动服务器并确认初始化、清理各执行一次按 docs/deployment/running-server.mdx 的方式运行服务器。把run()放在if __name__ __main__:块中是推荐的写法if __name__ __main__: mcp.run() # 默认 STDIO 传输然后用python my_server.py启动或使用 CLICLI 会自动找到文件中命名为mcp、server或app的 FastMCP 实例fastmcp run my_server.py需要网络访问或多客户端并发时改用 HTTP 传输服务器端点位于http://localhost:8000/mcpif __name__ __main__: mcp.run(transporthttp, host127.0.0.1, port8000)结果验证文档示例见 docs/servers/lifespan.mdx中启动服务器时控制台应输出Starting up...停止服务器如 CtrlC时输出Shutting down...。仓库测试 tests/server/test_server_lifespan.py 记录了这一行为的精确判定服务器启动后lifespan 事件为[enter]且只进入一次多个会话先后或重叠连接期间事件仍为[enter]会话关闭不触发退出服务器停止后事件为[enter, exit]。也就是说进入一次、退出一次、与客户端数量无关是文档和测试共同确认的预期行为。在工具中读取 lifespan context工具通过ctx.lifespan_context访问yield出去的 dictfrom fastmcp import FastMCP, Context from fastmcp.server.lifespan import lifespan lifespan async def app_lifespan(server): # Initialize shared state data {users: [alice, bob]} yield {data: data} mcp FastMCP(MyServer, lifespanapp_lifespan) mcp.tool def list_users(ctx: Context) - list[str]: data ctx.lifespan_context[data] return data[users]测试中的另一种访问写法是ctx.request_context.lifespan_context见 tests/server/test_server_lifespan.py 中lifespan_context.get(db_connection, no_db)的用法。lifespan_context属性定义见 docs/python-sdk/fastmcp-server-context.mdx。组合多个 lifespan用|运算符组合多个 lifespan例如把配置加载和数据初始化拆开from fastmcp import FastMCP from fastmcp.server.lifespan import lifespan lifespan async def config_lifespan(server): config {debug: True, version: 1.0} yield {config: config} lifespan async def data_lifespan(server): data {items: []} yield {data: data} # Compose with | mcp FastMCP(MyServer, lifespanconfig_lifespan | data_lifespan)组合规则来自 docs/servers/lifespan.mdx按从左到右的顺序进入按从右到左的反序退出各自的 context dict 合并键冲突时后者的值覆盖前者。API 层面的Lifespan、ComposedLifespan、ContextManagerLifespan说明见 docs/python-sdk/fastmcp-server-lifespan.mdx。已有的asynccontextmanagerlifespan 如何保留原有的asynccontextmanagerlifespan 直接传给 FastMCP 时仍然有效from contextlib import asynccontextmanager from fastmcp import FastMCP asynccontextmanager async def legacy_lifespan(server): yield {key: value} mcp FastMCP(MyServer, lifespanlegacy_lifespan)但要与lifespan函数组合时需先用ContextManagerLifespan显式包装旧式函数from contextlib import asynccontextmanager from fastmcp.server.lifespan import lifespan, ContextManagerLifespan asynccontextmanager async def legacy_lifespan(server): yield {legacy: True} lifespan async def new_lifespan(server): yield {new: True} combined ContextManagerLifespan(legacy_lifespan) | new_lifespan可选分支挂载到 FastAPI 时用combine_lifespans如果你把 FastMCP 挂载进 FastAPI且 FastAPI 应用本身已有 lifespan例如自己的数据库连接不能直接互相替换要用combine_lifespans同时运行两者from contextlib import asynccontextmanager from fastapi import FastAPI from fastmcp import FastMCP from fastmcp.utilities.lifespan import combine_lifespans asynccontextmanager async def app_lifespan(app): print(FastAPI starting...) yield print(FastAPI shutting down...) mcp FastMCP(Tools) mcp_app mcp.http_app() app FastAPI(lifespancombine_lifespans(app_lifespan, mcp_app.lifespan)) app.mount(/mcp, mcp_app)combine_lifespans按传入顺序进入、按逆序退出它同时兼容 FastAPI 风格yield None和 FastMCP 风格yield dict的 lifespan键冲突时后者覆盖前者见 docs/python-sdk/fastmcp-utilities-lifespan.mdx。更多挂载细节见 FastAPI 集成指南。限制与注意lifespan 只在服务器级执行一次与客户端会话数量无关需要按会话区分的状态应放在会话机制中不要塞进 lifespan。清理逻辑必须写在try/finally内否则服务器被取消时可能不执行。run()不能在 async 函数内调用它内部自建事件循环异步上下文应使用run_async()两者接受相同的传输参数。升级场景下lifespan参数在 v1/v2 低层 SDK 迁移时可直接沿用工具中通过ctx.lifespan_context读取 yield 的值不要丢失它见 docs/getting-started/upgrading/from-low-level-sdk-v2.mdx。完成上述步骤后你可以在控制台确认Starting up...与Shutting down...各出现一次、工具能正确返回 lifespan context 中的共享数据即表示一次性初始化与清理链路已按 docs/servers/lifespan.mdx 描述的行为工作。【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考