litestar-mcp


Namelitestar-mcp JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryLitestar plugin for Model Context Protocol (MCP) integration
upload_time2025-09-06 19:14:20
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT
keywords ai litestar mcp model-context-protocol plugin
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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.

[![PyPI - Version](https://img.shields.io/pypi/v/litestar-mcp)](https://pypi.org/project/litestar-mcp/)
[![Python Version](https://img.shields.io/pypi/pyversions/litestar-mcp)](https://pypi.org/project/litestar-mcp/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](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[![PyPI - Version](https://img.shields.io/pypi/v/litestar-mcp)](https://pypi.org/project/litestar-mcp/)\n[![Python Version](https://img.shields.io/pypi/pyversions/litestar-mcp)](https://pypi.org/project/litestar-mcp/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](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"
}
        
Elapsed time: 0.43239s