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.)


Related MCP server: Garmin MCP Server

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

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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