GARMIN & AI – Raccogliere i dati con Python

Sottotitolo: Come trasformare i dati raccolti quotidianamente da uno smartwatch in una base informativa strutturata, pronta per essere interrogata da un motore di intelligenza artificiale privato.

Introduzione: il valore dei dati che produciamo ogni giorno

Ogni giorno uno smartwatch raccoglie una quantità sorprendente di informazioni.

Frequenza cardiaca, passi, attività sportive, qualità del sonno, variabilità della frequenza cardiaca (HRV), stress e recupero sono soltanto alcuni dei parametri disponibili.

Nel mio caso utilizzo un Garmin Fenix per monitorare soprattutto gli allenamenti di nuoto, sia in piscina sia in acque libere.

Garmin Connect permette di visualizzare questi dati attraverso grafici e report, ma volevo realizzare qualcosa di diverso.

Volevo che un’intelligenza artificiale potesse leggere i miei dati Garmin, comprenderne l’evoluzione nel tempo e aiutarmi a interpretare allenamenti e recupero.

Per esempio:

  • Come è cambiata la mia frequenza cardiaca durante gli ultimi allenamenti?
  • Sto migliorando l’efficienza della nuotata?
  • Esiste una relazione tra qualità del sonno e prestazioni sportive?
  • Come varia la mia HRV nei periodi di maggiore carico?
  • Quanto recupero dopo un allenamento particolarmente impegnativo?

Per rispondere a queste domande, il primo problema da risolvere non era l’intelligenza artificiale; era l’accesso ai dati.

L’architettura del progetto

Ho deciso di costruire una pipeline completamente ospitata nel mio homelab.

L’architettura complessiva prevede quattro componenti principali:

  1. Garmin Connect,raccoglie e conserva le info provenienti dallo smartwatch.
  2. Garmin Collector, un’applicazione Python che interroga le API e scarica i dati.
  3. Uno storage persistente, nel quale vengono salvati i dati in formato JSON.
  4. Un server MCP, che permette al motore AI di accedere alle informazioni attraverso strumenti dedicati.

Il flusso logico è:

Garmin Fenix
     |
     v
Garmin Connect
     |
     | HTTPS / API
     v
Garmin Collector (Python)
     |
     | Normalizzazione
     v
File JSON strutturati
     |
     v
Storage persistente
     |
     v
Garmin MCP Server
     |
     v
OpenWebUI + Motore AI

In questo primo articolo ci concentreremo esclusivamente sulla parte iniziale: acquisizione, autenticazione, organizzazione e normalizzazione dei dati Garmin.

L’infrastruttura Kubernetes e l’integrazione MCP saranno affrontate nei prossimi articoli.

La prima difficoltà: accedere ai dati Garmin

A differenza di altri servizi, Garmin Connect non offre agli utenti privati una semplice API pubblica, liberamente utilizzabile per scaricare tutti i propri dati attraverso una chiave personale standard.

Garmin mette a disposizione programmi API ufficiali, come Garmin Health API, destinati principalmente a integrazioni approvate.

Esistono inoltre librerie e integrazioni non ufficiali che utilizzano gli endpoint di Garmin Connect.

Nel mio progetto ho utilizzato un sistema di autenticazione basato su una credenziale personale e sul rilascio di token temporanei.

È importante precisare che questa modalità di autenticazione dipende dal servizio effettivamente utilizzato e non deve essere considerata un’interfaccia pubblica Garmin universalmente disponibile.

L’implementazione concreta impiega due passaggi:

  1. Presentare la credenziale personale a un endpoint di autenticazione.
  2. Utilizzare il token ottenuto per le successive richieste API.

Questo approccio evita di trasmettere la credenziale principale a ogni richiesta.

La gestione delle credenziali

Durante lo sviluppo locale, ho utilizzato un file .env.local:

GARMIN_PERSONAL_API_KEY=<chiave_personale>

Il file deve essere escluso dal versionamento Git.

.env.local
token.json
__pycache__/

Le credenziali non devono essere inserite direttamente nel codice Python, nei manifest pubblici Kubernetes o nei repository GitHub.

Nel deployment definitivo, la credenziale viene invece gestita attraverso un Secret Kubernetes.

