内容
# 佳明 → 克劳德 MCP 服务器
> 分析您自己的佳明 Connect 数据 — 活动、睡眠、心率变异性、身体电池、训练准备度 — 直接在克劳德桌面端。
一个**完全本地**、**只读**的 MCP 服务器,允许您在**克劳德桌面**中分析您自己的佳明 Connect 数据。服务器作为克劳德桌面的本地子进程运行,通过 **stdio** 与其通信。
## 指导原则
- **100% 本地** — 没有任何内容被托管或暴露给网络(stdio)。
- **只读** — 没有写入端点到佳明。
- **无第三方** — 唯一的网络联系是佳明。无遥测,无外部日志记录。
- **运行时无密码** — 密码**从未**被存储;一次性登录后,仅使用本地令牌。
## 要求
- **Node.js ≥ 20**(已测试 Node 22 LTS),npm。
- 一个佳明 Connect 账户。
## 设置(4 步)
```bash
# 1) 安装依赖
npm install
# 2) 里程碑测试:客户端是否能通过佳明的 Cloudflare 保护?
npm run smoke
# 预期结果:"状态 200" 和 "挑战:否"。
# 3) 一次性交互式登录(提示输入电子邮件、隐藏密码、MFA 如果启用)
npm run login
# 创建 ~/.garmin-mcp/tokens.json(模式 0600)。密码**未**存储。
# 4) 将 TypeScript 编译到 build/
npm run build
```
## 连接克劳德桌面
克劳德桌面 → **设置 → 开发者 → 编辑配置**。添加服务器及其**绝对路径**(`claude_desktop_config.json`):
```json
{
"mcpServers": {
"garmin": {
"command": "node",
"args": ["/绝对路径/到/garmin-mcp/build/mcp/server.js"]
}
}
}
```
然后**重启**克劳德桌面。试试在聊天中:
> "我是否登录到佳明?使用 `whoami`。"
> "给我显示我的每日总结和最近的活动。"
## 可用工具
**13 个只读工具。** 日期参数为 `YYYY-MM-DD`(默认 = 今天);范围默认为最近 ~4 周。几个工具接受 `metrics[]` / `include[]` 选择器,因此一个工具涵盖许多数据类型(这保持工具列表的小尺寸以便于选择)。响应中的长时间序列被截断以保持紧凑。
| 工具 | 描述 |
|---|---|
| `whoami` | 连接检查 + 账户配置文件 |
| `get_daily_health` | 某日期的每日健康状况 — `metrics[]`:摘要、睡眠、压力、心率、HRV、SpO2、呼吸率、水分摄取、步数、楼层数、强度分钟数、身体电池、身体电池事件、统计数据和身体 |
| `get_training` | 某日期的训练状况 — `metrics[]`:准备度、晨间准备度、状态、VO2 最大值、健身年龄 |
| `get_fitness` | 健身/表现 — `metrics[]`:比赛预测、自行车 FTP、乳酸阈值、个人记录、耐力评分、山地评分、静息心率、每周强度分钟数(`startDate`/`endDate`) |
| `get_weight` | 体重和身体成分在一个范围内(`include_raw` 也返回称重数据) |
| `get_steps_history` | 一段时间内步数总数 — `granularity`:每日或每周 |
| `get_activity` | 通过 `activityId` 获取某项活动 — `include[]`:摘要、分段、天气、详情、心率区、锻炼组 |
| `list_activities` | 最近的活动,或按日期范围/类型(`limit`/`startDate`/`endDate`/`type`) |
| `get_devices` | 配对的佳明设备 |
| `get_user_profile` | 用户配置文件和设置(单位、偏好) |
| `get_goals` | 目标(`status`:活动/未来/过去) |
| `get_workouts` | 保存的锻炼计划(`limit`) |
| `get_scheduled_workouts` | 预定的锻炼计划/日历(`year`/`month`) |
## 工作原理
服务器将每个佳明数据方法注册为 MCP 工具,并通过 stdio 与克劳德桌面通信。每个调用都通过一个通用的 `connectapi()` 请求发送到 `connectapi.garmin.com`,带有 bearer token,使用 [`cycletls`](https://github.com/Danny-Dasilva/CycleTLS) 发送,以便 TLS 指纹看起来像一个真正的浏览器(佳明位于 Cloudflare 后面)。
身份验证发生一次(`npm run login`):登录级联 — 移动 iOS JSON 登录首先,经典小部件/CSRF 流程作为备用 — 产生一个 CAS 服务票据,该票据在佳明的 DI-OAuth2 流程中兑换为访问和刷新令牌。令牌缓存在本地,访问令牌在过期时自动刷新;您的密码**从未**被存储。
## 安全模型
- **密码**从未被存储 — 它仅用于一次性登录。
- 令牌存储在 `~/.garmin-mcp/tokens.json` 中,文件模式为 **`0600`**(只有您才能读取它们)。
- 访问令牌通过刷新令牌在过期时自动续期。
- **只读**:没有更改佳明任何内容的代码路径。
- 无遥测,无外部日志记录。诊断信息仅输出到 `stderr`(从未通过 stdio MCP 通道)。
## 架构(层)
- `src/http/impersonate.ts` — 通过 [`cycletls`](https://github.com/Danny-Dasilva/CycleTLS)(JA3 指纹)+ cookie jar 进行 TLS 伪装,以便佳明的机器人保护允许我们通过。
- `src/http/smoke.ts` — 针对 `sso/embed` 的里程碑测试。
- `src/garmin/auth.ts` — 登录级联(移动 iOS JSON 登录 → 小部件/CSRF 备用)+ MFA + DI-OAuth2 票据交换 + 刷新。
- `src/garmin/tokens.ts` — 本地令牌缓存(0600)。
- `src/garmin/client.ts` — 通用 `connectapi()` + 类型化、只读数据方法。
- `src/mcp/server.ts` — MCP 服务器、工具注册、stdio 传输。
- `src/cli/login.ts` — 一次性交互式登录。
## 维护和风险(诚实命名)
本项目使用佳明的**非官方**内部 API,从开源 Python 包 [`python-garminconnect`](https://github.com/cyberjunky/python-garminconnect) 移植而来。预期的故障点及修复方法:
- **非官方 API** — 端点路径可能会更改。在发生错误时,请将 `src/garmin/client.ts` 中的路径与当前的 `python-garminconnect` 源代码进行比较。
- **JA3 / 用户代理** — 在出现 `403` 或 "Just a moment …" Cloudflare 页面时,请将 `src/http/impersonate.ts` 中的 JA3/用户代理对更新为当前的 Chrome(两者)。
- **客户端 ID** — DI-OAuth2 客户端 ID(`GARMIN_CONNECT_MOBILE_ANDROID_DI_*`)会轮换;请在身份验证错误时更新 `src/garmin/auth.ts` 中的列表。
- **`garth` 已停止使用** — 曾经常用的身份验证库 `garth` 不再维护;权威参考资料是 `python-garminconnect`。
- **保持令牌文件夹私有** — `~/.garmin-mcp/` 保存有效的会话令牌;请勿分享或提交。
- **服务条款** — 通过非官方 API 访问可能会与佳明的服务条款相冲突。适用于**私人个人使用**您**自己的**数据。
## 故障排除
- **`403` 或 "Just a moment …" 页面** — 佳明的 Cloudflare 正在阻止 TLS 指纹。请将 `src/http/impersonate.ts` 中的 JA3/用户代理对更新为当前的 Chrome(两者),然后重新运行 `npm run smoke`。
- **`🔒 未登录` / 会话过期** — 请再次运行 `npm run login`。
- **`⏳` 速率限制(HTTP 429)** — 佳明正在限制;请稍后重试。
- **首次运行缓慢 / cycletls 错误** — `cycletls` 在首次使用时会下载一个小的 Go 助手二进制文件;请确保它可以执行且不受操作系统阻止。
## 重新登录
如果工具报告 `🔒 未登录`(令牌过期/无效):
```bash
npm run login
```
## 许可证
[MIT](LICENSE) © Marcel Fortmann
## 免责声明
本项目为非官方、社区项目。**不隶属于、不支持或赞助于佳明**。佳明® 和佳明 Connect™ 是 Garmin Ltd. 或其子公司的商标。