Skip to main content

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_paths and exclude_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; if False, use operationId (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 APIRouter instance
  • 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

  1. Decorator Registration: When you use @mcp_it.mcp(), the function is registered in an internal registry
  2. Route Analysis: During build(), mcp-it analyzes your FastAPI routes to detect:
    • Path parameters
    • Query parameters
    • Body parameters
    • Pydantic models
  3. Tool Creation: MCP tools are created with proper signatures and type annotations
  4. Internal Proxy: When an MCP tool is called, mcp-it makes an internal ASGI call to your FastAPI route
  5. Header Forwarding: Headers from MCP requests are automatically forwarded to your endpoints

External API Proxies

  1. Proxy Registration: When you use @mcp_it.proxy(), the function signature defines the tool interface
  2. Parameter Mapping: The param_structure parameter tells mcp-it where to send each parameter (query, path, or body)
  3. External Calls: When the tool is called, mcp-it makes an HTTP request to the external API
  4. Header Forwarding: Headers from MCP requests are automatically forwarded to external APIs

OpenAPI Binding

  1. Spec Fetching: bind_openapi() fetches the OpenAPI specification from the provided URL
  2. Path Filtering: Optional include_paths and exclude_paths filter which endpoints to expose
  3. Schema Parsing: OpenAPI schemas are parsed and converted to Python types and Pydantic models
  4. Tool Generation: MCP tools are automatically generated with proper signatures and descriptions
  5. 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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_it-0.3.1.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_it-0.3.1-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file mcp_it-0.3.1.tar.gz.

File metadata

  • Download URL: mcp_it-0.3.1.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mcp_it-0.3.1.tar.gz
Algorithm Hash digest
SHA256 ae1a764b519be32c5d6fd93befcbde2ed4a30fb4e18ceb36f3e357915b71f285
MD5 6083fddfda47264d6a066cecb7d207a2
BLAKE2b-256 456bd715b7f194b77eb7692e42dbbe1c114539d6ba1ee2ff5c4ce5ede4a1a50a

See more details on using hashes here.

File details

Details for the file mcp_it-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: mcp_it-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 14.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mcp_it-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 acacac62ddde64de0226f8145b2e8f166596b5de0b75e950942ca788470ad65a
MD5 e3c8bf0ad829badd659836d48e6ac9d9
BLAKE2b-256 0df8ae08b7595fa0b4d96b0bbbbcba233c896931308a538243272d0dc70b8b84

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 files

0.3

2 files

0.2.121

2 files

0.2.12

2 files

0.2.11

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page