Il modulo Python garmin_api.py

Per separare l’autenticazione dalla raccolta dei dati, ho organizzato il codice in due moduli:

  • garmin_api.py: autenticazione, token e richieste HTTP.
  • pull.py: acquisizione e salvataggio dei dati Garmin.

Questa separazione permette di modificare il sistema di autenticazione senza riscrivere tutta la logica di raccolta.

La struttura delle directory

garmin-test/
|
|-- garmin_api.py
|-- pull.py
|-- .env.local
|
`-- data/
    |-- activities.json
    |-- daily.json
    |-- sleep.json
    |-- hrv.json
    |-- weight.json
    |-- fitness_age.json
    |-- hr_zones.json
    |-- meta.json
    `-- token.json

Il file token.json è un file operativo contenente informazioni di autenticazione e deve essere protetto come una credenziale.

Lettura della chiave

Il modulo individua il file .env.local nella directory dello script.

Un esempio semplificato:

import os
from pathlib import Path

HERE = Path(__file__).resolve().parent
ENV_FILE = HERE / ".env.local"

def read_key():
    if not ENV_FILE.exists():
        raise RuntimeError(
            "File .env.local non trovato"
        )

    for line in ENV_FILE.read_text().splitlines():
        if line.startswith("GARMIN_PERSONAL_API_KEY="):
            return line.split("=", 1)[1].strip()

    raise RuntimeError("Chiave Garmin mancante")

Questa funzione illustra la lettura della credenziale. Non costituisce da sola un client Garmin completo.

Nella versione eseguita su Kubernetes, lo script di avvio crea il file .env.local a partire dalla variabile d’ambiente fornita da un Secret.

Token temporanei e rinnovo automatico

Uno degli aspetti più importanti del Collector è la gestione dei token.

Nel progetto il token viene memorizzato localmente, in modo da non dover eseguire una nuova autenticazione per ogni richiesta.

La logica generale è:

def get_token(force=False):
    if not force:
        token = read_cached_token()
        if token_is_valid(token):
            return token

    token = request_new_token()
    save_token(token)
    return token

Questo è pseudocodice illustrativo: le funzioni di cache e autenticazione devono essere implementate secondo il protocollo del servizio utilizzato.

Nel mio caso è stata configurata una durata massima locale del token di 20 ore.

La durata della cache non garantisce che il token rimanga valido per tutto quel periodo. Il server remoto può revocarlo o rifiutarlo prima della scadenza.

Per questo motivo è importante gestire anche le risposte HTTP 401.

Gestione degli errori di autenticazione

Il Collector segue questa logica:

Richiesta API
     |
     v
Token disponibile?
     |
     +-- NO --> Richiedi nuovo token
     |
     v
Esegui richiesta
     |
     +-- HTTP 200 --> Elabora i dati
     |
     +-- HTTP 401 --> Rinnova token
                          |
                          v
                    Riprova una volta
                          |
                          +-- OK
                          |
                          +-- Errore: interrompi

Il nuovo tentativo deve essere limitato: ripetere indefinitamente richieste con credenziali non valide non risolve il problema e può provocare ulteriori blocchi.

Durante il progetto abbiamo incontrato proprio un errore HTTP 401.

La causa è stata individuata confrontando la credenziale locale funzionante con quella configurata nell’ambiente Kubernetes.

Il test di autenticazione locale è riuscito, mentre la credenziale precedentemente presente nel Secret veniva rifiutata.

Questo episodio ha dimostrato l’importanza di separare la diagnosi delle credenziali dalla diagnosi dell’infrastruttura.

Quali dati abbiamo deciso di raccogliere

Una volta risolta l’autenticazione, il passo successivo è stato scegliere quali informazioni acquisire.

Ho organizzato la raccolta in diverse categorie.

Dataset Contenuto principale
activities.json Allenamenti, distanze, durate, frequenza cardiaca, carico
daily.json Passi, frequenza cardiaca, Body Battery e riepiloghi giornalieri
sleep.json Durata del sonno e relative fasi
hrv.json Variabilità della frequenza cardiaca
weight.json Storico delle pesate
fitness_age.json Informazioni sull’età fitness
hr_zones.json Zone di frequenza cardiaca
meta.json Metadati della raccolta

