Skip to main content

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

pip install mcp-craft

Or install with integrations:

# 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.

# 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:

python server.py

Dependency Injection

Inject shared components or services using Depends:

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:

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:

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:

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:

# 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.

Metadata

Release files for mcp-craft 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-craft 0.1.3
File Size Uploaded
mcp_craft-0.1.3.tar.gz 74.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-craft 0.1.3
File Interpreter ABI Platform
mcp_craft-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 92.2 kB

Release files / mcp_craft-0.1.3.tar.gz

Download URL mcp_craft-0.1.3.tar.gz
Size 74.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a9ceb10df69ed71d2b0f1bf26f88dda35ebb9a1785539b937fc4de58ff73416e
BLAKE2b-256 checksum
How to use checksums
2227a3f3289f87d93c14874f53295009013b3a8e1f04890a87a0f0d789b5b92e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release files / mcp_craft-0.1.3-py3-none-any.whl

Download URL mcp_craft-0.1.3-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
762c9f8b986b168a084811d47e420c0bab7206768560ddc423f237a3fdd7e946
BLAKE2b-256 checksum
How to use checksums
a1b97707882d5483a60ab4c429901d707e310bd0afb3377c8aeed7b667c317a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page