Metadata-Version: 2.4
Name: mcp-craft
Version: 0.1.3
Summary: A lightweight, production-ready developer framework for building Model Context Protocol (MCP) servers with a FastAPI-like experience.
Author: Rishav Sharma
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.11
Requires-Dist: mcp>=1.0.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: django
Requires-Dist: django>=4.0.0; extra == 'django'
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
Requires-Dist: starlette>=0.27.0; extra == 'fastapi'
Requires-Dist: uvicorn>=0.20.0; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: flask>=2.0.0; extra == 'flask'
Description-Content-Type: text/markdown

# mcp-craft

A modern, lightweight, production-ready framework for building **Model Context Protocol (MCP)** servers in Python with a developer experience inspired by **FastAPI**.

`mcp-craft` wraps the official MCP Python SDK to offer tool discovery, dependency injection, middleware chains, authentication, schema validation, and framework integrations (FastAPI, Flask, Django) without reimplementing the protocol.

---

## Features

- **Declarative Tool Registration**: Decorators (`@app.tool`) on functions and classes with automatic Pydantic-based schema generation and validation.
- **FastAPI-like Dependency Injection**: A lightweight, standalone DI engine supporting sync and async dependencies (`Depends`).
- **Flexible Middleware Pipeline**: Starlette-like async middleware with support for custom interceptors and built-in middlewares (`LoggingMiddleware`, `AuthenticationMiddleware`, `MetricsMiddleware`, `RateLimitMiddleware`).
- **Structured Authentication Helpers**: Easily secure your MCP server with API Keys, Bearer tokens, or custom callback functions.
- **Rich Context Object**: Expose execution context (`context.user`, `context.request`, `context.logger`, `context.metadata`, `context.storage`) to all tools automatically.
- **Error Handling**: Standard exception mapping that sanitizes tracebacks and converts Python errors to protocol-compliant MCP errors.
- **Extensible Plugin System**: Install reusable plugins (`app.install(plugin)`) to hook into startup, shutdown, middlewares, or register dependencies and tools.
- **Integrations**: Standalone runtime (via stdio) and first-class FastAPI, Flask, and Django integrations.
- **Testing Utilities**: A dedicated `TestMCPClient` and mocking helpers for rapid tool testing without network layers.

---

## Installation

```bash
pip install mcp-craft
```

Or install with integrations:

```bash
# For FastAPI / Starlette support
pip install "mcp-craft[fastapi]"

# For development / testing
pip install "mcp-craft[dev]"
```

---

## Quick Start (Standalone / Stdio)

Creating a server is as simple as defining your application and registering your tools.

```python
# server.py
import asyncio
from mcp_craft import MCPApplication

app = MCPApplication(
    name="Math Server",
    version="1.0.0",
    description="Exposes basic mathematical tools"
)

@app.tool()
async def add(a: int, b: int) -> int:
    """Add two numbers together."""
    return a + b

if __name__ == "__main__":
    app.run()
```

Run it locally with:
```bash
python server.py
```

---

## Dependency Injection

Inject shared components or services using `Depends`:

```python
from mcp_craft import MCPApplication, Depends

app = MCPApplication(name="DI Server")

def get_db():
    # Setup database connection
    return {"conn": "active"}

async def get_current_user(context):
    # Retrieve user from the execution context
    return context.user

@app.tool()
async def fetch_profile(
    user = Depends(get_current_user),
    db = Depends(get_db)
):
    """Retrieve profile for the authenticated user."""
    return {"username": user.get("name"), "status": "active", "db": db}
```

---

## Middleware & Authentication

Add global logic like logging, metrics, rate-limiting, and authentication:

```python
from mcp_craft import MCPApplication, APIKeyAuthentication
from mcp_craft.middleware import LoggingMiddleware, AuthenticationMiddleware, RateLimitMiddleware

app = MCPApplication(name="Secure Server")

# Configure authentication helper
auth_helper = APIKeyAuthentication(key="secret-token-123", header_name="x-api-key")

# Register middleware in order of execution
app.add_middleware(LoggingMiddleware)
app.add_middleware(AuthenticationMiddleware, auth_handler=auth_helper)
app.add_middleware(RateLimitMiddleware, limit=30, period=60.0) # 30 calls per minute
```

---

## FastAPI Integration

Mount your MCP server onto a FastAPI app using the Server-Sent Events (SSE) protocol:

```python
from fastapi import FastAPI
from mcp_craft import MCPApplication
from mcp_craft.integrations.fastapi import mount_mcp
import uvicorn

mcp_app = MCPApplication(name="Mounted Server")

@mcp_app.tool()
def hello(name: str) -> str:
    """Say hello."""
    return f"Hello, {name}!"

app = FastAPI()
# This registers:
# GET  /mcp/sse      - SSE connection route
# POST /mcp/messages - Client message gateway
mount_mcp(app, mcp_app, path="/mcp")

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

---

## Testing Tools

Unit test your tools cleanly without running servers or network loops:

```python
import pytest
from mcp_craft import MCPApplication
from mcp_craft.testing import TestMCPClient

app = MCPApplication(name="Test App")

@app.tool()
def square(x: int) -> int:
    return x * x

@pytest.mark.asyncio
async def test_square():
    client = TestMCPClient(app)
    result = await client.call_tool("square", {"x": 5})
    assert result.content[0].text == "25"
```

---

## Development & Publishing

To package and build:
```bash
# Install packaging tool
pip install build hatch

# Build source distribution and wheel
python3 -m build
```

---

## License

This project is licensed under the MIT License - see the LICENSE file for details.