Non tutti i campi sono necessariamente disponibili per ogni attività o per ogni giornata.

La disponibilità dipende dal dispositivo, dalle impostazioni Garmin e dalle informazioni effettivamente presenti nell’account.

Un esempio: le attività di nuoto

Per gli allenamenti di nuoto, i dati possono includere informazioni particolarmente interessanti:

  • Distanza percorsa.
  • Durata totale e tempo effettivo.
  • Frequenza cardiaca media e massima.
  • Velocità media.
  • Cadenza delle bracciate.
  • SWOLF, un indicatore combinato di tempo e numero di bracciate.
  • Distanza media per bracciata.
  • Training Effect aerobico e anaerobico.
  • Tempo trascorso nelle zone cardiache.

Questi dati costituiscono una base utile per confrontare le prestazioni nel tempo.

Tuttavia, è necessario interpretare correttamente il contesto: una sessione in piscina non è direttamente confrontabile con una gara in acque libere, dove condizioni ambientali, navigazione e correnti possono influenzare il risultato.

Normalizzare i dati: dal dato grezzo al JSON

Le risposte API possono contenere strutture complesse, campi opzionali e unità di misura differenti.

Per poter utilizzare questi dati in un sistema AI, è utile definire uno schema stabile.

Consideriamo, per esempio, una possibile rappresentazione normalizzata di un allenamento:

{
  "activity_id": "example-001",
  "date": "2026-11-10",
  "sport": "lap_swimming",
  "distance_m": 2400,
  "duration_s": 2880,
  "average_hr_bpm": 128,
  "average_swolf": 42,
  "source": "garmin"
}

I valori riportati sono illustrativi e non rappresentano una specifica attività realmente acquisita.

La normalizzazione permette di:

  • Utilizzare nomi di campo coerenti.
  • Esplicitare le unità di misura.
  • Gestire i valori mancanti.
  • Collegare i dati tramite identificatori e date.
  • Ridurre la complessità delle successive interrogazioni.

È importante conservare anche i dati originali, oppure almeno i campi necessari a ricostruire il significato delle misure.

Organizzare i dati per data

Per i riepiloghi giornalieri, una struttura indicizzata per data risulta particolarmente pratica.

{
  "2026-11-09": {
    "steps": 8500,
    "resting_hr": 54
  },
  "2026-11-10": {
    "steps": 10200,
    "resting_hr": 52
  }
}

Anche questi sono dati di esempio.

Una struttura del genere rende semplice selezionare intervalli temporali e costruire confronti.

Per un’analisi più avanzata, potremo successivamente trasferire i dati in un database relazionale o in un sistema dedicato alle serie temporali.

Per la prima versione del progetto, però, i file JSON sono stati sufficienti.

Il Collector: automatizzare la raccolta

Il secondo script, pull.py, si occupa di orchestrare la raccolta.

Il suo compito è:

  1. Inizializzare il client API.
  2. Richiedere i diversi dataset.
  3. Gestire gli errori.
  4. Salvare i risultati nei file JSON.
  5. Terminare con un codice di uscita che permetta di identificare eventuali fallimenti.

Il principio generale è semplice:

from pathlib import Path
import json

DATA_DIR = Path(__file__).resolve().parent / "data"
DATA_DIR.mkdir(exist_ok=True)

def save_json(filename, payload):
    destination = DATA_DIR / filename

    temporary = destination.with_suffix(".tmp")

    temporary.write_text(
        json.dumps(
            payload,
            ensure_ascii=False,
            indent=2
        ),
        encoding="utf-8"
    )

    temporary.replace(destination)

Questo esempio mostra il salvataggio tramite file temporaneo e sostituzione atomica, quando supportata dal filesystem.

Il codice completo di pull.py deve naturalmente includere le chiamate effettive alle API, la gestione dei dati mancanti e le regole di aggiornamento dei dataset.

La scrittura atomica riduce il rischio di lasciare file JSON parziali in caso di interruzione, ma non sostituisce backup e controlli di integrità.

Validare i dati raccolti

