Getting started¶
Install¶
The package requires Python 3.11+, Dishka 1.10.1+, and FastMCP 3.2.4 through the latest 3.x release.
Configure the server¶
Create the container before the FastMCP server so the lifespan can close it on shutdown:
from dishka import Provider, Scope, make_async_container, provide
from fastmcp import FastMCP
from dishka_fastmcp import FromDishka, dishka_lifespan, inject, setup_dishka
class Catalog:
_prices: dict[str, int] = {'book': 12, 'pen': 2}
def price(self, item: str) -> int:
return self._prices.get(item, 0)
class AppProvider(Provider):
catalog = provide(Catalog, scope=Scope.REQUEST)
container = make_async_container(AppProvider())
mcp = FastMCP('example', lifespan=dishka_lifespan(container))
setup_dishka(container, mcp)
@mcp.tool
@inject
async def get_price(item: str, catalog: FromDishka[Catalog]) -> int:
return catalog.price(item)
Decorator order matters
Put @inject below @mcp.tool, @mcp.resource, or @mcp.prompt. FastMCP
must inspect the signature after Dishka parameters have been removed.
Resources and prompts¶
The same decorator works for every supported FastMCP component:
@mcp.resource('users://{user_id}')
@inject
async def user(user_id: str, repo: FromDishka[UserRepo]) -> dict:
return await repo.get(user_id)
@mcp.prompt
@inject
async def summarize(text: str, service: FromDishka[Summarizer]) -> str:
return await service.run(text)
Sync handlers¶
Use a sync Dishka container for regular sync handlers. FastMCP runs them in a worker thread, and dishka-fastmcp keeps dependency creation, usage, and cleanup in that thread.