Skip to main content
Glama
AryanP45

Garmin Health MCP Server

by AryanP45

Garmin Health MCP Server

A remote MCP server that exposes your Garmin Connect health data as tools that Claude (or any MCP-compatible client) can call. Runs over Streamable HTTP so it can be added as a custom connector on claude.ai.

⚠️ Disclaimer: This project uses the unofficial garminconnect library, which authenticates with your Garmin email/password instead of Garmin's official OAuth partner API. This approach is common for personal projects but is against Garmin's Terms of Service — use it knowing that risk.


Features

  • 10 ready-to-use health tools (steps, sleep, HR, HRV, stress, Body Battery, activities, and more)

  • Bearer-token auth so only you can access your data

  • Session caching — logs in once, reuses the token for months

  • Docker-ready for deployment on any host (Fly.io, Render, Railway, VPS, etc.)


Project structure

File

Purpose

server.py

MCP server (FastMCP + Streamable HTTP) — defines all tools

garmin_client.py

Garmin session handling, retry-on-expiry

login_once.py

Run locally once to complete MFA and save the session

test_connection.py

Sanity-check that the cached token is still valid

Dockerfile

Container for deployment

.env.example

Required environment variables


Available tools

Tool

Description

get_daily_summary(target_date)

Steps, calories, floors climbed, resting HR, distance

get_heart_rate(target_date)

Resting HR, min/max, and full time-series

get_sleep(target_date)

Duration, stages (Deep/Light/REM/Awake), sleep score

get_body_battery(target_date)

Body Battery (energy reserve) levels

get_stress(target_date)

Stress level readings throughout the day

get_hrv(target_date)

Heart Rate Variability status

get_body_composition(target_date)

Weight, body fat %, muscle mass

get_recent_activities(limit)

Latest recorded workouts, newest first

get_activity_details(activity_id)

Full details for one activity by ID

get_week_summary(start_date)

7-day rollup of daily summaries

All target_date / start_date parameters accept YYYY-MM-DD. Omit them to default to today.


Setup

1. Clone & install

git clone https://github.com/<you>/garmin-mcp-server.git
cd garmin-mcp-server
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt

2. Configure environment

cp .env.example .env
# Edit .env — fill in GARMIN_EMAIL, GARMIN_PASSWORD, and MCP_AUTH_TOKEN

Generate a strong MCP_AUTH_TOKEN:

python -c "import secrets; print(secrets.token_urlsafe(32))"

3. Handle MFA locally (one-time)

Garmin may challenge the first login with an MFA code. A headless server can't answer that prompt, so do the interactive login on your own machine first:

python login_once.py

This saves a garmin_tokens/ directory containing the session token. Garmin tokens typically stay valid for months — the server auto-refreshes them.

Verify it worked:

python test_connection.py

4. Deploy the server

Build and run locally:

docker build -t garmin-mcp .
docker run -d -p 8000:8000 \
  -v $(pwd)/garmin_tokens:/data/garmin_tokens \
  --env-file .env \
  garmin-mcp

For cloud deployment (Fly.io, Render, Railway, etc.):

  1. Mount a persistent volume at /data — copy your local garmin_tokens/ folder into /data/garmin_tokens on it so the container resumes the session without needing a fresh login.

  2. Set these environment variables on the host:

    • GARMIN_EMAIL and GARMIN_PASSWORD — fallback credentials for full re-login

    • MCP_AUTH_TOKEN — the secret you generated above

  3. Expose port 8000. Your MCP endpoint will be https://your-domain.com/mcp.


Connect to Claude

  1. In claude.ai → Settings → Connectors → Add custom connector

  2. Enter your server URL: https://your-domain.com/mcp

  3. Open Advanced settings → Request headers and add:

    • Key: Authorization

    • Value: Bearer <your MCP_AUTH_TOKEN>

  4. Save, then enable the connector in a conversation.

Note: Request-header auth is currently a beta feature on claude.ai. If you don't see it yet, check back soon or swap the middleware in server.py for OAuth.


Running locally (without Docker)

source venv/bin/activate
python server.py
# Server starts at http://localhost:8000/mcp

Notes & limitations

  • Single-user only — this server is designed for your personal Garmin account.

  • Unofficial API — Garmin may change internal endpoints at any time and break the garminconnect library. A quick pip install -U garminconnect usually fixes it.

  • Keep your token secret — anyone with MCP_AUTH_TOKEN can read your Garmin health data through this server. Treat it like a password.

  • Token expiry — if Garmin invalidates your session (e.g. after a password change), re-run login_once.py locally and upload/mount the refreshed token store.


License

MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AryanP45/garmin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server