内容
-name: io.github.anup-shesh/garmin-local-mcp -->
# garmin-local-mcp
**本地优先的Garmin数据仓库,具备分析级别的MCP服务器。**
一次性同步,永久分析,即使API宕机亦然。
## 为什么选择另一个Garmin MCP?
现有的Garmin MCP服务器都遵循相同的设计:一个围绕Garmin限速、非官方API的薄封装。您的AI助手提出的每个问题都转换为一个或多个实时API调用,返回巨大的原始JSON数据块(单个原始睡眠响应约为230 KB)。诸如“我的睡眠与训练负荷如何相关?”之类的多月查询不切实际;当Garmin更改其身份验证(就像2026年3月所做的那样,打破了整个生态系统)时,这些服务器会完全瘫痪,即使是昨天已经获取的数据。
该项目颠覆了架构:
- **一次性同步,永久分析。** 增量同步到本地仓库:不可变的原始JSON快照和SQLite数据库,存放在您拥有的目录中。
- **服务器端分析,响应紧凑。** 趋势、相关性、个人基线和异常检测在本地计算,并以小型列式表格返回,单次工具调用即可完成。典型响应小于2 KB,因此不会占用模型的上下文。
- **离线恢复能力。** API中断只会暂停新的同步。所有查询已同步的历史记录仍可继续工作。
- **零身份验证备用路径。** 独立解码器,用于Garmin未公开的健康FIT消息(睡眠评分、HRV、皮肤温度、睡眠阶段、午睡),无需登录即可导入手动导出的捆绑包。这是其他Garmin MCP所的。
- **精选工具。** 12个可组合的工具,而不是110个。
| | garmin-local-mcp | 典型的API包装Garmin MCP |
|---|---|---|
| 您拥有的本地数据存储 | 是(原始JSON + SQLite) | 否 |
| API中断后离线工作 | 是(分析同步历史) | 否 |
| 服务器端分析(趋势、相关性、基线、异常) | 是 | 否(原始JSON直通) |
| 响应大小控制 | 紧凑的列式表格,通常 < 2 KB | 原最高可达数百KB |
| 零身份验证导入路径 | 是(FIT捆绑导入) | 否 |
| 工具数量 | 12个精选 | 通常20到110+ |
## 快速入门
需要Python 3.12+。
```
pip install garmin-local-mcp
```
或者,通过 [uv](https://docs.astral.sh/uv/) 运行,无需安装:
```
uvx garmin-local-mcp --help
```
**1. 登录一次**(支持多因素身份验证;令牌本地存储,因此未来运行无需输入密码):
```
garmin-local-mcp login
```
**2. 补全您的历史记录。** 同步是可恢复的,安全中断,并对Garmin服务器有所节制。一年的历史记录大约需要1,800次请求;对于长时间的补全,启动它并让它运行(过夜效果很好)。如果它受到速率限制或中断,请重新运行相同的命令,它将从中断的地方继续。
```
garmin-local-mcp sync --from 2026-01-01
```
**3. 将MCP服务器注册到Claude Code:claude mcp add --scope user garmin -- garmin-local-mcp serve
```
使用不同的MCP客户端?任何支持/输出的客户端都可以使用:配置它运行`garmin-local-mcp serve`作为服务器命令。
**4. 提问。** Claude现在可以从您的本地仓库中用一个或两个工具调用回答:
- “我的睡眠评分与静息心率有何关联?”
- “这个季度我的哪些HRV天数异常?”
- “显示过去3个月的每周训练负荷与睡眠情况。”
## 12种工具
| 工具 | 功能 |
|---|---|
| `auth_status` | 检查存储的Garmin Connect令牌是否存在(在同步前或身份验证错误后使用)。 |
| `sync` | 从Garmin Connect同步最多60天的数据到本地存储(默认:昨天结束的最近30天;大型补全应在CLI中进行)。 |
| `sync_status` | 每个表格数据覆盖范围、时间和待处理的同步 |
| `get_day` | 单日的合并视图:健康、睡眠、HRV、训练状态、活动和数据质量标志。 |
| `query_metrics` | 两个日期之间一个或多个指标的列式,具有每日/每周/每月聚合和可选统计。 |
| `correlate` | 两个指标之间的Pearpearman相关性,支持天滞后和可选扫描-7..+7的滞后。 |
| `baselines` | 每个指标在拖尾窗口(默认为28天)内的个人平均值+/-标准差带,用于判断用户正常的标准。 |
| `anomalies` | 离群日(z-score偏差)和持续趋势(5+个连续日处于均值的一侧)。 |
| `list_activities` | 最近的活动按时间倒序排列为紧凑表格,可按类型、日期范围和最小距离筛选。 |
| `get_activity` | 单个活动的完整存储摘要行(仅摘要字段,无GPS或样本流)。 |
| `g | 每个表格的缺失天数和未解决的同步错误,用于查找值得重新同步的空洞。 |
| `import_fit` | 零身份验证离线导入手动导出的Garmin健康FIT捆绑包。 |
只有`sync`和`import_fit`写入任何内容,并且仅在数据目录内。服务器从不提示:身份验证问题以结构化错误返回,并附有指向登录CLI的提示。
可用指标名称包括`resting_hr`、`sleep_score`、`hrv`、`steps`、`stress_avg`、`body_battery_high`、`skin_temp_dev_c`、`vo2max`、`training_load`等约25个;给定未知名称的任何工具都会返回完整列表。
## 数据布局和所有权
所有内容都存放在您拥有的一个目录中(默认为`~/.garmin-mcp`,可通过环境变量`GARMIN_MCP_DATA_DIR`或`--data-dir`覆盖):
```
~/.garmin-mcp/
├── config.toml # 可选设置
├── tokens/ # Garmin Connect会话令牌
├── raw/daily/YYYY/YYYY-MM-DD/<endpoint>.json # 不变的原始API快照
├── raw/activities/<activity_id>.json # 每个活动的快照
└── garmin.db # SQLite仓库
```
原始JSON快照是真实来源,永远不会被覆盖。SQLite数据库是一个派生的、可重建的索引:`garmin-local-mcp reparse`完全离线地从原始快照重建它,这是模式演化和解析器修复的通用逃生舱口。您的数据永远不会离开您的机器。
## 数据质量说明
Garmin手表报告了一个临时的设备静息心率,这可能与Garmin Connect的最终值有很大差异,特别是在采样稀疏的夜晚。一个实际观察到的案例:手表报告了69 bpm,而Garmin Connect后来确定了56 bpm。
该项目通过两种方式处理这个问题:
- API同步存储Garmin Connect的最终值。
- FIT导入器将暂时的设备值与夜间心率下限进行交叉检查。如果静息心率比最低夜间样本高出10 bpm以上,则会标记(hr_far_above_hr_floor`)并保留该字段,以便API进行回填,而不是存储误导性的数字。
稀疏的睡眠阶段日志记录也会被标记(`sparse_sleep_stage_logging`),并且标记出现在`get_day`中,以便分析层知道哪些数字是值得信赖的。
## 离线/备用运行手册
如果Garmin再次破坏非官方API(以前发生过):
1. **所有分析功能继续工作。** 所有查询、相关性、基线、异常和间隙工具都在您已经同步的本地历史记录上运行。只有新的同步会暂停。
2. **无需身份验证即可继续导入。** 从Garmin Connect网站下载每日FIT捆绑包并在本地导入(具体步骤如下)。`garmin-local-mcp import-fit <folder>`在没有身份验证的情况下解码捆绑包并填充缺失的天数。FIT来源的行永远不会覆盖API来源的行(除非您传递`--force`)。
3. **在社区跟进时恢复。** 在-garminconnect](https://github.comberjunky/python-gconnect) 项目上关注修复、升级`garmin-local sync`。状态可恢复,它停止的地方继续。
###数据包,步骤如下
1.浏览器中登录 [connect.garmin.com://connect.garmin.com)。
2. 直接 **<armin/settings/accountInformation>**
(或点击右上角的头像,然后点击**设置**,然后在左侧边栏点击**账户3.页面底部,进入**导出健康数据**部分(“下载特定日期FIT文件。这些文件数、睡眠、HRV等4. 在**日期**字段中选择一个日期,然后点击**导出**。您的浏览器会为该日期下载一个包含约12到15个二进制`.fit`文件的小型zip文件(`*_WELLNESS.fit`、`*_SLEEP_DATA.fit`、`*_HRV_STATUS.fit`、`*_SKIN_TEMP.fit`、`*_METRICS.fit`等)。
5. 将其解一个文件夹中:
```
garmin-local-mcp "path/to/unzolder"
6. 重复操作以填充缺失的每一天(每个日期一个捆绑包)。`gaps`工具或`garmin-local-mcp status`会告诉您哪些日期需要填充。
两点值得注意:
- **隔夜睡眠归属于醒来的日期。** 要获取昨晚的睡眠,如果您睡到了导出昨天的日期,即您醒来的日期。
- 此每日时于Garmin的完整帐户导出(同一页上的“数据管理”链接),后者是一个批量存档,可能需要几天时间通过电子邮件到达,并且不是`import-fit`期望的。
## 配置
数据目录中的可选`config.toml`:
| 键 | 默认值 | 含义 |
|---|---|---|
| `timezone` | 系统时区 | IANA名称(例如`America/Denver`)用于计算同步范围的“昨天” |
| `units` | `metric` | `metric`或`statute` |
request_delay_seconds`1.0`步期间API请求 |
| `baseline` | `28` | `baselines`默认拖尾窗口 |
环境变量:
变量 | 含义---|---|
| `_MCP_DATA_DIR` | 覆盖数据默认为`~/.garmin-mcp`) |
| `GARMINTOKENS` | 覆盖令牌存储位置(默认为`<data_dir>/tokens`) |
| `GARMIN_EMAIL` / `GARMIN_PASSWORD` | 可选,用于非交互式重新登录;,`garmin-local-mcp login`会跳过提示(如果您的帐户需要MFA,仍可能会提示) |
## 开发
```
python -m venv .venv
.venv/bin/pip install -e .[dev] # Windows: .venv\Scripts\pip install -e .[dev]
pytest
ruff check .
```
测试套件完全离线运行,针对清理的JSON固定件和小FIT样本;CI从不触及实时API。
## 免责声明
本项目与Garmin Ltd. 无关、未经其背书或支持。它使用社区 [python-garminconnect](https://github.com/cyberjunky/python-garminconnect) 库,使用您自己的凭证访问您自己的数据。Garmin的API是非官方的,随时可能更改或中断;当这种情况发生时,您的同步历史记录仍然完全可用,FIT导入路径仍然所有数据都保留在您的机器上。没有任何数据发送到无遥测服务,无云对待个人健康对待您的个人数据永远不要将其提交库中。
许可证
MIT