DkwtMCP
This server integrates Garmin and Apple Health data locally, enabling AI-driven analysis of training, recovery, and performance, plus creating and scheduling structured workouts.
Garmin Activities & Training: List recent activities with metrics, get full details and per-km splits. Estimate heart rate zones (Karvonen or %HRmax) and pace zones from threshold pace. Create multi-step structured workouts (running, cycling, walking, hiking) with heart rate, pace, or power targets, preview them (dry-run), and schedule them individually or as a weekly plan. Manage your Garmin workout library (list/delete).
Garmin Performance & Load: View race predictions (5K–marathon), personal records, VO2max (running/cycling), fitness age, training status, acute/chronic load, and endurance score. Manually log body composition (weight, body fat %, muscle mass) into Garmin Connect.
Recovery & Health Metrics (Garmin & Apple Health): Access daily readiness, sleep stages and scores, nightly HRV, resting heart rate, stress, Body Battery. Import Apple Health exports to query sleep, HRV, resting heart rate, steps, and active energy, plus view Apple Watch workouts (strength, walking, etc.).
Cross-Platform Analysis: Compare planned vs. executed workouts for adherence tracking. Generate weekly summaries of training and recovery. Produce day-by-day tables correlating training load with recovery metrics. Track trends in weight, body fat, and muscle mass over time. Receive a daily morning brief combining last night's recovery, yesterday's training, and today's scheduled workouts.
User Profile: Store and retrieve default max heart rate, resting heart rate, age, and threshold pace for consistent zone calculations without repeated input.
Integrates with Apple Health via exported data to provide health metrics (sleep analysis, HRV, resting heart rate, steps, active energy) and workouts (e.g., strength, walking, rowing, indoor cycling) from Apple Watch.
Integrates with Garmin Connect to read activities, estimate heart rate and pace zones, create structured workouts, schedule them on the Garmin calendar, and retrieve performance metrics such as race predictions, personal records, VO2max, and training status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DkwtMCP How did I sleep and what's my workout today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
DkwtMCP
Servidor MCP local que conecta Claude Desktop con tus datos de Garmin y Apple Health, para leer tu entrenamiento y recuperación, estimar tus zonas de frecuencia cardíaca y de ritmo, analizar tu rendimiento y crear/programar entrenos estructurados — todo desde una conversación con Claude. Sirve tanto para ciclismo como para running.
Proyecto personal del equipo DkwtMCP. Inspirado en FitMCP, pero de uso local: tus credenciales y datos se quedan en tu ordenador, sin servidor ni suscripciones.
Qué hace
Garmin — entreno y actividades: lee tus actividades y su detalle (con splits por km), estima tus zonas de FC y tus zonas de ritmo, y crea y programa entrenos estructurados por zonas de FC o por ritmo en tu calendario de Garmin.
Garmin — rendimiento y carga: predicciones de carrera (5K/10K/media/maratón), récords personales, VO2max y edad fitness, y estado de entrenamiento con carga aguda/crónica.
Apple Health (vía Apple Watch): datos de salud y recuperación (sueño, HRV, FC en reposo, pasos, energía) y todos tus entrenos del Apple Watch (fuerza, caminata, remo, ciclismo indoor, etc.).
Transversal: cruza lo planificado (Garmin) con lo ejecutado y calcula tu adherencia al plan.
La gracia es que Garmin y Apple no se hablan entre ellos, pero aquí conviven en la misma conversación: puedes preguntar "¿cómo dormí (Apple) y qué entreno me toca hoy (Garmin)?".
Related MCP server: Garmin MCP Server
Avisos importantes
Garmin usa la librería no oficial
python-garminconnect. Funciona muy bien pero es frágil ante cambios de Garmin; la versión está fijada enrequirements.txt. Es para uso personal.Apple Health no tiene API en la nube: los datos se obtienen exportando desde el iPhone (ver más abajo). Es solo lectura.
Este software se ofrece "tal cual", sin garantías. Úsalo con tu propia cuenta y bajo tu responsabilidad.
Requisitos
macOS (probado) o Linux. Windows debería funcionar con ajustes de rutas.
Claude Desktop.
Una cuenta de Garmin Connect.
Python 3.10 o superior — solo para la instalación desde el código (opción B). Con el binario (opción A) no necesitas Python.
(Opcional) Un Apple Watch + la app Health Auto Export para los datos de recuperación/fuerza.
Node.js solo si quieres probar con el MCP Inspector (opcional).
Instalación
Hay dos formas, según tu perfil:
A) Sin conocimientos técnicos (Mac, sin Python): usa el binario ya compilado. Solo tienes que colocar una carpeta, iniciar sesión en Garmin una vez y pegar una línea en Claude Desktop. Sigue la guía paso a paso con capturas:
packaging/GUIA_INSTALACION.pdf. (El binariodkwtmcphay que compilarlo en un Mac una vez conpackaging/build_mac.sh, o pedírselo a quien te comparta el proyecto.)B) Desde el código (desarrolladores, con Python): sigue los pasos de abajo.
C) Con pip, en una línea (si ya tienes Python y solo quieres usarlo) — la más sencilla:
pip install dkwtmcp dkwtmcp login # login de Garmin, una vezEsto instala el comando
dkwtmcp(servidor MCP) ydkwtmcp login. En la config de Claude Desktop pon comocommandla ruta que te devuelvawhich dkwtmcp. Nota: por esta vía no hay.envdel proyecto, así que los ajustes se pasan en el bloqueenvde la config.Para actualizar a la última versión:
pip install --upgrade dkwtmcp.
Instalación desde el código (opción B)
git clone <URL-de-tu-repo> DkwtMCP
cd DkwtMCP
python3 -m venv .venv
source .venv/bin/activate # en Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # y rellena tus valores (ver abajo)Configuración (.env)
Edita .env:
ENABLE_GARMIN=true
ENABLE_APPLE=false # ponlo a true si usas Apple Watch
GARMIN_EMAIL=tu_email@ejemplo.com
GARMIN_PASSWORD=tu_contraseña
APPLE_EXPORT_DIR= # ruta a tu carpeta de exports de Apple (ver sección Apple)Tu .env nunca se sube a git (está en .gitignore).
Login de Garmin (una sola vez)
El servidor no hace login interactivo (se colgaría pidiendo el código 2FA), así que se generan los tokens una vez con un script:
python scripts/garmin_login.pyTe pedirá tu email, contraseña y, si tienes verificación en dos pasos, el código 2FA. Los tokens quedan guardados en ~/.dkwtmcp/garmin/ y se reutilizan en cada arranque. Solo hay que repetirlo si caducan.
Nota: Garmin limita los intentos de login por IP. Si ves un error
429, espera 30–60 minutos (o cambia de red, p. ej. el punto de acceso del móvil) y reintenta.
Sincronización con Apple Health
Apple Health no se puede sincronizar hacia Garmin ni tiene API en la nube. La forma práctica de traer tus datos del Apple Watch (sueño, HRV, FC en reposo, fuerza) es la app Health Auto Export – JSON+CSV (App Store), que exporta automáticamente a una carpeta.
1. Instala y configura Health Auto Export
Instala Health Auto Export – JSON+CSV en el iPhone.
Crea una automatización (o exportación) con estas opciones:
Formato: JSON.
Destino: iCloud Drive (así los archivos aparecen también en tu Mac).
Frecuencia: por ejemplo, diaria.
Métricas de salud — asegúrate de incluir al menos:
Sleep Analysis,Heart Rate Variability,Resting Heart Rate,Heart Rate,Steps,Active Energy.Entrenos (Workouts) — es una categoría aparte. Si quieres ver tus sesiones de fuerza, añade también una exportación de Workouts en JSON al mismo sitio.
Puedes usar dos automatizaciones (una de métricas y otra de workouts) apuntando a subcarpetas dentro de una carpeta común; el MCP las lee de forma recursiva.
Sobre el sueño: el MCP entiende tanto el formato agregado (en minutos) como el detallado por segmentos, y calcula fases (Profundo, Esencial/Core, REM), Vigilia y Tiempo en la cama para que coincidan con la app Salud del iPhone.
2. Apunta APPLE_EXPORT_DIR a la carpeta
Health Auto Export guarda en su propia carpeta de iCloud, cuya ruta en el Mac es del tipo:
/Users/TU_USUARIO/Library/Mobile Documents/iCloud~com~ifunography~HealthExport/DocumentsPon esa carpeta (la que contiene tus subcarpetas de export) en APPLE_EXPORT_DIR, y ENABLE_APPLE=true. El escaneo es recursivo, así que basta con apuntar a la carpeta padre.
iCloud: si tienes activado "Optimizar almacenamiento del Mac", los archivos pueden estar solo en la nube. Haz clic derecho en la carpeta → Descargar ahora para que estén en local.
3. Importa
Los datos de Apple se importan bajo demanda. En una conversación de Claude di "importa mi Apple Salud" (ejecuta apple_import_export), que guarda una base local (SQLite) en ~/.dkwtmcp/apple/.
El import es incremental por defecto: solo procesa los archivos nuevos o cambiados desde la última vez (rápido, ideal para la automatización diaria de Health Auto Export). Si alguna vez quieres reconstruir desde cero, pide un import con full_rebuild.
Perfil de usuario (opcional)
Para no repetirle a Claude tu FC máxima o tu ritmo umbral cada vez, guárdalos en el .env:
USER_MAX_HR=179
USER_THRESHOLD_PACE=4:20
USER_RESTING_HR=
USER_AGE=Las herramientas de zonas (garmin_hr_zones, garmin_pace_zones) usan estos valores por defecto cuando no se los indicas. Consulta lo configurado con fitness_profile.
Conectar a Claude Desktop
En Claude Desktop: Ajustes → Developer → Edit Config (abre
claude_desktop_config.json).Añade el bloque de
mcpServers(verclaude_desktop_config.example.json), ajustando las rutas a tu instalación:
{
"mcpServers": {
"DkwtMCP": {
"command": "/ruta/a/DkwtMCP/.venv/bin/python",
"args": ["-m", "dkwt_mcp.server"],
"cwd": "/ruta/a/DkwtMCP/src",
"env": { "PYTHONPATH": "/ruta/a/DkwtMCP/src" }
}
}
}Cierra Claude Desktop del todo (Cmd+Q) y reábrelo. Deberías ver DkwtMCP en el menú de herramientas.
Usa el Python del entorno virtual (
.venv/bin/python), no el del sistema; si no, no encontrará las dependencias.
Consejo: instrucciones del proyecto
Para que Claude elija bien las herramientas, en tu Proyecto de Claude añade instrucciones tipo: "la recuperación (sueño, HRV, FC reposo) viene de Apple; las actividades, entrenos, zonas (FC y ritmo), rendimiento y carga, de Garmin". Y si eres corredor, indícalo ("entreno running, prográmame por ritmo con sport=running") para que use ritmo en vez de zonas de FC.
Herramientas disponibles
Herramienta | Plataforma | Qué hace |
| Garmin | Recuperación del día (readiness, HRV, sueño, FC reposo, estrés, Body Battery)* |
| Garmin | Últimas actividades con métricas |
| Garmin | Detalle de una actividad |
| Garmin | Desglose de sueño / HRV nocturna* |
| Garmin | Estima tus zonas de FC (Karvonen o %FCmax), filtrando lecturas imposibles |
| Garmin | Estima zonas de ritmo (running) a partir del ritmo umbral |
| Garmin | Parciales (splits) de una actividad con ritmo por km y FC |
| Garmin | Predicciones de tiempo 5K / 10K / media / maratón |
| Garmin | Récords personales (mejores marcas) |
| Garmin | VO2max (correr y ciclismo) y edad fitness |
| Garmin | Estado de entrenamiento, carga aguda/crónica, VO2max y endurance score |
| Garmin | Crea y programa entrenos estructurados: pasos por tiempo o distancia, series con repeticiones, y objetivos de FC, ritmo o potencia (previsualización por defecto) |
| Garmin | Programa varias sesiones de golpe (el plan de la semana o del bloque) |
| Garmin | Listar / borrar entrenos guardados |
| Transversal | Compara plan (entrenos programados) vs. ejecutado y calcula adherencia |
| Transversal | Resumen del periodo: km/horas (Garmin) + sueño/HRV/reposo/pasos (Apple) |
| Transversal | Cruce día a día de entreno vs. recuperación (HRV, sueño, FC reposo) |
| Garmin | Registra peso y composición corporal (para básculas que no sincronizan) |
| Transversal | Evolución de peso, % grasa y músculo (Garmin + Apple) con tendencia |
| Transversal | Brief de la mañana: recuperación de anoche + ayer + plan de hoy |
| Transversal | Genera un cuadro de mando en HTML interactivo: PMC (forma/fatiga/frescura), ACWR, zonas de FC, carga semanal y composición corporal |
| Transversal | Puntúa el esfuerzo de una sesión (RPE 1-10) para calcular la carga por sRPE |
| Apple | Importa tus exports de Apple Health/Health Auto Export a una base local |
| Apple | Sueño (por noche), HRV, FC reposo, pasos, energía en un rango |
| Apple | Entrenos del Apple Watch (fuerza, caminata, remo, etc.) |
| Perfil | Muestra tu perfil (FCmáx, FC reposo, edad, ritmo umbral) del |
| Nutrición | Alta guiada del perfil nutricional (con cribado de seguridad) |
| Nutrición | Muestra el perfil nutricional guardado |
| Nutrición | Pautas generales del día: macros, hidratos según carga y timing pre/intra/post |
* Las métricas de recuperación de Garmin (sueño, HRV, Body Battery…) requieren un reloj/pulsera Garmin; un ciclocomputador Edge no las registra. En ese caso usa las herramientas de Apple.
Ejemplos de uso
Una vez conectado, habla con Claude en lenguaje natural:
Ciclismo / general
"Lista mis últimas 5 actividades de Garmin."
"Estima mis zonas de frecuencia cardíaca."
"Prográmame un 4×5 minutos en Zona 4 para el sábado (primero en previsualización)."
"Móntame el plan de la semana que viene: rodaje Z2 el martes, series el jueves y salida larga el domingo." (
garmin_plan_week)"¿Cumplí el plan esta semana?" (plan vs. ejecutado)
Running
"Estima mis zonas de ritmo, mi umbral es 4:20/km."
"Prográmame un rodaje de 40 min en ritmo fácil el domingo."
"Un 5×1000 m a 4:20-4:30 con 2 min de recuperación, para el martes." (series por distancia, agrupadas como repeticiones)
"¿Cómo dosifiqué mi última carrera? Enséñame los splits."
"¿Qué tiempo predice Garmin para mi media maratón? ¿Y mis récords?"
"¿Cómo va mi estado de entrenamiento y mi carga aguda/crónica?"
Recuperación y fuerza (Apple)
"¿Cómo dormí anoche?"
"¿Cuántos entrenos de fuerza hice en junio y cuánto sumaron?"
Nutrición (orientación general, ver SECURITY.md)
"Créame el perfil nutricional." (
nutrition_setup_profile)"¿Qué debería comer hoy?" / "Hoy tengo salida larga, ¿cómo lo enfoco?" (
nutrition_guidance)
Resúmenes y correlaciones (Garmin + Apple)
"Hazme el resumen de esta semana." (
fitness_weekly_summary)"¿Mi HRV baja los días que entreno duro?" / "¿Duermo peor tras la fuerza?" (
fitness_recovery_vs_training)"Apunta mi medición de hoy: 89 kg, 38% de grasa, 30 kg de músculo." (
garmin_add_body_composition)"¿Cómo va mi peso y mi % de grasa estos 3 meses?" (
fitness_body_composition)"Dame el brief de hoy: ¿cómo vengo y qué me toca?" (
fitness_daily_brief)"Genérame el cuadro de mando." (
fitness_dashboard— crea el HTML endashboard/en segundos)
Seguridad en escritura
Las herramientas que escriben en Garmin llevan confirmación: garmin_schedule_workout usa dry_run (por defecto solo previsualiza) y garmin_delete_workout requiere confirm=true.
Los tres flujos del día a día
Brief de la mañana — fitness_daily_brief
"Dame el brief de hoy."
El vistazo antes de decidir si entrenas y cómo:
Recuperación de anoche: sueño, HRV y FC en reposo. Se fija en la noche de hoy; si el reloj aún no ha sincronizado devuelve
null, nunca la noche anterior disfrazada de anoche.Ayer y lo que llevas hoy: actividades de Garmin más entrenos del Apple Watch.
Planificado para hoy, por este orden: lo ya entrenado → lo programado en Garmin → el plan semanal local (
fitness_set_week_plan) → tu calendario habitual.
Cuadro de mando — fitness_dashboard
"Genérame el cuadro de mando."
Rellena una plantilla HTML con tus datos y devuelve la ruta del archivo. Se genera en segundos (frente a los minutos que tarda si le pides a Claude que dibuje el HTML desde cero en la conversación).
Dónde queda:
dashboard/cuadro_mando.htmlen el proyecto; si esa ruta no existe o no es escribible (por ejemplo con el binario o instalado porpip), va a~/.dkwtmcp/dashboard/. Puedes forzar otra conoutput_path.Qué incluye: PMC (forma/fatiga/frescura con CTL, ATL y TSB), ACWR, carga semanal por sRPE, reparto por zonas de FC y composición corporal.
Modos (
focus):completo(por defecto),entrenos(oculta el bloque de peso y composición) yrecomp(lo destaca). Basta con decirlo en lenguaje natural: "el cuadro de mando, solo entrenos".La carga usa sRPE (RPE × minutos), que sirve igual para fuerza y para e-bike. Puntúa las sesiones con
fitness_log_rpepara que el PMC sea fiel.
Perfil nutricional — nutrition_setup_profile → nutrition_guidance
"Créame el perfil nutricional." y luego "¿qué debería comer hoy?"
El alta es una entrevista guiada que empieza por el cribado de salud y solo después pregunta objetivo, patrón alimentario, alergias, horarios y entrenamiento. Se previsualiza (dry_run=true) antes de guardar en ~/.dkwtmcp/nutrition/profile.json.
Solo para personas adultas. Por debajo de 18 años no da pautas y deriva a pediatría o a un dietista-nutricionista: en crecimiento las necesidades son otras y es la etapa de mayor riesgo de trastorno alimentario.
Derivación en dos niveles. Ciertas condiciones (enfermedad renal, diabetes, anticoagulantes, TCA, embarazo, lactancia y otras) bloquean las pautas y derivan a un profesional; otras (hipertensión leve, colesterol, SOP, tiroides controlado…) las permiten con un aviso reforzado. Si mencionas una condición nueva en la conversación, pásala en
condiciones_hoyy se vuelve a comprobar.Solo patrones con respaldo científico: mediterráneo, comida real, DASH, nórdico y flexitariano, con modificadores (baja en hidratos moderada, vegetariano, vegano, ayuno intermitente moderado). Los estilos sin aval (keto estricta, carnívora, detox, alcalina, ayuno prolongado…) se reconducen al equivalente razonable en vez de aplicarse.
Qué devuelve
nutrition_guidance: rango de proteína (con el porqué), estrategia de hidratos según el tipo de día, mínimo de grasa, timing pre/intra/post y principios de calidad. El tipo de día se deduce con la misma prioridad que el brief y se expone entipo_dia_detectado_por, así que sabes si es un hecho o una previsión.Lo que nunca hace: calcular calorías, prohibir alimentos, proponer compensar excesos con restricción o ejercicio extra, ni aceptar objetivos por debajo de un IMC saludable.
Es orientación general de estilo de vida, no asesoramiento médico ni nutricional individualizado. Ver
SECURITY.md.
Probar sin Claude Desktop (opcional)
Con el MCP Inspector:
cd src
npx @modelcontextprotocol/inspector python -m dkwt_mcp.serverCompartir con otra persona
En packaging/ hay lo necesario para generar un binario de macOS autocontenido (con PyInstaller) que no requiere Python en el ordenador de destino, pensado para alguien sin conocimientos técnicos. Cada persona usa su propia cuenta de Garmin. Ver packaging/GUIA_INSTALACION.pdf.
Genéralo con bash packaging/build_mac.sh (resultado en dist/dkwtmcp). Notas:
El binario no lee el
.envdel proyecto. Trae Garmin, el cuadro de mando y la nutrición pública (las tresnutrition_*); Apple queda desactivado, y el módulo de nutrición personal no se incluye nunca (--exclude-module). Si hace falta configurar algo, se pasa por el bloqueenvde la config de Claude Desktop (verpackaging/claude_desktop_config.companero.json).Cada persona genera su propio perfil nutricional en su ordenador (
~/.dkwtmcp/nutrition/profile.json); no viaja dentro del binario.Hay que recompilarlo cada vez que quieras que la otra persona reciba mejoras: no se actualiza solo.
Para comprobar que un binario recién hecho responde, sin depender de otras herramientas:
{ printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"cli","version":"1"}}}' \ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"fitness_profile","arguments":{"params":{}}}}' ; sleep 8; } | ./dist/dkwtmcp 2>/dev/null
Solución de problemas
DkwtMCP no aparece en Claude Desktop.
Revisa que en claude_desktop_config.json la ruta a Python sea la del entorno virtual (.venv/bin/python) y que cwd/PYTHONPATH apunten a src. Cierra Claude del todo (Cmd+Q) y reábrelo; recargar la ventana no basta.
Cambié el código y no veo el cambio. El servidor MCP se carga al arrancar Claude Desktop. Tras editar código, cierra y reabre Claude Desktop. Si tocaste datos de Apple, vuelve a importar ("importa mi Apple Salud").
Login de Garmin: error 429.
Garmin limita los intentos por IP. Espera 30–60 minutos sin reintentar, o cambia de red (p. ej. el punto de acceso del móvil) y repite el login.
Login de Garmin falla / dejó de funcionar.
Los tokens pueden caducar, o Garmin puede haber cambiado su sistema (la librería es no oficial). Vuelve a ejecutar python scripts/garmin_login.py. Si sigue fallando, comprueba si hay una versión nueva de garminconnect.
Las métricas de recuperación de Garmin (sueño, HRV, Body Battery) salen vacías. Esas las mide un reloj/pulsera Garmin en la muñeca; un ciclocomputador Edge no las registra. Si llevas Apple Watch, usa las herramientas de Apple para la recuperación.
Apple: "no hay datos importados".
Ejecuta primero apple_import_export ("importa mi Apple Salud"). El import borra y reconstruye la base cada vez.
Apple: no encuentra la carpeta de exports.
Health Auto Export guarda en su propia carpeta de iCloud (.../iCloud~com~ifunography~HealthExport/Documents). Apunta APPLE_EXPORT_DIR ahí. Si usas iCloud con "Optimizar almacenamiento", haz clic derecho en la carpeta → Descargar ahora.
Herramientas de running (predicciones, récords, estado) salen con campos vacíos.
Requieren un reloj Garmin con esos datos calculados y actividades recientes. Si algún campo sale null pese a tenerlo en Garmin, es cosa del parseo: ábrelo con response_format: "json" y repórtalo.
Preguntas frecuentes (FAQ)
¿Necesito saber programar o tener Python? Para la vía del binario (opción A) no. Para instalar desde el código (opción B) sí necesitas Python.
¿Funciona con el plan gratuito de Claude? Sí. Los MCP locales por archivo de configuración funcionan en Claude Desktop, también en el plan Free.
¿Se suben mis datos a algún sitio?
No. Todo es local: tus credenciales van en .env (nunca al repo) y los datos se guardan en ~/.dkwtmcp/ de tu ordenador. No hay servidor.
¿Puedo compartirlo? ¿Y usarlo varias personas? Sí. El código se comparte; cada persona usa su propia cuenta de Garmin (su propio login y tokens).
¿Sirve para ciclismo y para running? Para ambos. Ciclismo por zonas de FC/potencia; running por zonas de ritmo, con análisis de rendimiento y carga.
¿Soporta Strava? No por ahora. Sus términos (2025) prohíben usar sus datos en IA, así que se retiró del alcance.
¿Por qué puede dejar de funcionar Garmin de repente? Usa una librería no oficial; si Garmin cambia su sistema de acceso, puede romperse hasta que la librería se actualice. Es un riesgo asumido de un proyecto personal.
¿Cada cuánto tengo que importar los datos de Apple? Cuando quieras refrescar. Con una automatización de Health Auto Export que deje los archivos en la carpeta, basta con volver a decir "importa mi Apple Salud".
¿Funciona en Windows? Debería, ajustando rutas. Está probado en macOS.
Estructura del proyecto
DkwtMCP/
├── src/dkwt_mcp/
│ ├── app.py # instancia FastMCP
│ ├── server.py # entrypoint (stdio)
│ ├── cli.py / login.py # login de Garmin y arranque
│ ├── config.py # configuración desde .env
│ ├── common.py # utilidades (errores, formato)
│ └── providers/
│ ├── garmin.py # herramientas garmin_*
│ ├── apple.py # herramientas apple_*
│ └── fitness.py # herramienta transversal fitness_*
├── scripts/garmin_login.py
├── packaging/ # binario y guía para compartir
├── requirements.txt
├── .env.example
└── claude_desktop_config.example.jsonDesarrollo y tests
El proyecto incluye una batería de tests (funciones puras de parseo y construcción de entrenos) que se ejecutan en cada push mediante GitHub Actions.
pip install -r requirements-dev.txt
pytest -qContribuir
Las aportaciones son bienvenidas: lee CONTRIBUTING.md para el entorno de desarrollo y las convenciones del proyecto.
Importante: al abrir un issue no incluyas credenciales, tokens ni datos de salud reales. Ver SECURITY.md para cómo se tratan tus datos y cómo reportar un problema de seguridad.
Licencia
Publicado bajo licencia MIT — ver LICENSE. Puedes usarlo, modificarlo y distribuirlo libremente, conservando el aviso de copyright (el crédito a la autora).
Cómo citar
Si usas este proyecto, cítalo por favor. GitHub mostrará un botón "Cite this repository" gracias a CITATION.cff. En resumen:
Infantes, N. (2026). DkwtMCP – MCP local para Garmin y Apple Health.
Aviso legal
Proyecto personal, sin relación con Garmin ni Apple. Usa una librería no oficial para Garmin; su funcionamiento puede romperse si Garmin cambia su sistema. No hay garantía de ningún tipo. Tú eres responsable del uso que hagas de tus propias cuentas y datos.
Available Tools
22 toolsfitness_body_compositionARead-onlyIdempotent
Evolucion de peso, % de grasa y masa muscular/magra en un periodo.
Lee de Garmin (bascula / entradas manuales) y de Apple Health, y muestra los valores por fecha mas la tendencia (diferencia entre el primero y el ultimo). Pensado para seguimiento mensual, no para pesarse a diario.
Args: params: start (YYYY-MM-DD), end? (por defecto start+6 dias; usa un rango amplio, p. ej. 3 meses, para ver tendencia), response_format.
Returns: str: series por fecha y tendencias de peso/grasa/musculo; o "Error: ...".
Inputs: params (required). Returns: result
fitness_daily_briefARead-onlyIdempotent
Resumen de la mañana: como vienes de recuperacion y que tienes planificado hoy.
Junta en una sola llamada: recuperacion de anoche (HRV, sueño y FC reposo de Apple, con Garmin como respaldo), lo que entrenaste ayer, y los entrenos que tengas programados para hoy en Garmin.
Args: params: date? (YYYY-MM-DD, por defecto hoy), response_format.
Returns: str: brief del dia; o "Error: ...".
Inputs: params (required). Returns: result
fitness_planned_vs_actualARead-onlyIdempotent
Compara los entrenos PLANIFICADOS con las actividades REALMENTE ejecutadas en un rango de fechas, y calcula la adherencia al plan.
"Planificado" = solo entrenos estructurados de tu biblioteca que hayas programado (no las actividades ya completadas que Garmin lista en el calendario). El cruce es por dia: si un dia tenia entreno programado y hubo actividad, se considera cumplido; si habia plan y no hubo actividad, no realizado; si hubo actividad sin plan, extra.
Args: params: start (YYYY-MM-DD), end? (YYYY-MM-DD, por defecto = start), response_format (markdown|json).
Returns: str: resumen con dias planificados, cumplidos, no realizados y extra, porcentaje de adherencia, y el detalle por dia; o "Error: ...".
Inputs: params (required). Returns: result
fitness_profileARead-onlyIdempotent
Muestra el perfil configurado (FCmax, FC reposo, edad, ritmo umbral).
Estos valores se guardan en el .env (USER_MAX_HR, USER_RESTING_HR, USER_AGE, USER_THRESHOLD_PACE) y los usan por defecto las herramientas de zonas cuando no se los indicas explicitamente. Asi no tienes que repetirlos cada vez.
Args: params: response_format (markdown|json).
Returns: str: los valores del perfil, o un aviso de que estan sin configurar.
Inputs: params (required). Returns: result
fitness_recovery_vs_trainingARead-onlyIdempotent
Cruza, dia a dia, lo que entrenaste (Garmin + Apple) con tu recuperacion (HRV, sueño y FC en reposo de Apple).
Sirve para ver correlaciones: si la HRV baja tras dias duros, si duermes peor los dias de fuerza, etc. Requiere Apple importado para la recuperacion.
Args: params: start (YYYY-MM-DD), end? (por defecto start+6 dias), response_format.
Returns: str: tabla por dia con entreno y metricas de recuperacion; o "Error: ...".
Inputs: params (required). Returns: result
fitness_weekly_summaryARead-onlyIdempotent
Resumen de entrenamiento y recuperacion de un periodo (por defecto una semana).
Cruza Garmin (actividades, km, horas) con Apple (sueño medio, HRV media, FC reposo media, pasos, entrenos de fuerza). Requiere haber importado Apple para la parte de recuperacion.
Args: params: start (YYYY-MM-DD), end? (por defecto start+6 dias), response_format.
Returns: str: resumen agregado del periodo; o "Error: ...".
Inputs: params (required). Returns: result
garmin_activity_splitsARead-onlyIdempotent
Devuelve las vueltas (laps) de una actividad con su ritmo, FC y distancia.
Util para ver como dosifico un corredor. Nota: usa las VUELTAS de la actividad; si el reloj tiene auto-lap cada km, saldra el ritmo km a km. Si la actividad no tiene vueltas (no se pulso lap ni hay auto-lap), saldra como un unico tramo.
Args: params: activity_id (str), response_format (markdown|json).
Returns: str: lista de splits con distancia_km, tiempo, ritmo (min/km) y FC media; o "Error: ...".
Inputs: params (required). Returns: result
garmin_add_body_compositionA
Guarda en Garmin Connect una medicion de peso y composicion corporal.
Util si tu bascula no se sincroniza con ninguna app: le dictas los valores y
quedan registrados en Garmin, donde luego los lee fitness_body_composition
para ver la evolucion.
SEGURIDAD: por defecto NO escribe (dry_run=True): devuelve una previsualizacion. Llama con dry_run=False para guardarlo.
Args: params: weight_kg (obligatorio), date?, time?, body_fat_pct?, water_pct?, muscle_mass_kg?, bone_mass_kg?, visceral_fat?, bmi?, basal_met_kcal?, metabolic_age?, dry_run, response_format.
Returns: str: previsualizacion de lo que se guardaria, o confirmacion del registro; o "Error: ...".
Inputs: params (required). Returns: result
garmin_daily_readinessARead-onlyIdempotent
Resume la recuperacion de un dia: training readiness, HRV, sueño, FC reposo, estres y Body Battery. La herramienta clave para decidir si empujar o descansar.
Args: params: date (YYYY-MM-DD), response_format (markdown|json).
Returns: str: dict con readiness_score, fc_reposo, estres_medio, body_battery_min/max, sueño_score, sueño_horas, hrv_media_noche; o "Error: ...".
Inputs: params (required). Returns: result
garmin_delete_workoutADestructiveIdempotent
Borra un entreno guardado de tu biblioteca de Garmin.
SEGURIDAD: requiere confirm=True. Sin confirmacion no borra nada.
Args: params: workout_id (str), confirm (bool), response_format (markdown|json).
Returns: str: confirmacion de borrado o aviso de que falta confirmar; o "Error: ...".
Inputs: params (required). Returns: result
garmin_fitness_metricsBRead-onlyIdempotent
VO2max (correr y ciclismo) y edad fitness de Garmin.
Args: params: date? (YYYY-MM-DD, por defecto hoy), response_format (markdown|json).
Returns: str: vo2max_running, vo2max_cycling y edad_fitness; o "Error: ...".
Inputs: params (required). Returns: result
garmin_get_activitiesARead-onlyIdempotent
Lista las ultimas actividades registradas con sus metricas resumidas.
Args: params: limit (1-50), response_format (markdown|json).
Returns: str: lista con id, nombre, tipo, fecha, distancia_m, duracion_s, fc_media, potencia_media_w; o "Error: ...".
Inputs: params (required). Returns: result
garmin_get_activityARead-onlyIdempotent
Devuelve el detalle de una actividad concreta de Garmin.
Args: params: activity_id (str), response_format (markdown|json).
Returns: str: metricas clave (distancia, duracion, desnivel, FC media/max, potencia, calorias, VO2max, training effect); o "Error: ...".
Inputs: params (required). Returns: result
garmin_hrvARead-onlyIdempotent
Variabilidad de la frecuencia cardiaca (HRV) de la noche indicada.
Args: params: date (YYYY-MM-DD), response_format (markdown|json).
Returns: str: dict con media de la ultima noche, media semanal, estado (balanced/ unbalanced/low) y rango base; o aviso si el dispositivo no reporta HRV.
Inputs: params (required). Returns: result
garmin_hr_zonesARead-onlyIdempotent
Estima tus zonas de frecuencia cardiaca (Z1-Z5) a partir de tus datos.
Determina la FC maxima por prioridad: max_hr (si lo das) > mayor FC max observada en tus ultimas actividades > formula de Tanaka (208 - 0.7*edad). Usa la FC de reposo de Garmin. Calcula las zonas por Karvonen (FC reserva) o por %FCmax.
OJO e-bike: con bici electrica cuesta llegar a la FC maxima real, asi que la estimacion observada puede quedarse corta. Un test de campo o dar tu max_hr real da mejores zonas. Esta tool NO escribe en Garmin: las zonas se configuran a mano en Garmin Connect (Ajustes de usuario > Zonas de FC).
Args: params: max_hr?, age?, scan_activities (1-100), method (karvonen|hrmax), response_format (markdown|json).
Returns: str: FCmax y FC reposo usadas, metodo, fuente de la FCmax, y la tabla de zonas Z1-Z5 con su rango en ppm; o "Error: ...".
Inputs: params (required). Returns: result
garmin_list_workoutsARead-onlyIdempotent
Lista los entrenos guardados en tu biblioteca de Garmin (con su id).
Util para obtener el workout_id que necesitan garmin_schedule_workout (reprogramar) o garmin_delete_workout.
Args: params: limit (1-100), response_format (markdown|json).
Returns: str: lista con id, nombre, deporte y duracion_s; o "Error: ...".
Inputs: params (required). Returns: result
garmin_pace_zonesARead-onlyIdempotent
Estima las zonas de ritmo de carrera (Z1-Z5) a partir del ritmo umbral.
Si das threshold_pace lo usa; si no, intenta leer tu umbral de lactato de Garmin. Las zonas se calculan como multiplos del ritmo umbral (modelo clasico de 5 zonas).
Args: params: threshold_pace? ('M:SS'/km), response_format (markdown|json).
Returns: str: ritmo umbral usado y la tabla de zonas Z1-Z5 con su rango de ritmo (min/km); o "Error: ...".
Inputs: params (required). Returns: result
garmin_personal_recordsBRead-onlyIdempotent
Lista tus records personales de Garmin (mejores marcas).
Args: params: response_format (markdown|json).
Returns: str: lista de records con tipo, valor y fecha; o "Error: ...".
Inputs: params (required). Returns: result
garmin_race_predictionsARead-onlyIdempotent
Predicciones de tiempo de Garmin para 5K, 10K, media maraton y maraton.
Args: params: response_format (markdown|json).
Returns: str: tiempos estimados por distancia; o "Error: ...".
Inputs: params (required). Returns: result
garmin_schedule_workoutA
Crea un entreno estructurado y lo programa en una fecha del calendario de Garmin.
SEGURIDAD: por defecto NO escribe (dry_run=True): devuelve una previsualizacion. Para crear y programar de verdad, hay que llamar con dry_run=False.
Cada paso tiene un tipo (warmup/interval/recovery/cooldown/rest), una duracion en minutos y un objetivo opcional:
ciclismo: ZONA DE FC (hr_zone 1-5) o rango de FC (hr_min/hr_max) o potencia.
correr (sport='running'): RITMO en 'M:SS' por km (pace_fast/pace_slow), o zona/rango de FC.
Args: params: date (YYYY-MM-DD), sport (por defecto cycling), name, steps[], description?, dry_run, response_format (markdown|json).
Returns: str: en dry_run, la previsualizacion (pasos + duracion estimada). Si se ejecuta de verdad, el workout_id creado y la confirmacion de programacion; o "Error: ...".
Inputs: params (required). Returns: result
garmin_sleepARead-onlyIdempotent
Desglose del sueño de una noche: fases, duracion total y puntuacion.
Args: params: date (YYYY-MM-DD), response_format (markdown|json).
Returns: str: dict con horas totales, fases (profundo/ligero/rem/despierto en horas), score y FC/respiracion media si estan disponibles; o "Error: ...".
Inputs: params (required). Returns: result
garmin_training_statusARead-onlyIdempotent
Estado de entrenamiento, carga aguda/cronica, VO2max y endurance score.
Reune training status (estado, carga aguda, ratio agudo/cronico), VO2max y, si estan disponibles, endurance score y hill score.
Args: params: date? (YYYY-MM-DD, por defecto hoy), response_format (markdown|json).
Returns: str: dict con estado de entrenamiento y metricas de carga; o "Error: ...".
Inputs: params (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Most tools target distinct metrics (readiness, sleep, HRV, zones, activities, workouts, body composition), but there is minor overlap between garmin_fitness_metrics and garmin_training_status (both include VO2max) and between fitness_weekly_summary and fitness_recovery_vs_training. Descriptions are detailed enough to guide selection.
Naming mixes prefixes 'garmin_' and 'fitness_' with inconsistent patterns: nouns ('garmin_sleep'), verb_noun ('garmin_get_activities'), and multi-word descriptors ('fitness_recovery_vs_training'). No uniform convention, but still readable.
22 tools is on the higher side for a single server, but each serves a distinct purpose within the fitness/health domain. The count is justifiable given the comprehensive coverage of data retrieval, analysis, and workout management.
The tool surface covers data retrieval, workout scheduling, and analysis, with CRUD for workouts. Minor gaps: no manual input tools for sleep or HRV, and activities are read-only. However, core training and recovery workflows are well-supported.
Related MCP Connectors
Adaptive running coach MCP server — training data, plans, and recovery for AI assistants.
tri-train is a training platform for triathletes that syncs activities from Strava and Garmin and exposes them to Claude through a remote MCP server. Ask Claude how your last block went, why your run pace dropped, or whether you are fresh enough for Sunday's race, and it answers from your real data: activities with laps and grade-adjusted pace, weekly load and the performance management chart (CTL/ATL/TSB), sleep, HRV and resting heart rate, and your race calendar with predictions. Claude can also act: create and adjust planned workouts with structured intervals, push them to your Garmin watch, add races and write notes. Every change is journaled and can be undone. Read and write access are separate OAuth scopes, and the server enforces them on every call. Built and hosted in Switzerland by a triathlete; data stays on our own servers (Swiss revDSG / GDPR).
Apple Health training load, recovery, HRV and workout detail for Claude, ChatGPT and any MCP client.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that connects Garmin Connect data to Claude, enabling training analysis, recovery checks, and personalized plans based on real metrics like HRV, training load, and activities.24MIT
- AlicenseNot gradedqualityDmaintenanceA local, read-only MCP server that allows Claude Desktop to access Garmin Connect data such as activities and recovery metrics, enabling AI-assisted running plan creation and adjustment.233 npmMIT
- AlicenseAqualityDmaintenanceA read-only MCP server that gives Claude Desktop access to your Garmin Connect data — daily health metrics, sleep, activities, training status, and body composition.6MIT
- AlicenseNot gradedqualityBmaintenanceA local, single-user, read-only MCP server that gives Claude Code access to your Garmin health and training data, exposing tools for health snapshots, training status, run details, body metrics, and training analysis.1MIT