Litestar MCP
Litestar MCP

Litestar plugin for Model Context Protocol (MCP) integration
Litestar MCP

Model Context Protocol (MCP), Multi-Agent Runtime, Durable DAG Workflows, and A2A 1.0 Interoperability for Litestar.

PyPI Version Python Versions Documentation License: MIT Discord

Getting Started · Architecture & Diagrams · MCP Core · Tasks, Queues & Workflows · Agents & A2A · Security · API Reference


Overview

litestar-mcp integrates Litestar web applications with the Model Context Protocol (MCP), multi-agent orchestration, distributed task queues, and the Agent2Agent (A2A) 1.0 protocol. Mark existing Litestar routes with mcp_tool=True, mcp_resource=True, or mcp_prompt=True — or author standalone servers with the MCP wrapper — and every tool and prompt call dispatches in-process through Litestar's ASGI pipeline so your authentication middleware, guards, dependency injection (Provide and Dishka FromDishka[T]), DTOs, and OpenTelemetry spans execute without duplication.

Capability Matrix

CapabilityPrimary SymbolsDocumentation
Route Marking & DecoratorsLitestarMCP, MCP, MCPConfig, mcp_tool, mcp_resource, mcp_prompt, ToolAnnotations, PromptControllerMCP Core Guide
Dual-Version Streamable HTTP & CLI2026-07-28 (server/discover + SEP-2575 headers) and 2025-06-18 (initialize, ping, DELETE /mcp), litestar mcp stdio, bridge, export-tool-specTransport & Discovery
Agent Skills (SEP-2640)MCPSkillsConfig, FilesystemSkillSource, SkillSource, Skill, SkillFile, SkillCatalog, SkillControllerAgent Skills Guide
Distributed MCP Tasks & QueuesMCPTaskConfig, QueueTaskExecutor, InProcessTaskExecutor, MCPTaskStore, MCPInputRequiredResult, PrincipalSnapshotDistributed Task Queues
Durable DAG WorkflowsDynamicWorkflow, WorkflowNode, WorkflowEngine, DurableWorkflowEngine, WorkflowStore, WorkflowRun, NodeRecordDurable Workflows
Multi-Agent Runtime & StreamingAgent, AgentGroup, AgentRuntime, TurnBudget, GoogleGenAIClient, SessionStore, AgentChatController, QueuedAgentChatControllerAgents & Runtime
A2A 1.0 & Protocol BridgesLitestarA2A, A2AConfig (JSON-RPC 2.0 + HTTP+JSON REST, /{tenant:str} + X-A2A-Tenant), agent_to_mcp, mcp_to_tools, discover_mcp_tools, agent_to_a2aA2A 1.0 Protocol
Security & ObservabilityLitestar auth middleware, litestar-security (route_opt={"auth": required(...)} + RFC 9728 metadata), guards/scopes, TelemetryConfigSecurity & Operations

Installation

Install the core package with uv, pip, pdm, or poetry:

# uv (recommended)
uv add litestar-mcp

# pip
pip install litestar-mcp

# pdm
pdm add litestar-mcp

# poetry
poetry add litestar-mcp

Optional Extras

litestar-mcp keeps its core dependency footprint focused on Litestar. Enable optional integrations by installing the corresponding extra:

ExtraInstall CommandPurpose
queuesuv add "litestar-mcp[queues]"Distributed MCP Tasks (QueueTaskExecutor), durable DAG workflows (DurableWorkflowEngine), and QueuedAgentChatController on litestar-queues>=0.13.0
a2auv add "litestar-mcp[a2a]"Official a2a-sdk 1.0 plugin (LitestarA2A) with JSON-RPC 2.0, HTTP+JSON REST bindings, and agent_to_a2a bridge
google-genaiuv add "litestar-mcp[google-genai]"First-class GoogleGenAIClient model adapter (defaults to gemini-3.8-flash with thought-signature round-tripping)
opentelemetryuv add "litestar-mcp[opentelemetry]"OpenTelemetry span emission and attribute recording via TelemetryConfig

Combine multiple extras in a single install command when needed:

uv add "litestar-mcp[a2a,queues,google-genai,opentelemetry]"

Quickstart

1. Expose Existing Litestar Routes (LitestarMCP Plugin)

Pass mcp_tool=True, mcp_resource=True, or mcp_prompt=True (or an explicit string name) directly to Litestar route decorators. LitestarMCP infers MCP ToolAnnotations from the HTTP method (GET sets readOnlyHint=True, PUT sets idempotentHint=True, DELETE sets destructiveHint=True) and strips DI parameters (Provide, FromDishka[T], Request, State, ToolContext) from public JSON Schemas while resolving them at invocation time:

from litestar import Litestar, delete, get, post
from litestar.openapi.config import OpenAPIConfig
from litestar_mcp import LitestarMCP, MCPConfig


