garmin-connect-mcp
Exposes a user's own Garmin Connect activity, health, and training data as read-only tools — including activities and workouts, daily summaries, sleep, steps, heart rate and zones, body battery, stress, HRV, SpO2, fitness age, hydration, weight, food logs, menstrual cycle data, plus training status, training readiness, VO2 max, race predictions, personal records, devices, activity splits/laps/weather/gear, and respiration. Uses Garmin's official Personal API for most data and an unofficial fallback for data not yet officially exposed.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@garmin-connect-mcpwhat was my sleep like last night?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
garmin-connect-mcp
An MCP server that exposes your own Garmin Connect activity, health, and training data as tools Claude (or Cursor, or any other MCP client) can call.
It's a hybrid server:
Most tools call Garmin's own official Personal API, launched October 2026 — you generate a key yourself from Garmin Connect's website, no password ever touches this code, and it's fully within Garmin's terms of service.
A smaller set of tools fall back to the unofficial
garminconnectlibrary, for data Garmin hasn't exposed officially yet (see below). Every one of those tools' descriptions starts with(unofficial API)so it's always clear which backend answered.
You only need to set up the backend(s) behind the tools you actually
want — if you never call an unofficial-API tool, you never need to run
garmin-mcp-auth or hand this code your Garmin password at all.
What this gives Claude
23 tools on the official Personal API — no password, ever:
Area | Tools |
Activities & workouts |
|
Health & wellness |
|
Women's health |
|
11 tools on the unofficial fallback — data Garmin's Personal API
doesn't cover yet, each clearly labeled (unofficial API) in its
description:
Area | Tools |
Training metrics |
|
Activities & workouts |
|
Health & wellness |
|
Every tool is read-only — nothing here can modify your Garmin account. (The official Personal API is pull/read-only by design; it also can't push structured workouts to your watch — that's a Business-tier-only capability Garmin calls the Training API.)
Related MCP server: garmin-mcp
⚠️ About the unofficial fallback tools
The 11 tools above are outside Garmin's terms of service, even though
they're just reading your own data — Garmin hasn't exposed this data via
an official API yet. In practice this is widely used and low-risk, but
not zero-risk. They use
garminconnect,
itself built on garth, whose docs
currently say it's deprecated and no longer actively maintained —
new logins may break if Garmin changes its login flow. If one of these
specific tools stops working, check the
python-garminconnect issues
before assuming it's something in this repo. As Garmin expands the
official Personal API, expect these tools to migrate over and this
section to shrink.
If you'd rather skip this entirely: just don't run garmin-mcp-auth.
The 23 official tools work completely independently of it; the 11
unofficial tools will return a clear {"error": ...} telling you (or
Claude) that they need it, instead of failing silently.
Two ways to run this
|
| |
Transport | stdio | HTTP (Streamable HTTP) |
Where it runs | your own machine | anywhere public (Railway, etc.) |
Reachable from | Claude Desktop/Cursor on that machine only | claude.ai on any device, including your phone |
Tools | all 34 (23 official + 11 unofficial) | 23 official only — no unofficial fallback |
Your Garmin password | only touches | never — this server doesn't have the code path at all |
Access control | whoever has your machine | OAuth2 + a password you set ( |
Use the local server if you only ever use Claude Desktop/Cursor on one machine and want every tool, unofficial fallback included. Use the remote server if you want this to work from claude.ai on your phone too — the trade-off is giving up the 11 unofficial-fallback tools (training status/readiness, VO2 max, race predictions, personal records, devices, activity splits/laps/weather/gear, respiration) on that path, since hosting the unofficial login anywhere but your own machine is the one thing this project won't do. Nothing stops you running both at once.
Setup
Requires Python 3.10+ (the official Garmin package needs 3.12+; if you're on 3.10 or 3.11 you can still use the unofficial-fallback tools, but install the official dependency separately once you upgrade).
git clone <this-repo-url>
cd garmin-connect-mcp
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .1. Official Personal API — generate a key (no password needed)
Sign in to Garmin Connect on the web.
Go to Settings → Personal API Key → Create Key. Pick an expiration (30/90/180 days, or 1 year). Garmin shows the key exactly once — copy it.
Save it locally:
garmin-mcp-save-keyPaste the key when prompted. It's written to
~/.config/garmin/connect-personal-api-keywith0600permissions. (Setting theGARMIN_PERSONAL_API_KEYenvironment variable instead also works and takes precedence —garmin-mcp-save-keyjust avoids putting the key in your shell history.)
Garmin emails you about a week before the key expires; when it does, repeat these steps with a new key.
2. Unofficial fallback — only if you want those 11 tools
From a real terminal — not from inside Claude or Cursor, since you may need to type an MFA code:
garmin-mcp-authAsks for your Garmin Connect email and password (and an MFA code, if
your account uses one), then caches a session token at
~/.garminconnect. You only need to do this once; the token refreshes
itself automatically as it's used, and commonly lasts close to a year.
If it ever stops working, run garmin-mcp-auth again. To delete the
cached session instead, run garmin-mcp-auth --logout.
3. Point your MCP client at the server
Claude Desktop — edit your claude_desktop_config.json:
{
"mcpServers": {
"garmin-connect": {
"command": "/absolute/path/to/garmin-connect-mcp/.venv/bin/garmin-mcp-server"
}
}
}Cursor — edit .cursor/mcp.json (project-level or
~/.cursor/mcp.json for all projects): same JSON as above.
Replace /absolute/path/to/garmin-connect-mcp with wherever you cloned
this repo. Restart the client afterward so it picks up the new server.
Remote server (phone-reachable)
This deploys garmin-mcp-remote-server — the 23-official-tools-only,
HTTP variant — somewhere public, then adds it to claude.ai as a custom
connector so it works from any device, phone included.
1. Deploy to Railway
Push this repo to GitHub (it already has a
DockerfileRailway will auto-detect — no other config needed).In Railway, New Project → Deploy from GitHub repo → pick this repo.
Under the service's Variables, set:
GARMIN_PERSONAL_API_KEY— your Garmin Personal API key (same key as the local setup's step 1, pasted directly as a secret env var — there's no terminal here to rungarmin-mcp-save-key).GARMIN_MCP_ACCESS_PASSWORD— a password you invent for this server. It's unrelated to your Garmin password and this server never sees your Garmin password at all; this is the one secret that decides who can get a token and call your tools.GARMIN_MCP_PUBLIC_URL— leave this for step 4, once Railway has assigned a domain.
Railway builds and deploys; under Settings → Networking, click Generate Domain to get a public HTTPS URL like
https://garmin-mcp-production.up.railway.app.Go back to Variables and set
GARMIN_MCP_PUBLIC_URLto that exact URL (no trailing slash). Redeploy (Railway usually does this automatically when a variable changes).Sanity check:
curl https://<your-domain>/healthshould returnok.
Garmin emails you about a week before your Personal API key expires;
when it does, generate a new one and update the
GARMIN_PERSONAL_API_KEY variable in Railway.
2. Add it to claude.ai as a custom connector
On claude.ai: Settings → Connectors → Add custom connector.
Paste your Railway URL as the connector URL.
Pick Register automatically for the OAuth client setup (Dynamic Client Registration) — the server handles this itself, no manual client ID/secret to create.
Connecting will open a small login page asking for the access password — the
GARMIN_MCP_ACCESS_PASSWORDyou set in Railway, not your Garmin password. Enter it once; claude.ai stores the resulting token and refreshes it automatically afterward.Add the connector to whichever Projects should use it (e.g. your cycling coach Project) under that Project's connector settings.
That's it — the 23 official-API tools are now reachable from claude.ai on web, desktop, and mobile.
How the login works, briefly
There's no user database — you're the only real user. claude.ai
registers itself as an OAuth client automatically (that's normal and
expected; registering isn't the same as getting access). Getting an
actual access token still requires your GARMIN_MCP_ACCESS_PASSWORD via
the login page. Tokens and registered clients are kept in memory, not in
a database, so a Railway restart or redeploy means reconnecting once
(claude.ai will prompt you) — there's nothing durable to go stale or get
out of sync.
Unofficial fallback tools on the remote server (optional, higher risk)
The 11 unofficial-fallback tools (see the warning above) are registered
on the remote server too, but return {"error": ...} until you log in to
Garmin's unofficial API there — deliberately a separate, opt-in step from
deploying the server itself, because it means your Garmin email/password
exist on a public host at least once, which is a meaningfully bigger risk
than the official-API-only setup above. Think it through before doing
this; a compromise of this server then means full Garmin account access,
not just read-only fitness data. If you'd rather not, skip this section —
everything else works exactly as described above.
If you do want it:
Visit
https://<your-domain>/admin/garmin-login.Enter your
GARMIN_MCP_ACCESS_PASSWORD(the same one from step 3 above — not your Garmin password) plus your Garmin email and password. These go straight to this server over HTTPS, never through Claude or claude.ai, and the server never writes the password to disk, an env var, or a log line — only the resulting session is kept, in memory.If Garmin challenges the login with an MFA code (likely, the first time, since a cloud host's IP looks new to it), you'll get a second form for the code it emailed or pushed to your Garmin Connect app.
On success, the page shows an opaque session token. Memory-only means a restart, redeploy, or (on Render's free tier) idle-spindown forgets it and you'll need to revisit this page — if that's annoying, paste that token into a
GARMIN_UNOFFICIAL_SESSIONenvironment variable and redeploy; the server will resume it automatically from then on, without needing your password again. Treat that token like a password too: whoever has it can read your Garmin data.
Testing without touching your real Garmin account
pip install -e ".[test]"
pytestThe test suite mocks out both backends entirely — it never logs in or hits a real API, Garmin or claude.ai. Two files:
tests/test_server.py— the local hybrid server. Checks that every tool calls the right underlying method with the right arguments, that a missing key/session comes back as a normal{"error": ...}result instead of crashing the server, that an expired official-API access token is transparently refreshed and retried once, and that all 34 tools register with the official ones unlabeled and the unofficial ones all starting with(unofficial API).tests/test_remote_server.py— the remote server's OAuth flow, driven through the real Starlette app (not just the provider in isolation): dynamic client registration, the password-gated login page (including a wrong-password attempt), PKCE code exchange, that an authorization code can't be redeemed twice, refresh-token rotation invalidating the old access token, bearer-token enforcement on the MCP endpoint, Host- header validation, and that only the 23 official tools are registered (no unofficial fallback, ever).
It's a fast sanity check — it does not replace actually running the setup steps above and trying a real tool call from Claude, Cursor, or claude.ai.
How it works
garmin_mcp/auth_official.py/authenticate_official.py— the official Personal API path.garmin-mcp-save-keyonly ever saves a key you already generated; the running server exchanges it for a short-lived bearer token (via Garmin's owngarmin-connect-personal-api-pythonclient) and transparently re-authenticates if a token expires mid-session.garmin_mcp/auth_unofficial.py/authenticate_unofficial.py— the unofficial fallback path. Onlyauthenticate_unofficial.py(run viagarmin-mcp-auth) ever touches your email/password; the server itself only ever resumes the cached session token. Not imported by the remote server at all.garmin_mcp/tools_official.py/tools_unofficial.py— the 23 and 11 tool implementations, as plain functions rather than tied to one server instance, so the local and remote servers can register the same official-tool code (mcp.add_tool(fn)) instead of maintaining two copies.garmin_mcp/server.py— the local, stdio MCP server: registers all 34 tools from the two modules above. Reachable only from the machine it runs on.garmin_mcp/remote_auth.py/remote_server.py— the remote, HTTP MCP server: registers only the 23 official tools, plus a minimal single-user OAuth 2.0 authorization server (Dynamic Client Registration + a password-gated/loginpage) so a bearer token, not just the URL, is what lets a client call it.
Troubleshooting
A tool returns
{"error": "No Garmin Personal API key found..."}— rungarmin-mcp-save-key.A tool returns
{"error": "...access token..."}— the saved key expired or was deleted on Garmin's side; create a new one and rungarmin-mcp-save-keyagain.A tool returns
{"error": "No cached Garmin Connect session found..."}— rungarmin-mcp-auth(only needed for the 11 unofficial-fallback tools).An unofficial-fallback tool's login fails — check the python-garminconnect issue tracker; Garmin's login flow has changed before and will likely change again.
Some fields seem missing from official-API activity data — there have been reports (e.g. from Runalyze) that Garmin strips some undocumented fields (VO2 max estimate, recovery time, performance condition) from API-delivered files. That's a Garmin-side limitation of the official API, not a bug here — it's part of why
get_max_metricsstill uses the unofficial fallback.claude.ai says it can't connect / the connector keeps failing — check
curl https://<your-domain>/healthreturnsokfirst; if that fails, check Railway's deploy logs for a missing-env-var error (garmin-mcp-remote-serverrefuses to start withoutGARMIN_PERSONAL_API_KEY,GARMIN_MCP_PUBLIC_URL, andGARMIN_MCP_ACCESS_PASSWORDall set).The remote server's login page says the link expired — pending logins and issued tokens are kept in memory only, so a Railway restart/redeploy clears them; just reconnect the connector in claude.ai and log in again.
A remote tool call fails but the same tool works locally — the remote server only has the official-API tools; if it's one of the 11 unofficial-fallback tools (see the table above), that's expected — use the local
garmin-mcp-serverfor those.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Unofficial Garmin Connect access: sleep, HRV, training, activities, workouts and weight.
Multi-tenant hosted MCP server for Oura Ring — 21 read-only tools, OAuth per user.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceExposes personal Garmin wellness data through MCP tools for accessing summary, sleep, HRV, heart rate, stress, body battery, and historical data.MIT
- AlicenseNot gradedqualityCmaintenancePersonal MCP server for interacting with your Garmin Connect data. Exposes 62 tools across 11 domains including activities, health, training, and workouts.1MIT
- FlicenseNot gradedqualityDmaintenanceExposes Garmin Connect health and activity data (steps, sleep, heart rate, etc.) via MCP tools, with built-in login and MFA support.-
- FlicenseNot gradedqualityDmaintenanceExposes Garmin Connect health data (steps, sleep, HR, HRV, stress, activities, etc.) as tools for MCP-compatible clients like Claude.-