内容
# garmin-mcp
[](https://github.com/yashhooda1/mcp-garmin/actions/workflows/ci.yml)
[](https://www.python.org/)
[](LICENSE)
> 将徽章和克隆URL中的`OWNER`替换为您的GitHub用户名。
一个 [MCP](https://modelcontextprotocol.io) 服务器,允许AI助手(Claude 或任何MCP客户端)**读取您的Garmin活动**,并**创建和安排结构化训练和多周训练计划**,直接在您的Garmin Connect日历中 - 在那里它们将与引导、逐次提示同步到您的手表。
用平语言描述一个训练,然后它就会出现在您的手表上:
```
"在星期二安排一个4×1mi门槛训练,在星期六安排一个16英里跑,包含4个马拉松配速英里。" → 已构建、安排、同步。
```
基于 [`python-garminconnect`](https://github.com/cyberjunky/python-garminconnect)(garth SSO 认证)和官方MCP Python SDK构建。活动**仅可读取**,设计如此;写入权限仅限于训练和训练日历。
---
## ⚠️ 请先阅读(安全性和条款)
- **没有官方个人API。** Garmin的API计划仅适用于企业,因此本项目使用Garmin的非官方SSO(单点登录),像其他Garmin自动化工具一样。它可能会因Garmin更改其登录流程而中断。
- **长期令牌。** 认证缓存了一个约1年的令牌,授予完全账户访问权限。请像对待生产秘密一样处理`GARMINTOKENS` - 它在这里被git忽略。
- **您自己的风险。** 这可能违反Garmin的使用条款。它旨在供您在自己的账户上个人使用。
- **确保HTTP传输安全。** 一个可以写入Garmin账户的公开可访问服务器存在风险。远程传输需要一个承载令牌(如下所示)。对于大多数人来说,使用Claude Desktop的本地`stdio`是正确选择。
---
## 快速开始
```bash
git clone https://github.com/yashhooda1/mcp-garmin
cd garmin-mcp
pip install -e ".[dev]"
# 一次性登录 - 缓存令牌到 $GARMINTOKENS(默认为 ~/.garminconnect)
export GARMINTOKENS="$HOME/.garminconnect"
garmin-mcp-auth # 提示输入电子邮件/密码/MFA
pytest -q # 离线健康检查(无Garmin调用)
```
认证后,服务器在环境中**不带凭证**运行 - 它从缓存的令牌中恢复。
## 连接到Claude
**本地(Claude Desktop,`stdio`)** - 添加到您的Claude Desktop MCP配置(参见`examples/claude_desktop_config.json`):
```json
{
"mcpServers": {
"garmin": {
"command": "garmin-mcp",
"env": { "TRANSPORT": "stdio", "GARMINTOKENS": "/Users/you/.garminconnect" }
}
}
}
```
**远程(claude.ai 自定义连接器,HTTP)** - 使用附带的`Dockerfile` / `railway.toml`部署,然后将服务器URL(`https://<host>/mcp`)作为自定义连接器添加。主机上所需的环境变量:
```
TRANSPORT=streamable-http
MCP_AUTH_TOKEN=<openssl rand -hex 32> # 客户端必须发送 Authorization: Bearer <token>
GARMINTOKENS=/data/.garminconnect # 挂载卷;上传您在本地生成的令牌
```
如果没有`MCP_AUTH_TOKEN`,服务器会记录一个大警告并保持开启 - 所以请设置它。每个HTTP请求都使用恒定时间承载令牌比较进行检查;缺少或错误的令牌会得到`401`响应。
---
## 工具
| 工具 | 访问权限 | 描述 |
|---|---|---|
| `list_activities` | 读取 | 最近的活动(id,类型,距离,心率…) |
| `get_activity` | 读取 | 单个活动的完整详细信息 |
| `get_athlete_zones` | 读取 | 心率区/设置 |
| `list_scheduled` | 读取 | 日历上的训练 |
| `create_workout` | 写入 | 从规范中构建结构化训练;可选地安排 |
| `schedule_workout` | 写入 | 将现有训练安排在某日期 |
| `delete_workout` | 写入 | 删除训练模板 |
| `unschedule_workout` | 写入 | 删除日历事件 |
| `create_training_plan` | 写入 | 构建 + 安排整个多周计划 |
| `create_boulderthon_demo` | 写入 | 捆绑的13周示例计划 |
## 训练规范
助手填写的格式 - 可读且单位感知:
```python
WorkoutSpec(name="4x1mi 阈值训练", steps=[
StepSpec(kind="warmup", duration="15:00", target="hr:2"),
RepeatSpec(repeat=4, steps=[
StepSpec(kind="run", duration="1mi", target="pace:6:35-6:55"),
StepSpec(kind="recovery", duration="2:30", target="hr:2"),
]),
StepSpec(kind="cooldown", duration="10:00", target="hr:2"),
])
```
- **时长:** `"15:00"`/`"90s"` = 时间 · `"1mi"`/`"1.5mi"`/`"400m"`/`"1km"` = 距离
- **目标:** `null` · `"hr:2"`(心率区) · `"pace:6:35-6:55"`(配速窗口,最小/英里)
所有内容都编译为Garmin的精确`workout-service` JSON模式(针对`garminconnect` 0.3.6验证)。
## 示例:一个完整的马拉松训练块
`plans/boulderthon.py`是一个完整的13周马拉松训练示例,以这种规范表达 - 配速目标的质量训练,心率区的轻松/长跑,周减,两个20英里跑,马拉松配速演练和减量。 这是一个有效的示例,证明了计划引擎。 在不触及Garmin的情况下进行干运行:
```bash
python -c "from plans.boulderthon import build_plan; from garmin_mcp.plans import preview_plan; \
[print(r['date'], r['name']) for r in preview_plan(build_plan())]"
```
以相同的方式编写您自己的计划:通过`garmin_mcp.plans`中的`week()`助手和`create_training_plan`(或`push_plan`)安排整个计划。
---
## 项目结构
```
garmin-mcp/
├── src/garmin_mcp/
│ ├── server.py FastMCP 应用 + 工具
│ ├── workouts.py 规范模型 + 验证的Garmin编译器
│ ├── plans.py 计划引擎(week() 助手,推送/预览)
│ ├── auth.py garth 登录 + 令牌缓存 + MFA
│ ├── http_auth.py HTTP传输的承载令牌门控
│ └── cli.py garmin-mcp-auth
├── plans/boulderthon.py 示例13周构建为数据
├── examples/ Claude Desktop 配置
├── tests/ 离线构建/序列化/认证测试(CI安全,无网络)
├── Dockerfile · railway.toml 远程部署
└── .github/workflows/ci.yml
```
## 测试
```bash
pytest -q # 离线 - 编译 + 序列化训练,检查认证门控
```
CI在每次推送时运行`ruff` + `pytest`。 没有测试会进行网络调用,因此测试套件可以在任何地方安全运行,无需Garmin凭证。
---
## 我为什么要构建这个
我想让我的跑步教练和手表成为同一个工作流程。 我遵循结构化的马拉松训练,但将教练的计划转化为Garmin训练意味着在Garmin网页界面中逐一手动构建每个间歇训练,一周又一周。 Garmin没有个人API,因此“直接编写”在开箱时不是一个选项。
所以我反向工程了训练模式,封装在一个类型化的、LLM友好的规范中,并通过MCP公开它 - 这样助手可以接受“给我一个13周的亚3块”并将其转化为60多个计划、结构化的训练会话出现在我的手表上。 在此过程中,它成为一个小但完整的工程项目:
- **协议集成** - 一个真正的MCP服务器(stdio + streamable-HTTP),具有最小权限工具设计(活动仅可读取,写入仅限于训练)。
- **模式反向工程** - 从友好的规范到Garmin的精确`workout-service` JSON的验证编译器,具有配速/心率/距离目标和嵌套重复组。
- **认证和安全性** - 具有缓存令牌恢复和MFA的garth SSO,以及用于安全远程部署的恒定时间承载令牌门控。
- **可操作性** - 类型化的Pydantic模型,离线测试套件,CI和一键Docker/Railway部署。
它解决了我的实际问题,也可以作为构建MCP服务器以围绕封闭的非官方API的参考。
## 许可证
MIT。不隶属于Garmin或得到其认可。