Skip to main content
Glama
javipaur
by javipaur

Garmin Coach MCP

Servidor MCP que conecta Garmin Connect con Claude y ChatGPT. ~95 herramientas, datos en tiempo real, multi-tenant: varias cuentas Garmin en un mismo servidor. · by AlejandrLucena


Qué es, en una frase

Un puente entre tu reloj de muñeca y tu IA: la IA lee tu VFC, Body Battery, sueño, predisposición para entrenar, carga y actividades directamente de tus datos reales de Garmin Connect — con la terminología exacta de Garmin en español.

  • Sin resúmenes inventados: cada métrica viene de la última sincronización del reloj.

  • Multi-cuenta: cada persona tiene su propio usuario, su API key y su sesión Garmin.

  • Sin abrir puertos: tu IA habla con un endpoint HTTPS (/mcp).


Related MCP server: garmin-mcp

Cómo funciona (3 piezas)

Cuenta Garmin ──► /login (tokens) ──► /data/users/{user}/tokens.json
                                             │
Claude / ChatGPT ──► Conector MCP ──► https://…/mcp (Authorization: Bearer gcm_sk_…)

Pieza

Qué es

API key (gcm_sk_…)

Nace al crear el usuario. Identifica con quién habla la IA.

Tokens Garmin

Se generan al conectar la cuenta en /login. Dan acceso a los datos.

Conector MCP

En Claude/ChatGPT: URL + cabecera Authorization: Bearer <key>.

Columna «Garmin» del /admin: Conectado = ese usuario ya guardó sus tokens de Garmin.


Puesta en marcha

1 · Despliega (Dokploy / VPS)

  1. Crea un Servicio Docker Compose en Dokploy apuntando a este repositorio.

  2. Monta un volumen en /data (guarda usuarios y tokens).

  3. Activa HTTPS y apunta tu dominio.

2 · Variables de entorno

Variable

Requerido

Descripción

ADMIN_TOKEN

Contraseña de /admin y /login. Genera una con openssl rand -hex 32.

PORT

8000

PUBLIC_URL

Tu dominio, ej. https://garmin.midominio.com

REQUIRE_MCP_AUTH

1/true para exigir Authorization: Bearer (API key o token OAuth) en /mcp y deshabilitar la cuenta legacy

GARMIN_TIMEZONE

Europe/Madrid

GARMIN_LANGUAGE

es

CACHE_MINUTES

30

GCM_LOG_LEVEL

Nivel de log (DEBUG, INFO, …). Por defecto INFO.

ALERT_WEBHOOK_URL

URL genérica (JSON) para alertas de sesión Garmin caducada.

TELEGRAM_BOT_TOKEN · TELEGRAM_CHAT_ID

Alertas a Telegram (alternativa al webhook genérico).

ALERT_MIN_INTERVAL_MIN

Deduplicación de alertas (min entre avisos del mismo evento). 360

BACKUP_KEEP_DAYS

Retención de backups automáticos diarios. 14

GIT_SHA

Commit a mostrar en /health y /admin (inútil a nivel app).

3 · Da de alta a un usuario (2 minutos)

  1. Abre https://tudominio.com/admin con tu ADMIN_TOKEN.

  2. Crear usuario → se genera tu API key al instante.

  3. Copia tu key (se muestra una sola vez), o usa el botón «Enlace de alta»: un enlace único (/alta/{user}?t=…) que muestra al usuario su key y los pasos para conectar.

  4. Conecta su Garmin: /login, elige al usuario en el desplegable, su email + contraseña + código MFA.

4 · Conecta a Claude

En Claude → Settings → Connectors → Add custom connector:

  • URL: https://tudominio.com/mcp

  • Request headers: Authorization: Bearer gcm_sk_… (la key del usuario)

  • Autenticación: elige Ninguno (la key va en la cabecera).

Repite por cada cuenta. Un mismo usuario puede usar la misma key en varios dispositivos.

Si usas «Ninguno» sin cabecera, todos los conectores comparten la cuenta global (legacy), no las claves por usuario.

5 · Conecta desde el móvil o la web (OAuth 2.0 + PKCE)

Los conectores de IA que no pueden mandar cabeceras estáticas (Claude móvil/web) usan el flujo OAuth integrado:

  1. Añade el conector apuntando a https://tudominio.com/mcp sin cabeceras.

  2. Al conectar, se abre el navegador → «Autorizar IA»: elige a qué cuenta Garmin vincular y pulsa Permitir.

  3. El conector recibe un token y ya habla con los datos de ese usuario.

