mcp-server-multitask
by Jotarose
README.md
# mcp_training
Servidor **MCP** con herramientas de clima, geocodificación y divisas, y un
cliente de consola que conversa con un modelo de OpenAI capaz de usarlas.
```
Tú › ¿Qué tiempo hace en Madrid?
Modelo:
En Madrid hay 24,3 °C, humedad del 41 % y cielo despejado.
· geocode_city → get_current_weather
```
## Cómo funciona
Por defecto (`MCP_MODE=local`) todo ocurre en tu máquina: el cliente se conecta
al servidor MCP en `127.0.0.1`, descubre sus herramientas, se las declara al
modelo y las ejecuta él cuando el modelo las pide.
```
main_server.py (MCP) <── 127.0.0.1:8002 ── main_client.py ──> OpenAI
5 herramientas tu terminal el modelo decide
sobre APIs públicas qué usar
```
La alternativa (`MCP_MODE=connector`) usa el conector MCP nativo de la Responses
API: se le pasa a OpenAI la URL del servidor y es OpenAI quien lista, llama y
encadena las herramientas. Como la conexión la abre OpenAI desde *sus*
servidores, `127.0.0.1` no le vale y hay que publicar el servidor con un túnel.
```
main_client.py ──> OpenAI (Responses API) ──> [túnel] ──> main_server.py (MCP)
```
En los dos modos el modelo encadena las llamadas por su cuenta (ciudad →
coordenadas → clima) y la CLI muestra la misma traza.
### Herramientas
| Herramienta | Entrada | Salida |
|---|---|---|
| `geocode_city` | nombre de ciudad | latitud, longitud, país y zona horaria |
| `get_current_weather` | coordenadas | temperatura, humedad, estado del cielo |
| `get_weather_forecast` | coordenadas | pronóstico de 7 días |
| `convert_currency` | importe + dos códigos ISO | importe convertido y tasa aplicada |
| `get_exchange_rates` | código ISO de la moneda base | sus tasas frente al resto de monedas |
Clima y geocodificación usan [Open-Meteo](https://open-meteo.com/) (gratis, sin
clave). Las divisas usan [ExchangeRate-API](https://www.exchangerate-api.com/),
que sí requiere clave, y admiten 20 monedas (`/monedas` en la CLI).
### Estructura
```
config/settings.py configuración y logging (todo sale del .env)
server/ herramientas + clientes HTTP de las APIs externas
client/ cliente de OpenAI + interfaz de terminal
main_server.py arranca el servidor MCP
main_client.py arranca la conversación
```
## Instalación
Requiere **Python 3.11+**. Con [uv](https://docs.astral.sh/uv/) (recomendado):
```bash
git clone <url-del-repo>
cd mcp_training
uv sync
```
O con pip y un entorno virtual:
```bash
python -m venv .venv
.venv\Scripts\activate # Windows; en Linux/macOS: source .venv/bin/activate
pip install -r requirements.txt
```
### Configuración
Copia el ejemplo y rellena tus claves:
```bash
cp .env.example .env
```
Solo dos variables son obligatorias:
| Variable | Para qué |
|---|---|
| `API_KEY_EXCHANGE` | tasas de cambio ([clave gratuita aquí](https://www.exchangerate-api.com/)) |
| `OPENAI_API_KEY` | el modelo del cliente |
Todo lo demás (modo, modelo, puerto, transporte, timeouts, nivel de log) tiene
valores por defecto sensatos y está documentado en [.env.example](.env.example).
## Uso
Hacen falta **dos terminales**: servidor y cliente.
### 1. Arranca el servidor MCP
```bash
uv run python main_server.py
```
Queda escuchando en `http://127.0.0.1:8002/mcp`.
### 2. Lanza el cliente
```bash
uv run python main_client.py
```
Escribe tu consulta y pulsa Enter. La conversación tiene memoria: tras
preguntar por Madrid puedes decir simplemente «¿y mañana?».
```
Convierte 100 USD a EUR
¿Cuál es el clima actual en Madrid?
Dame el pronóstico del tiempo para Nueva York
¿Qué coordenadas tiene Tokio?
```
Comandos de la CLI:
| Comando | Qué hace |
|---|---|
| `/ayuda` | herramientas, ejemplos y comandos |
| `/monedas` | códigos de moneda soportados |
| `/salir` | terminar (también Ctrl+C y Ctrl+D) |
### Modo connector: dejar que OpenAI llame a las herramientas
Con `MCP_MODE=connector` es OpenAI quien lista y ejecuta las herramientas, así
que el servidor tiene que ser accesible desde internet. Hace falta una tercera
terminal con un túnel; con
[devtunnel](https://learn.microsoft.com/azure/developer/dev-tunnels/):
```bash
devtunnel port create -p 8002 --allow-anonymous
devtunnel host
```
Copia la URL que imprime y ponla en el `.env`:
```
MCP_MODE=connector
MCP_PUBLIC_URL=https://xxxxxxx-8002.euw.devtunnels.ms
```
Vale cualquier túnel (ngrok, Cloudflare Tunnel…); solo importa que la URL sea
accesible desde fuera. El cliente añade `/mcp` por su cuenta si no lo lleva.
### Usar el servidor sin el cliente
El servidor es un MCP estándar: sirve para cualquier cliente compatible. Para
conectarlo como subproceso (Claude Desktop, Claude Code…) pon
`MCP_TRANSPORT=stdio` en el `.env`; así no hace falta ni el puerto.
## Problemas frecuentes
| Síntoma | Causa |
|---|---|
| `API_KEY_EXCHANGE Field required` al arrancar | falta el `.env` o la clave |
| `No se pudo conectar con el servidor MCP en http://127.0.0.1:8002/mcp` | falta arrancar `main_server.py` en otra terminal |
| El cliente no arranca y avisa de `MCP_PUBLIC_URL` | con `MCP_MODE=connector`, falta la URL del túnel en el `.env` |
| El modelo dice que no puede usar las herramientas | en modo connector, el túnel está caído o `MCP_PUBLIC_URL` está obsoleta (cambia en cada `devtunnel host`) |
| Error de cuota de OpenAI | saldo agotado; reintentar no lo arregla |
Para ver el detalle de cada llamada (argumentos, respuestas, URLs) pon
`LOG_LEVEL=DEBUG` en el `.env`. Los logs van a stderr, así que
`python main_client.py > charla.txt` guarda solo la conversación.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues