Skip to main content
Glama
javipaur

Garmin Training MCP

by javipaur
README.md
# Garmin Training MCP

Servidor MCP que conecta Claude con tu cuenta de Garmin Connect para que
Claude pueda ver tus actividades, tu sueño y tus datos de recuperación, y con eso
crear y **adaptar día a día** tu plan de entrenamiento (running, natación, ciclismo,
fuerza) según tu meta.

## Modos de uso

| Modo | Transporte | Dónde corre | Ventaja |
|---|---|---|---|
| **Local** | stdio | Tu ordenador, con Claude Desktop | Cero infraestructura, cero latencia |
| **VPS (Dokploy)** | HTTP | Tu VPS, accesible por HTTPS | Accesible desde Claude Desktop, Claude Code, móvil... |

Puedes usar ambos simultáneamente: el local para uso rápido en el PC, el VPS para
cuando estés fuera o desde el móvil.

---

## 1. Instalación

```bash
cd garmin-training-mcp
python3 -m venv venv
source venv/bin/activate        # en Windows: venv\Scripts\activate
pip install -r requirements.txt
```

## 2. Credenciales de Garmin

La primera vez que el servidor se conecte necesita tu email y contraseña de Garmin
Connect (las mismas que usas en la app). Después de ese primer login, el servidor
guarda un token de sesión en `~/.garmin_mcp/tokens` y **no vuelve a pedir credenciales**
(hasta que el token caduque).

```bash
export GARMIN_EMAIL="tu_email@ejemplo.com"
export GARMIN_PASSWORD="tu_contraseña"
```

## 3. Modo local (stdio con Claude Desktop)

### 3.1 Configurar Claude Desktop

Abre (o crea) el archivo de configuración de Claude Desktop:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "garmin-training": {
      "command": "/ruta/absoluta/a/garmin-training-mcp/venv/bin/python3",
      "args": ["/ruta/absoluta/a/garmin-training-mcp/server.py"],
      "env": {
        "GARMIN_EMAIL": "tu_email@ejemplo.com",
        "GARMIN_PASSWORD": "tu_contraseña"
      }
    }
  }
}
```

Reinicia Claude Desktop. Verás "garmin-training" en las herramientas disponibles.

---

## 4. Modo VPS con Dokploy

### 4.1 Subir el código a GitHub

```bash
cd garmin-training-mcp
git init && git add -A && git commit -m "initial"
git remote add origin https://github.com/TU_USUARIO/garmin-training-mcp.git
git push -u origin main
```

### 4.2 Crear el proyecto en Dokploy

1. En tu VPS con Dokploy: **Projects → Create Project** → nombre `garmin-training`
2. **Applications → Deploy from GitHub** → selecciona el repo
3. **Build Settings**: Dokploy detecta el `Dockerfile` automáticamente. Si no:
   - Build Pack: `Dockerfile`
   - Dockerfile path: `Dockerfile`
4. **Puerto**: `8080`

### 4.3 Variables de entorno en Dokploy

En tu proyecto → **Environment** → añade:

```
GARMIN_EMAIL=tu_email@example.com
GARMIN_PASSWORD=tu_contraseña
SUPABASE_URL=https://tu-proyecto.supabase.co    # opcional
SUPABASE_KEY=tu_clave_anon                        # opcional
MCP_PORT=8080
```

> ⚠️ Si usas Supabase, crea primero las tablas (ver sección más abajo).

### 4.4 Dominio + HTTPS

1. En Dokploy → **Domains** → añade tu dominio (ej: `garmin.tudominio.com`)
2. Dokploy configura SSL automáticamente con Let's Encrypt
3. Tu MCP server queda accesible en `https://garmin.tudominio.com/mcp/`

### 4.5 Conectar Claude al VPS

En `claude_desktop_config.json` (o `.claude/settings.json` para Claude Code):

```json
{
  "mcpServers": {
    "garmin-training": {
      "transport": {
        "type": "streamable-http",
        "url": "https://garmin.tudominio.com/mcp/"
      }
    }
  }
}
```

Reinicia Claude Desktop. Las mismas tools estarán disponibles, pero ahora
corriendo en tu VPS.

### 4.6 Probar la conexión

