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)])
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 opt-in io.modelcontextprotocol/tasks extension by passing an
MCPTaskConfig. Task records use a Litestar
Store; the default in-memory Store is intended for development.
A shared Store persists records but does not distribute the task runner, input queue or cancellation queue. Applications must coordinate worker ownership and recovery for tasks that cross processes or survive restarts. Require authentication on every protected Tasks operation; an owner-aware Store does not authenticate anonymous callers. See Security for the task-handle authorization boundary.
docs/examples/snippets/configuration_tasks.py#config = MCPConfig(
tasks=MCPTaskConfig(
default_ttl_ms=300_000,
max_ttl_ms=3_600_000,
poll_interval_ms=1_000,
),
)
app = Litestar(route_handlers=[], plugins=[LitestarMCP(config)])
Skills#
Enable the opt-in io.modelcontextprotocol/skills extension by passing an
MCPSkillsConfig. The catalog is loaded once
from the configured directories at startup; a skill folder that fails
validation fails application startup, not a later request.
Pass Path objects for paths — the annotation is
Sequence[Path], and while a plain string is coerced at runtime, a
type-checked caller passing str sees a mypy or pyright error. See
MCP Skills for the directory layout, wire methods, and error contract.
docs/examples/snippets/configuration_skills.py#config = MCPConfig(
skills=MCPSkillsConfig(
paths=[SKILLS_ROOT],
directory_read=True,
max_files_per_skill=512,
max_bytes_per_skill=16_777_216,
),
)
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. |
|
|
Route |
|
|
Restrict accepted |
|
|
Filter exposure by Litestar operation name. |
|
|
Filter exposure by OpenAPI tags. |
|
|
Enable the Tasks extension, optionally with a persistent Store. |
|
|
Serve Agent Skills over MCP from the configured directories; see MCP Skills. |
|
|
Cache hints on discovery, list, and resource-read results. |
|
|
Maximum concurrent |
|
|
Seconds between subscription keepalive comments. |
|
|
Optional configured Litestar |
|
|
Bounds subscription and request-progress queues. Progress applies backpressure; slow subscription consumers are completed and disconnected. |
|
|
Positive finite seconds allowed for cooperative response cleanup; expiry is logged as incomplete cleanup. |
|
|
Optional callback invoked once before each |
|
|
Optional callback invoked once after each |
|
|
Server-chosen page size for the |
|
|
Maximum raw byte size for embedded MCP blobs in tool results and
|
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. Implement application-data pagination inside an individual tool. The Tasks extension intentionally has no list method.
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.