Garmin MCP Server

Se conecta a Garmin Connect para exponer tus datos de fitness y salud a clientes compatibles con MCP.

Documentación

MseeP.ai Security Assessment Badge

Servidor Garmin MCP

Este servidor del Protocolo de Contexto de Modelos (MCP) se conecta a Garmin Connect y expone tus datos de fitness y salud a Claude y otros clientes compatibles con MCP.

La API de Garmin se accede mediante la excelente biblioteca python-garminconnect.

Características

  • Listar actividades recientes con soporte de paginación
  • Obtener información detallada de actividades
  • Editar actividades: nombre, tipo, descripción/notas, tipo de evento, esfuerzo percibido (RPE) y sensación
  • Acceder a métricas de salud (pasos, frecuencia cardíaca, sueño, estrés, respiración)
  • Ver datos de composición corporal
  • Rastrear estado de entrenamiento y disposición
  • Acceder a FTP de ciclismo y métricas de umbral de lactato
  • Gestionar equipo y accesorios, incluyendo notas de texto libre devueltas por get_gear
  • Acceder a entrenamientos y planes de entrenamiento
  • Inspeccionar estructuras detalladas de pasos de entrenamiento, incluidos grupos de repeticiones y objetivos de ritmo de natación
  • Agregados semanales de salud (pasos, estrés, minutos de intensidad)
  • Análisis avanzados de ciclismo: zonas de potencia, análisis de archivos FIT, inteligencia de cambios electrónicos DI2
  • Tendencia de carga de entrenamiento (CTL/ATL/TSB), tendencia de VFC, tendencia de VO2 máx, tendencia de frecuencia respiratoria
  • Curva de duración de potencia, detección de ascensos con VAM, deriva cardíaca (desacoplamiento aeróbico), cálculos de W/kg

Cobertura de herramientas

Este servidor MCP implementa más de 110 herramientas que cubren ~90% de la biblioteca python-garminconnect (v0.3.2):

  • ✅ Gestión de actividades (20 herramientas) - incluye herramientas de escritura para tipo, descripción, tipo de evento, esfuerzo percibido y sensación
  • ✅ Salud y bienestar (34 herramientas) - incluye herramientas personalizadas de resumen ligero
  • ✅ Entrenamiento y rendimiento (13 herramientas) - incluye tendencias de CTL/ATL/TSB, VFC, VO2 máx y respiración
  • ✅ Entrenamientos (8 herramientas)
  • ✅ Dispositivos (7 herramientas)
  • ✅ Gestión de equipo (5 herramientas)
  • ✅ Seguimiento de peso (5 herramientas)
  • ✅ Desafíos e insignias (10 herramientas)
  • ✅ Nutrición (9 herramientas) - registros de alimentos, comidas, alimentos personalizados, registro de alimentos y resúmenes de ingesta de varios días
  • ✅ Salud de la mujer (3 herramientas)
  • ✅ Perfil de usuario (3 herramientas)
  • ✅ Constructores de entrenamientos de alto nivel (4 herramientas) - crea y programa entrenamientos sin escribir JSON
  • ✅ Cursos (5 herramientas) - listar / obtener detalles / subir GPX como curso / descargar GPX / eliminar curso
  • ✅ Análisis de actividad (2 herramientas) - análisis de archivos FIT, curva de duración de potencia; requiere medidor de potencia y/o Di2
  • ✅ Descargas de archivos de actividad (2 herramientas) - descarga archivos de actividad en formato FIT, GPX, TCX o CSV

Nota: Las herramientas de análisis de actividad requieren un medidor de potencia compatible (por ejemplo, Garmin Rally, Favero Assioma, PowerTap P1) y/o cambios electrónicos Shimano Di2 / SRAM eTap. La dependencia fitparse se instala automáticamente.

Notas de equipo

Cada elemento en el array gear devuelto por get_gear incluye un campo notes que contiene el valor de Notas de texto libre que se muestra en Garmin Connect. El equipo sin valor de Notas devuelve null; todos los campos existentes de equipo permanecen sin cambios.

Descargas de archivos de actividad

Dos herramientas te permiten descargar un archivo de actividad sin procesar al disco:

  • download_activity_file(activity_id, format="fit", output_dir=None) — descarga la actividad y la guarda en el directorio configurado. format acepta fit (predeterminado), gpx, tcx o csv.
  • set_fit_download_dir(path) — establece y persiste el directorio de descarga predeterminado (escrito en el archivo de configuración).

Dónde se guardan los archivos (precedencia):

  1. Argumento output_dir — anulación única, no persistida.
  2. Variable de entorno GARMIN_FIT_DOWNLOAD_DIR.
  3. Configuración persistida establecida mediante set_fit_download_dir.

Comportamiento en el primer uso: si no se configura ningún directorio, download_activity_file devuelve status: "needs_setup". El asistente preguntará dónde quieres guardar los archivos (sugiriendo el directorio actual como predeterminado), llamará a set_fit_download_dir para persistir tu elección y luego reintentará la descarga automáticamente.

