Codync
免费开源的 1:1 Grok Bot 与 Muse 替代方案。可在 iPhone、Mac 或 Linux 桌面上将 Claude 代码、Codex、Cursor 以及 40 多个编码代理作为持久机器人使用。支持群组聊天、线程、应用。
AI 翻译
MCP server for Garmin Connect on Garmin's official Personal API: sleep, HRV, body battery, activities, and more from Claude or any MCP client
翻译准备中
开发工具GitHub @Mason-Levyy自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Ask your AI about your Garmin data, on Garmin's official API.
Quickstart · Tools · Authentication · Changelog
Garmin Personal MCP is a free, open-source MCP server that connects your Garmin Connect account to Claude, Cursor, VS Code, or any other MCP client. Ask about last night's sleep, HRV trends, Body Battery, stress, training load, weight, or a specific run, all from your real Garmin account. It runs on Garmin's official Personal API with a revocable key, so it never needs your Garmin password, and it's read-only.
Published on PyPI as garmin-personal-mcp
and in the official MCP Registry as io.github.Mason-Levyy/garmin-personal-mcp.
Unofficial project, official API. This isn't made by Garmin, but it only talks to Garmin's documented Personal API through Garmin's own Python client.
Most Garmin MCP servers sign in with your Garmin password through the
unofficial garminconnect library, which breaks whenever Garmin changes its
login. In October 2026 Garmin opened a Personal
API for individuals. This server uses it:
Save your Personal API key (one-time; see Authentication):
uvx garmin-personal-mcp auth
Add the server to your client. The install buttons at the top do this in one click for Cursor and VS Code.
Claude Code
claude mcp add garmin -- uvx garmin-personal-mcp
Or install it as a plugin, which asks for your key in place of step 1:
/plugin install garmin-personal-mcp --marketplace Mason-Levyy/garmin-personal-mcp
Claude Desktop (claude_desktop_config.json), Cursor
(~/.cursor/mcp.json), Windsurf (~/.codeium/windsurf/mcp_config.json),
and Cline (cline_mcp_settings.json) all take the same entry:
{
"mcpServers": {
"garmin": {
"command": "uvx",
"args": ["garmin-personal-mcp"]
}
}
}
VS Code (or use the button above):
code --add-mcp '{"name":"garmin","command":"uvx","args":["garmin-personal-mcp"]}'
Codex CLI:
codex mcp add garmin -- uvx garmin-personal-mcp
Gemini CLI:
gemini mcp add garmin uvx garmin-personal-mcp
Ask it something: "how did I sleep last night?", "is my HRV trending down this month?", "compare my last three long runs".
Requires uv. Any MCP client that speaks stdio or streamable HTTP works, not just Claude.
Finding this useful? A ⭐ on GitHub helps other Garmin users find it.
garmin-personal-mcp auth and paste it at the hidden prompt. The
server checks it with Garmin before saving it to
~/.config/garmin/connect-personal-api-key with owner-only permissions.Where there's no terminal to prompt in (a script, or a shell an agent runs),
pipe the key in instead, e.g. pbpaste | garmin-personal-mcp auth.
garmin-personal-mcp auth --check reports whether the saved key still works,
without prompting. Garmin emails you about a week before a key expires: create
a new one and run auth again. No restart is needed; the server reads the key
on every call.
Instead of the key file you can set GARMIN_PERSONAL_API_KEY, which takes
precedence. The key file and bearer-token cache are the same ones Garmin's
gc-personal CLI uses, so a key saved by either works for both.
Run the server as a background HTTP service using the prebuilt image. Save
this as compose.yaml:
services:
garmin:
image: ghcr.io/mason-levyy/garmin-personal-mcp:latest
command: ["--http", "--host", "0.0.0.0"]
environment:
- GARMIN_PERSONAL_API_KEY
ports:
- "127.0.0.1:8491:8491"
volumes:
- garmin-config:/home/garmin/.config/garmin
- ./downloads:/home/garmin/Downloads/garmin
restart: unless-stopped
volumes:
garmin-config:
latest is the newest release, the same version PyPI serves. To stay on one
version, use a version tag such as :0.2.0 instead.
From the directory containing compose.yaml, create the downloads folder and
pull the image:
mkdir -p downloads
docker compose pull
Activity files from garmin_download_activity land in ./downloads. The tool
reports the path inside the container (/home/garmin/Downloads/garmin/...),
which is the same file. The container runs as uid 1000, so on Linux, if your
uid isn't 1000, run sudo chown 1000 downloads.
Don't mount an existing ~/.config/garmin from the host into the container.
The key file there is readable only by its owner, so the container can't read
it unless your uid is 1000. Use one of the options below instead.
The container paths above and uid 1000 stay the same across releases.
Choose one of these authentication options:
.env fileCreate .env next to compose.yaml and add your Personal API key:
GARMIN_PERSONAL_API_KEY='your-personal-api-key'
Compose loads this file automatically. You do not need to run auth.
auth commandLeave GARMIN_PERSONAL_API_KEY unset in your shell and .env, then run:
docker compose run --rm garmin auth
Paste your Personal API key at the prompt. It is saved for subsequent starts.
docker compose up -d
In your MCP client, add a Streamable HTTP server with the URL
http://127.0.0.1:8491/mcp.
The server only accepts requests addressed to 127.0.0.1 or localhost, and
it has no authentication. To reach it from another machine, keep the port on
127.0.0.1, put an authenticating proxy or tailnet in front (see
Remote / HTTP mode), and add the hostname clients use to
command:
command: ["--http", "--host", "0.0.0.0", "--allowed-host", "garmin.example.ts.net"]
Without --allowed-host, requests to any other hostname are rejected.
Clone the repository and use compose.yaml in its root, which builds the image from source. From the repository directory, run:
docker compose build
Then follow the authentication and startup steps above. After updating the source, rebuild and restart with:
docker compose up --build -d
All tools take dates as YYYY-MM-DD. Range tools default to the 7 days ending
today. Tools that return a list wrap it as {"results": [...]}.
| Tool | What it returns |
|---|---|
garmin_get_day | One day at a glance: summary, sleep, HRV, Body Battery, stress, and activities |
garmin_get_daily_summary | Every all-day wellness total for one date |
garmin_get_daily_summaries | Daily summaries across a range (trends over weeks or months) |
garmin_get_steps | Daily steps, distance, and goal |
garmin_get_stress | Daily stress level and time in each stress band |
garmin_get_hydration | Daily intake, goal, and sweat loss |
garmin_get_body_battery | Daily charge/drain and the events behind it; chunks for intraday lows/highs |
garmin_get_heart_rate | Resting/min/max HR, 7-day resting average, abnormal HR alerts; samples on request |
garmin_get_spo2 | Pulse ox averages, hourly averages, acclimation; readings on request |
garmin_get_wellness_activities | Wellness activities with summary values and time in zones |
garmin_get_sleep | One night in full: score, stages, timings, overnight vitals |
garmin_get_sleep_summaries | Nightly sleep records across a range |
garmin_get_hrv | One night of HRV with every reading |
garmin_get_hrv_summaries | Nightly HRV, weekly average, baseline, and status across a range |
garmin_get_weight | Daily weight summaries, range average, and adjacent weigh-ins; every weigh-in with include_all |
garmin_get_weight_goals | Weight goals in effect and their target ranges |
garmin_get_food_log | Garmin Connect nutrition log: foods, nutrients, goals, meals |
garmin_search_activities | Activities with every filter Garmin supports (type, dates, distance, power, area, dives, ...) |
garmin_get_activity | One activity in full, with splits |
Weights are in grams, distances in meters, and durations in seconds, as Garmin returns them.
The default transport is stdio. For network clients:
garmin-personal-mcp --http --host 127.0.0.1 --port 8491
This serves streamable HTTP at /mcp. There is no built-in authentication.
Never expose it to the internet. Bind to localhost and front it with
something that authenticates for you: a VPN or tailnet (e.g. tailscale serve), an authenticating reverse proxy, or an OAuth-aware MCP gateway. Behind
a proxy, pass --allowed-host <proxy hostname> (repeatable) so the
DNS-rebinding check accepts its Host header.
| Variable | Purpose | Default |
|---|---|---|
GARMIN_PERSONAL_API_KEY | Personal API key; overrides the saved key file | – |
GARMIN_MCP_DOWNLOAD_DIR | Where garmin_download_activity saves files; the tool can't write outside it | ~/Downloads/garmin (platform downloads dir) |
garmin-personal-mcp auth.garmin-personal-mcp auth, or
set GARMIN_PERSONAL_API_KEY in the client config.{"no_data": ...}: Garmin has nothing for that date yet (today's HRV
before you've slept, for example), or your device doesn't record that
metric.Is this the official Garmin API? Yes. It uses Garmin's Personal API, which anyone with a Garmin Connect account can enable without applying, through Garmin's Apache-licensed Python client. The project itself is independent.
Can it change my Garmin data? No. The Personal API is read-only. The one
tool that writes anything, garmin_download_activity, saves a file on your
own machine.
Which MCP clients does it work with? Any client that runs a stdio or streamable HTTP server, including Claude Desktop, Claude Code, Cursor, Windsurf, Cline, and VS Code. AI coding agents can follow llms-install.md.
Where does my data go? The server talks only to Garmin. Your key and
bearer token stay in ~/.config/garmin/. Tool results go to whichever MCP
client and model you connect it to.
Can I use it for other people's accounts? No. Garmin's Personal API is for your own data. Apps serving other users need Garmin's business developer program.
garmin-personal-mcp auth saves the key; each call exchanges it for a
bearer token through Garmin's PersonalApiAuthenticator, which caches the
token until an hour before it expires. A token rejected early gets one
retry with a fresh exchange.personal.connectapi.garmin.com
(garmin_get_day combines several). Ranges longer than an endpoint's
documented maximum are fetched in consecutive windows and concatenated.include_samples or chunks bring them back.git clone https://github.com/Mason-Levyy/garmin-personal-mcp
cd garmin-personal-mcp
uv sync
uv run pytest
Tests run against synthetic fixtures; no account needed. Lint and formatting
are enforced with ruff (uv run ruff check ., uv run ruff format .).
Issues and pull requests are welcome, especially when Garmin adds endpoints to the Personal API. See CONTRIBUTING.md for setup, style, and the PR checklist, and SECURITY.md for how to report vulnerabilities privately. Release history is in CHANGELOG.md.
If this server saves you time, please star the repo. Stars are how other Garmin users find it in GitHub search and MCP directories. Bug reports and endpoint requests are just as welcome in issues.
MIT. Garmin and Garmin Connect are trademarks of Garmin Ltd. or its subsidiaries; this project is not affiliated with or endorsed by Garmin.
garmin_get_activity_workouts |
| The structured workout followed during an activity |
garmin_download_activity | Save an activity's original file (ZIP with the .fit) on the server's machine |
garmin_get_profile | Units, formats, time zone, and training-day preferences |
garmin_get_heart_rate_zones | Zone floors per sport and the HRs they're based on |
garmin_get_fitness_age | Fitness age, achievable fitness age, and its components |
garmin_get_menstrual_cycle | Cycle phase, day, fertile window, and predictions |
garmin_get_menstrual_day | One day's logged symptoms, flow, and cycle detail |