关于 Garmin Mcp
Garmin Mcp 是用于查询和管理 Garmin Connect 健身与健康数据的 MCP 服务,面向个人和训练指导场景,涵盖活动、健康指标、训练、锻炼和营养。
主要功能
- 01浏览和编辑活动
- 02读取健康与身体指标
- 03跟踪训练状态和趋势
- 04创建并安排锻炼
- 05管理装备、路线和营养
- 06下载活动文件
适用场景
- 01查看近期锻炼和分段数据
- 02比较睡眠、压力和心率数据
- 03制定并安排训练计划
- 04分析骑行功率和活动文件
MCP 相关
它将 Garmin Connect 数据和操作作为工具提供给 Claude 及其他兼容 MCP 的客户端。可通过工具配置文件和允许列表限制注册的工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Garmin MCP 服务
此模型上下文协议(MCP)服务连接到 Garmin Connect,并向 Claude 和其他兼容 MCP 的客户端提供您的健身与健康数据。
Garmin 的 API 通过优秀的 python-garminconnect 库访问。
功能
- 列出近期活动,支持分页
- 获取详细的活动信息
- 编辑活动:名称、类型、描述/备注、赛事类型、主观用力程度(RPE)、感受和力量训练组
- 访问健康指标(步数、心率、睡眠、压力、呼吸)
- 查看身体成分数据
- 跟踪训练状态和准备度
- 访问骑行 FTP 和乳酸阈值指标
- 管理装备,包括
get_gear返回的自由文本备注 - 访问训练和训练计划
- 检查详细的训练步骤结构,包括重复组和游泳配速目标
- 每周健康汇总(步数、压力、强度分钟数)
- 高级骑行分析:功率区间、FIT 文件分析、DI2 电子变速智能分析
- 训练负荷趋势(CTL/ATL/TSB)、HRV 趋势、VO2 max 趋势、呼吸频率趋势
- 功率持续时间曲线、爬坡检测与 VAM、心脏漂移(有氧解耦)、W/kg 计算
工具覆盖范围
此 MCP 服务实现了 110 多个工具,覆盖 python-garminconnect 库(v0.3.2)约 90% 的功能:
- ✅ 活动管理(21 个工具)- 包括用于编辑类型、描述、赛事类型、主观用力程度、感受和训练组的写入工具
- ✅ 健康与保健(34 个工具)- 包括自定义轻量级摘要工具
- ✅ 训练与表现(13 个工具)- 包括 CTL/ATL/TSB、HRV、VO2 max 和呼吸趋势
- ✅ 训练(8 个工具)
- ✅ 设备(8 个工具)- 包括向设备发送训练
- ✅ 装备管理(5 个工具)
- ✅ 体重跟踪(5 个工具)
- ✅ 挑战与徽章(10 个工具)
- ✅ 营养(9 个工具)- 食物日志、餐食、自定义食物、食物记录和多日摄入量摘要
- ✅ 女性健康(3 个工具)
- ✅ 用户资料(3 个工具)
- ✅ 高级训练构建工具(4 个工具)- 无需编写 JSON 即可创建和安排训练
- ✅ 路线(5 个工具)- 列出 / 获取详情 / 将 GPX 上传为路线 / 下载 GPX / 删除路线
- ✅ 活动分析(2 个工具)- FIT 文件解析、功率持续时间曲线;需要功率计和/或 Di2
- ✅ 活动文件下载(2 个工具)- 以 FIT、GPX、TCX 或 CSV 格式下载活动文件
注意: 活动分析工具需要兼容的功率计(例如 Garmin Rally、Favero Assioma、PowerTap P1)和/或 Shimano Di2 / SRAM eTap 电子变速系统。
fitparse依赖项会自动安装。
装备注释
get_gear 返回的 gear 数组中的每个项目都包含 notes 字段,
其中存放 Garmin Connect 中显示的自由文本备注值。没有备注值的装备会返回
null;所有现有装备字段保持不变。
活动文件下载
两个工具可用于将原始活动文件下载到磁盘:
download_activity_file(activity_id, format="fit", output_dir=None)— 下载活动并保存到已配置的目录。format接受fit(默认值)、gpx、tcx或csv。set_fit_download_dir(path)— 设置并持久保存默认下载目录(写入配置文件)。
文件保存位置(优先级):
output_dir参数 — 单次覆盖,不会持久保存。GARMIN_FIT_DOWNLOAD_DIR环境变量。- 通过
set_fit_download_dir设置并持久保存的配置。
**首次运行行为:**如果未配置目录,download_activity_file 会返回 status: "needs_setup"。助手会询问你希望将文件保存在哪里(默认建议使用当前目录),调用 set_fit_download_dir 保存你的选择,然后自动重试下载。
力量训练组
set_activity_exercise_sets(activity_id, sets) 会将结构化训练组写入已记录的力量训练活动,格式与 Garmin Connect“编辑训练组”页面保存的逐组表格相同,因此这些数据会显示在 Garmin 的训练历史和训练量图表中。它会替换所有现有训练组,包括手表检测到的训练组;如果想保留其中任何训练组,请先用 get_activity_exercise_sets 读取。
每组需包含 category,以及可选的 exercise_name;这些字段使用 Garmin 在
Exercises.json 中定义的键名。此外,还可选填
reps、weight_kg 或 weight_lb(自重训练时省略)、duration_seconds 和
rest_seconds。Garmin 会拒绝未知键,并保持活动不变。
如果手表记录的训练组正确,但识别出的动作有误,请传入
keep_timing: true:系统会保留记录的开始时间、持续时间和休息时长,只按顺序替换动作、次数和重量。训练组数量必须与活动记录的有效训练组数量一致。
{
"activity_id": 12345678901,
"sets": [
{"category": "DEADLIFT", "exercise_name": "BARBELL_DEADLIFT", "reps": 5, "weight_kg": 150, "rest_seconds": 180},
{"category": "PULL_UP", "reps": 8}
]
}
有意跳过的端点
出于性能或复杂度方面的考虑,部分端点未实现:
高数据量:
get_activity_details()- 返回大型 GPS 轨迹和图表数据(50KB-500KB)。如需摘要,请改用get_activity()。
专用训练格式:
upload_running_workout()、upload_cycling_workout()、upload_swimming_workout()- 上传特定运动类型的训练。通用训练请使用upload_workout()。
维护和破坏性操作:
delete_blood_pressure()- 执行破坏性操作前需要仔细考虑。delete_activity()已通过确认机制实现:先调用一次预览,再传入confirm=true再次调用以删除。删除记录会写入 stderr。无法撤销。- 内部/身份验证方法:
login()、resume_login()、connectapi()、download()- 由库自动处理。
如需使用这些端点,请提交问题。
工具筛选
此服务默认注册 155 个工具,对于 LLM 来说,每次会话都要携带这么多上下文负担不小。你可以通过三个可选环境变量,只开放所需的工具:
| 环境变量 | 作用 |
|---|---|
GARMIN_TOOL_PROFILE | 按类别选择内置子集:minimal、health、activities、workouts、training、nutrition 或 all(默认值)。可用逗号组合多个值,例如 health,training。 |
GARMIN_ENABLED_TOOLS | 以逗号分隔的允许列表——设置后,仅注册这些工具。如果同时设置了配置,则这些工具会在配置基础上额外添加。 |
GARMIN_DISABLED_TOOLS | 以逗号分隔的拒绝列表——跳过列出的工具。如果设置了允许列表,则此项会被忽略;但如果同时设置了配置,则会从配置中移除这些工具。 |
工具名称不区分大小写。如果都未设置,则注册所有工具(默认行为不变)。与任何工具都不匹配的名称会被忽略,并在 stderr 上显示警告,便于发现拼写错误。未知配置名称会导致服务在启动时停止,并列出已知配置。
配置
| 配置 | 工具数 | 涵盖内容 |
|---|---|---|
minimal | 20 | 最近活动及分段、每日统计、睡眠、HRV、压力、身体电量、训练准备度和状态 |
health | 53 | 所有 health_wellness 工具,以及体重、身体成分、血压、水合状态、女性健康、体能年龄、HRV 和呼吸趋势 |
activities | 41 | 活动列表、详情、分段和编辑;FIT 分析和功率曲线;装备;路线 |
workouts | 26 | 训练库、上传、安排和删除;高级构建工具;日历 |
training | 38 | 训练状态、负荷、效果、VO2max、FTP、乳酸阈值、耐力和爬坡评分、准备度、恢复时间、个人纪录、比赛预测、目标、徽章 |
nutrition | 23 | 食物日志、自定义食物、每日营养设置、水合状态、能量平衡 |
每个配置还包含身份和单位工具(get_full_name、get_heart_rate_zones、get_unit_system、get_user_profile、get_userprofile_settings),这样客户端就能为返回的数据标注含义。
示例——需要训练指标和训练工具的教练会话:
"env": {
"GARMIN_TOOL_PROFILE": "training,workouts"
}
示例——健康配置加上近期活动,但不包含写入工具:
"env": {
"GARMIN_TOOL_PROFILE": "health",
"GARMIN_ENABLED_TOOLS": "get_activities,get_activity",
"GARMIN_DISABLED_TOOLS": "add_weigh_in,add_weigh_in_with_timestamps,delete_weigh_ins,add_body_composition,add_hydration_data,set_blood_pressure"
}
示例——不使用配置,手动选择工具:
"env": {
"GARMIN_ENABLED_TOOLS": "get_sleep_data,get_stress_summary,get_activities"
}
高级训练工具
这些构建工具让 LLM 无需编写原始 Garmin JSON,即可创建和安排训练。
create_walk_run_workout
创建步行/跑步间歇训练,可选择心率区间目标。
{
"name": "W3 Mié 2:2",
"run_seconds": 120,
"walk_seconds": 120,
"repeats": 9,
"warmup_min": 10,
"cooldown_min": 8,
"hr_zone": "Z3"
}
返回:{"status": "success", "workout_id": 1234567890, ...}
create_z2_walk_workout
创建稳定的 Z2 步行训练。
{
"name": "Z2 Walk 45m",
"duration_min": 45,
"hr_min": 110,
"hr_max": 130
}
返回:{"status": "success", "workout_id": 1234567890, ...}
create_strength_workout
根据一组练习创建力量训练。每项练习都会变成一个基于次数的步骤,名称会保留在步骤描述中。名称也会作为 exerciseName 发送,但 Garmin 只会在名称与其自带的练习键匹配时保留该值(例如 FARMERS_CARRY)——其他任何值都会被接受,但之后存储为空。
category 是可选项,会直接传递。省略该项时,整个载荷中不会包含此键,Garmin 可以接受这种格式。提供该项时,其值必须是 Garmin 的练习类别之一——任何其他值(包括 OTHER 和 UNASSIGNED)都会被拒绝,并返回 400 - Invalid category。完整列表发布在
Exercises.json。
{
"name": "Full Body A",
"exercises": [
{"name": "Sentadillas", "sets": 3, "reps": 12, "rest_seconds": 90},
{"name": "Flexiones", "sets": 3, "reps": 15, "rest_seconds": 60},
{"name": "Peso muerto", "sets": 3, "reps": 10, "rest_seconds": 90},
{"name": "Farmers Carry 40m", "sets": 3, "reps": 1, "rest_seconds": 90, "category": "CARRY"}
]
}
返回:{"status": "success", "workout_id": 1234567890, ...}
schedule_week
一次调用即可安排多个训练。
{
"week": [
{"date": "2026-05-12", "workout_id": 1234567890},
{"date": "2026-05-14", "workout_id": 1234567891}
]
}
返回:{"status": "complete", "scheduled": [...]}
完整流程示例
create_walk_run_workout(name="W3 Mié 2:2", run_seconds=120, walk_seconds=120,
repeats=9, warmup_min=10, cooldown_min=8)
→ workout_id = 1560092011
schedule_workout(workout_id=1560092011, date="2026-05-06")
→ OK
同步手表后,训练会显示在 Forerunner 965 的日历中。
原始 upload_workout 结束条件
为 upload_workout 或 upload_workouts 构建自定义训练 JSON 时,endCondition.conditionTypeId 和 endCondition.conditionTypeKey 必须与 Garmin 的规范映射一致。Garmin 将数字 conditionTypeId 视为事实来源;如果键与 ID 冲突,Garmin 会存储与该 ID 对应的条件。
例如,以下内容不能用于心率结束条件,因为 ID 4 表示 calories,而不是 heart.rate:
{
"endCondition": {
"conditionTypeId": 4,
"conditionTypeKey": "heart.rate"
},
"endConditionValue": 145
}
心率请使用 ID 6:
{
"endCondition": {
"conditionTypeId": 6,
"conditionTypeKey": "heart.rate"
},
"endConditionValue": 145
}
对于基于区域的心率结束条件,请在同一个 endCondition 对象上使用 endConditionZone(1-5),并省略 endConditionValue。如果同时发送这两个字段,Garmin 会保留区域并丢弃值(已通过生产 API 验证,日期为 2026-09-01):
{
"endCondition": {
"conditionTypeId": 6,
"conditionTypeKey": "heart.rate",
"endConditionZone": 2
}
}
常见结束条件 ID:
| ID | 键 |
|---|---|
| 1 | lap.button |
| 2 | time |
| 3 | distance |
| 4 | calories |
| 5 | power |
| 6 | heart.rate |
| 7 | iterations |
| 8 | fixed.rest |
| 9 | fixed.repetition |
| 10 | reps |
| 11 | training.peaks.tss |
原始 upload_workout 目标类型
构建原始 Garmin 训练 JSON 时,targetType.workoutTargetTypeId 和 targetType.workoutTargetTypeKey 必须使用 Garmin 的规范映射。Garmin 将数字 ID 视为权威值:类似 {"workoutTargetTypeId": 6, "workoutTargetTypeKey": "heart.rate"} 的不匹配载荷会被存储为 pace.zone,因为 ID 6 表示 pace.zone。
对于自定义心率范围,请使用目标类型 ID 4 和 heart.rate.zone,并将 bpm 范围放在 targetValueOne / targetValueTwo 中。这些值字段应与 targetType 并列放在训练步骤上;不要将它们嵌套在 targetType 对象中:
{
"targetType": {
"workoutTargetTypeId": 4,
"workoutTargetTypeKey": "heart.rate.zone"
},
"targetValueOne": 143,
"targetValueTwo": 157
}
自定义跑步配速范围也适用相同的结构。配速边界使用米每秒:
{
"targetType": {
"workoutTargetTypeId": 6,
"workoutTargetTypeKey": "pace.zone"
},
"targetValueOne": 1.9607843,
"targetValueTwo": 2.0833333
}
此示例表示 8:00–8:30 min/km。为与心率示例保持一致,较小的数值边界列在前;Garmin 会规范化任意顺序的边界。Garmin 会静默丢弃嵌套在 targetType 内的值,导致配速目标没有生效范围。上传工具会修正这种明确无误的嵌套错误,但如果嵌套值与步骤级值冲突,则会拒绝请求。
对于命名的 Garmin HR 区域,请改用同一目标类型并设置 zoneNumber:
{
"targetType": {
"workoutTargetTypeId": 4,
"workoutTargetTypeKey": "heart.rate.zone"
},
"zoneNumber": 3
}
对同一个目标,请使用 zoneNumber 或 targetValueOne / targetValueTwo,不要同时使用两者。Garmin 将命名区域视为权威值,并会静默丢弃同时存在的自定义范围,因此上传工具会拒绝这种含糊的结构。
一键安装(Claude Desktop)
将此服务添加到 Claude Desktop 的最简单方法是使用 .dxt Desktop Extension 文件——无需编辑 JSON。
下载并安装
- 从 Releases 页面下载最新的
garmin-mcp.dxt。 - 将
.dxt文件拖入 Claude Desktop 窗口,或双击该文件,或前往设置 → 扩展 → 安装扩展并选择该文件。 - Claude Desktop 会提示你进行可选配置(令牌路径、电子邮件、密码)。
首次身份验证
扩展会自动安装并运行服务,但在获取数据之前,你必须先向 Garmin 完成一次身份验证:
uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp-auth
这会将 OAuth 令牌保存到 ~/.garminconnect。之后,服务无需在配置中提供任何凭据即可运行。
**注意:**令牌有效期约为 6 个月。令牌过期后,请重新运行
garmin-mcp-auth。
自行构建 .dxt
bash scripts/build_dxt.sh # produces garmin-mcp.dxt in the repo root
设置
MCP 客户端快速入门
将此 MCP 服务添加到配置之前,先完成一次身份验证,这是将其与 Claude Desktop、Codex 或其他 MCP 客户端配合使用的最简单方法。
前置条件
- Python 3.12+
- Garmin Connect 账户
- 如果账户启用了 MFA,可能需要进行多重身份验证
第 1 步:预先完成身份验证(一次性操作)
将服务添加到 MCP 客户端之前,请先在终端中完成一次身份验证:
# Install and run authentication tool
uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp-auth
# You'll be prompted for:
# - Email (or set GARMIN_EMAIL env var)
# - Password (or set GARMIN_PASSWORD env var)
# - MFA code (if enabled on your account)
# OAuth tokens will be saved to ~/.garminconnect
你可以随时使用以下命令验证凭据:
uv run garmin-mcp-auth --verify
注意: 你也可以通过环境变量设置凭据:
[email protected] GARMIN_PASSWORD=secret garmin-mcp-auth
如果未启用 MFA,也可以跳过 garmin-mcp-auth,直接将 GARMIN_EMAIL 和 GARMIN_PASSWORD 作为环境变量传递给 MCP 客户端(如果客户端支持)。为提高安全性,建议使用上面的预先身份验证流程,并避免将凭据放入 MCP 客户端配置中。
第 2 步:配置 Claude Desktop
将以下内容添加到 Claude Desktop 的 MCP 设置中,不要填写凭据:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"garmin": {
"command": "uvx",
"args": [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
]
}
}
}
重要提示: 配置中无需填写 GARMIN_EMAIL 或 GARMIN_PASSWORD!服务会使用已保存的令牌。
第 3 步:重启 MCP 客户端
现在,你的 Garmin 数据已可供 MCP 客户端使用。
Codex 和其他客户端的示例见下文。
使用多个 Garmin 账户
单个服务进程绑定一个 Garmin 账户。若要同时使用多个账户,请为每个账户运行一个服务实例,并通过 GARMINTOKENS 环境变量为每个实例指定独立的令牌目录。
GARMINTOKENS 默认为 ~/.garminconnect。将其指向其他位置后,服务会在该位置读取和写入令牌,而不会更改默认存储目录。
第 1 步:将每个账户验证到各自的目录中
garmin-mcp-auth --token-path ~/.garminconnect-alice
garmin-mcp-auth --token-path ~/.garminconnect-bob
--token-path 也接受 $GARMINTOKENS,因此 GARMINTOKENS=~/.garminconnect-alice garmin-mcp-auth 与之等效。
第 2 步:为每个账户声明一个服务
{
"mcpServers": {
"garmin-alice": {
"command": "uvx",
"args": ["--python", "3.12", "--from", "git+https://github.com/Taxuspt/garmin_mcp", "garmin-mcp"],
"env": {
"GARMINTOKENS": "${HOME}/.garminconnect-alice"
}
},
"garmin-bob": {
"command": "uvx",
"args": ["--python", "3.12", "--from", "git+https://github.com/Taxuspt/garmin_mcp", "garmin-mcp"],
"env": {
"GARMINTOKENS": "${HOME}/.garminconnect-bob"
}
}
}
}
每个服务启动时都会记录进行身份验证的目录,以便你确认配置是否正确:
Trying to login to Garmin Connect using token data from directory '/home/you/.garminconnect-alice'...
注意事项
-
不会静默回退。 如果
GARMINTOKENS指向的目录中没有有效令牌,且登录失败,服务会记录失败信息,工具调用也会失败;HTTP/readyz将继续不可用(503)。服务不会切换到默认令牌存储,因此,配置错误的第二个服务不会在不知情的情况下复用第一个账户的会话。 -
即使 MCP 客户端传入的
${HOME}尚未解析,也会对其进行展开;在 Windows 上,~会通过USERPROFILE正常工作。 -
限制次要账户的写入工具。
upload_workout和schedule_workout等工具会将数据写入服务绑定的账户。将GARMINTOKENS与GARMIN_ENABLED_TOOLS配合使用(参见工具筛选),可将账户设为只读:"env": { "GARMINTOKENS": "${HOME}/.garminconnect-bob", "GARMIN_ENABLED_TOOLS": "get_activities,get_activities_by_date,get_activity,get_activity_splits" } -
令牌目录包含长期有效的凭据。 这些目录仅授予所有者权限;请勿将其放在共享或同步文件夹中。
开发环境设置
- 在新环境中安装所需的软件包:
uv sync
运行服务
配置
Garmin Connect 凭据通过环境变量读取:
GARMIN_EMAIL:Garmin Connect 邮箱地址GARMIN_EMAIL_FILE:包含 Garmin Connect 邮箱地址的文件路径GARMIN_PASSWORD:Garmin Connect 密码GARMIN_PASSWORD_FILE:包含 Garmin Connect 密码的文件路径GARMIN_IS_CN:设为true时使用 Garmin Connect China(garmin.cn),而非国际版(默认值:false)GARMIN_FIT_DOWNLOAD_DIR:下载的活动文件的默认目录。设置后,download_activity_file将跳过首次运行设置提示。GARMIN_FIT_CONFIG:持久化下载目录配置文件的路径(默认值:~/.garminconnect_fit_config.json)。
在某些环境中(例如 Docker 容器内),使用基于文件的机密信息会很方便。请注意,不能同时设置 GARMIN_EMAIL 和 GARMIN_EMAIL_FILE;同样,也不能同时设置 GARMIN_PASSWORD 和 GARMIN_PASSWORD_FILE。
传输方式
默认情况下,服务器通过 stdio 通信,这是 Claude Desktop、MCP Inspector 和大多数本地客户端所使用的方式。若要改用 HTTP 服务(例如在容器或 Kubernetes 中运行时),请通过环境变量设置传输方式:
GARMIN_MCP_TRANSPORT:stdio(默认)、streamable-http或sseGARMIN_MCP_HOST:HTTP 传输的绑定地址(默认为127.0.0.1;只有同时设置GARMIN_MCP_HTTP_TOKEN或在带身份验证的反向代理后运行时,才设置为0.0.0.0)GARMIN_MCP_PORT:HTTP 传输的绑定端口(默认为8000)GARMIN_MCP_HTTP_TOKEN:HTTP 传输的共享密钥。设置后,每个发往/mcp、/sse和/messages/的请求都必须携带Authorization: Bearer <token>;否则将收到401。/healthz和/readyz仍保持开放,供探针使用。请参阅保护 HTTP 端点。GARMIN_MCP_STATELESS_HTTP:设置为true可在无会话模式下运行streamable-http(默认为false)。MCP SDK 会在会话空闲 30 分钟后丢弃有状态会话,因此空闲一段时间后的首次调用会收到404 Session not found;部分客户端(包括 claude.ai 自定义连接器)会将其报告为工具调用失败,而不是重新初始化并重试。无状态模式没有会话,因此不会过期。此服务器中的工具均不依赖会话状态,因此不会丢失任何内容。建议用于长期运行的远程部署。GARMIN_MCP_CALL_TIMEOUT:调用 Garmin 时每个请求的超时时间(秒,默认为90)。Garmin 的 API 偶尔会导致单个请求无限期挂起;如果没有此限制,调用会一直卡住,直到 MCP 客户端自身的超时触发,并报告整个服务器无响应。超时后,工具会返回明确且可重试的错误。设置为0可禁用此限制。
GARMIN_MCP_TRANSPORT=streamable-http garmin-mcp
选择 HTTP 传输方式后:
- MCP 客户端连接到
/mcp路径(例如http://localhost:8000/mcp)。 GET /healthz会在服务器启动后立即返回ok——可将其用作存活探针。GET /readyz会报告 Garmin 登录是否已完成——可将其用作就绪探针。登录成功后会返回200 {"status": "ready"};登录仍在进行时返回503和{"status": "pending"},登录失败时返回{"status": "failed"}(请重新运行garmin-mcp-auth并重启)。
保护 HTTP 端点
HTTP 传输方式会提供对 Garmin 账户的完整读写权限,因此 服务器默认绑定到环回地址。若要让其他设备能够访问, 请设置共享密钥,并让客户端将其作为 Bearer 令牌发送:
export GARMIN_MCP_HTTP_TOKEN="$(openssl rand -hex 32)"
GARMIN_MCP_TRANSPORT=streamable-http GARMIN_MCP_HOST=0.0.0.0 garmin-mcp
# rejected: 401 {"error": "unauthorized", ...}
curl -i http://localhost:8000/mcp
# accepted (the MCP handshake then proceeds as usual)
curl -i -H "Authorization: Bearer $GARMIN_MCP_HTTP_TOKEN" http://localhost:8000/mcp
大多数 MCP 客户端都支持为远程服务设置自定义标头(Claude Desktop 和
claude.ai 连接器、MCP Inspector 以及 SDK 客户端均支持);请在其中设置
相同的 Authorization: Bearer … 标头。比较过程采用恒定时间。
/healthz 和 /readyz 无需令牌,因为它们只报告进程是否已启动以及
Garmin 登录是否已完成。
未设置令牌时,服务器仍会启动;但如果 GARMIN_MCP_HOST 不是
环回地址,它会在 stderr 中打印警告,提示账户已暴露。使用自带身份验证的
反向代理(nginx、Traefik、Authelia 等)也是不错的替代方案;
对于常见的可自托管场景,令牌是内置的轻量选项。
Garmin Connect China (garmin.cn)
如果你使用的是 Garmin Connect China (garmin.cn),而非国际版,请将 GARMIN_IS_CN 环境变量设置为 true:
# Pre-authenticate with Garmin Connect China
GARMIN_IS_CN=true garmin-mcp-auth
# Or use the CLI flag
garmin-mcp-auth --is-cn
对于 Claude Desktop,请在 env 部分添加 GARMIN_IS_CN:
{
"mcpServers": {
"garmin": {
"command": "uvx",
"args": [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
],
"env": {
"GARMIN_IS_CN": "true"
}
}
}
}
对于 Docker,请将 GARMIN_IS_CN=true 添加到 .env 文件中,或在 docker-compose.yml 中取消其注释。
使用 MCP Inspector 在本地测试服务器
Inspector 可通过 npx 直接运行,无需安装。从项目根目录运行:
npx @modelcontextprotocol/inspector uv run garmin-mcp
之后即可检查并测试这些工具。
使用 Claude Desktop
- 在 Claude Desktop 中创建配置:
编辑 Claude Desktop 配置文件:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
你可以通过两种方式在本地使用 Claude 运行 MCP。
直接从 github 运行,无需克隆仓库:
- 添加此服务配置:
{
"mcpServers": {
"garmin": {
"command": "uvx",
"args": [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
],
"env": {
"GARMIN_EMAIL": "YOUR_GARMIN_EMAIL",
"GARMIN_PASSWORD": "YOUR_GARMIN_PASSWORD"
}
}
}
}
你可能需要添加 uvx 的完整路径,可使用 which uvx 查看完整路径。
- 重启 Claude Desktop
直接从本地仓库副本运行:
- 添加此服务配置:
{
"mcpServers": {
"garmin-local": {
"command": "uv",
"args": [
"--directory",
"<full path to your local repository>/garmin_mcp",
"run",
"garmin-mcp"
]
}
}
}
- 重启 Claude Desktop
使用 Codex
Codex 使用 TOML 配置 MCP 服务。使用 garmin-mcp-auth 完成身份验证后,将以下任一条目添加到 ~/.codex/config.toml。
你也可以让支持 MCP 的客户端为你完成设置。例如:
Install the Garmin MCP server from https://github.com/Taxuspt/garmin_mcp, authenticate with garmin-mcp-auth, and add it to my MCP configuration without storing my Garmin email or password.
直接从 GitHub 安装,无需克隆仓库
[mcp_servers.garmin]
command = "uvx"
args = [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
]
直接从本地仓库副本运行
[mcp_servers.garmin-local]
command = "uv"
args = [
"--directory",
"/full/path/to/garmin_mcp",
"run",
"garmin-mcp"
]
保存文件后,重启 MCP 客户端。
使用 opencode
opencode 从仓库根目录启动时会自动加载项目级 opencode.json,因此克隆此仓库的贡献者无需额外配置,即可将 Garmin MCP 连接到本地源代码。
从此仓库的克隆副本运行(推荐用于开发)
此仓库提供了一个 opencode.json,通过 uv run garmin-mcp 运行 MCP,因此它始终使用工作树中的代码。
git clone https://github.com/Taxuspt/garmin_mcp.git
cd garmin_mcp
uv sync # install dependencies
garmin-mcp-auth # one-time Garmin login (skip if ~/.garminconnect already exists)
opencode # launches with the garmin MCP attached
确认服务已连接:
opencode mcp list
# ● ✓ garmin connected
# uv run garmin-mcp
从其他目录运行(GitHub 安装)
运行 garmin-mcp-auth 后,将服务添加到全局 opencode 配置文件 ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"garmin": {
"type": "local",
"command": [
"uvx",
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
],
"enabled": true,
"timeout": 30000
}
}
}
保存文件后,重启 opencode。首次调用 uvx 时会下载并缓存软件包,因此首次启动可能需要几秒钟。
使用 Docker
Docker 可提供隔离且一致的环境来运行 MCP 服务。
使用 Docker Compose 快速开始(推荐)
- 创建包含凭据的
.env文件:
echo "[email protected]" > .env
echo "GARMIN_PASSWORD=your_password" >> .env
- 启动容器:
docker compose up -d
- 查看日志以监控服务:
docker compose logs -f garmin-mcp
直接使用 Docker
# Build the image
docker build -t garmin-mcp .
# Run the container
docker run -it \
-e GARMIN_EMAIL="[email protected]" \
-e GARMIN_PASSWORD="your_password" \
-v garmin-tokens:/root/.garminconnect \
garmin-mcp
使用基于文件的密钥(更安全)
为增强安全性,尤其是在生产环境中,请使用基于文件的密钥,而不要使用环境变量:
- 创建密钥目录并添加凭据:
mkdir -p secrets
echo "[email protected]" > secrets/garmin_email.txt
echo "your_password" > secrets/garmin_password.txt
chmod 600 secrets/*.txt
- 编辑 docker-compose.yml,取消注释密钥部分:
services:
garmin-mcp:
environment:
- GARMIN_EMAIL_FILE=/run/secrets/garmin_email
- GARMIN_PASSWORD_FILE=/run/secrets/garmin_password
secrets:
- garmin_email
- garmin_password
secrets:
garmin_email:
file: ./secrets/garmin_email.txt
garmin_password:
file: ./secrets/garmin_password.txt
- 启动容器:
docker compose up -d
在 Docker 中处理 MFA
如果你的 Garmin 账户启用了多因素身份验证(MFA):
- 使用该服务的令牌卷运行身份验证 CLI:
docker compose run --rm --entrypoint garmin-mcp-auth garmin-mcp
- 按提示输入 MFA 代码:
Garmin Connect MFA required. Please check your email/phone for the code.
Enter MFA code: 123456
-
OAuth 令牌将保存到 Docker 卷(
garmin-tokens)中,因此后续运行时无需重新进行身份验证。 -
完成 MFA 设置后,即可正常运行容器:
docker compose up -d
Docker 卷管理
OAuth 令牌存储在持久化 Docker 卷中,以避免重新进行身份验证:
# List volumes
docker volume ls
# Inspect the tokens volume
docker volume inspect garmin_mcp_garmin-tokens
# Remove the volume (will require re-authentication)
docker volume rm garmin_mcp_garmin-tokens
通过 Docker 与 Claude Desktop 配合使用
如需在 Claude Desktop 中使用 Docker 化的 MCP 服务,可以将其配置为与容器通信。不过请注意,MCP 服务通常通过 stdio 通信,直接执行进程的方式最为适用。对于基于 Docker 的部署,建议改用使用 Claude Desktop部分所示的标准 uvx 方法。
使用示例
连接到 Claude 后,你可以提出如下问题:
- “显示我最近的活动”
- “我昨晚的睡眠情况怎么样?”
- “我昨天走了多少步?”
- “显示我最近一次跑步的详细信息”
- “分析我上一次骑行的功率区间,并与我的训练区间进行比较”
- “显示我过去 6 周的 CTL、ATL 和 TSB 趋势”
- “我昨天骑行的功率持续时间曲线是什么样的?估算我的 FTP。”
- “分析我最近一次骑行活动的 FIT 数据——我爬坡时的变速质量怎么样?”
- “显示我过去 2 周的 HRV 趋势,并标出任何恢复方面的隐患”
- “我 20 分钟功率的赛季最佳值是多少?我是什么时候达到的?”
故障排除
get_training_effect 对有效活动返回 HTTP 403
Garmin 的活动详情端点(/activity-service/activity/{id})可能会返回 403 Forbidden,即使同一活动在列表工具中可见。
现在,get_training_effect 会回退到活动列表搜索,该搜索仍会包含近期活动的有氧/无氧训练效果。
如果活动早于近期搜索时间范围,请使用
get_activities / get_activities_by_date 列出该活动并重试,或者直接使用这些列表字段。
get_goals 未返回 Garmin Connect 中已有的目标
Garmin 的 goal-service 只会返回在 Connect 当前“目标”界面中创建的目标(例如每月骑行目标这类指定距离/时间的目标),且请求必须发送 Sec-Fetch-Site: same-origin 并使用从 1 开始的 start 值。使用 start=0 时会返回空列表。python-garminconnect 的 get_goals()(截至 0.3.16)无法同时满足这两项要求,因此这里的 get_goals 会像 Connect 的“目标”页面一样,直接调用 /goal-service/goal/goals,并仅在回退时使用库调用。
“Failed to spawn process: No such file or directory”
如果 Claude Desktop 找不到 uvx,原因是 uvx 不在 Claude Desktop 使用的 PATH 中。解决方法如下:
- 找到
uvx的安装位置:
which uvx
- 在配置中使用完整路径。例如,如果
uvx位于/Users/username/.cargo/bin/uvx:
{
"mcpServers": {
"garmin": {
"command": "/Users/username/.cargo/bin/uvx",
"args": [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
]
}
}
}
Windows:Smart App Control 阻止 uv / uvx
在启用了 Smart App Control 的 Windows 11 上,启动 Garmin_MCP 时,uv.exe / uvx.exe 可能会被阻止,包括 uv 尝试从本地 .venv 加载未签名的 garmin-mcp.exe 时。
这与 Microsoft Defender Antivirus 隔离并非一回事。Smart App Control 位于:
Windows 安全中心 → 应用和浏览器控制 → Smart App Control
症状
- 运行
uv、uvx或使用command: "uvx"的 Claude Desktop 时收到 Smart App Control 通知 - Claude Desktop 无法启动服务,即使
uvx看起来已安装 - 事件查看器 → 应用程序和服务日志 → Microsoft → Windows → CodeIntegrity → Operational 显示 CodeIntegrity Error 3077,其中提到
uv.exe和garmin-mcp.exe(策略/Enterprise 签名级别)
确认
- Smart App Control 处于 On 状态(Evaluation 或 Enforcement)。
- 检查 CodeIntegrity Operational 日志中启动失败前后的事件 3077。
- Defender“病毒和威胁防护”历史记录可能为空——这并不能排除 SAC。
恢复方法(建议保持 Smart App Control 开启)
- 通过软件包渠道安装或重新安装
uv,然后在 PowerShell 中验证:winget install --id=astral-sh.uv -e # or: scoop install main/uv uvx --version - 将 Claude Desktop 指向
uvx.exe的完整路径(方法与上文 PATH 故障排除相同),例如:"command": "C:\\Users\\<you>\\.local\\bin\\uvx.exe" - 如果 Enforcement 仍阻止加载
garmin-mcp.exe,你可能需要针对该二进制文件路径添加管理员/策略例外。全局关闭 Smart App Control 是最后手段,不是默认建议。 - 如果本地 uvx 仍被阻止,请改用 Docker Compose 安装方式。
登录问题
如果遇到登录问题:
- 确认凭据正确
- 检查 Garmin Connect 是否需要额外验证
- 确保 garminconnect 包为最新版本
日志
如遇其他问题,请查看 Claude Desktop 日志:
- macOS:
~/Library/Logs/Claude/mcp-server-garmin.log - Windows:
%APPDATA%\Claude\logs\mcp-server-garmin.log
Garmin Connect 多重身份验证(MFA)
了解 MCP 服务中的 MFA
MCP 服务以后台进程运行,无法直接访问终端。如果你的 Garmin 账户启用了 MFA,必须先使用预身份验证工具完成一次身份验证,服务才能运行。
推荐:预身份验证工具
处理 MFA 最简单的方式是使用专用身份验证工具:
garmin-mcp-auth
该工具会将 OAuth 令牌保存到 ~/.garminconnect,供以后使用。在 Claude Desktop 或其他 MCP 客户端中运行时,服务会自动使用这些令牌。
其他选项:
# Use environment variables for credentials
[email protected] GARMIN_PASSWORD=secret garmin-mcp-auth
# Verify existing tokens
garmin-mcp-auth --verify
# Show where tokens are looked up, what is on disk, and whether they work
garmin-mcp-auth --diagnose
# Force re-authentication (e.g., when tokens expire)
garmin-mcp-auth --force-reauth
# Use custom token location
garmin-mcp-auth --token-path ~/.garmin_tokens
替代方案:首次手动运行
你可以通过文件向身份验证 CLI 提供凭据:
# Store credentials in files for security
echo "[email protected]" > ~/.garmin_email
echo "your_password" > ~/.garmin_password
chmod 600 ~/.garmin_email ~/.garmin_password
# Run the authentication CLI before starting the server
GARMIN_EMAIL_FILE=~/.garmin_email GARMIN_PASSWORD_FILE=~/.garmin_password \
uvx --python 3.12 --from git+https://github.com/Taxuspt/garmin_mcp garmin-mcp-auth
# Enter MFA code when prompted
# Tokens will be saved automatically
# Now add to Claude Desktop config without credentials
完成初次身份验证后,配置 Claude Desktop 时不要填写凭据(令牌已保存):
{
"mcpServers": {
"garmin": {
"command": "uvx",
"args": [
"--python",
"3.12",
"--from",
"git+https://github.com/Taxuspt/garmin_mcp",
"garmin-mcp"
]
}
}
}
使用 Docker 和 MFA
如果使用 Docker,请按照上文的使用 Docker 处理 MFA部分操作,以便简化流程并持久保存令牌。
MFA 故障排除
错误:“MFA required; run 'garmin-mcp-auth' before starting the server.”
解决方法:
- 打开终端
- 运行:
garmin-mcp-auth - 输入凭据和 MFA 代码
- 重启 Claude Desktop
令牌已过期
OAuth 令牌会定期过期(约每 6 个月)。请重新进行身份验证:
garmin-mcp-auth --force-reauth
验证令牌是否有效
garmin-mcp-auth --verify
garmin-mcp-auth 已成功,但服务仍无法登录
服务只会从令牌目录($GARMINTOKENS,默认为 ~/.garminconnect)中的
garmin_tokens.json 加载令牌。启动错误会说明该目录中的情况:目录不存在、令牌文件不存在、文件无法读取,或 Garmin 拒绝了令牌。常见原因是 MCP 客户端启动服务时使用的 GARMINTOKENS 或 HOME 与运行
garmin-mcp-auth 的 shell 不同(在 Windows 上使用 Claude Desktop 时很常见),导致两者解析出的目录不同。请比较以下输出:
garmin-mcp-auth --diagnose
garmin-mcp-auth 还会写入 ~/.garminconnect_base64 文件,这是供其他基于 garminconnect 的工具使用的副本;服务不会读取该文件。
测试
本项目包含针对所有 MCP 工具的全面测试。目前所有测试均已通过(100%)。
运行测试
# Run unit and integration tests (default - uses mocked Garmin API, e2e tests are deselected)
uv run pytest
# Run only the integration tests
uv run pytest tests/integration/
# Run tests with verbose output
uv run pytest tests/integration/ -v
# Run a specific test module
uv run pytest tests/integration/test_health_wellness_tools.py -v
# Run end-to-end tests (requires real Garmin credentials).
# Some of these create and delete foods, food logs and workouts in your account.
uv run pytest tests/e2e/ -m e2e -v
测试结构
- 集成测试(200 多项):使用 FastMCP 集成测试所有 MCP 工具,并模拟 Garmin API 响应
- 端到端测试(
tests/e2e/):使用真实 MCP 服务和 Garmin API 进行测试(需要有效凭据)。仅在使用-m e2e时运行。
从本地路径重新安装
如果你正在使用本地检出版本或 fork:
uv tool install --python 3.12 --force C:\Users\aresd\Desktop\programacion\garmin_mcp
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