Puntos finales omitidos intencionalmente

Algunos puntos finales no se implementan debido a consideraciones de rendimiento o complejidad:

Alto volumen de datos:

  • get_activity_details() - Devuelve grandes pistas GPS y datos de gráficos (50KB-500KB). Usa get_activity() para resúmenes en su lugar.

Formatos de entrenamiento especializados:

  • upload_running_workout(), upload_cycling_workout(), upload_swimming_workout() - Cargas de entrenamiento específicas para deportes. Usa upload_workout() para entrenamientos generales.

Operaciones de mantenimiento y destructivas:

  • delete_activity(), delete_blood_pressure() - Las operaciones destructivas requieren consideración cuidadosa.
  • Métodos internos/Auth: login(), resume_login(), connectapi(), download() - Gestionados automáticamente por la biblioteca.

Si necesitas alguno de estos puntos finales, por favor abre un problema.

Filtrado de herramientas

Este servidor registra más de 110 herramientas por defecto, lo que puede ser mucho contexto para que un LLM lo lleve en cada sesión. Puedes exponer solo las herramientas que necesitas con dos variables de entorno opcionales:

Variable de entornoEfecto
GARMIN_ENABLED_TOOLSLista de permitidos separada por comas — si se establece, solo se registran estas herramientas.
GARMIN_DISABLED_TOOLSLista de denegados separada por comas — las herramientas listadas se omiten. Se ignora si se establece una lista de permitidos.

Los nombres de las herramientas no distinguen entre mayúsculas y minúsculas. Con ninguna variable establecida, se registran todas las herramientas (comportamiento predeterminado sin cambios). Los nombres que no coinciden con ninguna herramienta se ignoran con una advertencia en stderr, lo que facilita detectar errores tipográficos.

Ejemplo — exponer solo sueño, estrés y actividades recientes:

"env": {
  "GARMIN_ENABLED_TOOLS": "get_sleep_data,get_stress_summary,get_activities"
}

Herramientas de entrenamiento de alto nivel

Estas herramientas constructoras permiten que un LLM cree y programe entrenamientos sin escribir JSON sin procesar de Garmin.

create_walk_run_workout

Crea un entrenamiento de intervalos de caminata/carrera con objetivo opcional de zona de frecuencia cardíaca.

{
  "name": "W3 Mié 2:2",
  "run_seconds": 120,
  "walk_seconds": 120,
  "repeats": 9,
  "warmup_min": 10,
  "cooldown_min": 8,
  "hr_zone": "Z3"
}

Devuelve: {"status": "success", "workout_id": 1234567890, ...}

create_z2_walk_workout

Crea un entrenamiento de caminata constante en Z2.

{
  "name": "Z2 Walk 45m",
  "duration_min": 45,
  "hr_min": 110,
  "hr_max": 130
}

Devuelve: {"status": "success", "workout_id": 1234567890, ...}

create_strength_workout

Crea un entrenamiento de fuerza a partir de una lista de ejercicios. Cada uno se convierte en un paso basado en repeticiones, con el nombre mantenido en la descripción del paso. El nombre también se envía como exerciseName, pero Garmin solo lo retiene cuando coincide con una de sus propias claves de ejercicio (por ejemplo, FARMERS_CARRY) — cualquier otro valor se acepta y luego se almacena vacío.

category es opcional y se pasa directamente. Omítelo y la clave se deja fuera del payload por completo, lo que Garmin acepta. Proporciónalo y debe ser una de las categorías de ejercicio de Garmin — cualquier otra cosa, incluidos OTHER y UNASSIGNED, se rechaza con 400 - Invalid category. La lista completa se publica en Exercises.json.

{
  "name": "Full Body A",
  "exercises": [
    {"name": "Sentadillas", "sets": 3, "reps": 12, "rest_seconds": 90},
    {"name": "Flexiones",   "sets": 3, "reps": 15, "rest_seconds": 60},
    {"name": "Peso muerto", "sets": 3, "reps": 10, "rest_seconds": 90},
    {"name": "Farmers Carry 40m", "sets": 3, "reps": 1, "rest_seconds": 90, "category": "CARRY"}
  ]
}

Devuelve: {"status": "success", "workout_id": 1234567890, ...}

schedule_week

Programa múltiples entrenamientos en una sola llamada.

{
  "week": [
    {"date": "2026-05-12", "workout_id": 1234567890},
    {"date": "2026-05-14", "workout_id": 1234567891}
  ]
}

Devuelve: {"status": "complete", "scheduled": [...]}

Ejemplo de flujo completo

create_walk_run_workout(name="W3 Mié 2:2", run_seconds=120, walk_seconds=120,
                        repeats=9, warmup_min=10, cooldown_min=8)
  → workout_id = 1560092011

schedule_workout(workout_id=1560092011, date="2026-05-06")
  → OK

Después de sincronizar tu reloj, el entrenamiento aparece en el calendario del Forerunner 965.