```bash
curl -X POST https://garmin.tudominio.com/mcp/ \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

---

## 5. Cómo usarlo con Claude

Ejemplos de cosas que puedes pedirle a Claude una vez conectado:

- *"Mi meta es correr una media maratón en menos de 1h50 el 15 de noviembre.
   Entreno 4 días por semana. Créame un plan."*
- *"Buenos días, ¿qué toca hoy?"* → Claude usará `get_daily_briefing`
- *"¿Puedo hacer series hoy o mejor lo dejo suave?"* → `get_training_recommendation`
- *"Ayer nadé 2000m, ¿cómo voy?"* → `get_recent_activities` / `get_activity_detail`
- *"He dormido fatal esta semana, ajusta el plan"* → `get_sleep` + `save_training_plan`
- *"¿Cómo entrené el mes pasado?"* → `query_activities_by_date_range`

## 6. Herramientas (tools) que expone el servidor

| Tool | Para qué sirve |
|---|---|
| `get_recent_activities` | Actividades de los últimos N días |
| `get_activity_detail` | Detalle + parciales de una actividad concreta |
| `get_sleep` | Sueño (score, fases, horas) de los últimos N días |
| `get_recovery` | HRV, FC reposo, estrés, Body Battery, training readiness |
| `get_fitness_status` | Estado de forma general y predicciones de marca |
| `query_activities_by_date_range` | Actividades entre dos fechas concretas |
| `get_training_load` | Minutos entrenados por semana y ratio ACWR |
| `get_training_recommendation` | Veredicto de "¿qué puedo hacer hoy?" con razones |
| `import_strava_csv` | Importa el `activities.csv` del export de Strava |
| `get_strava_activities` | Actividades importadas de Strava |
| `get_combined_activities` | Garmin + Strava juntas, ordenadas por fecha |
| `get_goal` / `set_goal` | Leer / definir tu meta |
| `get_training_plan` / `save_training_plan` | Leer / guardar el plan |
| `get_adaptation_journal` | Histórico de ajustes al plan |
| `get_exercise_library` | Ejercicios de fuerza/core reales |
| `log_strength_session` | Registra una sesión de gimnasio |
| `get_strength_history` | Histórico de sesiones de fuerza |
| `get_daily_briefing` | Resumen todo-en-uno para decidir el ajuste del día |

## 7. Multi-dispositivo con Supabase (opcional)

Por defecto, el objetivo/plan/diario/histórico se guardan en JSON local.
Si defines `SUPABASE_URL` + `SUPABASE_KEY`, se usa Supabase (Postgres en la nube).

### Crear las tablas en Supabase

En el SQL Editor de tu proyecto Supabase:

```sql
create table if not exists goals (
  id int primary key default 1,
  sport text,
  description text,
  target_date date,
  details jsonb,
  updated_at timestamptz default now()
);

create table if not exists training_plan (
  id int primary key default 1,
  plan jsonb,
  updated_at timestamptz default now()
);

create table if not exists journal (
  id bigserial primary key,
  ts timestamptz default now(),
  note text
);

create table if not exists strength_log (
  id bigserial primary key,
  date date,
  exercises jsonb,
  notes text,
  logged_at timestamptz default now()
);
```

En Project Settings → API → copia la Project URL y la clave **anon/public**.

### Importar histórico de Strava

1. Strava → Configuración → Mi cuenta → "Descargar o eliminar tu cuenta"
2. Dentro del ZIP: `activities.csv`
3. Dile a Claude: *"Importa mi CSV de Strava, está en /ruta/activities.csv"*
4. Puedes re-importar: las actividades no se duplican

## 8. Notas y límites

- **Librería no oficial**: si Garmin cambia su API, puede dejar de funcionar
  hasta que se actualice `garminconnect` (`pip install -U garminconnect`).
- **Sin push/webhooks**: Claude tira de los datos cuando se lo pides; no hay
  notificación automática en tiempo real.
- **Los datos de fuerza** dependen de que tu reloj/app los registre con detalle.
- **El motor de recomendación** es un motor de reglas transparente, no un
  diagnóstico médico. Si hay dolor o enfermedad, eso pesa más que cualquier número.

### Variables de entorno

| Variable | Requerido | Descripción |
|---|---|---|
| `GARMIN_EMAIL` | Sí | Email de Garmin Connect |
| `GARMIN_PASSWORD` | Sí | Contraseña de Garmin Connect |
| `SUPABASE_URL` | No | URL del proyecto Supabase |
| `SUPABASE_KEY` | No | Clave anon/public de Supabase |
| `MCP_HOST` | No | Host del servidor HTTP (default: `0.0.0.0`) |
| `MCP_PORT` | No | Puerto del servidor HTTP (default: `8080`) |