Futureweb Intervals MCP
Servidor MCP de Intervals.icu autoalojado para ChatGPT y Claude: análisis de entrenamiento (plan vs ejecución, carga, intensidad, recuperación, alimentación, durabilidad), todos los campos personalizados y flujos de datos, datos de Garmin. Solo lectura por defecto, OAuth integrado, GPL-3.0.
Documentación
![]()
Futureweb Intervals MCP
Servidor MCP avanzado de Intervals.icu para ChatGPT, Claude y cualquier cliente MCP: métricas enriquecidas con Garmin, todos los campos y flujos personalizados, información de recuperación y análisis de rendimiento de resistencia.
Un servidor de Model Context Protocol que permite a los asistentes de IA leer y analizar tus datos de entrenamiento de Intervals.icu como lo haría un entrenador: actividades con todos los campos y flujos personalizados, intervalos, bienestar frente a líneas base personales, umbrales y zonas, entrenamientos planificados frente a ejecutados, ascensos, medidores de potencia duales, mejores esfuerzos, eficiencia y resistencia a la fatiga, nutrición y peso, resúmenes de entrenamiento y el calendario. Se ejecuta donde tú lo ejecutes, solo habla con la API de Intervals.icu y no expone nada que escriba a menos que lo habilites.
Continuación de mvilanova/intervals-mcp-server. El proyecto original ya no se desarrolla activamente (último commit el 2 de agosto de 2026, 29 pull requests abiertas). Este fork mantenido por la comunidad lo continúa: las pull requests abiertas útiles fueron revisadas y fusionadas con crédito a sus autores, los errores corregidos y el servidor reconstruido en torno al análisis de entrenamiento, datos de Garmin y acceso remoto seguro. No está afiliado a Intervals.icu ni a Garmin.
Proyecto complementario: el Garmin Intervals Bridge restaura las métricas que Garmin elimina de los archivos que envía a Intervals.icu (resistencia, efecto de entrenamiento, tiempo de recuperación, VO₂max, dinámica de carrera, detalles de sueño y HRV…). Este MCP está diseñado para leer todo eso, pero funciona igualmente bien sin el bridge.
Contenido
- Aspectos destacados
- Funciona con el Garmin Intervals Bridge
- Herramientas
- Inicio rápido
- Conectar un cliente de IA
- Compartir el servidor con amigos
- Configuración
- Permisos y seguridad
- Estado del proyecto y hoja de ruta
- Documentación
- Desarrollo
- Créditos y licencia
Aspectos destacados
- Cada elemento personalizado, resuelto dinámicamente. Los campos personalizados de actividades, campos de intervalos, flujos y campos de bienestar se leen de tus propias definiciones y se informan con nombre, código, valor y unidades. Nada específico del dispositivo está codificado; null, NaN, cero y ausente permanecen distintos, los campos que no pertenecen al deporte se mantienen separados y las cargas del dispositivo nunca se mezclan con la carga de Intervals.icu.
- Flujos a resolución completa. Cualquier flujo como resumen, CSV o JSON, segmentado por índice o tiempo, reducido de muestreo y paginado, además de estadísticas por intervalo de cualquier flujo (por ejemplo, la caída de resistencia de cada intervalo).
- Análisis de entrenamiento en lugar de volcados brutos. Informe de actividad en una sola llamada, planificado frente a ejecutado por paso (también para eventos eliminados y recorridos extendidos más allá del plan), ascensos y descensos, verificación del segundo medidor de potencia, mejores esfuerzos, intervalos similares, entrenamientos repetidos a lo largo del tiempo, eficiencia potencia-frecuencia cardíaca, resistencia a la fatiga, carga de entrenamiento (relación agudo:crónico, monotonía, tensión), distribución de intensidad en tres zonas con índice de polarización, durabilidad aeróbica, proyección de carga sobre el plan, instantánea de recuperación con líneas base de 42 días, tendencias y correlaciones de bienestar, tendencias de nutrición y peso, resúmenes semanales y mensuales. Estadísticas con sus tamaños de muestra; la interpretación queda para el entrenador.
- Eficiente en tokens.
detail_level(compact,standard,full) youtput_format="json"en las herramientas pesadas, nueve indicaciones de entrenamiento listas y dos recursos MCP. - Acceso remoto seguro. Servidor OAuth 2.1 integrado con inicio de sesión "Continuar con
Intervals.icu", página de consentimiento con permisos por conexión, documentos de metadatos de
cliente con
private_key_jwt(ChatGPT), PKCE y RFC 9207. HTTP transmisible (/mcp) y SSE desde un solo proceso. - Solo lectura por defecto. Las herramientas se agrupan en clases de permisos (
read,write,destructive,admin) aplicadas en el servidor; soloreadestá activa a menos que habilites más. - Probado. Más de 400 pruebas con datos sintéticos, ruff, mypy, CodeQL, GitHub Actions fijadas, pruebas de compilación y smoke tests de Docker en cada pull request.
Funciona con el Garmin Intervals Bridge
Garmin device ──► Garmin Connect ──► official sync ──► Intervals.icu activity (filtered FIT)
│ ▲
└── Garmin Intervals Bridge ──────────┘ restores custom fields, streams, wellness
│
Futureweb Intervals MCP (this project)
│
ChatGPT / Claude / any MCP client
El Garmin Intervals Bridge escribe las métricas que Garmin filtra en los campos personalizados de actividad, flujos personalizados y campos de bienestar que definiste en Intervals.icu. El MCP lee esas definiciones en tiempo de ejecución, por lo que cada valor restaurado aparece automáticamente en las herramientas:
| Restaurado por el bridge | Dónde lo muestra el MCP |
|---|---|
| Efecto de entrenamiento, EPOC, carga de entrenamiento de Garmin, tiempo de recuperación, VO₂max, condición de rendimiento, resistencia inicio/fin, pérdida de sudor, temperaturas | get_activity_details, get_activity_report, get_training_summary, get_training_load (cargas del dispositivo separadas de la carga de Intervals.icu), get_fueling_analysis (pérdida de sudor por hora), get_activity_data_audit (qué campos aún tienen un marcador de cero o ningún valor) |
| Resistencia y resistencia potencial, segundo medidor de potencia, velocidad ajustada por pendiente, selección de marchas, flujos de dinámica de carrera | get_activity_streams, get_activity_intervals, analyze_workout_execution, analyze_climbs, compare_power_streams |
| SpO₂ nocturna, respiración, frecuencia cardíaca durante el sueño, detalles de HRV, Body Battery, etapas de sueño y estrés, disposición, nutrición | get_wellness_data, get_recovery_snapshot, get_wellness_trends, get_nutrition_summary |
El MCP nunca contacta con Garmin; el bridge es opcional y otros dispositivos o herramientas de sincronización que llenen elementos personalizados reciben el mismo tratamiento. Ejemplos prácticos y notas sobre cómo leer las métricas del dispositivo correctamente: docs/GARMIN_BRIDGE.md.
Herramientas
67 herramientas; 52 de ellas solo leen. Las herramientas de escritura están marcadas con ✎ (write), ✖ (destructive) o
⚙ (admin) y están ocultas a menos que su clase esté habilitada. La mayoría de las herramientas aceptan output_format="json"
y detail_level (compact primero). Las herramientas nunca toman una clave de API: las credenciales provienen solo del
entorno del servidor.
El catálogo se mantiene pequeño para el cliente de IA: descripciones cortas que dicen cuándo usar
una herramienta, una descripción y (donde los valores son fijos) un enum para cada parámetro, y
resultados de texto sin una copia estructurada duplicada. Los detalles de métodos y el formato de
entrenamiento viven en recursos MCP (intervals://methods/<topic>, intervals://workout-syntax) y en get_guide(topic) para clientes
que solo llaman herramientas. tools/list es de aproximadamente 22.7k tokens en MCP_PERMISSIONS=read,write
(antes 42.0k; cl100k); consulta Conjuntos de herramientas para un conjunto más pequeño.
Análisis de actividad
| Herramienta | Qué hace |
|---|---|
get_activity_report | Análisis completo en una llamada: resumen con combustible (carbohidratos usados/ingeridos por hora, pérdida de sudor, energía), clima (temperatura, sensación térmica, viento, proporción de viento en contra/a favor), balance de W′ (agotamiento máximo, tiempo por debajo del 75/50/25 % de W′), plan frente a ejecución o intervalos, verificación del segundo medidor de potencia, ascensos, notas de calidad de datos (fuente, tiempos de carga y análisis, paradas de grabación, marcadores de cero); include_route_history compara actividades anteriores en la misma ruta de Intervals.icu (tiempo, potencia, W/kg, FC, clima, resistencia); detail_level compacto (números centrales, una línea de contexto y hallazgos clave, aproximadamente 2-2.5k caracteres), estándar o completo |
get_activity_data_audit | Procedencia y calidad de datos de una actividad: fuente y archivo (sincronización de Garmin, exportación de Garmin o carga del bridge, stub de Strava), tiempos de carga y análisis, duplicados filtrados, paradas de grabación y vacíos, vueltas FIT frente a intervalos y ediciones manuales, identidad del dispositivo y sensores, flujos habituales para el deporte pero faltantes, cobertura por flujo, campos personalizados con valor / marcador de cero / ninguno y qué podría llenar el Garmin Intervals Bridge; sin una actividad, la cobertura de datos por deporte de un período |
analyze_workout_execution | Planificado frente a ejecutado por paso (duración, adherencia al objetivo, tiempo en rango, respuesta de FC, caída, deriva Pw:FC con el signo de desacoplamiento de Intervals.icu, resistencia). Un paso puede abarcar cualquier número de vueltas; con auto-vueltas del dispositivo, los límites de paso dentro de las vueltas se colocan en el cambio de intensidad (las pulsaciones de vuelta se conservan), los pasos sin vuelta propia se encuentran entre sus vecinos, y una advertencia con alignment_confidence dice hasta qué punto se pueden confiar los resultados por paso. Los objetivos abiertos (zona superior) son límites inferiores, los pasos de distancia se comparan por distancia. Los pasos se limitan a su duración planificada, los intervalos más largos se dividen para el análisis, y el recorrido más allá del plan se informa por separado con su carga y esfuerzos adicionales. Tolerancias para desplazamiento de inicio, pausas y longitud de paso; planned_workout_doc para eventos eliminados; eventos coincidentes sugeridos solo lectura |
analyze_climbs | Ascensos, descensos y pausas con potencia, NP, FC, VAM y flujos personalizados por segmento; pendiente suavizada sobre una ventana de distancia (pendiente bruta opcional), confianza de pendiente alta/media/baja por segmento (sin pendiente por debajo de la distancia horizontal mínima, bruta incluida), pausas reales frente a movimiento lento, perfiles de deporte para ciclismo, carrera y senderismo, indicadores de calidad de datos |
compare_power_streams | Comparación alineada por muestras de dos medidores de potencia: desfase, bandas de potencia, ventanas estables, deriva, retraso; sin activity_id (rango de fechas o activity_ids) cada recorrido con un segundo flujo de potencia se compara por sí mismo y se resume por bicicleta, interior/exterior, medidor principal y segunda fuente de potencia con n, mediana, DE entre recorridos y rango (general, por banda de potencia, ventanas estables), deriva, retraso, valores atípicos y recorridos lejos de la mediana; nunca un factor de corrección |
get_best_efforts | Mejores esfuerzos de una actividad por duraciones o distancias, con sus ventanas de tiempo transcurrido (índice final exclusivo); las ventanas que cruzan una pausa de grabación se marcan |
get_activity_histogram | Distribución de tiempo de potencia, frecuencia cardíaca, ritmo o GAP |
Actividades y flujos
| Herramienta | Qué hace |
|---|---|
get_activities | Lista con filtros de deporte, equipo y medidor de potencia, ordenación, paginación, salida compacta o JSON; sin start_date los 30 días antes de end_date (o hoy) |
get_activity_details | Resumen, umbrales utilizados (FTP, eFTP, LTHR, zonas), dispositivo y medidor de potencia, dinámica de carrera, cada campo personalizado con unidades, combustible, clima, balance de W′ y fuente/frescura |
get_activity_intervals | Intervalos y grupos, campos personalizados de intervalos, estadísticas por intervalo de cualquier flujo, opcionalmente el tipo de paso planificado junto al tipo de Intervals.icu |
list_activity_streams, get_activity_streams | Descubrir y obtener cualquier flujo: resumen, CSV o JSON, segmentación, reducción de muestreo, paginación (2000 muestras por página por defecto) |
get_activity_messages, add_activity_message ✎, update_activity ✎ | Notas y comentarios, RPE, sensación, nombre, descripción (dry_run muestra la solicitud exacta) |
Rendimiento a lo largo del tiempo
| Herramienta | Qué hace |
|---|---|
compare_best_efforts | Mejores esfuerzos en todas las actividades (ids, rango de fechas, deporte, equipo) lado a lado; los ids se deduplican y se limitan antes de cualquier solicitud |
find_similar_intervals | Actividades con intervalos comparables, desde una actividad de referencia o una longitud e intensidad dadas; misma familia de deporte por defecto, clasificadas por comparabilidad, con contexto de equipo y medidor de potencia; con una referencia, los 365 días anteriores por defecto (ventana mostrada, start_date para cualquier rango) |
compare_workouts | Entrenamientos repetidos a lo largo del tiempo, comparando solo intervalos de trabajo comparables (actividad de referencia, familia de deporte, longitud, intensidad, repeticiones, rango de FTP); la actividad de referencia siempre se obtiene y siempre es el patrón, con una búsqueda por nombre en los 365 días anteriores; los picos se mantienen aparte, medias ponderadas por tiempo, potencia, FC, cadencia y tendencias de RPE de toda la actividad, indicadores de equipo y medidor de potencia |
get_power_hr_efficiency | Vatios por latido por banda de potencia y bicicleta a lo largo del tiempo, con tamaños de muestra mínimos y filtros para equipo, interior/exterior y posición del intervalo |
get_fatigue_resistance | Mejor potencia en fresco vs. después de los umbrales de kJ del atleta; sin umbrales configurados, explica el ajuste y sugiere valores en lugar de mostrar pseudo-resultados |
get_long_ride_fatigue_profile | FC, W/lpm, cadencia y resistencia Garmin a potencia igualada en segmentos estables antes vs. después de umbrales de trabajo (por defecto 750 / 1.500 kJ, o kJ/kg), para salidas dadas o las salidas largas de un período; trabajo previo en cada umbral y subida (kJ, kJ/kg, kJ y tiempo por encima de FTP, esfuerzos por encima de FTP), subidas después de N horas con resistencia al inicio y al final, mediana y rango entre salidas, método indicado, muestras pequeñas marcadas |
get_submax_test_trends | Pruebas de fatiga submáximas detectadas por Intervals.icu (#SFT) con un filtro de validez (tolerancia objetivo, CV, ignoradas, detectadas dentro de un entrenamiento regular, esfuerzo duro previo, recuperación de FC opcional) y razones para cada prueba excluida; FC al final, factor de eficiencia, HRRc y tendencia del curso de FC por familia de deporte y tipo de prueba (potencia y ritmo nunca combinados) y semana ISO solo sobre las pruebas válidas |
get_training_load | Carga aguda y crónica, ratio agudo:crónico, monotonía y tensión de Foster (días de descanso como 0), semanas tipo deload, por deporte con el deporte principal, tabla de semana ISO, CTL/ATL/form/rampa; cargas de dispositivos mantenidas separadas; rangos de referencia con fuentes, sin veredicto |
get_intensity_distribution | Distribución de tres zonas desde zonas de potencia, FC o ritmo (mapeo por número de zonas; tiempos de zona GAP donde Intervals.icu los usa), índice de polarización según Treff et al. 2019, clase, sesiones y días duros, deriva entre las mitades, por deporte y semana, cobertura de zonas, una advertencia cuando los totales mezclan zonas de potencia y FC |
get_durability | Desacoplamiento aeróbico de sesiones largas estables después de un filtro de calidad (sesiones excluidas por razón), mediana y recuento por encima del 5 %, reciente vs. ventana con banda de estabilidad, tendencia del factor de eficiencia; proporción calificada por deporte, menos de 8 sesiones marcadas, interior/exterior mixto, bicicletas o medidores de potencia señalados; filtro de calor en el sensor del dispositivo o la temperatura de clima / sensación térmica de la actividad (temperature_source), las sesiones listan ambas temperaturas |
get_load_projection | CTL, ATL y forma proyectados sobre los entrenamientos planificados (modelo de 42/7 días), cargas planificadas faltantes reportadas, días de carrera, la propia proyección de Intervals.icu y una verificación del modelo para comparar; dice de manera prominente cuando no hay nada planificado. Simulación de qué pasaría si (scenario): sesiones o plantillas semanales que no están en el calendario (carga dada o estimada como horas x IF² x 100), añadidas o reemplazando el plan, comparadas con el plan del calendario; forma en un día objetivo o el próximo RACE_A y una búsqueda de cuadrícula para la carga de los últimos días que alcanza un rango de forma dado; estadísticas del plan por semana (rampa, monotonía, sesión más larga, días de descanso) con rangos comúnmente citados y fuentes. Nada se escribe |
get_athlete_power_curves, get_hr_curves, get_pace_curves | Curvas de temporada y rango de fechas |
get_training_summary | Totales por semana, mes, deporte o equipo con la carga de Intervals.icu (potencia, si no FC, si no ritmo por actividad) y las sumas superpuestas por método, tiempo en zonas de potencia (sweet spot aparte) y zonas de FC, CTL/ATL al final de cada semana o mes; campos personalizados agregados por unidades y significado (sumas solo donde tienen sentido, si no media, mediana, rango o cambio); un detail_level explícito también selecciona las partes JSON (sin él, el JSON está completo) |
get_weekly_summary, get_plan_compliance | Revisión semanal y visión general de planificado vs. hecho |
Bienestar y recuperación
| Herramienta | Qué hace |
|---|---|
get_recovery_snapshot | Hoy y los días anteriores, líneas base de 42 días, carga reciente y sesiones planificadas en una sola llamada; nombra los campos habituales de bienestar que el registro de hoy aún no tiene (aún no disponibles, no normal) |
get_coach_context | Primera llamada recomendada para un análisis semanal: visión general en aproximadamente 2-2,5k caracteres con carga, forma física, distribución de intensidad (desglose por deporte cuando las bases de zonas se mezclan), HRV / FC en reposo / sueño medias de 7 días frente a los 42 días anteriores (z frente a la variación semana a semana de los 90 días previos), durabilidad, mejores sesiones, el plan de los próximos 7 días, campos de bienestar de hoy aún no disponibles y una línea de método (ventanas, ACWR acoplado, threshold_as, regla de sesión dura); un detail_level explícito también selecciona las partes JSON (sin él, el JSON está completo) |
get_wellness_trends | Medias móviles, líneas base, valores atípicos, cambios semana a semana, correlaciones, eFTP por deporte; período solicitado, retroceso y ventana de línea base indicados por separado, muestras pequeñas marcadas |
get_nutrition_summary | Ingesta, gasto del dispositivo, balance energético en días registrados, tendencia de peso, carga de entrenamiento por día |
get_fueling_analysis | Combustible de una actividad o las sesiones largas de un período: carbohidratos usados (estimación de Intervals.icu) e ingeridos por hora en movimiento, proporción ingerida de lo usado, energía, ingesta de líquidos, sodio y pérdida de sudor de campos personalizados encontrados por unidades y nombre (ceros de archivos de dispositivo tratados como marcadores de posición); por familia de deporte, y dentro de ella por duración e intensidad, con tamaños de muestra, cobertura de registro y correlaciones de Spearman desde 8 sesiones; sin objetivos |
get_wellness_data, update_wellness ✎ | Registros diarios (include_all_fields añade cada campo de bienestar personalizado; sin start_date los 30 días antes de end_date o hoy), con una línea que nombra los campos habituales que el registro de hoy aún no tiene (valores de noche/mañana, métricas diarias como VO2max o puntuación de resistencia, y totales del día aparte); puntuaciones subjetivas (dry_run muestra la solicitud exacta) |
Atleta, equipo, calendario y entrenamientos
| Herramienta | Qué hace |
|---|---|
get_athlete_profile, get_sport_settings, get_training_zones | Perfil, umbrales por deporte, zonas con rangos absolutos |
update_sport_settings ⚙ | Cambio validado de FTP, LTHR, FC máxima o ritmo umbral (ritmo con su unidad, p. ej. 4:30/km); dry_run muestra la solicitud con los valores actuales |
get_gear_list, get_gear_details | Bicicletas, zapatillas y componentes con kilometraje y recordatorios de mantenimiento |
get_events, get_event_by_id, get_training_plan | Calendario con el documento completo de entrenamiento; fases del plan, objetivos semanales, carreras |
validate_workout, preview_workout | Verificar y renderizar un documento de entrenamiento antes de escribirlo |
add_or_update_event ✎, add_or_update_note ✎, add_events_bulk ⚙, delete_event ✖, delete_events_by_date_range ✖ | Cambios en el calendario: los entrenamientos se validan antes de escribirse, dry_run devuelve la solicitud exacta, un nuevo evento se rechaza cuando ese día ya tiene el mismo (allow_duplicate), la respuesta lee lo que Intervals.icu almacenó y analizó (pasos analizados vs. enviados, advertencias de análisis); las eliminaciones nombran lo que se eliminó; la eliminación por rango muestra una vista previa por defecto |
get_workout_library, get_library_workout, create_library_workout ✎, add_event_from_library ✎, delete_library_workout ✖ | Biblioteca de entrenamientos (prueba en seco, verificación de duplicados al programar, lectura de vuelta, las eliminaciones nombran lo que se eliminó) |
Elementos personalizados y servidor
| Herramienta | Qué hace |
|---|---|
get_custom_items, get_custom_item_by_id, create_custom_item ⚙, update_custom_item ⚙, delete_custom_item ✖ | Definiciones de campos personalizados, flujos y gráficos (create_custom_item y update_custom_item con dry_run; actualización: el contenido después de la fusión) |
get_server_status | Versión, permisos habilitados, conjunto de herramientas, herramientas ocultas, transporte y modo de inicio de sesión, verificación de API (también --doctor) |
get_guide | Guía de uso, sintaxis de entrenamientos y guías de método (los recursos a continuación) para clientes que solo llaman herramientas |
Prompts: recovery_check, workout_deep_dive, weekly_training_review,
training_load_review, performance_progression, long_ride_climbing_analysis,
nutrition_weight_trend, power_meter_comparison, workout_planning_validation, race_week
(taper y forma el día de la carrera, plan de combustible desde el historial, clima, logística), fueling_review,
plan_health_check (proyección de carga y escenario de qué pasaría si de las semanas planificadas) y
coach_handoff (resumen compacto para otro entrenador o sesión).
Recursos: intervals://guide (cómo usar las herramientas), intervals://workout-syntax (el
formato de entrenamiento estructurado), intervals://methods/<topic> (cómo funciona un análisis: datos de actividad,
ejecución, subidas, medidores de potencia, carga, intensidad, durabilidad, resumen, comparaciones, fatiga,
bienestar, combustible), intervals://custom-items (tus definiciones de elementos personalizados).
El servidor también envía instrucciones breves en la respuesta de MCP initialize (comienza con
get_coach_context o get_activity_report, compacto primero, los valores faltantes no son normales,
escribe solo a petición después de una vista previa), y su icono y sitio web en serverInfo. Los transportes HTTP
sirven el icono sin autenticación en /favicon.ico, /favicon.png, /icon.png,
/icon.svg y /apple-touch-icon.png (también usado en la página de inicio de sesión).
Conjuntos de herramientas
MCP_TOOLSET=full (por defecto) registra cada herramienta de las clases de permisos habilitadas.
MCP_TOOLSET=core registra un conjunto seleccionado de 23 herramientas para clientes con un presupuesto de herramientas pequeño (aproximadamente
9,4k tokens en MCP_PERMISSIONS=read,write); MCP_PERMISSIONS todavía se aplica dentro del conjunto:
| Propósito | Herramientas principales |
|---|---|
| Orientación | get_server_status, get_guide |
| Revisión semanal, carga y plan | get_coach_context, get_training_summary, get_load_projection, get_events, get_event_by_id, get_training_plan |
| Una actividad | get_activities, get_activity_report, get_activity_details, get_activity_intervals, get_best_efforts, get_fueling_analysis |
| Recuperación | get_recovery_snapshot, get_wellness_data, get_wellness_trends |
| Planificación | get_sport_settings, validate_workout, preview_workout |
Escrituras (clase write) | add_or_update_event ✎, update_wellness ✎, update_activity ✎ |
get_server_status y --doctor muestran el conjunto de herramientas activo y cuántas herramientas deja fuera; las descripciones
de herramientas, prompts y guías marcan las herramientas fuera del conjunto "(conjunto de herramientas completo)".
Después de una actualización del servidor que cambie herramientas o conjuntos de herramientas, actualiza la lista de herramientas en el cliente
(ChatGPT: la actualización del conector en la configuración de la aplicación; Claude: reconecta el conector).
Convenciones de salida: las horas de inicio se muestran locales con el nombre de la zona horaria cuando Intervals.icu
almacena una, si no con el desfase UTC derivado de la hora local y UTC de inicio, más UTC; cadencia de
carrera, caminata y senderismo en pasos por minuto (spm, 2 x el valor por pierna que Intervals.icu almacena,
que se muestra como almacenado), cadencia de bicicleta en rpm; temperaturas en °C (un campo personalizado de temperatura
sin unidades toma la unidad en la que coinciden sus campos de temperatura hermanos); los valores faltantes son n/a,
nunca 0.
Inicio rápido
Requisitos: una clave de API de Intervals.icu (Configuración → Configuración de desarrollador) y tu ID de atleta
(i123456); para el paquete de Python uv (o Python 3.12+ y pip),
para la imagen de contenedor Docker. Cada instalación ejecuta tu propio servidor con tus propias
credenciales; no hay servicio alojado.
Las versiones etiquetadas se publican como el paquete PyPI
futureweb-intervals-mcp, las imágenes de contenedor
ghcr.io/futureweb/intervals-mcp-server y
futurewebat/futureweb-intervals-mcp
(Docker Hub), un paquete de Claude Desktop (.mcpb) en el
release de GitHub y una entrada en el
registro oficial de MCP.
Beta:
1.0.0b1es una versión preliminar. Nombra la versión (uvx futureweb-intervals-mcp@1.0.0b1,pip install futureweb-intervals-mcp==1.0.0b1) o permite versiones preliminares (uvx --prerelease allow futureweb-intervals-mcp,pip install --pre futureweb-intervals-mcp). uv y pip eligen una versión preliminar por su cuenta solo mientras no exista una versión final; desde 1.0.0 en adelanteuvx futureweb-intervals-mcpsimple obtiene la última versión final.
Desde PyPI (uvx o pip)
export API_KEY=your-api-key ATHLETE_ID=i123456 # or put both into a .env file
uvx futureweb-intervals-mcp@1.0.0b1 --doctor # checks configuration and API access
uvx futureweb-intervals-mcp@1.0.0b1 # starts the server on stdio
Con pip, en un entorno virtual:
pip install futureweb-intervals-mcp==1.0.0b1
futureweb-intervals-mcp --doctor
Desde el código fuente
git clone https://github.com/futureweb/intervals-mcp-server.git
cd intervals-mcp-server
uv sync --locked
cp .env.example .env # set API_KEY and ATHLETE_ID
uv run futureweb-intervals-mcp --doctor # checks configuration and API access
uv run futureweb-intervals-mcp # starts the server on stdio
Sin clonar:
uvx --from git+https://github.com/futureweb/intervals-mcp-server futureweb-intervals-mcp --version
Docker
Las versiones etiquetadas publican la misma imagen multi-arquitectura (amd64, arm64) en el GitHub Container
Registry y en Docker Hub (latest solo para versiones finales, etiquetas beta como 1.0.0b1
explícitamente):
docker run --rm -i -e API_KEY=... -e ATHLETE_ID=i123456 ghcr.io/futureweb/intervals-mcp-server:1.0.0b1
docker run --rm -i -e API_KEY=... -e ATHLETE_ID=i123456 futurewebat/futureweb-intervals-mcp:1.0.0b1
Con MCP_AUTH=oauth monta un volumen en /data (la imagen mantiene OAUTH_STATE_FILE allí), por ejemplo
-v intervals-mcp:/data; de lo contrario, cada contenedor recreado desconecta a todos los clientes.
Paquete de Claude Desktop (.mcpb)
Cada release de GitHub incluye futureweb-intervals-mcp-<version>.mcpb. Ábrelo con Claude
Desktop (doble clic, o Configuración → Extensiones → Instalar extensión…) e introduce la clave API
(almacenada como secreto), el ID del atleta y, opcionalmente, los permisos (read por defecto) y el
conjunto de herramientas. El paquete contiene las fuentes y el archivo de bloqueo; Claude Desktop lo inicia con
uv (uv run --frozen), que instala las dependencias bloqueadas en
el primer inicio. Necesita una versión de Claude Desktop que soporte el manifiesto MCPB 0.4 (uv
tipo de servidor).
Registro MCP
Los releases se listan en el registro oficial de MCP
como io.github.futureweb/intervals-mcp-server, con el paquete PyPI y la imagen GHCR y las
variables de entorno que necesitan. Los clientes que leen el registro pueden instalar el servidor desde
allí. La entrada solo lista paquetes: cada usuario ejecuta su propia instancia con sus propias
credenciales de Intervals.icu.
Conectar un cliente de IA
Claude Desktop y Claude Code (local, stdio)
Además del paquete anterior, Claude Desktop puede iniciar el servidor desde PyPI con uvx (añade a
claude_desktop_config.json; Claude Desktop necesita la ruta completa a uvx si no está en su
PATH, por ejemplo /Users/you/.local/bin/uvx):
{
"mcpServers": {
"intervals-icu": {
"command": "uvx",
"args": ["futureweb-intervals-mcp@1.0.0b1"],
"env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
}
}
}
Con Docker en su lugar (los valores provienen de env, -e NAME los pasa al contenedor):
{
"mcpServers": {
"intervals-icu": {
"command": "docker",
"args": ["run", "--rm", "-i", "-e", "API_KEY", "-e", "ATHLETE_ID", "-e", "MCP_PERMISSIONS",
"ghcr.io/futureweb/intervals-mcp-server:1.0.0b1"],
"env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
}
}
}
Desde un checkout de las fuentes:
{
"mcpServers": {
"intervals-icu": {
"command": "uv",
"args": ["--directory", "/path/to/intervals-mcp-server", "run", "futureweb-intervals-mcp"],
"env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
}
}
}
Claude Code: claude mcp add intervals-icu -e API_KEY=your-api-key -e ATHLETE_ID=i123456 -- uvx futureweb-intervals-mcp@1.0.0b1,
o desde un checkout claude mcp add intervals-icu -- uv --directory /path/to/intervals-mcp-server run futureweb-intervals-mcp.
ChatGPT, Claude.ai y otros clientes remotos (OAuth)
Los clientes remotos necesitan un endpoint HTTPS. Ejecuta el servidor detrás de un proxy inverso TLS con OAuth:
MCP_TRANSPORT=http+sse FASTMCP_HOST=127.0.0.1 FASTMCP_PORT=8001 \
MCP_AUTH=oauth MCP_PUBLIC_URL=https://mcp.example.com \
INTERVALS_OAUTH_CLIENT_ID=... INTERVALS_OAUTH_CLIENT_SECRET=... \
MCP_PERMISSIONS=read,write \
uv run futureweb-intervals-mcp
- Elige el inicio de sesión: sin más configuraciones inicias sesión con tu clave API de Intervals.icu
(opcionalmente más un código de autenticador,
OAUTH_TOTP_SECRET). Para Continuar con Intervals.icu crea una aplicación OAuth en https://intervals.icu/oauth/apply con la URL de redirecciónhttps://mcp.example.com/oauth/intervals/callback; una contraseña de servidor es la tercera opción. - En ChatGPT (modo desarrollador) añade una conexión con la URL
https://mcp.example.com/mcpy autenticación OAuth; deja el ID de cliente y el secreto vacíos. Claude.ai: Añadir conector personalizado con la misma URL. - En la página de consentimiento elige los permisos para esta conexión e inicia sesión. Con
Intervals.icu solo los atletas en
OAUTH_ALLOWED_ATHLETES(por defectoATHLETE_ID) pueden iniciar sesión. - Después de las actualizaciones del servidor usa Actualizar en la conexión de ChatGPT para recargar las herramientas.
Todo sobre el servidor OAuth, el proxy inverso (ejemplos de Apache y nginx) y el
modelo de seguridad: docs/REMOTE_ACCESS.md. Los clientes sin OAuth pueden usar una
ruta de endpoint secreta en su lugar (FASTMCP_SSE_PATH=/mcp-<random>/sse).
Compartir el servidor con amigos
Por defecto el servidor es de un solo usuario (MCP_TENANCY=single): cada llamada de herramienta usa el
API_KEY y ATHLETE_ID del servidor. Quien tenga permitido conectarse ve tus datos, por lo que en este
modo el servidor se niega a iniciar cuando OAUTH_ALLOWED_ATHLETES nombra a alguien que no seas tú (tus otras
cuentas de Intervals.icu pueden listarse en OAUTH_OWNER_ACCOUNTS).
Para permitir que algunos amigos usen la misma implementación con sus propios datos de Intervals.icu, cambia al modo multiusuario opcional:
MCP_TENANCY=single (por defecto) | MCP_TENANCY=multi | |
|---|---|---|
| Acceso a datos | el API_KEY del servidor para cada conexión | cada conexión con su propia credencial |
| Los amigos inician sesión con | – (verían tus datos) | "Continuar con Intervals.icu" (la única forma para no propietarios) |
| Su token de Intervals.icu | usado para la verificación de identidad, nunca almacenado | almacenado cifrado (AES-256-GCM) por conexión |
| Tus propias conexiones | clave API | clave API, solo después de que tú inicies sesión (Intervals.icu como ATHLETE_ID, o contraseña / clave API más código de autenticador) |
Argumentos de athlete_id | cualquier atleta que la clave pueda leer | solo el atleta propio de la conexión (0 = propio); cualquier otra cosa se rechaza antes de una solicitud |
| Cachés, presupuestos de solicitudes | uno | por conexión / por atleta, parte justa del límite de la aplicación |
Configuración (detalles en docs/REMOTE_ACCESS.md):
# 1. While still in single-user mode: confirm once that your existing connections are yours
futureweb-intervals-mcp grants list
futureweb-intervals-mcp grants adopt-legacy --owner
# 2. A key for the stored tokens (mode 0600, owned by the service user; back it up separately)
futureweb-intervals-mcp token-key --file /etc/intervals-mcp/token.key
# 3. Settings, then restart and check
MCP_TENANCY=multi
OAUTH_TOKEN_KEY_FILE=/etc/intervals-mcp/token.key
OAUTH_LOGIN=intervals # you sign in with Intervals.icu as ATHLETE_ID (or add OAUTH_TOTP_SECRET for a password)
OAUTH_ALLOWED_ATHLETES=i123456,i234567,i345678 # you plus your friends
futureweb-intervals-mcp --doctor
Ejecuta los comandos grants y token-key como el usuario de servicio con el entorno del servidor
(OAUTH_STATE_FILE, ATHLETE_ID), por ejemplo docker exec -u <uid> en el contenedor. Como root se
niegan a cambiar un directorio de estado que pertenece a otro usuario (--allow-root anula; nunca
siguen enlaces allí). Las conexiones del modo de un solo usuario que no fueron adoptadas se
rechazan en el modo multiusuario, nunca se tratan como tuyas. Si vuelves a una versión anterior después de
esta, vuelve a eliminar los atletas registrados: las conexiones creadas o actualizadas mientras tanto necesitan
grants adopt-legacy --owner una vez más antes del siguiente cambio (hasta entonces se rechazan).
Tus amigos añaden la misma URL de conector en ChatGPT o Claude, eligen los permisos en la
página de consentimiento y aprueban la aplicación de Intervals.icu. Los permisos de Intervals.icu solicitados coinciden
con las clases que eligen (read solicita acceso de lectura a ACTIVITY, WELLNESS, CALENDAR, LIBRARY y
SETTINGS; write y superiores añaden los alcances de escritura que las herramientas necesitan). Los comentarios de actividades
necesitan el permiso CHATS de Intervals.icu, que también cubre los chats privados: nunca se solicita
a menos que establezcas INTERVALS_OAUTH_OFFER_CHATS=true y el atleta marque "Comentarios de actividades" en
la página de consentimiento; de lo contrario, las dos herramientas de comentarios indican que falta el permiso.
Qué se almacena. Por conexión, el archivo de estado guarda el ID del atleta, el cliente MCP, las fechas de creación
y último uso, los alcances de Intervals.icu otorgados y el token de acceso de Intervals.icu del atleta,
cifrado con la clave de OAUTH_TOKEN_KEY / OAUTH_TOKEN_KEY_FILE (sin la clave el token
no se puede leer; mantén la clave separada de las copias de seguridad del archivo de estado). Se mantienen como máximo
OAUTH_MAX_GRANTS_PER_ATHLETE conexiones (por defecto 5) por atleta; las tuyas nunca se
eliminan. Los datos no se almacenan en caché en
disco; las cachés en memoria caducan en minutos y están separadas por conexión.
Privacidad. Los datos de bienestar como HRV, sueño, frecuencia cardíaca en reposo o peso son datos de salud (en la
UE una categoría especial según el Art. 9 GDPR), y como operador eres responsable de ellos. Invita
solo a personas que acepten explícitamente, diles en una nota breve qué se almacena (arriba), quién puede verlo
(tú: el archivo de estado y los registros del servidor con IDs de atletas, nombres de herramientas, rutas de solicitudes y errores,
nunca tokens o cuerpos de datos), cuánto tiempo se conservan los registros (por ejemplo journalctl --vacuum-time=14d) y cómo
salir. Mantén la implementación actualizada. Si la clave o el archivo de estado pueden haber sido filtrados, coloca una nueva clave
primero en OAUTH_TOKEN_KEY, y pide a tus amigos que revoquen la aplicación en Intervals.icu.
Eliminación. El token almacenado de una conexión se elimina cuando el cliente MCP revoca la conexión al
desconectarse (/revoke; no todos los clientes lo hacen), después de OAUTH_REFRESH_TOKEN_TTL sin uso (por defecto
30 días; OAUTH_TOKEN_RETENTION_DAYS lo hace más corto), o con el comando grants. Para eliminar a un
amigo por completo:
futureweb-intervals-mcp grants remove <athlete id>(un servidor en ejecución elimina las conexiones en su siguiente solicitud);- elimina al atleta de
OAUTH_ALLOWED_ATHLETESy reinicia; - el amigo revoca la aplicación en su configuración de Intervals.icu (el servidor no puede revocar un token sin desconectar todas las conexiones del atleta; hasta entonces el token eliminado seguiría siendo válido en Intervals.icu);
- opcionalmente purga líneas de registro antiguas (
journalctl --vacuum-time=...).
Límites. Todos los atletas comparten los límites de solicitudes de la única aplicación OAuth de Intervals.icu: cada
atleta tiene un presupuesto diario suave (MCP_ATHLETE_DAILY_REQUESTS, por defecto 1000), todos juntos un
presupuesto de 15 minutos (MCP_APP_REQUESTS_PER_15MIN, por defecto 2000) del cual un atleta puede usar como máximo
MCP_ATHLETE_SHARE_PERCENT (por defecto 25; 0 aún permite una solicitud por ventana, 100 significa sin
límite por atleta) y los demás dejan MCP_OWNER_RESERVED_PERCENT (por defecto 20; 100 bloquea a cada
atleta menos a ti) para ti; los reintentos cuentan. El límite por llamada se aplica además. get_server_status muestra el modo
y el atleta propio de la conexión que llama, los alcances y el presupuesto, nunca otros usuarios. Volver a
single elimina las conexiones y tokens de los otros atletas en la siguiente escritura; tus propias conexiones
siguen funcionando en ambos modos.
Configuración
Variables de entorno; un archivo .env en el directorio de trabajo se carga automáticamente
(.env.example).
| Variable | Valor por defecto | Significado |
|---|---|---|
API_KEY | – | Clave de API de Intervals.icu (obligatoria) |
ATHLETE_ID | – | ID de atleta, i123456 o 123456 (obligatorio) |
MCP_PERMISSIONS | read | Clases de herramientas habilitadas, p. ej. read,write o all |
MCP_TOOLSET | full | full (cada herramienta de las clases habilitadas) o core (conjunto seleccionado, ver Conjuntos de herramientas) |
CUSTOM_UNITS_OVERRIDES | – | Unidades de visualización por código de elemento personalizado, p. ej. Stamina=%,RecoveryTime=h |
CUSTOM_AGGREGATE_OVERRIDES | – | Agregación por código de campo personalizado en resúmenes (sum, device_load_sum, trend, mean, none), p. ej. TrainingLoad=device_load_sum |
MCP_TRANSPORT | stdio | stdio, sse, http o http+sse (/mcp y /sse en un proceso) |
FASTMCP_HOST / FASTMCP_PORT | 127.0.0.1 / 8000 | Dirección de enlace de los transportes HTTP |
FASTMCP_SSE_PATH / FASTMCP_MESSAGE_PATH | /sse / /messages/ | Rutas de los endpoints SSE |
FASTMCP_ALLOWED_HOSTS / FASTMCP_ALLOWED_ORIGINS | host de MCP_PUBLIC_URL | Encabezados de Host públicos aceptados detrás de un proxy inverso (protección contra rebinding de DNS); obligatorio para un endpoint público sin OAuth |
MCP_AUTH | none | oauth habilita el servidor OAuth 2.1 integrado |
MCP_PUBLIC_URL | – | URL base pública, obligatoria con MCP_AUTH=oauth |
INTERVALS_OAUTH_CLIENT_ID / INTERVALS_OAUTH_CLIENT_SECRET | – | Aplicación OAuth de Intervals.icu para "Continuar con Intervals.icu" |
OAUTH_LOGIN | intervals con una aplicación, si no password si está definido, si no apikey | Método(s) de inicio de sesión: intervals, password, apikey |
OAUTH_TOTP_SECRET | – | Código de autenticador como segundo factor para inicio de sesión con contraseña y clave de API (python -m intervals_mcp_server.auth totp-secret) |
OAUTH_ALLOWED_ATHLETES | ATHLETE_ID | Atletas permitidos para iniciar sesión (* solo con MCP_TENANCY=multi y OAUTH_ALLOW_ANY_ATHLETE=true) |
MCP_TENANCY | single | multi: cada conexión usa su propia credencial de Intervals.icu (Compartir el servidor con amigos) |
OAUTH_TOKEN_KEY / OAUTH_TOKEN_KEY_FILE | – | Modo multiusuario (obligatorio): clave(s) que cifran los tokens de Intervals.icu almacenados (futureweb-intervals-mcp token-key) |
MCP_ATHLETE_DAILY_REQUESTS / MCP_APP_REQUESTS_PER_15MIN | 1000 / 2000 | Modo multiusuario: presupuesto de solicitudes por atleta y día, y de todos los atletas juntos por 15 minutos (0 = desactivado) |
MCP_ATHLETE_SHARE_PERCENT / MCP_OWNER_RESERVED_PERCENT | 25 / 20 | Modo multiusuario: parte del presupuesto de 15 minutos que un atleta puede usar (0 = una solicitud por ventana, no desactivado) y la parte reservada para el propietario (100 bloquea a cualquier otro atleta) |
INTERVALS_OAUTH_OFFER_CHATS | false | Modo multiusuario: ofrecer "Comentarios de actividad" (Intervals.icu CHATS, que también cubre chats privados) en la página de consentimiento |
OAUTH_MAX_GRANTS_PER_ATHLETE | 5 | Modo multiusuario: conexiones mantenidas por atleta (las menos usadas recientemente se revocan; las del propietario están exentas) |
OAUTH_OWNER_ACCOUNTS | – | Tus propias otras cuentas de Intervals.icu; los únicos otros atletas que el modo de usuario único acepta en la lista de permitidos |
OAUTH_PASSWORD_HASH / OAUTH_USERNAME | – / athlete | Inicio de sesión con contraseña (hash: python -m intervals_mcp_server.auth hash-password) |
OAUTH_STATE_FILE | ./oauth_state.json | Clientes registrados y resúmenes de tokens de actualización |
INTERVALS_API_BASE_URL | https://intervals.icu/api/v1 | URL base de la API |
ATHLETE_TIMEZONE | perfil de atleta | Zona horaria para "hoy" y rangos de fechas predeterminados, p. ej. Europe/Vienna; server usa el reloj del servidor. Sin definir: el timezone del perfil de atleta de Intervals.icu (consultado una vez al día) |
MCP_TOOL_MAX_REQUESTS / MCP_TOOL_TIMEOUT_S | 300 / 120 | Límites de una llamada de herramienta (solicitudes de Intervals.icu, segundos); una herramienta que los alcanza se detiene y dice que su resultado está incompleto |
MCP_MAX_OUTPUT_CHARS | 100000 | Resultado de herramienta más grande; texto más largo se corta con una nota sobre cómo obtener el resto, en JSON las listas más grandes se cortan (truncated indica qué se conservó) |
Opciones adicionales de OAuth (listas de permitidos de host de cliente y redirección, duraciones de token, límite de tasa) se enumeran en docs/REMOTE_ACCESS.md.
Permisos y seguridad
| Clase | Herramientas | Habilitar con |
|---|---|---|
read | todo lo que solo lee | predeterminado |
write | add_or_update_event, add_or_update_note, add_activity_message, update_activity, update_wellness, create_library_workout, add_event_from_library | MCP_PERMISSIONS=read,write |
destructive | delete_event, delete_events_by_date_range, delete_custom_item, delete_library_workout | MCP_PERMISSIONS=read,write,destructive |
admin | create_custom_item, update_custom_item, add_events_bulk, update_sport_settings | MCP_PERMISSIONS=all |
Las herramientas de una clase deshabilitada no se registran en absoluto. Con OAuth, cada conexión adicionalmente
solo obtiene las clases otorgadas en la página de consentimiento (intervals:read, intervals:write, …);
otras herramientas están ocultas para ella y se rechazan si se llaman.
Las herramientas de escritura que pueden reemplazar valores existentes (add_or_update_event, add_or_update_note,
update_activity, update_wellness) llevan la pista MCP destructiveHint: true, para que los clientes pregunten
antes de ejecutarlas; su clase permanece write. Nada se crea, empareja, renombra o elimina
automáticamente: delete_events_by_date_range primero solo lista lo que coincide; elimina solo con
dry_run=false y los ids confirmados de esa lista (confirm_ids), toca solo las categorías
nombradas (entrenamientos planificados predeterminados), como máximo 31 días, nunca entrenamientos ya emparejados con una
actividad a menos que se solicite. Los valores vacíos de un cliente nunca borran texto o entrenamientos existentes.
Cada escritura es predecible y verificable (detalles: seguridad de escritura en intervals://guide):
-
dry_run=trueen cada herramienta de crear/actualizar (incluyendocreate_custom_item) devuelve la solicitud exacta (método, ruta, cuerpo después de todos los valores predeterminados y fusiones, como JSON compacto) y el resultado de validación; no se envía ninguna solicitud de escritura (el servidor rechaza cada solicitud no GET durante una ejecución de prueba). -
Crear un evento (individual, masivo o desde la biblioteca) primero lee los eventos de su fecha (una solicitud sobre el rango de fechas) y rechaza un duplicado (misma categoría y deporte con el mismo nombre, o el mismo entrenamiento o texto no trivial) a menos que
allow_duplicate=true; un día de ladrillo o un par AM/PM con nombres diferentes no es un duplicado. La herramienta masiva decide por entrada, lista los rechazados y crea sesiones dobles planificadas (mismo nombre, contenido diferente). -
Después de cada escritura de evento o entrenamiento de biblioteca, la respuesta lee de nuevo lo que Intervals.icu almacenó y analizó: fecha, nombre, categoría, deporte, duración, carga, pasos analizados vs enviados y advertencias de análisis (notas: fecha, nombre, categoría, longitud de texto).
-
delete_event,delete_library_workoutydelete_custom_itemleen el objeto primero y nombran lo que se eliminó; un id faltante no elimina nada. -
Las credenciales nunca aparecen en registros o salida de herramientas; en el modo de usuario único, el token de inicio de sesión de Intervals.icu se usa solo para la verificación de identidad y nunca se almacena (en el modo multiusuario se almacena cifrado, ver arriba).
-
Nunca expongas los transportes HTTP sin OAuth o una ruta secreta, y siempre detrás de TLS.
-
En el modo de usuario único, una implementación sirve la clave de API de un atleta y la lista de permitidos de inicio de sesión decide quién puede conectarse; comparte una implementación solo en el modo multiusuario.
Detalles y cómo reportar una vulnerabilidad: SECURITY.md.
Estado del proyecto y hoja de ruta
1.0.0b1 es la primera beta pública de este fork. El desarrollo ocurre en solicitudes de extracción revisadas;
main está protegido y cada cambio ejecuta el CI completo.
Hecho
- Campos personalizados, flujos personalizados y estadísticas de intervalos para cualquier dato de dispositivo (también ofrecido upstream como mvilanova/intervals-mcp-server#153)
- Herramientas de entrenamiento, clases de permisos, correcciones upstream y solicitudes de extracción de la comunidad fusionadas
- Análisis de rendimiento, análisis de ejecución para entrenamientos eliminados y extendidos, niveles de detalle, informe de actividad en una llamada, prompts y recursos
- OAuth con "Continuar con Intervals.icu", permisos por conexión, documentos de metadatos de cliente, HTTP transmisible y SSE en un proceso
- Calidad de análisis: paseos extendidos divididos correctamente, solo intervalos comparables comparados, agregación de campos personalizados por significado, períodos de bienestar claros, tamaños de muestra mínimos para tendencias de eficiencia, resistencia a la fatiga honesta, grados de pendiente suavizados, informe compacto
- Carga de entrenamiento e intensidad: relación agudo:crónico, monotonía y tensión, distribución de tres zonas con índice de polarización, durabilidad aeróbica, proyección de carga y contexto semanal de entrenador
Siguiente
- Primera versión etiquetada: paquete PyPI, imágenes GHCR y Docker Hub, entrada MCP Registry y paquete Claude Desktop, todo publicado por el flujo de trabajo de versión desde una etiqueta
- Modo multi-atleta opcional que usa el token OAuth de Intervals.icu de cada atleta
- Migración a MCP SDK v2 una vez que sea estable para los transportes usados aquí
Documentación
| Documento | Contenido |
|---|---|
| docs/REMOTE_ACCESS.md | Servidor OAuth, inicio de sesión de Intervals.icu, configuración de ChatGPT y Claude, proxy inverso, operaciones |
| docs/GARMIN_BRIDGE.md | Trabajar con el Garmin Intervals Bridge, ejemplos trabajados, lectura de métricas de dispositivo |
| docs/FEATURE_COMPARISON.md | Comparación con otros servidores MCP de Intervals.icu |
| docs/UPSTREAM_AUDIT.md | Cada solicitud de extracción upstream abierta y qué pasó con ella |
| docs/RELEASE_CHECKLIST.md | Proceso de versión y puertas |
| RELEASING.md | Publicar una versión (PyPI, GHCR, Docker Hub, MCP Registry, paquete Claude Desktop) y qué hacer cuando un paso falla |
| CHANGELOG.md | Cambios por versión |
| SECURITY.md | Política de seguridad y reporte de vulnerabilidades |
Desarrollo
uv sync --all-extras --locked
uv run --locked pytest # synthetic fixtures, no credentials needed
uv run --locked ruff check .
uv run --locked mypy src tests
uv run --locked --with pylint pylint --disable=C0301 $(git ls-files '*.py') # advisory
CI ejecuta ruff, mypy y pytest en Python 3.12 y 3.13, construye e importa la rueda y el sdist,
construye y prueba el humo de la imagen Docker y el paquete Claude Desktop, valida server.json
contra el esquema MCP Registry, lint los flujos de trabajo, y CodeQL escanea el código. Todas las GitHub Actions están fijadas
a SHAs de commit; Dependabot las mantiene y las dependencias actualizadas. Las versiones se construyen desde etiquetas
(docs/RELEASE_CHECKLIST.md,
RELEASING.md); las etiquetas beta se convierten en pre-lanzamientos de GitHub.
Las contribuciones son bienvenidas: ver CONTRIBUTING.md. Nunca pongas datos reales de atletas, claves de API o nombres de host en problemas, fixtures o registros.
Créditos y licencia
Proyecto original por Marc Vilanova y contribuyentes: mvilanova/intervals-mcp-server. Este fork integra solicitudes de extracción de la comunidad por arnold-maderthaner (#140, #142 a #147), biochaos (#131) y kokostitiahah (#149), y corrige reportados y las métricas de carga de entrenamiento e intensidad propuestas por morritter (#150); gracias. Mantenido por Futureweb, junto con el Garmin Intervals Bridge.
Licenciado bajo la Licencia Pública General GNU v3.0, ver LICENSE. Intervals.icu y Garmin son marcas comerciales de sus respectivos propietarios y se usan solo para describir compatibilidad.