Condiciones finales sin procesar de upload_workout

Al construir JSON de entrenamiento personalizado para upload_workout o upload_workouts, el endCondition.conditionTypeId y endCondition.conditionTypeKey deben coincidir con el mapeo canónico de Garmin. Garmin trata el conditionTypeId numérico como la fuente de verdad; si la clave y el ID entran en conflicto, Garmin almacena la condición que coincide con el ID.

Por ejemplo, esto es inválido para una condición final de frecuencia cardíaca porque el ID 4 es calories, no heart.rate:

{
  "endCondition": {
    "conditionTypeId": 4,
    "conditionTypeKey": "heart.rate"
  },
  "endConditionValue": 145
}

Usa el ID 6 para frecuencia cardíaca:

{
  "endCondition": {
    "conditionTypeId": 6,
    "conditionTypeKey": "heart.rate"
  },
  "endConditionValue": 145
}

Para una condición final de frecuencia cardíaca basada en zonas, usa endConditionZone (1-5) en el mismo objeto endCondition y omite endConditionValue. Si se envían ambos, Garmin conserva la zona y descarta el valor (verificado contra la API de producción el 2026-09-01):

{
  "endCondition": {
    "conditionTypeId": 6,
    "conditionTypeKey": "heart.rate",
    "endConditionZone": 2
  }
}

IDs comunes de condiciones finales:

IDClave
1lap.button
2time
3distance
4calories
5power
6heart.rate
7iterations
8fixed.rest
9fixed.repetition
10reps
11training.peaks.tss

Tipos de objetivo sin procesar de upload_workout

Al construir JSON de entrenamiento sin procesar de Garmin, targetType.workoutTargetTypeId y targetType.workoutTargetTypeKey deben usar el mapeo canónico de Garmin. Garmin trata el ID numérico como autoritativo: un payload no coincidente como {"workoutTargetTypeId": 6, "workoutTargetTypeKey": "heart.rate"} se almacena como pace.zone, porque el ID 6 significa pace.zone.

Para un rango de frecuencia cardíaca personalizado, usa el tipo de objetivo ID 4 con heart.rate.zone y coloca el rango de bpm en targetValueOne / targetValueTwo. Estos campos de valor pertenecen al paso del entrenamiento, junto con targetType; no los anides dentro del objeto targetType:

{
  "targetType": {
    "workoutTargetTypeId": 4,
    "workoutTargetTypeKey": "heart.rate.zone"
  },
  "targetValueOne": 143,
  "targetValueTwo": 157
}

La misma forma se aplica a un rango de ritmo de carrera personalizado. Los límites de ritmo usan metros por segundo:

{
  "targetType": {
    "workoutTargetTypeId": 6,
    "workoutTargetTypeKey": "pace.zone"
  },
  "targetValueOne": 1.9607843,
  "targetValueTwo": 2.0833333
}

Ese ejemplo representa 8:00–8:30 min/km. El límite numérico inferior se lista primero por consistencia con el ejemplo de frecuencia cardíaca; Garmin normaliza cualquier orden de límites. Garmin descarta silenciosamente los valores anidados dentro de targetType, dejando un objetivo de ritmo sin rango activo. Las herramientas de carga reparan ese error de anidación inequívoco, pero rechazan la solicitud si los valores anidados y a nivel de paso entran en conflicto.

Para una zona de FC nombrada de Garmin, usa el mismo tipo de objetivo con zoneNumber en su lugar:

{
  "targetType": {
    "workoutTargetTypeId": 4,
    "workoutTargetTypeKey": "heart.rate.zone"
  },
  "zoneNumber": 3
}

Usa ya sea zoneNumber o targetValueOne / targetValueTwo en un objetivo, no ambos. Garmin trata la zona nombrada como autoritativa y descarta silenciosamente un rango personalizado coexistente, por lo que las herramientas de carga rechazan esa forma ambigua.

Instalación con un clic (Claude Desktop)

La forma más fácil de agregar este servidor a Claude Desktop es mediante el archivo de Extensión de Escritorio .dxt — sin necesidad de editar JSON.

Descargar e instalar

  1. Descarga el último garmin-mcp.dxt desde la página de Lanzamientos.
  2. Arrastra el archivo .dxt a la ventana de Claude Desktop, o haz doble clic en él, o ve a Configuración → Extensiones → Instalar Extensión y selecciona el archivo.
  3. Claude Desktop te pedirá configuración opcional (ruta del token, correo electrónico, contraseña).

Autenticación por primera vez

La extensión instala y ejecuta el servidor automáticamente, pero debes autenticarte con Garmin una vez antes de que se puedan obtener datos:

uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp-auth

Esto guarda los tokens OAuth en ~/.garminconnect. Después de eso, el servidor funciona sin credenciales en la configuración.

Nota: Los tokens son válidos por aproximadamente 6 meses. Vuelve a ejecutar garmin-mcp-auth cuando expiren.

Construye el .dxt tú mismo