@get("/users", mcp_tool="list_users")
async def get_users(limit: int = 20) -> list[dict[str, object]]:
    """List active users in the workspace."""
    return [{"id": 1, "name": "Alice", "limit": limit}]


@post(
    "/reports/analyze",
    mcp_tool=True,
    mcp_annotations={"title": "Analyze Dataset", "idempotentHint": True},
)
async def analyze_data(dataset: str, threshold: float = 0.95) -> dict[str, object]:
    """Run statistical analysis over a named dataset."""
    return {"dataset": dataset, "threshold": threshold, "status": "ok"}


@delete("/users/{user_id:int}", mcp_tool="remove_user")
async def delete_user(user_id: int) -> dict[str, object]:
    """Delete a user account by ID."""
    return {"deleted": user_id}


@get("/config", mcp_resource="app_config")
async def get_app_config() -> dict[str, object]:
    """Return read-only application configuration metadata."""
    return {"environment": "production", "version": "2.0.0"}


app = Litestar(
    route_handlers=[get_users, analyze_data, delete_user, get_app_config],
    plugins=[LitestarMCP(MCPConfig(name="Workspace Service"))],
    openapi_config=OpenAPIConfig(title="Workspace Service", version="2.0.0"),
)

2. Standalone Declarative Server (MCP Wrapper)

When building a dedicated MCP service, use the standalone MCP class. Its @mcp.tool(), @mcp.resource(), and @mcp.prompt() decorators accept full Litestar route kwargs (dependencies, guards, opt, DTOs) and expose mcp.app for the Litestar CLI:

from litestar_mcp import MCP

mcp = MCP("math-service", instructions="Provides deterministic arithmetic tools.")


@mcp.tool()
def add(a: int, b: int) -> int:
    """Return the sum of two integers."""
    return a + b


@mcp.resource("config://limits", name="service_limits")
def limits() -> dict[str, int]:
    """Return service rate and payload limits."""
    return {"max_batch": 100}


app = mcp.app

if __name__ == "__main__":
    mcp.run(port=8000)

3. Dual-Version Stateless Streamable HTTP & CLI

A single /mcp endpoint negotiates both MCP 2026-07-28 (server/discover with SEP-2575 MCP-Protocol-Version and Mcp-Method headers) and MCP 2025-06-18 / 2025-03-26 (initialize, notifications/initialized, ping, 202 Accepted notifications, and 204 No Content on DELETE /mcp):

# MCP 2026-07-28 stateless discovery
curl -sX POST http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: server/discover' \
  -d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

# MCP 2025-06-18 initialize handshake
curl -sX POST http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2025-06-18' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

For local desktop hosts and CI pipelines, litestar-mcp registers subcommands under litestar mcp:

# Serve the application over stdin/stdout in-process with full Litestar lifespan
litestar --app my_app:app mcp stdio

# Bridge local stdio to a remote Streamable HTTP deployment
litestar mcp bridge --base-url https://api.example.com --endpoint /mcp

# Export static {"tools": [...]} JSON schemas without booting an HTTP server
litestar --app my_app:app mcp export-tool-spec --indent 2

4. Distributed MCP Tasks & Durable Workflows (litestar-queues)

Pair LitestarMCP with QueuePlugin from litestar-queues to execute long-running io.modelcontextprotocol/tasks and durable DAG workflows across worker processes. QueueTaskExecutor snapshots request.user, request.auth, and litestar-security SecurityContext at submission time, rehydrates the internal HTTP scope and Dishka Scope.REQUEST container on the worker, and supports cooperative cancellation plus multi-round MCPInputRequiredResult resume across replicas:

from litestar import Litestar, post
from litestar.stores.memory import MemoryStore
from litestar.stores.registry import StoreRegistry
from litestar_queues import QueueConfig, QueuePlugin

from litestar_mcp import LitestarMCP, MCPConfig, MCPTaskConfig
from litestar_mcp.agent import DynamicWorkflow, WorkflowContext
from litestar_mcp.queues import DurableWorkflowEngine, QueueTaskExecutor


@post("/backfill", mcp_tool="run_backfill", mcp_task=True)
async def run_backfill(batch_size: int = 500) -> dict[str, object]:
    """Execute a background backfill task on a litestar-queues worker."""
    return {"processed": batch_size, "status": "completed"}


async def extract_step(ctx: WorkflowContext) -> dict[str, object]:
    """Extract source records for the workflow run."""
    return {"rows": 250}


pipeline = DynamicWorkflow("etl_pipeline")
pipeline.add_node("extract", handler=extract_step)

queue_plugin = QueuePlugin(QueueConfig(backend="memory"))
task_executor = QueueTaskExecutor(queue="mcp", timeout=3600)
workflow_engine = DurableWorkflowEngine([pipeline])

