# Litestar MCP Plugin
A lightweight plugin that integrates Litestar web applications with the Model Context Protocol (MCP) by exposing marked routes as MCP tools and resources through REST API endpoints.
[](https://pypi.org/project/litestar-mcp/)
[](https://pypi.org/project/litestar-mcp/)
[](https://opensource.org/licenses/MIT)
## Overview
This plugin automatically discovers routes marked with the `opt` attribute and exposes them as MCP-compatible REST endpoints. Routes marked with `mcp_tool="name"` become executable tools, while routes marked with `mcp_resource="name"` become readable resources.
## Features
- 🚀 **Zero Dependencies** - Only requires Litestar
- 📡 **REST API Endpoints** - No stdio transport or MCP libraries needed
- 🔧 **Simple Route Marking** - Use Litestar's `opt` attribute pattern
- 🛡️ **Type Safe** - Full type hints with dataclasses
- 📊 **Automatic Discovery** - Routes are discovered at app initialization
- 🎯 **OpenAPI Integration** - Server info derived from OpenAPI config
## Quick Start
### Installation
```bash
pip install litestar-mcp
# or
uv add litestar-mcp
```
### Basic Usage
```python
from litestar import Litestar, get, post
from litestar.openapi.config import OpenAPIConfig
from litestar_mcp import LitestarMCP
# Mark routes for MCP exposure using the opt attribute
@get("/users", mcp_tool="list_users")
async def get_users() -> list[dict]:
"""List all users in the system."""
return [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
@post("/analyze", mcp_tool="analyze_data")
async def analyze_data(data: dict) -> dict:
"""Analyze the provided data and return insights."""
return {"result": f"Analyzed {len(data)} items"}
@get("/config", mcp_resource="app_config")
async def get_app_config() -> dict:
"""Get the current application configuration."""
return {"debug": True, "version": "1.0.0"}
# Add the MCP plugin to your Litestar app
app = Litestar(
route_handlers=[get_users, analyze_data, get_app_config],
plugins=[LitestarMCP()],
openapi_config=OpenAPIConfig(title="My API", version="1.0.0"),
)
```
### With Configuration
```python
from litestar_mcp import LitestarMCP, MCPConfig
config = MCPConfig(
base_path="/api/mcp", # Change the base path
name="Custom Server Name", # Override server name
include_in_schema=True, # Include MCP routes in OpenAPI schema
)
app = Litestar(
route_handlers=[get_users, analyze_data, get_app_config],
plugins=[LitestarMCP(config)],
openapi_config=OpenAPIConfig(title="My API", version="1.0.0"),
)
```
## Resources vs Tools: When to Use Each
### Use Resources (`mcp_resource`) for
- **Read-only data** that AI models need to reference
- **Static or semi-static information** like documentation, schemas, configurations
- **Data that doesn't require parameters** to retrieve
- **Reference material** that AI models should "know about"
**Examples:**
```python
@get("/schema", mcp_resource="database_schema")
async def get_schema() -> dict:
"""Database schema information."""
return {"tables": ["users", "orders"], "relationships": [...]}
@get("/docs", mcp_resource="api_docs")
async def get_documentation() -> dict:
"""API documentation and usage examples."""
return {"endpoints": [...], "examples": [...]}
```
### Use Tools (`mcp_tool`) for
- **Actions that perform operations** or mutations
- **Dynamic queries** that need input parameters
- **Operations that change state** in your application
- **Computations or data processing** tasks
**Examples:**
```python
@post("/users", mcp_tool="create_user")
async def create_user(user_data: dict) -> dict:
"""Create a new user account."""
# Perform user creation logic
return {"id": 123, "created": True}
@get("/search", mcp_tool="search_data")
async def search(query: str, limit: int = 10) -> dict:
"""Search through application data."""
# Perform search with parameters
return {"results": [...], "total": 42}
```
## How It Works
1. **Route Discovery**: At app initialization, the plugin scans all route handlers for the `opt` attribute
2. **Automatic Exposure**: Routes marked with `mcp_tool` or `mcp_resource` are automatically exposed
3. **MCP Endpoints**: The plugin adds REST endpoints under the configured base path (default `/mcp`)
4. **Server Info**: Server name and version are derived from your OpenAPI configuration
## MCP Endpoints
Once configured, your application exposes these MCP-compatible endpoints:
- `GET /mcp/` - Server info and capabilities
- `GET /mcp/resources` - List available resources
- `GET /mcp/resources/{name}` - Get specific resource content
- `GET /mcp/tools` - List available tools
- `POST /mcp/tools/{name}` - Execute a tool
**Built-in Resources:**
- `openapi` - Your application's OpenAPI schema (always available)
## Configuration
Configure the plugin using `MCPConfig`:
```python
from litestar_mcp import MCPConfig
config = MCPConfig()
```
**Configuration Options:**
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `base_path` | `str` | `"/mcp"` | Base path for MCP API endpoints |
| `include_in_schema` | `bool` | `False` | Whether to include MCP routes in OpenAPI schema |
| `name` | `str \| None` | `None` | Override server name. If None, uses OpenAPI title |
## Complete Example
```python
from litestar import Litestar, get, post, delete
from litestar.openapi.config import OpenAPIConfig
from litestar_mcp import LitestarMCP, MCPConfig
# Resources - read-only reference data
@get("/users/schema", mcp_resource="user_schema")
async def get_user_schema() -> dict:
"""User data model schema."""
return {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"email": {"type": "string"}
}
}
@get("/api/info", mcp_resource="api_info")
async def get_api_info() -> dict:
"""API capabilities and information."""
return {
"version": "2.0.0",
"features": ["user_management", "data_analysis"],
"rate_limits": {"requests_per_minute": 1000}
}
# Tools - actionable operations
@get("/users", mcp_tool="list_users")
async def list_users(limit: int = 10) -> dict:
"""List users with optional limit."""
# Fetch users from database
return {"users": [{"id": 1, "name": "Alice"}], "total": 1}
@post("/users", mcp_tool="create_user")
async def create_user(user_data: dict) -> dict:
"""Create a new user account."""
# Create user logic
return {"id": 123, "created": True, "user": user_data}
@post("/analyze", mcp_tool="analyze_dataset")
async def analyze_dataset(config: dict) -> dict:
"""Analyze data with custom configuration."""
# Analysis logic
return {"insights": [...], "metrics": {...}}
# Regular routes (not exposed to MCP)
@get("/health")
async def health_check() -> dict:
return {"status": "healthy"}
# MCP configuration
mcp_config = MCPConfig(
name="User Management API",
base_path="/mcp"
)
# Create Litestar app
app = Litestar(
route_handlers=[
get_user_schema, get_api_info, # Resources
list_users, create_user, analyze_dataset, # Tools
health_check # Regular route
],
plugins=[LitestarMCP(mcp_config)],
openapi_config=OpenAPIConfig(
title="User Management API",
version="2.0.0"
),
)
```
## Development
```bash
# Clone the repository
git clone https://github.com/litestar-org/litestar-mcp.git
cd litestar-mcp
# Install with development dependencies
uv install --dev
# Run tests
make test
# Run example
uv run python docs/examples/basic/main.py
```
## License
MIT License. See [LICENSE](LICENSE) for details.
## Contributing
Contributions welcome! Please see our [contributing guide](CONTRIBUTING.md) for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "litestar-mcp",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "Litestar Developers <hello@litestar.dev>, Cody Fincher <cody@litestar.dev>",
"keywords": "ai, litestar, mcp, model-context-protocol, plugin",
"author": null,
"author_email": "Cody Fincher <cody@litestar.dev>",
"download_url": "https://files.pythonhosted.org/packages/f1/4d/da183793681bb35a7b9c55443cfdee730754fa66ed915093fb8159ae5749/litestar_mcp-0.1.0.tar.gz",
"platform": null,
"description": "# Litestar MCP Plugin\n\nA lightweight plugin that integrates Litestar web applications with the Model Context Protocol (MCP) by exposing marked routes as MCP tools and resources through REST API endpoints.\n\n[](https://pypi.org/project/litestar-mcp/)\n[](https://pypi.org/project/litestar-mcp/)\n[](https://opensource.org/licenses/MIT)\n\n## Overview\n\nThis plugin automatically discovers routes marked with the `opt` attribute and exposes them as MCP-compatible REST endpoints. Routes marked with `mcp_tool=\"name\"` become executable tools, while routes marked with `mcp_resource=\"name\"` become readable resources.\n\n## Features\n\n- \ud83d\ude80 **Zero Dependencies** - Only requires Litestar\n- \ud83d\udce1 **REST API Endpoints** - No stdio transport or MCP libraries needed\n- \ud83d\udd27 **Simple Route Marking** - Use Litestar's `opt` attribute pattern\n- \ud83d\udee1\ufe0f **Type Safe** - Full type hints with dataclasses\n- \ud83d\udcca **Automatic Discovery** - Routes are discovered at app initialization\n- \ud83c\udfaf **OpenAPI Integration** - Server info derived from OpenAPI config\n\n## Quick Start\n\n### Installation\n\n```bash\npip install litestar-mcp\n# or\nuv add litestar-mcp\n```\n\n### Basic Usage\n\n```python\nfrom litestar import Litestar, get, post\nfrom litestar.openapi.config import OpenAPIConfig\nfrom litestar_mcp import LitestarMCP\n\n# Mark routes for MCP exposure using the opt attribute\n@get(\"/users\", mcp_tool=\"list_users\")\nasync def get_users() -> list[dict]:\n \"\"\"List all users in the system.\"\"\"\n return [{\"id\": 1, \"name\": \"Alice\"}, {\"id\": 2, \"name\": \"Bob\"}]\n\n@post(\"/analyze\", mcp_tool=\"analyze_data\")\nasync def analyze_data(data: dict) -> dict:\n \"\"\"Analyze the provided data and return insights.\"\"\"\n return {\"result\": f\"Analyzed {len(data)} items\"}\n\n@get(\"/config\", mcp_resource=\"app_config\")\nasync def get_app_config() -> dict:\n \"\"\"Get the current application configuration.\"\"\"\n return {\"debug\": True, \"version\": \"1.0.0\"}\n\n# Add the MCP plugin to your Litestar app\napp = Litestar(\n route_handlers=[get_users, analyze_data, get_app_config],\n plugins=[LitestarMCP()],\n openapi_config=OpenAPIConfig(title=\"My API\", version=\"1.0.0\"),\n)\n```\n\n### With Configuration\n\n```python\nfrom litestar_mcp import LitestarMCP, MCPConfig\n\nconfig = MCPConfig(\n base_path=\"/api/mcp\", # Change the base path\n name=\"Custom Server Name\", # Override server name\n include_in_schema=True, # Include MCP routes in OpenAPI schema\n)\n\napp = Litestar(\n route_handlers=[get_users, analyze_data, get_app_config],\n plugins=[LitestarMCP(config)],\n openapi_config=OpenAPIConfig(title=\"My API\", version=\"1.0.0\"),\n)\n```\n\n## Resources vs Tools: When to Use Each\n\n### Use Resources (`mcp_resource`) for\n\n- **Read-only data** that AI models need to reference\n- **Static or semi-static information** like documentation, schemas, configurations\n- **Data that doesn't require parameters** to retrieve\n- **Reference material** that AI models should \"know about\"\n\n**Examples:**\n\n```python\n@get(\"/schema\", mcp_resource=\"database_schema\")\nasync def get_schema() -> dict:\n \"\"\"Database schema information.\"\"\"\n return {\"tables\": [\"users\", \"orders\"], \"relationships\": [...]}\n\n@get(\"/docs\", mcp_resource=\"api_docs\")\nasync def get_documentation() -> dict:\n \"\"\"API documentation and usage examples.\"\"\"\n return {\"endpoints\": [...], \"examples\": [...]}\n```\n\n### Use Tools (`mcp_tool`) for\n\n- **Actions that perform operations** or mutations\n- **Dynamic queries** that need input parameters\n- **Operations that change state** in your application\n- **Computations or data processing** tasks\n\n**Examples:**\n\n```python\n@post(\"/users\", mcp_tool=\"create_user\")\nasync def create_user(user_data: dict) -> dict:\n \"\"\"Create a new user account.\"\"\"\n # Perform user creation logic\n return {\"id\": 123, \"created\": True}\n\n@get(\"/search\", mcp_tool=\"search_data\")\nasync def search(query: str, limit: int = 10) -> dict:\n \"\"\"Search through application data.\"\"\"\n # Perform search with parameters\n return {\"results\": [...], \"total\": 42}\n```\n\n## How It Works\n\n1. **Route Discovery**: At app initialization, the plugin scans all route handlers for the `opt` attribute\n2. **Automatic Exposure**: Routes marked with `mcp_tool` or `mcp_resource` are automatically exposed\n3. **MCP Endpoints**: The plugin adds REST endpoints under the configured base path (default `/mcp`)\n4. **Server Info**: Server name and version are derived from your OpenAPI configuration\n\n## MCP Endpoints\n\nOnce configured, your application exposes these MCP-compatible endpoints:\n\n- `GET /mcp/` - Server info and capabilities\n- `GET /mcp/resources` - List available resources\n- `GET /mcp/resources/{name}` - Get specific resource content\n- `GET /mcp/tools` - List available tools\n- `POST /mcp/tools/{name}` - Execute a tool\n\n**Built-in Resources:**\n\n- `openapi` - Your application's OpenAPI schema (always available)\n\n## Configuration\n\nConfigure the plugin using `MCPConfig`:\n\n```python\nfrom litestar_mcp import MCPConfig\n\nconfig = MCPConfig()\n```\n\n**Configuration Options:**\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `base_path` | `str` | `\"/mcp\"` | Base path for MCP API endpoints |\n| `include_in_schema` | `bool` | `False` | Whether to include MCP routes in OpenAPI schema |\n| `name` | `str \\| None` | `None` | Override server name. If None, uses OpenAPI title |\n\n## Complete Example\n\n```python\nfrom litestar import Litestar, get, post, delete\nfrom litestar.openapi.config import OpenAPIConfig\nfrom litestar_mcp import LitestarMCP, MCPConfig\n\n# Resources - read-only reference data\n@get(\"/users/schema\", mcp_resource=\"user_schema\")\nasync def get_user_schema() -> dict:\n \"\"\"User data model schema.\"\"\"\n return {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\"type\": \"integer\"},\n \"name\": {\"type\": \"string\"},\n \"email\": {\"type\": \"string\"}\n }\n }\n\n@get(\"/api/info\", mcp_resource=\"api_info\")\nasync def get_api_info() -> dict:\n \"\"\"API capabilities and information.\"\"\"\n return {\n \"version\": \"2.0.0\",\n \"features\": [\"user_management\", \"data_analysis\"],\n \"rate_limits\": {\"requests_per_minute\": 1000}\n }\n\n# Tools - actionable operations\n@get(\"/users\", mcp_tool=\"list_users\")\nasync def list_users(limit: int = 10) -> dict:\n \"\"\"List users with optional limit.\"\"\"\n # Fetch users from database\n return {\"users\": [{\"id\": 1, \"name\": \"Alice\"}], \"total\": 1}\n\n@post(\"/users\", mcp_tool=\"create_user\")\nasync def create_user(user_data: dict) -> dict:\n \"\"\"Create a new user account.\"\"\"\n # Create user logic\n return {\"id\": 123, \"created\": True, \"user\": user_data}\n\n@post(\"/analyze\", mcp_tool=\"analyze_dataset\")\nasync def analyze_dataset(config: dict) -> dict:\n \"\"\"Analyze data with custom configuration.\"\"\"\n # Analysis logic\n return {\"insights\": [...], \"metrics\": {...}}\n\n# Regular routes (not exposed to MCP)\n@get(\"/health\")\nasync def health_check() -> dict:\n return {\"status\": \"healthy\"}\n\n# MCP configuration\nmcp_config = MCPConfig(\n name=\"User Management API\",\n base_path=\"/mcp\"\n)\n\n# Create Litestar app\napp = Litestar(\n route_handlers=[\n get_user_schema, get_api_info, # Resources\n list_users, create_user, analyze_dataset, # Tools\n health_check # Regular route\n ],\n plugins=[LitestarMCP(mcp_config)],\n openapi_config=OpenAPIConfig(\n title=\"User Management API\",\n version=\"2.0.0\"\n ),\n)\n```\n\n## Development\n\n```bash\n# Clone the repository\ngit clone https://github.com/litestar-org/litestar-mcp.git\ncd litestar-mcp\n\n# Install with development dependencies\nuv install --dev\n\n# Run tests\nmake test\n\n# Run example\nuv run python docs/examples/basic/main.py\n```\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n\n## Contributing\n\nContributions welcome! Please see our [contributing guide](CONTRIBUTING.md) for details.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Litestar plugin for Model Context Protocol (MCP) integration",
"version": "0.1.0",
"project_urls": {
"Changelog": "https://docs.litestar-mcp.litestar.dev/latest/changelog",
"Discord": "https://discord.gg/litestar",
"Documentation": "https://docs.litestar-mcp.litestar.dev/latest/",
"Funding": "https://github.com/sponsors/litestar-org",
"Homepage": "https://docs.litestar-mcp.litestar.dev/latest/",
"Issue": "https://github.com/litestar-org/litestar-mcp/issues/",
"Source": "https://github.com/litestar-org/litestar-mcp"
},
"split_keywords": [
"ai",
" litestar",
" mcp",
" model-context-protocol",
" plugin"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "5a4a508632f2597bc98401271291bba350909c5603f6cb618a4816be97099089",
"md5": "789fe71f40a5329e67f912d0946d0a80",
"sha256": "ff59276ee90646d2ec9d92280152af5f6714c79641cb05588dfe92c84b3f1e78"
},
"downloads": -1,
"filename": "litestar_mcp-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "789fe71f40a5329e67f912d0946d0a80",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 9640,
"upload_time": "2025-09-06T19:14:18",
"upload_time_iso_8601": "2025-09-06T19:14:18.564458Z",
"url": "https://files.pythonhosted.org/packages/5a/4a/508632f2597bc98401271291bba350909c5603f6cb618a4816be97099089/litestar_mcp-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f14dda183793681bb35a7b9c55443cfdee730754fa66ed915093fb8159ae5749",
"md5": "032f3460d54a21c46d6b3ff89d00fb53",
"sha256": "da7ee529d1150d1fbd4d589f9b1b80c2ce6283d6bfc7a52a5ffbabbfc5c6d423"
},
"downloads": -1,
"filename": "litestar_mcp-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "032f3460d54a21c46d6b3ff89d00fb53",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 240916,
"upload_time": "2025-09-06T19:14:20",
"upload_time_iso_8601": "2025-09-06T19:14:20.353090Z",
"url": "https://files.pythonhosted.org/packages/f1/4d/da183793681bb35a7b9c55443cfdee730754fa66ed915093fb8159ae5749/litestar_mcp-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-06 19:14:20",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sponsors",
"github_project": "litestar-org",
"github_not_found": true,
"lcname": "litestar-mcp"
}