---
schema: rendered-html/v1
title: "Lifespans - FastMCP"
source_url: https://gofastmcp.com/servers/lifespan
generated_at: 2026-06-11T19:36:16.374104+00:00
---




[FastMCP home page![light logo](images/gofastmcp__com__servers__lifespan__wordmark.avif)![dark logo](images/gofastmcp__com__servers__lifespan__wordmark-white.avif)](gofastmcp__com.md)







Extensibility

Lifespans









  - [Middleware](gofastmcp__com__servers__middleware.md)
  - [Dependencies

    NEW](gofastmcp__com__servers__dependency-injection.md)
  - [Lifespan

    NEW](/servers/lifespan)
  - [Storage Backends

    NEW](gofastmcp__com__servers__storage-backends.md)
  - [Background Tasks

    NEW](gofastmcp__com__servers__tasks.md)
  - [Versioning

    NEW](gofastmcp__com__servers__versioning.md)














- [Basic Usage](#basic-usage)
- [Accessing Lifespan Context](#accessing-lifespan-context)
- [Composing Lifespans](#composing-lifespans)
- [Backwards Compatibility](#backwards-compatibility)
- [With FastAPI](#with-fastapi)

Extensibility

# Lifespans


Server-level setup and teardown with composable lifespans


Lifespans let you run code once when the server starts and clean up when it stops. Unlike per-session handlers, lifespans run exactly once regardless of how many clients connect.

## [​](#basic-usage) Basic Usage

Use the `@lifespan` decorator to define a lifespan:

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", lifespan=app_lifespan)

The dict you yield becomes the **lifespan context**, accessible from tools.

Always use `try/finally` for cleanup code to ensure it runs even if the server is cancelled.

## [​](#accessing-lifespan-context) Accessing Lifespan Context

Access the lifespan context in tools via `ctx.lifespan_context`:

from 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", lifespan=app_lifespan)

def list_users(ctx: Context) -> list[str]:
    data = ctx.lifespan_context["data"]
    return data["users"]

## [​](#composing-lifespans) Composing Lifespans

Compose multiple lifespans with the `|` operator:

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", lifespan=config_lifespan | data_lifespan)

Composed lifespans:

- Enter in order (left to right)
- Exit in reverse order (right to left)
- Merge their context dicts (later values overwrite earlier on conflict)

## [​](#backwards-compatibility) Backwards Compatibility

Existing `@asynccontextmanager` lifespans still work when passed directly to FastMCP:

from contextlib import asynccontextmanager

@asynccontextmanager
async def legacy_lifespan(server):
    yield {"key": "value"}

mcp = FastMCP("MyServer", lifespan=legacy_lifespan)

To compose an `@asynccontextmanager` function with `@lifespan` functions, wrap it with `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}

# Wrap the legacy lifespan explicitly for composition
combined = ContextManagerLifespan(legacy_lifespan) | new_lifespan

## [​](#with-fastapi) With FastAPI

When mounting FastMCP into FastAPI, use `combine_lifespans` to run both your app’s lifespan and the MCP server’s lifespan:

from contextlib import asynccontextmanager

from fastapi import FastAPI
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(lifespan=combine_lifespans(app_lifespan, mcp_app.lifespan))
app.mount("/mcp", mcp_app)

See the [FastAPI integration guide](gofastmcp__com__integrations__fastapi.md) for full details.

[Dependency Injection

Previous](gofastmcp__com__servers__dependency-injection.md)[Storage Backends

Next](gofastmcp__com__servers__storage-backends.md)