app = Litestar(
    route_handlers=[run_backfill],
    plugins=[
        queue_plugin,
        workflow_engine,
        LitestarMCP(
            MCPConfig(
                tasks=MCPTaskConfig(executor=task_executor),
            )
        ),
    ],
    stores=StoreRegistry(
        stores={
            "litestar_mcp_tasks": MemoryStore(),
            "litestar_mcp_workflows": MemoryStore(),
        }
    ),
)

5. Multi-Agent Runtime & GoogleGenAIClient

Orchestrate single agents or hierarchical AgentGroup coordinator-specialist trees under AgentRuntime with strict TurnBudget guardrails (max_turns, max_tool_calls, timeout_seconds) and GoogleGenAIClient (defaulting to gemini-3.8-flash with thought-signature round-tripping):

from litestar import Litestar
from litestar_mcp.agent import (
    Agent,
    AgentChatController,
    AgentRuntime,
    GoogleGenAIClient,
    MemorySessionStore,
    TurnBudget,
)
from litestar_mcp.core.tools import tool


@tool
def lookup_order(order_id: str) -> dict[str, str]:
    """Look up order shipment status by ID."""
    return {"order_id": order_id, "status": "in_transit"}


support_agent = Agent(
    name="support",
    description="Answers customer order inquiries.",
    instructions="Use lookup_order to verify shipment status before replying.",
    tools=[lookup_order],
)

runtime = AgentRuntime(
    support_agent,
    default_model=GoogleGenAIClient(),
    sessions=MemorySessionStore(),
    budget=TurnBudget(max_turns=6, max_tool_calls=8, timeout_seconds=30.0),
)

app = Litestar(route_handlers=[AgentChatController], plugins=[runtime])

6. Official A2A 1.0 JSON-RPC + HTTP+JSON REST (LitestarA2A)

Mount LitestarA2A (or use the agent_to_a2a bridge) to expose an Agent or official a2a-sdk AgentExecutor over A2A 1.0 JSON-RPC 2.0 (POST /a2a), native A2A 1.0 HTTP+JSON REST routes (/a2a/message:send, /a2a/message:stream, /a2a/tasks/{id}:cancel, /a2a/tasks/{id}:subscribe), and GET /.well-known/agent-card.json with optional /{tenant:str} path and X-A2A-Tenant header multi-tenancy:

from litestar import Litestar
from litestar_mcp.agent import agent_to_a2a

a2a_plugin = agent_to_a2a(
    support_agent,
    path="/a2a",
    base_url="https://agents.example.com",
    runtime=runtime,
)

app = Litestar(plugins=[runtime, a2a_plugin])

Single-File Reference Examples (uv run & uvx)

The repository ships a 10-variant Notes reference application under docs/examples/notes/ comparing SQLSpec and Advanced Alchemy across Litestar Provide and Dishka FromDishka[T] dependency injection and four authentication tiers (no-auth, JWT, Cloud Run, and Google IAP). Every variant embeds a PEP 723 script block so uv run provisions dependencies automatically:

uv run docs/examples/notes/sqlspec/no_auth.py
uv run docs/examples/notes/sqlspec/jwt_auth_dishka.py
uv run docs/examples/notes/sqlspec/google_iap.py
uv run docs/examples/notes/advanced_alchemy/no_auth.py

See the Single-File uvx & PEP 723 Guide for remote GitHub URL execution and uvx commands.


Documentation

Full documentation, interactive architecture diagrams, and API reference are published at https://cofin.github.io/litestar-mcp/:

  • Getting Started — Installation, optional extras, 5-minute quickstart, standalone MCP servers, and core concepts
  • Architecture & Examples — Interactive system diagrams, Notes reference matrix, and single-file PEP 723 guide
  • MCP Core — MCPConfig, route markers, ToolAnnotations, resources, prompts, Agent Skills (SEP-2640), discovery, stdio, and bridge
  • Tasks, Queues & Workflows — io.modelcontextprotocol/tasks, QueueTaskExecutor, DurableWorkflowEngine, QueuedAgentChatController, and multi-replica deployment
  • Agents & A2A — AgentRuntime, TurnBudget, GoogleGenAIClient, AgentGroup, protocol bridges, LitestarA2A, and multi-tenancy
  • Security & Operations — Authentication middleware, litestar-security & RFC 9728 metadata, authorization guards/scopes, OpenTelemetry, and migration guides
  • API Reference & CLI — Curated API reference, litestar mcp CLI reference, contributor guide, and Changelog

Development & Conformance

git clone https://github.com/cofin/litestar-mcp.git
cd litestar-mcp

# Create the virtual environment with all extras and dev groups
make install

# Run linters, type checkers (mypy + pyright), slotscheck, and unit/example tests
make lint
make test

# Run the pinned MCP 2026-07-28 conformance suite (in-process and queue executors)
make conformance
make conformance-queue

# Run the documentation verification pipeline (docstring AST scan, CLI check, build, artifact verification)
make docs-check

See the Contributing Guide for full development workflow details.

License

MIT License. See LICENSE for details.