Detalles: PKCE obligatorio (S256), tokens de acceso de 1 h con refresh_token rotatorio de 30 días, tokens guardados en hash en /data/oauth_tokens.json. Metadatos de descubrimiento en /.well-known/oauth-protected-resource-metadata.json y /oauth/.well-known/oauth-authorization-server.


Hackeos útiles

  • ¿Con qué cuenta habla mi IA? El panel /dashboard muestra la última conexión: «IA conectada · Usuario Juan · hace 2 min».

  • ¿Se filtró una key? Regenera desde /admin: la anterior deja de valer al instante.

  • ¿Se filtró un enlace de alta? Botón «Rotar» en /admin: el enlace antiguo deja de valer y sale uno nuevo.

  • ¿Perdiste un usuario o algo se rompió? Export/Import en /admin: descarga un bundle JSON con claves cifradas y tokens Garmin cifrados, y lo restaura.

  • ¿Caducó la sesión Garmin? No debería pasar a menudo: el servidor carga la sesión guardada y la renueva sola vía di_refresh_token (arreglado: antes no cargaba bien los tokens guardados). Solo cuando Garmin revoca del todo el refresh token hace falta re-conectar en /login (MFA).

  • ¿Se te olvida el estado? Configura TELEGRAM_BOT_TOKEN+TELEGRAM_CHAT_ID (o ALERT_WEBHOOK_URL) y recibirás un aviso en cuanto una sesión Garmin caduque (deduplicado cada ALERT_MIN_INTERVAL_MIN min).

  • ¿Tienes copia de seguridad? Cada día se guarda un snapshot cifrado en /data/backups/ (retención BACKUP_KEEP_DAYS, 14 por defecto). Réstáuralo o descárgalo desde la sección «Backups automáticos» de /admin.

  • ¿Quieres saber qué commit corre? /health expone version y git_sha; /admin/status da el estado por usuario.

  • ¿Has tenido actividad sospechosa? /admin guarda un registro (creaciones, borrados, rotaciones, autorizaciones OAuth…) en un log de actividad acotado.

  • ¿Tienes una página bonita de inicio? / sirve una landing pública; el estado real vive en /dashboard.


Endpoints HTTP

Ruta

Descripción

Acceso

GET /

Landing pública del proyecto

Público

GET /health

Estado del servidor, versión, git sha y caché

Público

GET /admin/status

Diagnóstico por usuario (tokens OAuth activos, último refresco, errores)

Admin

GET /admin/backups · POST /admin/restore-backup

Lista y restaura los backups automáticos diarios

Admin

GET /dashboard

Panel de estado (IA conectada, Garmin, admin)

Admin

GET /dashboard/rows

Filas de estado del panel

Público

GET /admin

Gestión de usuarios (crear, ver/regenerar key, enlace de alta, eliminar)

Admin

POST /admin/create

Crea un usuario nuevo (devuelve key + share_token)

Admin

POST /admin/delete

Elimina un usuario y sus tokens

Admin

POST /admin/regenerate

Regenera la API key de un usuario

Admin

POST /admin/update

Edita el nombre de un usuario

Admin

POST /admin/rotate-share

Rota el share_token (enlace de alta) de un usuario

Admin

POST /admin/revoke-oauth

Revoca todos los accesos OAuth de un usuario

Admin

GET /admin/export · POST /admin/import

Backup / restore completo (users + tokens, cifrados)

Admin

GET /alta/{user_id}?t=…

Página de alta del usuario (muestra su key + instrucciones)

Enlace secreto

GET/POST /login (+ /submit, /wait, /mfa, /result)

Wizard para conectar la cuenta Garmin de un usuario

Admin o API Key

GET/POST /setup/proteccion

Poner / cambiar la contraseña del panel

Admin

GET /activities?limit=30

Actividades recientes (JSON)

Admin o API Key

GET /download/{activity_id}

Descarga el .zip/.fit de una actividad

Admin o API Key