bash scripts/build_dxt.sh   # produces garmin-mcp.dxt in the repo root

Configuración

Inicio rápido para clientes MCP

La forma más fácil de usar este servidor MCP con Claude Desktop, Codex u otro cliente MCP es autenticarte una vez antes de agregar el servidor a tu configuración.

Requisitos previos

  • Python 3.12+
  • Cuenta de Garmin Connect
  • Puede requerirse MFA si está habilitada en tu cuenta

Paso 1: Pre-autenticación (una sola vez)

Antes de agregar el servidor a tu cliente MCP, autentícate una vez en tu terminal:


# Install and run authentication tool
uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp-auth

# You'll be prompted for:
# - Email (or set GARMIN_EMAIL env var)
# - Password (or set GARMIN_PASSWORD env var)
# - MFA code (if enabled on your account)

# OAuth tokens will be saved to ~/.garminconnect

Puedes verificar tus credenciales en cualquier momento con

uv run garmin-mcp-auth --verify

Nota: También puedes establecer credenciales mediante variables de entorno:

GARMIN_EMAIL=your@email.com GARMIN_PASSWORD=secret garmin-mcp-auth

Si no tienes MFA habilitada, también puedes omitir garmin-mcp-auth y pasar GARMIN_EMAIL y GARMIN_PASSWORD como variables de entorno directamente a tu cliente MCP, si es compatible. Para mayor seguridad, prefiere el flujo de pre-autenticación anterior y mantén las credenciales fuera de la configuración del cliente MCP.

Paso 2: Configurar Claude Desktop

Agrega a tu configuración MCP de Claude Desktop SIN credenciales:

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

{
  "mcpServers": {
    "garmin": {
      "command": "uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ]
    }
  }
}

Importante: ¡No se necesitan GARMIN_EMAIL ni GARMIN_PASSWORD en la configuración! El servidor usa tus tokens guardados.

Paso 3: Reinicia tu cliente MCP

Tus datos de Garmin ahora están disponibles para tu cliente MCP.

Para Codex y otros clientes, consulta los ejemplos a continuación.


Usar más de una cuenta de Garmin

Un solo proceso de servidor está vinculado a una cuenta de Garmin. Para usar varias cuentas a la vez, ejecuta una instancia de servidor por cuenta, cada una con su propio directorio de tokens, seleccionado con la variable de entorno GARMINTOKENS. GARMINTOKENS por defecto es ~/.garminconnect. Si lo apuntas a otro lugar, el servidor lee y escribe tokens allí en su lugar, dejando el almacén predeterminado intacto.

Paso 1: Autentica cada cuenta en su propio directorio

garmin-mcp-auth --token-path ~/.garminconnect-alice
garmin-mcp-auth --token-path ~/.garminconnect-bob

--token-path también acepta $GARMINTOKENS, por lo que GARMINTOKENS=~/.garminconnect-alice garmin-mcp-auth es equivalente.

Paso 2: Declara un servidor por cuenta

{
  "mcpServers": {
    "garmin-alice": {
      "command": "uvx",
      "args": ["--python", "3.12", "--from", "git+https://github.com/Taxuspt/garmin_mcp", "garmin-mcp"],
      "env": {
        "GARMINTOKENS": "${HOME}/.garminconnect-alice"
      }
    },
    "garmin-bob": {
      "command": "uvx",
      "args": ["--python", "3.12", "--from", "git+https://github.com/Taxuspt/garmin_mcp", "garmin-mcp"],
      "env": {
        "GARMINTOKENS": "${HOME}/.garminconnect-bob"
      }
    }
  }
}

Cada servidor registra el directorio desde el que autentica al iniciarse, para que puedas confirmar la configuración:

Trying to login to Garmin Connect using token data from directory '/home/you/.garminconnect-alice'...

Notas

  • Sin respaldo silencioso. Si GARMINTOKENS apunta a un directorio sin tokens válidos, el inicio falla con GarminConnectAuthenticationError en lugar de recurrir al almacén predeterminado. Un segundo servidor mal configurado no puede reutilizar silenciosamente la sesión de la primera cuenta.

  • ${HOME} se expande incluso cuando un cliente MCP lo pasa sin resolver, y ~ funciona en Windows mediante USERPROFILE.

  • Restringe las herramientas de escritura en cuentas secundarias. Herramientas como upload_workout y schedule_workout escriben en la cuenta a la que el servidor está vinculado. Combina GARMINTOKENS con GARMIN_ENABLED_TOOLS (consulta Filtrado de herramientas) para que una cuenta sea de solo lectura:

    "env": {
      "GARMINTOKENS": "${HOME}/.garminconnect-bob",
      "GARMIN_ENABLED_TOOLS": "get_activities,get_activities_by_date,get_activity,get_activity_splits"
    }
    
  • Los directorios de tokens contienen credenciales de larga duración. Se crean con permisos solo para el propietario; mantenlos fuera de carpetas compartidas o sincronizadas.


Configuración de desarrollo

  1. Instala los paquetes necesarios en un entorno nuevo:
