A lightweight, production-ready developer framework for building Model Context Protocol (MCP) servers with a FastAPI-like experience.
Project description
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
TestMCPClientand 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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_craft-0.1.1.tar.gz.
File metadata
- Download URL: mcp_craft-0.1.1.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5de1d9952afd14aa655bb20ebd354a0a9e0cd91dc3a0019e777a8e570c777c4e
|
|
| MD5 |
c93fe18a7934768caabca0c4f37555c3
|
|
| BLAKE2b-256 |
c8ccb0d8e889fc7d730a780142f62422bd975686cc7613c42967160dd08d2dba
|
File details
Details for the file mcp_craft-0.1.1-py3-none-any.whl.
File metadata
- Download URL: mcp_craft-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffd7fdaf7e582fd0533cd969c7b096cc4adb3423fe41bf52616c26574155c6eb
|
|
| MD5 |
6be879021dd0ba2d944a00813f2d7df8
|
|
| BLAKE2b-256 |
154dd5a98656d00566c3271f90ca5d51492a0bb0135823d4e4cd2505c2bc7699
|