Scaricare un file non significa necessariamente aver acquisito informazioni corrette.

Per questo ho introdotto verifiche sui dataset.

Per esempio:

import json
from pathlib import Path

data_dir = Path("data")

for name in [
    "activities.json",
    "daily.json",
    "sleep.json",
    "hrv.json"
]:
    path = data_dir / name

    if not path.exists():
        print(f"{name}: MANCANTE")
        continue

    with path.open(encoding="utf-8") as f:
        payload = json.load(f)

    print(
        f"{name}: "
        f"{len(payload)} elementi"
    )

Nel nostro progetto abbiamo verificato la presenza di 366 chiavi per i dataset giornalieri relativi a riepiloghi, sonno e HRV durante una delle prime raccolte.

È stata una verifica utile, ma il solo numero di record non basta.

Un Collector affidabile dovrebbe controllare anche:

  • Data più recente disponibile.
  • Presenza di identificatori duplicati.
  • Coerenza delle unità di misura.
  • Integrità sintattica dei JSON.
  • Completezza della finestra temporale richiesta.

La lezione più importante: distinguere raccolta e consultazione

Una delle decisioni architetturali fondamentali è stata separare il componente che raccoglie i dati da quello che li espone all’intelligenza artificiale.

Il Garmin Collector comunica con il servizio remoto.

Il Garmin MCP Server, invece, legge i dati già presenti nello storage.

Questo significa che il motore AI non deve necessariamente autenticarsi presso Garmin ogni volta che riceve una domanda.

Il vantaggio è duplice.

Da un lato, riduciamo la dipendenza dalle API esterne. Dall’altro, manteniamo un archivio locale che può essere consultato anche quando il servizio remoto non è temporaneamente disponibile.

C’è però una conseguenza importante: se il Collector smette di funzionare, il server MCP può continuare a rispondere utilizzando dati non aggiornati.

È esattamente il problema che abbiamo incontrato durante una verifica dell’infrastruttura.

Il server MCP rispondeva correttamente, ma l’ultima attività disponibile risaliva al 1° novembre.

Dopo aver ripristinato l’autenticazione del Collector, una nuova raccolta ha permesso al motore AI di leggere anche l’attività del 10 novembre.

Questo ci ha insegnato che la disponibilità del servizio e la freschezza dei dati sono due indicatori distinti.

In futuro sarà utile esporre anche la data dell’ultima raccolta riuscita, così che l’assistente AI possa dichiarare esplicitamente quanto sono aggiornate le informazioni utilizzate.

Sicurezza e protezione dei dati personali

I dati Garmin comprendono informazioni potenzialmente sensibili, soprattutto quando riguardano salute, sonno e parametri fisiologici.

Per questo motivo il progetto segue alcuni principi:

  • Le credenziali non vengono inserite nel codice.
  • I token sono conservati in file protetti.
  • I dati vengono archiviati su infrastruttura privata.
  • L’accesso agli strumenti MCP viene limitato ai componenti autorizzati.
  • Le informazioni personali non vengono pubblicate nei repository.
  • Le copie di backup devono essere protette quanto i dati originali.

È inoltre importante ricordare che le integrazioni non ufficiali possono cambiare comportamento o smettere di funzionare in seguito a modifiche del servizio remoto.

Un sistema di produzione dovrebbe prevedere monitoraggio, gestione delle credenziali e procedure di recupero.

Conclusioni

Il primo obiettivo del progetto è stato raggiunto: trasformare i dati raccolti da Garmin in informazioni strutturate e disponibili localmente.

Abbiamo costruito una pipeline capace di:

  • Autenticarsi presso il servizio di accesso ai dati Garmin.
  • Gestire token temporanei.
  • Scaricare attività e parametri fisiologici.
  • Organizzare i dati in file JSON.
  • Conservare uno storico utilizzabile da applicazioni successive.
  • Separare la raccolta dalla consultazione tramite intelligenza artificiale.

Il risultato non è ancora un coach AI.

È qualcosa di più fondamentale: una base dati personale, strutturata e interrogabile, sulla quale costruire un sistema intelligente.

