Configuration¶
The Litestar MCP plugin is configured through MCPConfig.
This page walks through each knob the plugin exposes, from a default
registration to task-lifecycle support.
Minimal Setup¶
The plugin registers with sensible defaults when no configuration is passed.
Every marked route is picked up and served from /mcp.
docs/examples/snippets/configuration_minimal.py¶app = Litestar(route_handlers=[], plugins=[LitestarMCP()])
Custom Configuration¶
Override the base path, server name, or OpenAPI visibility via
MCPConfig.
docs/examples/snippets/configuration_custom.py¶config = MCPConfig(
base_path="/api/mcp",
name="My MCP Server",
include_in_schema=True,
)
app = Litestar(route_handlers=[], plugins=[LitestarMCP(config)])
Auth-Enabled Configuration¶
Attach an MCPAuthConfig to require bearer tokens
on MCP endpoints and publish /.well-known/oauth-protected-resource.
See Authentication for the full authentication story.
docs/examples/snippets/configuration_auth.py¶auth = MCPAuthConfig(
issuer="https://auth.example.com",
audience="https://api.example.com/mcp",
scopes={"mcp:read": "Read access to MCP resources"},
)
config = MCPConfig(auth=auth)
app = Litestar(route_handlers=[], plugins=[LitestarMCP(config)])
Standalone Prompts¶
Prompt callables that are not bound to an HTTP route are registered by
passing them to LitestarMCP(prompts=[...]). Each function must first
be decorated with mcp_prompt(); the plugin rejects
plain callables to keep prompt metadata explicit.
docs/examples/snippets/configuration_prompts.py¶app = Litestar(
route_handlers=[],
plugins=[
LitestarMCP(
MCPConfig(name="prompt-demo"),
prompts=[greet],
),
],
)
See Marking Routes for the handler-based mcp_prompt opt-key
form, which routes a prompt under HTTP and publishes it via
prompts/get.
Task Lifecycle¶
Enable the experimental in-memory task endpoints by passing an
MCPTaskConfig. Tasks let MCP clients submit
long-running work and poll for completion.
docs/examples/snippets/configuration_tasks.py¶config = MCPConfig(
tasks=MCPTaskConfig(enabled=True, default_ttl=300_000),
)
app = Litestar(route_handlers=[], plugins=[LitestarMCP(config)])
Configuration Options¶
Option |
Default |
Description |
|---|---|---|
|
|
Base path for the MCP Streamable HTTP endpoint. |
|
|
Whether to include MCP routes in the OpenAPI schema. |
|
|
Server name override (falls back to the OpenAPI title). |
|
|
Litestar guards applied to the MCP router. |
|
|
Restrict accepted |
|
|
Filter exposure by Litestar operation name. |
|
|
Filter exposure by OpenAPI tags. |
|
|
Enable bearer-token validation and OAuth protected-resource metadata. |
|
|
Enable experimental in-memory MCP task support. |
|
|
Optional callback invoked once before each |
|
|
Optional callback invoked once after each |
|
|
Server-chosen page size for the |
The LitestarMCP constructor also accepts a top-level prompts
argument — a sequence of @mcp_prompt-decorated callables — for
standalone prompt registration (see above).
Filters apply both to list responses and direct invocation. A filtered tool
or resource is omitted from tools/list, resources/list, or
resources/templates/list and a direct tools/call / resources/read
returns the same not-found response as an unknown name or URI. Filters narrow
the MCP exposure surface; use guards or auth middleware for access
control.
Tool-Call Callbacks¶
Use before_tool_call and after_tool_call when you need audit,
metrics, or tracing hooks that are independent of route ownership layers.
Both callbacks receive the MCP tool name, a shallow copy of the submitted
arguments, and the synthesized litestar.Request used for the
handler dispatch. after_tool_call also receives result,
exception, and duration keyword-only values, and fires for
successes, guard failures, error responses, and unhandled exceptions.
Callback exceptions are logged and swallowed so observability code does
not alter tool-call behavior.
docs/examples/snippets/configuration_tool_callbacks.py¶async def after_tool_call(
tool_name: str,
arguments: dict[str, Any],
request: Request[Any, Any, Any],
*,
result: Any,
exception: Exception | None,
duration: float,
) -> None:
request.app.logger.info(
"mcp tool=%s duration=%0.4f failed=%s",
tool_name,
duration,
exception is not None,
)
config = MCPConfig(after_tool_call=after_tool_call)
List Pagination¶
tools/list, resources/list, resources/templates/list, and
prompts/list are paginated per the MCP spec's opaque-cursor model.
Each accepts an optional cursor parameter and returns nextCursor
when another page is available; treat nextCursor as an opaque token
and pass it back as params.cursor until the response omits it. An
invalid cursor returns INVALID_PARAMS (-32602).
The MCP spec lets the server pick the page size — clients cannot
request a limit on these methods. Set it with the
MCPConfig.list_page_size option (e.g. MCPConfig(list_page_size=25));
it defaults to 100 and must be a positive integer.
These methods enumerate the catalog of registered primitives, which is
built once at startup; the cursor is a base64-encoded offset into that
stable list. For paginating application data, see tasks/list (which
accepts a client limit and delegates to a task store) or implement
paging inside an individual tool.
Environment Overrides¶
MCPConfig is a plain dataclass, so the ordinary
Litestar pattern applies: read the environment before constructing it and
pass the resolved values through. For example, to keep base_path and
name configurable at deploy time:
export MCP_BASE_PATH=/api/mcp
export MCP_SERVER_NAME="My MCP Server"
Then build MCPConfig using os.getenv for each option - the shape
is identical to the Custom Configuration snippet above, just with environment lookups replacing
literal values.