I want my AI agents to become my personal health coaches.
I’d like them to help me follow my progress, make sense of my training, and notice when my sleep or activity starts slipping. For that to be useful, they need to know how I’m actually doing. I don’t want to start every conversation by telling them how much I slept or copying over a week of stats.
My Garmin already collects a lot of that context. Giving my agents access to it felt like the obvious first step: let them look up my sleep, activity, and recovery data themselves, and follow how those numbers change over time.
So I built garmin-mcp: a small pipeline that copies my Garmin data to my home server and gives my agents tools to read it. I use a Garmin Cirqa, but the project works with Garmin Connect data rather than depending on that particular band.
The first step: let the agent see how I’m doing
Here’s an actual conversation with Hermes in Discord. I asked how my sleep had been over the last seven days, and what my step statistics looked like. It’s a simple check that the agent can find and use that context on its own.
It reported an average of 8 hours of sleep per night, a Garmin sleep score averaging 90/100, and 45,289 steps for November 1–7, or about 6,470 a day.
The detail I liked most was at the end: it said it had left November 8 out because that day’s sleep and step fields were still missing from the latest sync. That matters. A missing day shouldn’t quietly become a day with zero steps.
I didn’t have to tell Hermes what my week looked like. It called the Garmin tools, did some calculations, and answered in the chat. I’m still asking the questions here; the part I’ve removed is having to supply the numbers. That gives me a starting point for the coaching I want to build.
How the pieces fit together
The band syncs to Garmin Connect. From there, I pull the data onto a remote machine, store it in SQLite, and make it available to both a dashboard and my agents.
Sync first, keep the original
A systemd user timer runs garmin-optimizer sync at 07:20 and 21:40, with up to 20 minutes of random delay. The Python script uses the community python-garminconnect library to fetch data over HTTPS, reusing a cached login token rather than storing my password.
Every API response is saved untouched in SQLite’s raw_response table before anything is transformed. That gives me a record of what Garmin returned and lets me rebuild the derived data when the parsing logic changes.
Turn responses into something an agent can query
Replayable transformers populate clean tables for daily summaries, sleep stages, HRV, readiness, and training status, plus per-minute series for heart rate, stress, Body Battery, and SpO₂ where available.
On top of those tables sit v_day, v_week, and v_trends. The trends view adds 7- and 28-day baselines and z-scores, so the agent can compare a measurement with my recent history. A metric_catalog table describes the metrics, giving it context for interpreting the columns.
One read-only layer, two ways in
A shared service layer reads the database and feeds two front ends. The first is FastAPI with a React dashboard.
The second is an MCP server. It exposes tools such as get_day, get_range_summary, compare_periods, get_sleep_detail, and get_timeseries. A restricted run_sql tool handles questions that need a custom query. Those tools can read the cleaned tables and views, but access to the raw payloads is blocked.
Hermes brings the data into the conversation
My Hermes gateway runs on the same remote machine. When it needs Garmin data, it launches the MCP server on demand over stdio: the processes communicate through standard input and output.
That lets me ask, “How did I sleep this week compared with last week?” Hermes can query the relevant days, compare them against my baselines, and bring the answer back to Discord. In the screenshot, it checks sync status, retrieves days, and requests a range summary. The agent gets the context it needs without me assembling it first.
What I want to add next
Food, weight, and a training log are next. Garmin gives my agents a useful starting point, but there’s plenty it doesn’t capture: what I ate, which exercises I did, or how much weight I lifted.
I’m also thinking about getting a pair of Meta glasses. I’d like to experiment with taking photos of meals and capturing the weights I’m using at the gym, then feeding that context to my health coach. The idea is to make logging these things easy enough that I actually keep doing it.
With that extra context alongside my Garmin history, I’d like my agents to help me follow my progress and spot patterns worth looking into. Eventually, I want them to bring useful changes to my attention without waiting for me to ask. For now, giving them access to my stats is the first step.
If you want to try it, the setup and agent commands are in the repository. It’s a personal project using an unofficial integration, so expect some maintenance when Garmin changes things.