Nel prossimo articolo vedremo come portare questa pipeline all’interno di un cluster Kubernetes RKE2, utilizzando CronJob per la raccolta automatica, Secret per le credenziali e volumi persistenti Synology iSCSI per la conservazione dei dati.

Affronteremo anche problemi reali incontrati durante l’implementazione, come i conflitti Multi-Attach e i Job bloccati.

Garmin + Claude: una dashboard di allenamento tutta mia

In un pomeriggio domenicale, il geek in me ha preso il sopravvento e ha deciso di colleare il mio account Garmin a Claude per creare una dashboard di allenamento costruita sulle mie domande, non su quelle di un’app e …. senza scrivere una riga di codice!!!

Nuoto in piscina e in acque libere, cammino, faccio yoga !

Garmin Connect registra tutto, ma ogni schermata risponde a una domanda generica.

Io ne ho di molto precise:  sto diventando più veloce in acqua? Sto recuperando abbastanza? Il peso va nella direzione giusta?

Volevo una pagina sola che rispondesse a queste domande, con i miei dati, e che restasse sul mio computer.

La chiave ufficiale di Garmin

Garmin offre una Personal API: una chiave personale che dà accesso ai propri dati, in sola lettura.

Niente librerie non ufficiali, niente password salvate in giro.

La chiave si crea in Garmin Connect, nella pagina Personal API Key, con una scadenza a scelta.

Viene mostrata una sola volta e ne può esistere una sola attiva.

Con la chiave si ottiene un token che dura 24 ore, e con il token si leggono attività, riepiloghi giornalieri, sonno, HRV, peso, età fitness e zone cardio.

Sola lettura significa che nessuno script può modificare o cancellare nulla nel mio account.

Un passo alla volta, senza scrivere codice

Ho usato Claude in modalità Cowork, collegato al mio Mac.

Prima ho scritto le istruzioni una volta sola e le ho salvate come skill, così posso riusarle.

Poi Claude mi ha guidato in sette passi, fermandosi ogni volta che serviva qualcosa da me.

  1. Progetto: Claude ha creato la cartella, verificato Python e preparato i file di configurazione.
  2. Chiave: Ho creato la chiave su Garmin Connect seguendo le istruzioni, per poi  copiarla nel file giusto.
  3. Test: un comando nel Terminale ha mostrato le mie ultime cinque attività. Connessione funzionante 🙂
  4. Domande: obiettivo, sport, stile grafico, unità di misura, numeri che guardo di più.
  5. Download: 12 mesi di storia in circa un minuto.
  6. Dashboard: un unico file HTML che si apre nel browser.
  7. Aggiornamento: un solo comando scarica le novità e ricostruisce tutto.

Il mio lavoro è stato  copiare una chiave e incollare due righe nel terminale, il  codice l’ha scritto e controllato Claude.

Le regole d’oro: chiave e dati restano a casa

Sono dati di salute, quindi ho fissato poche regole chiare fin dall’inizio.

  • Sola lettura: nessuna chiamata che modifichi il mio account.
  • La chiave non passa dalla chat: la incollo io in un file sul Mac. Claude controlla solo che ci sia, senza mai leggerla o mostrarla.
  • Tutto in locale: chiave, dati scaricati e dashboard restano sul mio computer, esclusi da qualsiasi caricamento online.
  • Niente cloud aziendale: avevo chiesto di mettere il progetto in Documenti, ma Claude mi ha fatto notare che sul mio Mac quella cartella è sincronizzata con OneDrive. Abbiamo scelto una cartella solo locale.

Anche il backup che tengo su Dropbox contiene solo il codice, mai la chiave né i dati.

Cosa c’è nella dashboard

Ogni grafico risponde a una domanda che mi faccio davvero. Lo stile è pulito e chiaro, come un diario di allenamento, e funziona anche sul telefono. Passando sopra un grafico vedo i valori esatti del giorno o della settimana.

