Transform any FastAPI server into an MCP server
Project description
mcp-it
Transform any FastAPI server into an MCP (Model Context Protocol) server.
mcp-it allows you to seamlessly convert your FastAPI routes into MCP tools. Decorate your FastAPI endpoints with @mcp_it.mcp() and your API becomes an MCP server that can be used with MCP-compatible clients.
Features
- Minimal Code Changes: Convert existing FastAPI routes to MCP tools with a simple decorator
- Automatic Parameter Detection: Automatically detects path, query, and body parameters from your FastAPI routes - no boilerplate reimplementation
- Header Forwarding: Maps and preserves headers from MCP requests to your FastAPI endpoints
- Dependency Injection: Full support for FastAPI's dependency injection system
- Pydantic Models: Full integration with Pydantic models for request/response validation
- Multiple Transports: Support for both sse and streamable-http transports
- Type Safety: Maintains type hints and annotations for proper MCP tool introspection
- Auto Docs: Automatically documents the MCP tools with your functions docstrings
- Proxy Support: Proxy external APIs as MCP tools with automatic parameter mapping
- OpenAPI Binding: Dynamically register tools from any OpenAPI specification - turn any REST API into MCP tools instantly
Installation
pip install mcp-it
Quick Start
from fastapi import FastAPI, APIRouter
from mcpit import MCPIt
# Create your FastAPI app
app = FastAPI()
# Initialize MCPIt
mcp_it = MCPIt("My API Tools", json_response=True)
# Decorate your routes with @mcp_it.mcp()
@app.post("/multiply")
@mcp_it.mcp(mode='tool', description="Multiply two numbers")
def multiply(a: float, b: float):
"""Multiplies two numbers together."""
return {"result": a * b}
# Build and mount the MCP server
mcp_it.build(app.router, transport='streamable-http', mount_path="/mcp")
# Your MCP server is now available at /mcp
Usage
Basic Example
from fastapi import FastAPI, APIRouter
from mcpit import MCPIt
from pydantic import BaseModel, Field
app = FastAPI()
router = APIRouter()
mcp_it = MCPIt("Calculator Tools", json_response=True)
class CalculationInput(BaseModel):
a: float = Field(..., description="The first number")
b: float = Field(..., description="The second number")
@router.post("/add")
@mcp_it.mcp(mode='tool', name="add", description="Add two numbers") #If no route is annonotaded MCP It will make all routes on the router available
def add(input: CalculationInput):
"""Adds two numbers together."""
return {"result": input.a + input.b}
mcp_it.build(router, transport='streamable-http', mount_path="/mcp")
app.include_router(router)
With Authentication
mcp-it automatically forwards headers from MCP requests, so your authentication dependencies work seamlessly:
from fastapi import Header, Depends
from typing import Optional
def fake_auth_dependency(authorization: Optional[str] = Header(None)):
"""Validate authorization header"""
if authorization:
return True
return False
@router.get("/protected")
@mcp_it.mcp(mode='tool', description="Protected endpoint")
def protected_route(auth_result: bool = Depends(fake_auth_dependency)):
"""A protected route that requires authentication."""
return {"message": "Access granted", "authenticated": auth_result}
With Dependency Injection
Full support for FastAPI's dependency injection:
class BasicService:
def __init__(self):
self.counter = 0
def increment(self) -> int:
self.counter += 1
return self.counter
service = BasicService()
def get_service() -> BasicService:
return service
from typing import Annotated
from fastapi import Depends
ServiceDep = Annotated[BasicService, Depends(get_service)]
@router.get("/increment")
@mcp_it.mcp(mode='tool', description="Increment counter")
def increment(service: ServiceDep):
"""Increment the counter using dependency injection."""
return {"count": service.increment()}
Path and Query Parameters
mcp-it automatically detects and handles path and query parameters:
@router.get("/users/{user_id}/posts")
@mcp_it.mcp(mode='tool', description="Get user posts")
def get_user_posts(user_id: int, limit: int = 10, offset: int = 0):
"""Get posts for a specific user with pagination."""
return {
"user_id": user_id,
"posts": [],
"limit": limit,
"offset": offset
}
Proxy External APIs
Transform any external API endpoint into an MCP tool. Perfect for creating unified MCP interfaces to multiple services:
from fastapi import FastAPI, APIRouter
from mcpit import MCPIt
app = FastAPI()
router = APIRouter()
mcp_it = MCPIt("Proxy Tools", json_response=True)
# Proxy an external API endpoint
@mcp_it.proxy(
url="http://api.example.com/multiply",
method="POST",
param_structure={"a": "query", "b": "query"}
)
def multiply(a: float, b: float):
"""Multiply two numbers via external API"""
pass
mcp_it.build(router, transport='streamable-http', mount_path="/mcp")
app.include_router(router)
The param_structure parameter tells mcp-it where each parameter should be sent:
"query": Query parameter"path": Path parameter (will replace{param_name}in the URL)"body": Request body parameter
OpenAPI Binding
Automatically generate MCP tools from any OpenAPI specification. This is perfect for:
- Wrapping existing REST APIs as MCP servers
- Creating MCP interfaces to third-party services
- Rapidly prototyping MCP tools from API documentation
from fastapi import FastAPI, APIRouter
from mcpit import MCPIt
app = FastAPI()
router = APIRouter()
mcp_it = MCPIt("API Tools", json_response=True)
# Bind tools from an OpenAPI specification
mcp_it.bind_openapi(
openapi_url="http://localhost:8800/openapi.json",
include_paths=["/hello", "/multiply", "/subtract_with_auth"], # Optional: filter specific paths
exclude_paths=["/admin"], # Optional: exclude paths
name_from_summary=False # Use operationId (True) or summary (False) for tool names
)
# You can also combine with manual tools
@router.post("/custom")
@mcp_it.mcp(mode='tool', description="Custom tool")
def custom_tool():
"""A custom tool alongside OpenAPI-bound tools"""
return {"message": "Hello"}
mcp_it.build(router, transport='streamable-http', mount_path="/mcp")
app.include_router(router)
OpenAPI Binding Features:
- Automatically parses OpenAPI 3.x specifications
- Extracts path, query, and body parameters
- Generates proper type annotations from schemas
- Supports filtering with
include_pathsandexclude_paths - Preserves descriptions and summaries from the OpenAPI spec
API Reference
MCPIt
The main class for creating MCP servers from FastAPI routes.
Constructor
MCPIt(name: str, json_response: bool = True)
- name: Name of your MCP server
- json_response: Whether to return JSON responses (default: True)
Methods
mcp(mode='tool', **kwargs)
Decorator to register a FastAPI route as an MCP capability.
Parameters:
- mode: Type of MCP capability (
'tool','resource', or'prompt') - name: (optional) Custom name for the tool (defaults to function name)
- description: (optional) Tool description (defaults to function docstring)
Example:
@mcp_it.mcp(mode='tool', name="custom_name", description="Custom description")
def my_function():
pass
proxy(url, method='GET', mode='tool', **kwargs)
Decorator to register an external API endpoint as an MCP capability. The decorated function's signature defines the tool interface, while the implementation proxies to the specified URL.
Parameters:
- url: The external API endpoint URL
- method: HTTP method (
'GET','POST','PUT','DELETE', etc.) - mode: Type of MCP capability (
'tool','resource', or'prompt') - param_structure: (optional) Dict mapping parameter names to their location (
'query','path', or'body') - name: (optional) Custom name for the tool (defaults to function name)
- description: (optional) Tool description (defaults to function docstring)
Example:
@mcp_it.proxy(
url="http://api.example.com/users/{user_id}",
method="GET",
param_structure={"user_id": "path", "include_posts": "query"}
)
def get_user(user_id: int, include_posts: bool = False):
"""Get user information from external API"""
pass
bind_openapi(openapi_url, base_url=None, include_paths=None, exclude_paths=None, name_from_summary=False)
Dynamically register tools from an OpenAPI specification.
Parameters:
- openapi_url: URL to the OpenAPI JSON specification
- base_url: (optional) Base URL for API calls. If not provided, inferred from
openapi_url - include_paths: (optional) List of path patterns to include (e.g.,
["/users", "/posts"]) - exclude_paths: (optional) List of path patterns to exclude (e.g.,
["/admin"]) - name_from_summary: (optional) If
True, use operation summary for tool names; ifFalse, useoperationId(default:False)
Example:
mcp_it.bind_openapi(
openapi_url="https://api.example.com/openapi.json",
include_paths=["/users", "/posts"],
exclude_paths=["/admin"],
name_from_summary=False
)
build(router, transport='streamable-http', mount_path='/mcp')
Builds the MCP server and mounts it to your FastAPI router.
Parameters:
- router: Your FastAPI
APIRouterinstance - transport: Transport type (
'sse'or'streamable-http') - mount_path: Path where the MCP server will be mounted (default:
/mcp)
Example:
mcp_it.build(router, transport='streamable-http', mount_path="/mcp")
How It Works
Local FastAPI Routes
- Decorator Registration: When you use
@mcp_it.mcp(), the function is registered in an internal registry - Route Analysis: During
build(),mcp-itanalyzes your FastAPI routes to detect:- Path parameters
- Query parameters
- Body parameters
- Pydantic models
- Tool Creation: MCP tools are created with proper signatures and type annotations
- Internal Proxy: When an MCP tool is called,
mcp-itmakes an internal ASGI call to your FastAPI route - Header Forwarding: Headers from MCP requests are automatically forwarded to your endpoints
External API Proxies
- Proxy Registration: When you use
@mcp_it.proxy(), the function signature defines the tool interface - Parameter Mapping: The
param_structureparameter tellsmcp-itwhere to send each parameter (query, path, or body) - External Calls: When the tool is called,
mcp-itmakes an HTTP request to the external API - Header Forwarding: Headers from MCP requests are automatically forwarded to external APIs
OpenAPI Binding
- Spec Fetching:
bind_openapi()fetches the OpenAPI specification from the provided URL - Path Filtering: Optional
include_pathsandexclude_pathsfilter which endpoints to expose - Schema Parsing: OpenAPI schemas are parsed and converted to Python types and Pydantic models
- Tool Generation: MCP tools are automatically generated with proper signatures and descriptions
- Proxy Creation: Each tool is registered as a proxy that calls the original API endpoint
Transport Modes
Streamable HTTP (Recommended)
mcp_it.build(router, transport='streamable-http', mount_path="/mcp")
- Uses HTTP with streaming support
- Better for production environments
- Supports all HTTP methods
SSE (Server-Sent Events)
mcp_it.build(router, transport='sse', mount_path="/mcp")
- Uses Server-Sent Events for streaming
- Good for real-time updates
- Simpler connection model
Development
Setup
# Clone the repository
git clone https://github.com/enzobjmendonca/mcp-it.git
cd mcp-it
# Install development dependencies
pip install -r requirements.txt
# Install the package in editable mode
pip install -e .
Running Tests
pytest
Examples
Basic Example (example.py)
See the example.py file in the repository for a complete working example with:
- Multiple route types
- Pydantic models
- Authentication
- Dependency injection
- Path and query parameters
Proxy Example (example_proxy.py)
See the example_proxy.py file for examples of:
- Manual proxy configuration with
@mcp_it.proxy() - OpenAPI binding with
bind_openapi() - Combining proxied tools with local FastAPI routes
Requirements
- Python 3.8+
- FastAPI
- FastMCP
- httpx
- Pydantic
Contributing
Contributions are more than welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Links
Project details
Release history Release notifications | RSS feed
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_it-0.2.1.tar.gz.
File metadata
- Download URL: mcp_it-0.2.1.tar.gz
- Upload date:
- Size: 15.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ed88846fa2f637aeaea0bb0d1e4200244c9095cdf4b23c30c4237df41cc0056
|
|
| MD5 |
dddbc77a3927df7d19851cde2d145fd3
|
|
| BLAKE2b-256 |
062720a1bdd920ead41f32a1171bc7556922953f33461767ddc5008e98c6ff6c
|
File details
Details for the file mcp_it-0.2.1-py3-none-any.whl.
File metadata
- Download URL: mcp_it-0.2.1-py3-none-any.whl
- Upload date:
- Size: 13.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da63f5e5ee9ba88a15136053f2d1387b58884d62624ba68d55d734baecd331a3
|
|
| MD5 |
8140c8b0756908985515ee380252edf6
|
|
| BLAKE2b-256 |
750810f136179d873df6a44e1a4850749ed3167ae566b6f136392822a348f7c3
|