garmin-coach-mcp
This server enables Claude to read and analyze your Garmin Connect data, and optionally create or manage workouts.
Read & Analysis
Connection status & account info
List recent activities (filter by type) and retrieve detailed metrics for any activity
Per-set strength data (exercises, reps, weight, estimated 1RM) and strength history trends
Recovery snapshot: sleep, daily stats, training readiness
Health trends: time series for resting HR, steps, stress, body battery, etc.
Progressive overload suggestions based on history
Write Capabilities (disable with GARMIN_COACH_READONLY=1)
List, create, schedule, and delete workouts (strength)
Schedule existing workouts onto your calendar
Delete workouts (e.g., to undo experimental creations)
Integrates with Garmin Connect to read activity data (recent activities, per-set strength history, sleep, recovery, trends) and optionally create, schedule, and delete strength workouts on the user's Garmin watch.
Click on "Install 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-coach-mcphow was my sleep and recovery today?"
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-coach-mcp
An MCP server that lets Claude read and answer questions about your Garmin Connect data — recent activities, per-set strength history, sleep and recovery, and simple trends — and optionally build workouts back onto your watch.
Same code, two ways to run it:
Mode | Where | Use it for | Setup |
Local | Your PC, launched by Claude Code | Day-to-day at your desk | ~2 min, free |
Hosted | Azure Container Apps | Asking from your phone, PC off | ~20 min, ~$5/mo |
Local is the default: nothing listens on a socket, so nothing needs authenticating. Hosted is opt-in and sits behind Microsoft Entra sign-in.
Garmin's API is unofficial. This uses
python-garminconnect, which is not sanctioned by Garmin and can break when they change their backend. Fine for personal use; don't build anything load-bearing on it.
Quick start
Local
git clone https://github.com/jhoy1020/garmin-coach-mcp.git
cd garmin-coach-mcp
./scripts/setup.sh # or .\scripts\setup.ps1 on WindowsCreates the virtualenv, installs the package, runs the one-time Garmin login, and
registers the server with Claude Code using this checkout's own path. Nothing to edit.
Verify with python scripts/doctor.py, then restart Claude Code and ask it something.
Hosted — after the local setup works:
python scripts/deploy.pyProvisions Azure, registers the Entra application, seeds your Garmin token, and prints the connector URL.
Related MCP server: garth-mcp-server
What leaves your machine
Local mode: nothing. The server talks to Garmin directly from your PC. Your Garmin password is typed into a subprocess and never stored — only a refreshable token, in
~/.garminconnect.Hosted mode: that token is uploaded to an Azure file share in your own subscription, and your Garmin data passes through your own container. Requests come from claude.ai's servers. See docs/security.md.
Tools
Read (9)
Tool | What it answers |
| Is the connection working? Whose account? |
| "Show my last N workouts" |
| Detailed metrics for one activity |
| Per-set exercise / reps / weight / est. 1RM |
| "Is my squat going up?" |
| Sleep + daily stats + training readiness |
| Resting HR, steps, stress over time |
| Progressive-overload recommendation |
| Saved workouts (name + id) |
Write (3) — set GARMIN_COACH_READONLY=1 to drop these from the manifest entirely.
Tool | What it does |
| Build a strength workout on Garmin (experimental) |
| Put an existing workout on your calendar |
| Undo / remove a workout |
Strength answers only have data if you log Strength activities with weights on your watch.
create_strength_workoutuses Garmin's unofficial workout schema — check the result in the Garmin Connect app anddelete_workoutif it's wrong.
Layout
src/garmin_coach_mcp/
server.py tool definitions + entry point
config.py settings; refuses to start on unsafe combinations
http_app.py SecretGate - the auth ladder for hosted requests
oauth.py validates Entra-issued tokens
oauth_broker.py a small OAuth 2.1 server (the path real clients use)
ratelimit.py token buckets for the unauthenticated endpoints
garmin_client.py cached, token-authenticated Garmin client
analysis.py strength-history and trend computations, argument clamps
strength_workout.py Garmin workout payload builder
login.py one-time interactive Garmin login
scripts/ setup, deploy, doctor, rotate, secret scanner
infra/ Bicep for the hosted deployment
tests/ 109 tests
docs/ setup, architecture, security, troubleshootingDocumentation
Run it on your PC | |
Deploy to Azure with Microsoft sign-in | |
How it's built and why | |
Threat model, what protects what, rotating secrets | |
Organised by what you actually see | |
Context for AI agents working on this repo |
Scripts
Task | Command |
Set up locally |
|
Diagnose anything |
|
Deploy to Azure |
|
Register the Entra app |
|
Upload the Garmin token |
|
Rotate secrets |
|
Get the connector URL |
|
Scan for secrets |
|
Configuration
.env.example documents every setting. The ones you are most likely to touch:
Variable | Default | Meaning |
|
|
|
| off | Hide the three write tools entirely |
|
| Where the Garmin OAuth token lives |
| your machine's | Container |
|
| Hosts that may receive an authorization code |
Hosted mode also needs the Entra values, which scripts/deploy.py sets for you — see
docs/remote-setup.md for the name mapping between what you type
and what the container reads.
config.py refuses to start on unsafe combinations rather than running half-secured:
a partial Entra configuration, an http transport with no way to authenticate, a
too-short secret, a non-https public URL, access logging alongside a URL secret, or a
wildcard redirect-host allowlist without an explicit second opt-in.
Tests
python scripts/setup_local.py --dev # installs pytest
python -m pytest109 tests. The security-relevant ones are written to fail if the fix is reverted — the
concurrency test genuinely serialises without the threadpool, and the rate-limiter test
fails if the limiter key goes back to the spoofable leftmost X-Forwarded-For entry.
Contributing
python scripts/install_hooks.py enables the pre-commit scanner (setup does this for
you). It blocks credentials and personal data — this repository is public, and the
thing that actually needed cleaning up was absolute paths and resource names, not keys.
CI runs the same checks.
Licence
MIT.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for Garmin Connect that provides read-only access to daily health metrics, activities, workouts, and body composition data.Last updated32MIT
- Alicense-qualityCmaintenanceMCP server to interact with Garmin Connect, enabling retrieval of health, activity, and device data through natural language.Last updated63MIT
- Alicense-qualityCmaintenancePersonal MCP server for interacting with your Garmin Connect data. Exposes 62 tools across 11 domains including activities, health, training, and workouts.Last updated1MIT
- Alicense-qualityDmaintenanceMCP server that exposes Garmin Connect health and activity data (steps, sleep, stress, activities, etc.) via tools for querying, analysis, and visualization.Last updatedApache 2.0
Related MCP Connectors
MCP server for Withings health data — sleep, activity, heart, and body metrics.
MCP server wrapping the Tesla Fleet API and TeslaMate API
List, fetch, create, edit (replace), delete and schedule structured workouts on Garmin Connect (runn
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/jhoy1020/garmin-coach-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server