Sezione La domanda Cosa mostra
Verso l’obiettivo Sto andando nella direzione giusta? Peso, passo in piscina, km in acque libere, volume di nuoto
Salute Come sto oggi rispetto al solito? HRV, FC a riposo, sonno, carico, Body Battery, età fitness
Questa settimana Mi sto allenando come al solito? Km, ore e sessioni per sport, ultime 16 settimane
Tendenze Cosa sta cambiando nei mesi? HRV con la fascia personale, FC a riposo, fasi del sonno, carico, stress
Nuoto Sto diventando più veloce? Passo per 100 m di ogni nuotata, km al mese
Record Qual è il mio meglio? Nuotate più lunghe, passo migliore, giornate più impegnative

Cosa mi hanno detto i miei dati

In un anno: 700 attività, 366 notti di sonno e HRV, 19 uscite in acque libere. Vederli tutti insieme ha cambiato la mia lettura.

  • Recupero: in questo periodo l’HRV notturna è sotto la mia fascia abituale e la FC a riposo della settimana è sopra la media del mese. Due segnali che, insieme, chiedono un po’ più di riposo.
  • Velocità in acqua: il passo medio in piscina è intorno a 1:58 ogni 100 m, con un miglior risultato di 1:35 su almeno un chilometro. Ora posso seguirlo nuotata dopo nuotata.
  • Acque libere: la nuotata più lunga è stata di 3,64 km. È il punto di partenza per le gare.
  • Peso: solo 7 pesate in un anno sono troppo poche per seguire un obiettivo. La prima cosa da cambiare non è l’allenamento, ma l’abitudine di salire sulla bilancia.

Aggiornarla e portarla con sé

Dopo un allenamento basta un comando: scarica solo le novità, ricostruisce la pagina e la apre. La chiave dura un anno, poi se ne crea una nuova in due minuti.

Se cambio computer, copio la cartella del progetto, installo Python e rilancio lo stesso comando. Su Windows c’è un file equivalente con doppio clic.

In conclusione

Non serve essere programmatori per avere i propri dati in una forma utile.

Serve sapere quali domande farsi e avere un assistente che traduca quelle domande in codice, rispettando le regole che decidiamo noi.

La mia prossima domanda per la dashboard è già pronta: quanti giorni mancano alla prossima gara in acque libere?

Dall’analisi video agli allenamenti strutturati

L’ultimo passaggio è stato il più divertente.

Ho caricato un video di una mia nuotata in piscina, con riprese dalla superficie e sott’acqua frontali.

Claude non guarda il video in movimento come faremmo noi, ma ne ha estratto i fotogrammi e li ha analizzati uno per uno.

Il responso è stato onesto e utile.

Tra le cose positive: recupero del braccio con gomito alto e ritmo regolare.

Da migliorare:

  • una trazione spesso a braccio teso, che spinge l’acqua verso il fondo invece che indietro;
  • braccia che in allungo escono dalla linea delle spalle, probabilmente durante la respirazione;
  • molta aria all’entrata della mano;
  • la testa a tratti un po’ alta.

Claude ha anche indicato con chiarezza i limiti dell’analisi: risoluzione bassa e nessuna ripresa laterale, quindi niente giudizio sulla gambata.

Il tutto è finito in un documento Word con i fotogrammi commentati.

Poi siamo passati alla programmazione della settimana:

Scarico il lunedì, soglia il venerdì, aerobico lungo la domenica.

Ogni seduta include esercizi mirati ai difetti emersi dal video, come il remate, il nuoto a pugni chiusi, il braccio singolo e il catch-up con entrata sulla linea della spalla.

Le andature sono calcolate sul mio passo di soglia, circa 1:58 ogni 100 metri.

La parte che mi è piaciuta di più è stata la discussione.

Ho chiesto più volume: 2.000, 2.500 e 2.800 metri.

Poi ho chiesto perché alcune ripetute fossero in zona B2 e non B1.

Claude mi ha spiegato il ragionamento, cioè attivazione prima della serie centrale e richiamo di velocità a fine seduta, ma mi ha anche detto che B1 era una scelta altrettanto valida e più prudente.

Abbiamo cambiato, e alla fine ho avuto tre documenti Word, uno per seduta, da stampare e portare a bordo vasca.

Non è un sostituto di un allenatore in carne e ossa che ti guarda dal bordo, ma come strumento per ragionare sui propri dati e tenere il filo della programmazione funziona davvero bene.