GET/POST /config · GET/POST /adj/*

Config web persistente · ajustes por actividad

Admin o API Key

GET /debug/*

Diagnóstico con datos crudos

Admin o API Key

POST /mcp

Endpoint MCP principal

Open (red) · OAuth · API Key

/.well-known/… · /oauth/authorize · /oauth/token (+ metadatos)

Servidor OAuth 2.0 + PKCE

Público (flujo OAuth)

Leyenda: Admin = contraseña ADMIN_TOKEN (cookie o ?token=). Admin o API Key = admin o una key gcm_sk_… por cabecera. OAuth = los conectores móvil/web lo resuelven solos con PKCE. /mcp acepta API keys de usuario, tokens OAuth, o la cuenta global legacy; la frontera real es tu red: solo HTTPS y, si quieres, IP/credenciales en Dokploy/Traefik. Todas las respuestas llevan cabeceras de seguridad y rate limiting.


Seguridad

  • /admin*, /setup/proteccion exigen ADMIN_TOKEN.

  • Rutas de datos y login exigen admin o API key válida.

  • Las API keys nunca se guardan en claro: en disco solo hay SHA-256 + una vista enmascarada (gcm_sk_…abcd). La key se muestra una sola vez al crearla/regenerarla, y se puede volver a revelar en /alta/{user} solo cuando ADMIN_TOKEN está definido como variable de entorno (si lo rotas, las keys viejas deben regenerarse; la autenticación por hash sigue funcionando).

  • Los tokens de Garmin se guardan cifrados en reposo (enc:v1: + XOR con keystream derivado de ADMIN_TOKEN, pbkdf2 200k). Límite conocido: los archivos que genera la librería garminconnect en su token_dir (por ejemplo /data/legacy/…) quedan en claro; lo cifrado es lo que escribe el servidor.

  • Los tokens OAuth se guardan en hash (SHA-256) en /data/oauth_tokens.json; el refresh_token se rota en cada renovación y el flujo exige PKCE (S256), redirect_uri restringida a localhost o tu propio dominio, y códigos de un solo uso de 10 min. Revócalos desde /admin.

  • REQUIRE_MCP_AUTH=1: /mcp deja de aceptar la cuenta legacy y exige Bearer válido (API key de usuario o token OAuth) → 401 en el resto. Ideal para cerrar /mcp una vez que todos tus conectores usan OAuth o cabecera.

  • Sesiones Garmin auto-renovables: el servidor carga los tokens guardados y refresca di_refresh_token automáticamente (se re-cifran en cada renovación). Cuando ya no es posible, se marca el error y salta la alerta de reconexión.

  • Rate limiting: por IP (30/min login y admin, 180/min /mcp, 240/min general) y además por usuario en /mcp cuando llevas Bearer válido; los 429 incluyen Retry-After.

  • Cabeceras de seguridad (nosniff, X-Frame-Options: DENY, CSP de referrer, COOP, Permissions-Policy).

  • API key de 48 caracteres aleatorios (gcm_sk_{32 bytes hex}) + id de usuario aleatorio.

  • Recomendadísimo: define siempre ADMIN_TOKEN fuerte (openssl rand -hex 32).


Instalación local (solo desarrollo)

git clone https://github.com/Alejandrlucena/garmin-coach-mcp.git
cd garmin-coach-mcp
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py                 # → http://localhost:8000

Test: pytest tests/


Arquitectura

Claude (PC/móvil) ── Authorization: Bearer gcm_sk_xxx ──► /mcp
        │
    _UserAuthMiddleware ──► _current_user_id (contextvar)
        │
    Garmin API client + caché POR USUARIO ──► /data/users/{user_id}/tokens.json
  • server.py: servidor principal — tools MCP + endpoints HTTP + auth multi-tenant + servidor OAuth/PKCE.

  • users.py: UserManager — creación/borrado/regeneración de usuarios y API keys, cifrado de tokens en reposo, backup/restore.

  • index.html: landing pública que se sirve en /.

  • requirements.txt · Dockerfile (con healthcheck) · docker-compose.yml · .env.example.


Solución de problemas

Síntoma

Causa típica

Arreglo

Server disconnected al arrancar Claude

Conector configurado como command/args (stdio)

Usa custom connector por URL (/mcp)

Usuario dice «Sin tokens»

No conectó su Garmin, o se logueó con el usuario equivocado en /login

/login → elegir ese usuario → MFA

Claude funciona pero panel sin usuario

Conector sin cabecera (legacy)

Ponle su Authorization: Bearer

Key perdida

/admin → «Regenerar» (se muestra la nueva una vez)

El enlace de alta no muestra la key

ADMIN_TOKEN no está en env, o se rotó

Pon ADMIN_TOKEN en las variables del despliegue o regenera la key

El conector móvil/web no entra por OAuth

El cliente no sigue PKCE, o el flujo se quedó a mitad

Reintenta; usa Claude versión actual. El consentimiento caduca en 10 min

No entro a /admin

ADMIN_TOKEN ≠ lo que tecleas (o file /data/legacy/admin_token manda más)

Revisa Dokploy variables; rm /data/legacy/admin_token

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to access and query Garmin Connect health and fitness data, including sleep, HRV, training load, and activities, with an optional coaching plugin for personalized training plans.
    11
    4
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes Garmin Connect data and workout management to AI agents, supporting tools, resources, and prompts for health data, workout creation, and coaching workflows.
    1
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to query live Garmin Connect health and fitness data, including daily metrics, activities, sleep analysis, and trends via natural language.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/javipaur/garmin-coach-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server