Install
$ agentstack add mcp-tinoferrucci-fastapi-fastmcp-autogen ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
FastAPI + FastMCP Auto-Generator
Harto de escribir el mismo código dos veces para tener una API REST y un servidor MCP? Este proyecto resuelve eso generando automáticamente una cosa desde la otra.
El problema
Cuando trabajas con FastAPI y FastMCP, terminas duplicando lógica:
# Primero defines la tool MCP
@mcp.tool()
def sumar(a: float, b: float) -> dict:
return {"resultado": a + b}
# Luego defines el endpoint (el mismo código otra vez)
@app.post("/sumar")
async def sumar_endpoint(req: Request):
return {"resultado": req.a + req.b}
Esto es tedioso y propenso a errores. Si cambias algo, tienes que acordarte de cambiarlo en ambos lados.
La solución
Dos enfoques dependiendo de tu caso de uso:
main.py - Escribes las herramientas MCP, se generan los endpoints automáticamente main2.py - Escribes los endpoints FastAPI, se generan las herramientas MCP automáticamente
Eliges el punto de partida que te convenga más y el otro lado se crea solo.
Instalación
git clone
cd mcp_test
uv sync
Uso
Opción 1: Empezar desde MCP (main.py)
uv run uvicorn main:app --reload
Defines herramientas así:
@mcp.tool()
def multiplicar(a: float, b: float) -> dict:
"""Multiplica dos números."""
return {"resultado": a * b}
Y automáticamente tienes POST /multiplicar disponible.
Opción 2: Empezar desde FastAPI (main2.py)
uv run uvicorn main2:app --port 8001 --reload
Defines endpoints así:
@app.post("/multiplicar")
async def multiplicar(req: OperacionRequest):
"""Multiplica dos números."""
return {"resultado": req.a * req.b}
Y automáticamente tienes la herramienta MCP multiplicar disponible.
Ejemplos
Ambos servidores exponen las mismas operaciones:
# Llamar al endpoint REST
curl -X POST "http://localhost:8000/sumar" \
-H "Content-Type: application/json" \
-d '{"a": 10, "b": 5}'
# Respuesta: {"a":10.0,"b":5.0,"operacion":"suma","resultado":15.0}
El servidor MCP está montado en /calculadora/mcp/ y la documentación Swagger en /docs.
Cómo funciona
main.py (MCP → FastAPI)
- Registras funciones con
@mcp.tool() - Una función inspecciona todas las tools del registry de FastMCP
- Para cada una, crea un modelo Pydantic con los mismos parámetros
- Registra un endpoint POST en FastAPI que llama a la tool original
main2.py (FastAPI → MCP)
- Defines endpoints POST normales en FastAPI
- Una función recorre todas las rutas registradas
- Extrae el modelo Pydantic que usa cada endpoint
- Genera dinámicamente una función con parámetros explícitos (FastMCP no acepta **kwargs)
- Registra esa función como tool MCP que llama al endpoint original
El truco en main2.py es que FastMCP requiere parámetros explícitos, así que uso exec() para generar el código de la función dinámicamente. No es lo más elegante pero funciona.
Cuál usar?
Depende de tu situación:
Usa main.py si:
- Estás empezando un proyecto nuevo enfocado en MCP
- Prefieres el estilo minimalista de FastMCP
- No necesitas control fino sobre HTTP
Usa main2.py si:
- Ya tienes una API FastAPI y quieres agregarle MCP
- Necesitas controlar códigos de estado, headers, etc.
- Prefieres trabajar con FastAPI directamente
Yo personalmente prefiero main.py porque es más limpio, pero main2.py es útil si ya tienes código FastAPI existente.
Agregar operaciones nuevas
Solo defines en tu lado preferido:
main.py:
@mcp.tool()
def dividir(a: float, b: float) -> dict:
if b == 0:
return {"error": "División por cero"}
return {"resultado": a / b}
main2.py:
@app.post("/dividir")
async def dividir(req: OperacionRequest):
if req.b == 0:
raise HTTPException(400, "División por cero")
return {"resultado": req.a / req.b}
El resto se genera automáticamente.
Estructura
.
├── main.py # MCP → FastAPI
├── main2.py # FastAPI → MCP
├── pyproject.toml # Dependencias (FastAPI, FastMCP, Uvicorn)
└── uv.lock
Limitaciones
- Los parámetros tienen que ser tipos básicos (int, float, str, bool)
- En main2.py cada endpoint necesita exactamente un parámetro Pydantic
- Solo endpoints POST se convierten en tools (GET no tiene mucho sentido como tool)
- El código generado con
exec()en main2.py es medio feo pero funciona
Tecnologías
- FastAPI para el servidor HTTP
- FastMCP para el servidor MCP
- Pydantic para validación
- Uvicorn como servidor ASGI
Notas
Este es un proyecto de demostración. En producción probablemente querrías agregar:
- Autenticación
- Rate limiting
- Logging apropiado
- Tests
- Manejo de errores más robusto
Pero el concepto base de auto-generación funciona bien y ahorra bastante código repetitivo.
License
MIT - haz lo que quieras con esto.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: TinoFerrucci
- Source: TinoFerrucci/fastapi-fastmcp-autogen
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.