uv sync

Ejecutar el servidor

Configuración

Tus credenciales de Garmin Connect se leen desde variables de entorno:

  • GARMIN_EMAIL: Tu dirección de correo de Garmin Connect
  • GARMIN_EMAIL_FILE: Ruta a un archivo que contiene tu dirección de correo de Garmin Connect
  • GARMIN_PASSWORD: Tu contraseña de Garmin Connect
  • GARMIN_PASSWORD_FILE: Ruta a un archivo que contiene tu contraseña de Garmin Connect
  • GARMIN_IS_CN: Establécelo en true para usar Garmin Connect China (garmin.cn) en lugar de la versión internacional (predeterminado: false)
  • GARMIN_FIT_DOWNLOAD_DIR: Directorio predeterminado para archivos de actividad descargados. Cuando se establece, omite el aviso de configuración de primera ejecución en download_activity_file.
  • GARMIN_FIT_CONFIG: Ruta al archivo de configuración persistente del directorio de descargas (predeterminado: ~/.garminconnect_fit_config.json).

Los secretos basados en archivos son útiles en ciertos entornos, como dentro de un contenedor Docker. Ten en cuenta que no puedes establecer tanto GARMIN_EMAIL como GARMIN_EMAIL_FILE, de manera similar no puedes establecer tanto GARMIN_PASSWORD como GARMIN_PASSWORD_FILE.

Transporte

Por defecto, el servidor se comunica a través de stdio, que es lo que esperan Claude Desktop, el Inspector MCP y la mayoría de los clientes locales. Para servir a través de HTTP en su lugar (por ejemplo, cuando se ejecuta en un contenedor o Kubernetes), establece el transporte mediante variables de entorno:

  • GARMIN_MCP_TRANSPORT: stdio (predeterminado), streamable-http o sse
  • GARMIN_MCP_HOST: dirección de enlace para transportes HTTP (predeterminado 127.0.0.1; establécelo en 0.0.0.0 solo cuando el endpoint esté protegido por un proxy inverso autenticado)
  • GARMIN_MCP_PORT: puerto de enlace para transportes HTTP (predeterminado 8000)
  • GARMIN_MCP_CALL_TIMEOUT: tiempo de espera por solicitud en segundos para llamadas a Garmin (predeterminado 90). La API de Garmin ocasionalmente detiene una sola solicitud indefinidamente; sin este límite, la llamada se cuelga hasta que el tiempo de espera del propio cliente MCP se agota y reporta todo el servidor como no receptivo. Al agotarse el tiempo, la herramienta devuelve un error claro y reintentable. Establécelo en 0 para deshabilitar el límite.
GARMIN_MCP_TRANSPORT=streamable-http garmin-mcp

