🐍 MCP Server Starter — Python / FastMCP
Plantilla lista para desarrollar servidores MCP en Python usando FastMCP, con soporte completo para probarlos localmente con MCP Inspector — ya sea via Docker o directamente en tu máquina.
📁 Estructura del proyecto
mcp-python-starter/
├── src/
│ ├── server.py # Entry point — inicia el servidor (stdio o HTTP)
│ ├── constants.py # Constantes globales (puerto, URL base, etc.)
│ ├── tools/
│ │ ├── hello.py # Tools de ejemplo: hello_world, echo
│ │ └── calculator.py # Tool de ejemplo: calculator
│ └── services/
│ └── api_client.py # Cliente HTTP asíncrono reutilizable
├── Dockerfile # Imagen del servidor MCP
├── docker-compose.yml # Servidor MCP + MCP Inspector (todo en Docker)
├── docker-compose.dev.yml # Solo servidor con hot-reload
├── mcp.json # Config para MCP Inspector CLI y Claude Code
├── .env.example # Variables de entorno de ejemplo
└── pyproject.toml # Dependencias del proyecto
🚀 Inicio rápido
Opción A — Todo en Docker (recomendado para probar rápido)
Levanta el servidor MCP y el MCP Inspector en un solo comando:
cp .env.example .env
docker compose up --build
Luego abre http://localhost:6274 en el browser.
En el Inspector:
- Transport → Streamable HTTP
- URL →
http://mcp-server:8000/mcp(dentro de Docker usa el nombre del servicio) - Click Connect
- Ve a la pestaña Tools → List Tools
⚠️ Si corres el Inspector en el host (no en Docker), usa
http://localhost:8000/mcpcomo URL.
Opción B — Servidor en Docker + Inspector en el host
# Terminal 1 — levantar solo el servidor
docker compose -f docker-compose.dev.yml up --build
# Terminal 2 — abrir el Inspector en tu máquina (abre browser automáticamente)
npx @modelcontextprotocol/inspector
En el Inspector: Transport → Streamable HTTP → URL → http://localhost:8000/mcp
Opción C — Sin Docker (virtualenv local)
# Crear entorno virtual e instalar dependencias
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
# Modo HTTP (para MCP Inspector)
TRANSPORT=http python -m src.server
# En otra terminal — abrir el Inspector
npx @modelcontextprotocol/inspector
# → Connect: Streamable HTTP → http://localhost:8000/mcp
🧪 Probar con MCP Inspector CLI
Sin browser, desde la terminal:
# Listar todas las tools disponibles
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server my-mcp-server-stdio \
--method tools/list
# Llamar hello_world
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server my-mcp-server-stdio \
--method tools/call --tool-name hello_world \
--tool-arg 'params={"name": "Mundo", "language": "es"}'
# Llamar calculator
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server my-mcp-server-stdio \
--method tools/call --tool-name calculator \
--tool-arg 'params={"a": 10, "b": 3, "operation": "divide"}'
➕ Agregar una nueva tool
- Crea
src/tools/mi_tool.py:
import json
from mcp.server.fastmcp import Context, FastMCP
from pydantic import BaseModel, ConfigDict, Field
class MiInput(BaseModel):
model_config = ConfigDict(extra="forbid")
param: str = Field(..., description="Descripción del parámetro")
def register_mi_tools(mcp: FastMCP) -> None:
@mcp.tool(
name="mi_tool",
annotations={
"title": "Mi Tool",
"readOnlyHint": True,
"destructiveHint": False,
"idempotentHint": True,
"openWorldHint": False,
},
)
async def mi_tool(params: MiInput, ctx: Context) -> str:
"""Descripción de la tool — FastMCP la usa como 'description'.
Args:
params (MiInput):
- param (str): Descripción del parámetro
Returns:
str: Resultado de la operación.
"""
await ctx.log_info("mi_tool llamado", {"param": params.param})
result = {"resultado": f"Procesado: {params.param}"}
return json.dumps(result, ensure_ascii=False, indent=2)
- Regístrala en
src/server.py:
from src.tools.mi_tool import register_mi_tools
# ...
register_mi_tools(mcp)
- Prueba sin reconstruir (hot-reload activo con
docker-compose.dev.yml).
🔌 Transportes disponibles
| Transporte | Cómo activar | Cuándo usar |
|---|---|---|
| stdio | TRANSPORT=stdio python -m src.server |
Claude Code, Cursor, integración local |
| HTTP | TRANSPORT=http python -m src.server |
MCP Inspector web, servidores remotos |
🔗 Conectar a Claude Code
# Agregar el servidor (modo stdio)
claude mcp add my-mcp-server python -m src.server
# O editar ~/.claude/mcp.json con la entrada de mcp.json de este repo
⚙️ Variables de entorno
| Variable | Default | Descripción |
|---|---|---|
TRANSPORT |
stdio |
stdio o http |
PORT |
8000 |
Puerto del servidor HTTP |
API_BASE_URL |
https://api.example.com |
URL base de tu API |
API_TOKEN |
(vacío) | Token Bearer para tu API |
🛠️ Características del starter
- ✅ FastMCP con
@mcp.tooldecorators - ✅ Pydantic v2 para validación de inputs
- ✅ async/await en todas las tools (con
httpx.AsyncClient) - ✅ Context injection para logging y progress reporting
- ✅ Lifespan management para recursos compartidos (DB, caché, etc.)
- ✅ Doble transporte: stdio y Streamable HTTP
- ✅ Docker con multi-stage build
- ✅ Hot-reload en modo desarrollo
- ✅ MCP Inspector integrado en Docker Compose
📚 Referencias
Metadata
Release files for aws-cost-mcp 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aws_cost_mcp-1.0.0.tar.gz | 698.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aws_cost_mcp-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 725.1 kB
Release files / aws_cost_mcp-1.0.0.tar.gz
| Download URL | aws_cost_mcp-1.0.0.tar.gz |
|---|---|
| Size | 698.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c1d50c566e595209c8a719565b16194c7ab2a4c3369816420be3eb671ba9c7a1
|
|
BLAKE2b-256 checksum How to use checksums |
a2c72f7bc4314f754d7fac910d87a068b2631547e817e05c0178419320ceaab9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / aws_cost_mcp-1.0.0-py3-none-any.whl
| Download URL | aws_cost_mcp-1.0.0-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ac41b027eff23aeb9cb12b1530a27adf446d02e2338115425b15e9a7f92ae05
|
|
BLAKE2b-256 checksum How to use checksums |
80d9612f2d766a5269123f63030357dda17181140e768a880ff16655d7b58734
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|