Claude legge i miei allenamenti

Con il server MCP attivo, il collegamento tra Claude e intervals.icu è diventato reale.

Ho creato un Progetto su Claude dedicato al nuoto, che ho chiamato “AI-nuoto”, e ci ho caricato come riferimento lo storico delle mie sedute esportato da Final Surge, con la mia struttura abituale: sedute A, B e C e zone di intensità da A1 a C3.

La prova del nove è stata la domanda più semplice: “vedi i miei allenamenti?”.

Claude ha interrogato intervals.icu e in pochi secondi mi ha restituito il riepilogo delle ultime due settimane: le nuotate in piscina con il passo medio su 100 metri, le uscite in acque libere, le camminate, lo yoga, e l’andamento di fitness e fatica.

La cosa interessante non è tanto l’elenco, che vedo anche su intervals.icu, quanto la lettura.

Claude ha notato per esempio che in una sessione in mare avevo tenuto lo stesso passo della piscina, un buon segnale visto che in acque libere non ci sono virate e spinte dal muro.

Ha anche calcolato che il carico era moderato e che la mia forma era leggermente positiva, cioè ero riposato.

Da qui in poi i dati non sono più solo numeri da guardare: diventano la base per ragionare sulla programmazione.

Creare un server MCP per intervals.icu

Avere i dati su intervals.icu è utile, ma volevo fare un passo in più.

Poterli discutere con Claude, l’assistente di intelligenza artificiale di Anthropic, come farei con un allenatore.

Il problema è che un assistente AI, da solo, non ha accesso ai miei dati.

Qui entra in gioco MCP.

MCP, cioè Model Context Protocol, è uno standard aperto che permette di collegare un assistente AI a strumenti e servizi esterni. Un “server MCP” è un piccolo programma che fa da ponte.

Da un lato parla con il servizio (in questo caso intervals.icu), dall’altro espone a Claude una serie di strumenti, come “leggi le attività”, “leggi i dati di benessere” o “aggiungi un evento al calendario”.

Per intervals.icu esiste un server MCP open source.

La configurazione ha richiesto questi passaggi:

  1. Installare i requisiti sul computer [Python e il gestore di pacchetti indicato nella documentazione del progetto].
  2. Scaricare il progetto e creare un file di configurazione con due dati: la chiave API personale, che si genera nelle impostazioni per sviluppatori di intervals.icu, e l’ID atleta.
  3. Registrare il server nella configurazione di Claude Desktop, così che Claude lo avvii e lo possa usare.

Un’avvertenza: la chiave API dà accesso ai propri dati, quindi va trattata come una password e non va mai condivisa o pubblicata.

Garmin e intervals.icu: far parlare l’orologio con la piattaforma di analisi

Da qualche tempo registro tutto con il mio Garmin fenix 7

Nuoto in piscina, acque libere, bici, camminate e perfino le sessioni di yoga.

Garmin Connect è comodo per avere un colpo d’occhio, ma quando si vuole capire davvero come sta andando l’allenamento serve qualcosa di più.

Per questo ho scelto intervals.icu, una piattaforma di analisi molto apprezzata da ciclisti, triatleti e nuotatori, che calcola carico di allenamento, fitness, fatica e forma nel tempo.

Il collegamento è semplice.

Dalle impostazioni di intervals.icu si apre la sezione delle connessioni, si sceglie Garmin Connect e si autorizza l’accesso con le proprie credenziali Garmin.

Da quel momento ogni attività registrata con l’orologio arriva automaticamente su intervals.icu pochi minuti dopo la sincronizzazione con il telefono. Vengono inoltre importati i dati di benessere, come frequenza a riposo, sonno e peso.

Il vantaggio è immediato.

Per ogni nuotata intervals.icu mostra distanza, passo, frequenza cardiaca, carico e il suo contributo alla curva di fitness.

Guardando le ultime settimane posso capire se sto accumulando fatica o se sono fresco, e tutto senza inserire un solo dato a mano.

Questo è il primo mattone. Nel prossimo articolo racconto come ho dato a un’intelligenza artificiale la possibilità di leggere questi dati.

Notate che in questa modalità non serve utilizzare strava.