Cuando se selecciona un transporte HTTP:

  • Los clientes MCP se conectan a la ruta /mcp (por ejemplo, http://localhost:8000/mcp).
  • Se expone un endpoint GET /healthz simple para sondas de actividad/disponibilidad.

El servidor en sí no realiza autenticación en el endpoint HTTP: colócalo detrás de un proxy inverso (nginx, Traefik, Authelia, etc.) si es accesible más allá de localhost.

Garmin Connect China (garmin.cn)

Si usas Garmin Connect China (garmin.cn) en lugar de la versión internacional, establece la variable de entorno GARMIN_IS_CN en true:

# Pre-authenticate with Garmin Connect China
GARMIN_IS_CN=true garmin-mcp-auth

# Or use the CLI flag
garmin-mcp-auth --is-cn

Para Claude Desktop, agrega GARMIN_IS_CN a la sección env:

{
  "mcpServers": {
    "garmin": {
      "command": "uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ],
      "env": {
        "GARMIN_IS_CN": "true"
      }
    }
  }
}

Para Docker, agrega GARMIN_IS_CN=true a tu archivo .env o descoméntalo en docker-compose.yml.

Probar el servidor localmente con MCP Inspector

El Inspector se ejecuta directamente a través de npx sin requerir instalación. Ejecuta desde la raíz del proyecto:

npx @modelcontextprotocol/inspector uv run garmin-mcp

Podrás inspeccionar y probar las herramientas.

Con Claude Desktop

  1. Crea una configuración en Claude Desktop:

Edita tu archivo de configuración de Claude Desktop:

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

Tienes dos opciones para ejecutar el MCP localmente con Claude.

Directamente desde GitHub sin clonar el repositorio:

  1. Agrega esta configuración de servidor:
{
  "mcpServers": {
    "garmin": {
      "command": "uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ],
      "env": {
        "GARMIN_EMAIL": "YOUR_GARMIN_EMAIL",
        "GARMIN_PASSWORD": "YOUR_GARMIN_PASSWORD"
      }
    }
  }
}

Es posible que tengas que agregar la ruta completa a uvx; puedes verificar la ruta completa con which uvx

  1. Reinicia Claude Desktop

Directamente desde tu copia local del repositorio:

  1. Agrega esta configuración de servidor:
{
  "mcpServers": {
    "garmin-local": {
      "command": "uv",
      "args": [
        "--directory",
        "<full path to your local repository>/garmin_mcp",
        "run",
        "garmin-mcp"
      ]
    }
  }
}
  1. Reinicia Claude Desktop

Con Codex

Codex usa TOML para la configuración del servidor MCP. Agrega una de las siguientes entradas a ~/.codex/config.toml después de autenticarte con garmin-mcp-auth.

También puedes pedirle a tu cliente compatible con MCP que configure esto por ti. Por ejemplo:

Install the Garmin MCP server from https://github.com/Taxuspt/garmin_mcp, authenticate with garmin-mcp-auth, and add it to my MCP configuration without storing my Garmin email or password.

Directamente desde GitHub sin clonar el repositorio

[mcp_servers.garmin]
command = "uvx"
args = [
  "--python",
  "3.12",
  "--from",
  "git+https://github.com/Taxuspt/garmin_mcp",
  "garmin-mcp"
]

Directamente desde tu copia local del repositorio

[mcp_servers.garmin-local]
command = "uv"
args = [
  "--directory",
  "/full/path/to/garmin_mcp",
  "run",
  "garmin-mcp"
]

Reinicia tu cliente MCP después de guardar el archivo.

Con opencode

opencode carga automáticamente un opencode.json a nivel de proyecto cuando se inicia desde la raíz de un repositorio, por lo que los contribuyentes que clonen este repositorio obtienen el Garmin MCP conectado al código fuente local sin configuración adicional.

Desde un clon de este repositorio (recomendado para desarrollo)

Este repositorio incluye un opencode.json que ejecuta el MCP mediante uv run garmin-mcp, por lo que siempre sigue el árbol de trabajo.

git clone https://github.com/Taxuspt/garmin_mcp.git
cd garmin_mcp
uv sync                # install dependencies
garmin-mcp-auth        # one-time Garmin login (skip if ~/.garminconnect already exists)
opencode               # launches with the garmin MCP attached

Verifica que el servidor esté conectado:

opencode mcp list
# ●  ✓ garmin   connected
#       uv run garmin-mcp

Desde cualquier otro directorio (instalación desde GitHub)

Agrega el servidor a tu configuración global de opencode en ~/.config/opencode/opencode.json después de ejecutar garmin-mcp-auth:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "garmin": {
      "type": "local",
      "command": [
        "uvx",
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ],
      "enabled": true,
      "timeout": 30000
    }
  }
}

Reinicia opencode después de guardar el archivo. La primera invocación de uvx descarga y almacena en caché el paquete, por lo que el inicio inicial puede tardar unos segundos.

Con Docker

Docker proporciona un entorno aislado y consistente para ejecutar el servidor MCP.

Inicio rápido con Docker Compose (recomendado)

  1. Crea un archivo .env con tus credenciales:
echo "GARMIN_EMAIL=your_email@example.com" > .env
echo "GARMIN_PASSWORD=your_password" >> .env
  1. Inicia el contenedor:
docker compose up -d
  1. Consulta los registros para monitorear el servidor:
docker compose logs -f garmin-mcp

Usando Docker directamente

# Build the image
docker build -t garmin-mcp .

# Run the container
docker run -it \
  -e GARMIN_EMAIL="your_email@example.com" \
  -e GARMIN_PASSWORD="your_password" \
  -v garmin-tokens:/root/.garminconnect \
  garmin-mcp

Usando secretos basados en archivos (más seguro)

Para mayor seguridad, especialmente en entornos de producción, usa secretos basados en archivos en lugar de variables de entorno:

  1. Crea un directorio de secretos y agrega tus credenciales:
mkdir -p secrets
echo "your_email@example.com" > secrets/garmin_email.txt
echo "your_password" > secrets/garmin_password.txt
chmod 600 secrets/*.txt
  1. Edita docker-compose.yml y descomenta la sección de secretos:
services:
  garmin-mcp:
    environment:
      - GARMIN_EMAIL_FILE=/run/secrets/garmin_email
      - GARMIN_PASSWORD_FILE=/run/secrets/garmin_password
    secrets:
      - garmin_email
      - garmin_password

secrets:
  garmin_email:
    file: ./secrets/garmin_email.txt
  garmin_password:
    file: ./secrets/garmin_password.txt
  1. Inicia el contenedor:
docker compose up -d

Manejo de MFA con Docker

Si tienes autenticación multifactor (MFA) habilitada en tu cuenta de Garmin:

  1. Ejecuta el contenedor en modo interactivo:
docker compose run --rm garmin-mcp
  1. Cuando se te solicite, ingresa tu código MFA:
Garmin Connect MFA required. Please check your email/phone for the code.
Enter MFA code: 123456
  1. Los tokens OAuth se guardarán en el volumen de Docker (garmin-tokens), por lo que no necesitarás volver a autenticarte en ejecuciones posteriores.

  2. Después de la configuración de MFA, puedes ejecutar el contenedor normalmente:

docker compose up -d

Gestión de volúmenes de Docker

Los tokens OAuth se almacenan en un volumen persistente de Docker para evitar la reautenticación:

# List volumes
docker volume ls

# Inspect the tokens volume
docker volume inspect garmin_mcp_garmin-tokens

# Remove the volume (will require re-authentication)
docker volume rm garmin_mcp_garmin-tokens

Uso con Claude Desktop mediante Docker

Para usar el servidor MCP en Docker con Claude Desktop, puedes configurarlo para que se comunique con el contenedor. Sin embargo, ten en cuenta que los servidores MCP normalmente se comunican a través de stdio, que funciona mejor con la ejecución directa de procesos. Para implementaciones basadas en Docker, considera usar el método estándar uvx que se muestra en la sección Con Claude Desktop en su lugar.

Ejemplos de uso

Una vez conectado en Claude, puedes hacer preguntas como:

  • "Muéstrame mis actividades recientes"
  • "¿Cómo fue mi sueño anoche?"
  • "¿Cuántos pasos di ayer?"
  • "Muéstrame los detalles de mi última carrera"
  • "Analiza las zonas de potencia de mi último recorrido y compáralas con mis zonas de entrenamiento"
  • "Muéstrame la tendencia de mi CTL, ATL y TSB de las últimas 6 semanas"
  • "¿Cuál fue mi curva de duración de potencia del recorrido de ayer? Estima mi FTP."
  • "Analiza los datos FIT de mi última actividad de ciclismo: ¿cómo fue mi calidad de cambios en las subidas?"
  • "Muéstrame la tendencia de mi VFC de las últimas 2 semanas y señala cualquier preocupación de recuperación"
  • "¿Cuál es mi mejor potencia de 20 minutos de la temporada y cuándo la establecí?"

Solución de problemas

get_training_effect devuelve HTTP 403 para una actividad válida

El endpoint de detalles de actividad de Garmin (/activity-service/activity/{id}) puede devolver 403 Prohibido incluso cuando la misma actividad es visible en las herramientas de lista. get_training_effect ahora recurre a la búsqueda de la lista de actividades, que aún incluye el efecto de entrenamiento aeróbico/anaeróbico para actividades recientes.

Si la actividad es más antigua que la ventana de búsqueda reciente, lista la actividad con get_activities / get_activities_by_date y reintenta, o usa esos campos de lista directamente.

get_goals no devuelve objetivos que existen en Garmin Connect

El servicio de objetivos de Garmin solo devuelve objetivos creados en la interfaz de objetivos actual de Connect (objetivos de distancia/tiempo con nombre, como un objetivo mensual de ciclismo) cuando la solicitud envía Sec-Fetch-Site: same-origin y usa un start basado en 1. Con start=0, devuelve una lista vacía. El get_goals() de python-garminconnect no hace ambas cosas (hasta 0.3.16), por lo que get_goals aquí llama a /goal-service/goal/goals directamente de la misma manera que lo hace la página de objetivos de Connect, y usa la llamada de la biblioteca solo como respaldo.

"Error al iniciar el proceso: No existe el archivo o directorio"

Si Claude Desktop no puede encontrar uvx, es porque uvx no está en el PATH que usa Claude Desktop. Para solucionarlo:

  1. Encuentra dónde está instalado uvx:
which uvx
  1. Usa la ruta completa en tu configuración. Por ejemplo, si uvx está en /Users/username/.cargo/bin/uvx:
{
  "mcpServers": {
    "garmin": {
      "command": "/Users/username/.cargo/bin/uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ]
    }
  }
}

Windows: Smart App Control bloquea uv / uvx

En Windows 11 con Smart App Control habilitado, uv.exe / uvx.exe pueden estar bloqueados al iniciar Garmin_MCP, incluido cuando uv intenta cargar un garmin-mcp.exe sin firmar desde un .venv local.

Esto no es lo mismo que la cuarentena de Microsoft Defender Antivirus. Smart App Control está en:

Seguridad de Windows → Control de aplicaciones y navegador → Smart App Control

Síntomas

  • Notificación de Smart App Control al ejecutar uv, uvx o Claude Desktop con command: "uvx"
  • Claude Desktop no puede iniciar el servidor incluso cuando uvx parece estar instalado
  • Visor de eventos → Registros de aplicaciones y servicios → Microsoft → Windows → CodeIntegrity → Operativo muestra Error de CodeIntegrity 3077 que menciona uv.exe y garmin-mcp.exe (nivel de firma de política / Enterprise)

Confirmación

  1. Smart App Control está Activado (Evaluación o Aplicación).
  2. Revisa el registro operativo de CodeIntegrity para el evento 3077 alrededor del inicio fallido.
  3. El historial de "Protección contra virus y amenazas" de Defender puede estar vacío; eso no descarta SAC.

Recuperaciones (se recomienda mantener Smart App Control activado)

  1. Instale o reinstale uv a través de un canal empaquetado, luego verifique en PowerShell:
    winget install --id=astral-sh.uv -e
    # or: scoop install main/uv
    uvx --version
    
  2. Apunte Claude Desktop a la ruta completa de uvx.exe (misma idea que la solución de problemas de PATH anterior), por ejemplo:
    "command": "C:\\Users\\<you>\\.local\\bin\\uvx.exe"
    
  3. Si Enforcement aún bloquea la carga de garmin-mcp.exe, es posible que necesite una excepción de administrador/política para esa ruta binaria. Desactivar Smart App Control globalmente es un último recurso, no el consejo predeterminado.
  4. Si uvx local sigue bloqueado, use la ruta de instalación de Docker Compose en su lugar.

Problemas de inicio de sesión

Si encuentra problemas de inicio de sesión:

  1. Verifique que sus credenciales sean correctas
  2. Compruebe si Garmin Connect requiere verificación adicional
  3. Asegúrese de que el paquete garminconnect esté actualizado

Registros

Para otros problemas, revise los registros de Claude Desktop en:

  • macOS: ~/Library/Logs/Claude/mcp-server-garmin.log
  • Windows: %APPDATA%\Claude\logs\mcp-server-garmin.log

Autenticación multifactor de Garmin Connect (MFA)

Comprensión de MFA con servidores MCP

Los servidores MCP se ejecutan como procesos en segundo plano sin acceso directo a la terminal. Si su cuenta de Garmin tiene MFA habilitado, debe autenticarse una vez usando la herramienta de preautenticación antes de que el servidor pueda ejecutarse.

Recomendado: Herramienta de preautenticación

La forma más fácil de manejar MFA es usando la herramienta de autenticación dedicada:

garmin-mcp-auth

Esto guarda los tokens OAuth en ~/.garminconnect para uso futuro. El servidor usará automáticamente estos tokens cuando se ejecute en Claude Desktop u otros clientes MCP.

Opciones adicionales:

# Use environment variables for credentials
GARMIN_EMAIL=you@example.com GARMIN_PASSWORD=secret garmin-mcp-auth

# Verify existing tokens
garmin-mcp-auth --verify

# Force re-authentication (e.g., when tokens expire)
garmin-mcp-auth --force-reauth

# Use custom token location
garmin-mcp-auth --token-path ~/.garmin_tokens

Alternativa: Primera ejecución manual

También puede autenticarse ejecutando el servidor una vez de forma interactiva:

# Store credentials in files for security
echo "your_email@example.com" > ~/.garmin_email
echo "your_password" > ~/.garmin_password
chmod 600 ~/.garmin_email ~/.garmin_password

# Run server interactively to authenticate
GARMIN_EMAIL_FILE=~/.garmin_email GARMIN_PASSWORD_FILE=~/.garmin_password \
  uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp

# Enter MFA code when prompted
# Tokens will be saved automatically
# Now add to Claude Desktop config without credentials

Después de la autenticación inicial, configure Claude Desktop sin credenciales (los tokens ya están guardados):

{
  "mcpServers": {
    "garmin": {
      "command": "uvx",
      "args": [
        "--python",
        "3.12",
        "--from",
        "git+https://github.com/Taxuspt/garmin_mcp",
        "garmin-mcp"
      ]
    }
  }
}

Uso de Docker con MFA

Si usa Docker, siga la sección Manejo de MFA con Docker anterior para una experiencia optimizada con almacenamiento persistente de tokens.

Solución de problemas de MFA

Error: "Se requiere autenticación MFA pero no hay terminal interactiva disponible"

Solución:

  1. Abra la terminal
  2. Ejecute: garmin-mcp-auth
  3. Ingrese las credenciales y el código MFA
  4. Reinicie Claude Desktop

Token caducado

Los tokens OAuth caducan periódicamente (aproximadamente cada 6 meses). Vuelva a autenticarse:

garmin-mcp-auth --force-reauth

Verificar que los tokens funcionen

garmin-mcp-auth --verify

Pruebas

Este proyecto incluye pruebas exhaustivas para todas las herramientas MCP. Todas las pruebas están pasando actualmente (100%).

Ejecución de pruebas

# Run all integration tests (default - uses mocked Garmin API)
uv run pytest tests/integration/

# Run tests with verbose output
uv run pytest tests/integration/ -v

# Run a specific test module
uv run pytest tests/integration/test_health_wellness_tools.py -v

# Run end-to-end tests (requires real Garmin credentials)
uv run pytest tests/e2e/ -m e2e -v

Estructura de pruebas

  • Pruebas de integración (más de 200 pruebas): Prueban todas las herramientas MCP usando integración FastMCP con respuestas simuladas de la API de Garmin
  • Pruebas de extremo a extremo (4 pruebas): Prueban con el servidor MCP real y la API de Garmin (requiere credenciales válidas)

Reinstalación desde ruta local

Si está trabajando desde un checkout o fork local:

uv tool install --python 3.12 --force C:\Users\aresd\Desktop\programacion\garmin_mcp