关于 caddie-mcp
caddie-mcp 将 Garmin 高尔夫数据提供给 Claude 等 MCP 客户端,面向希望分析球场表现和健康数据的球手。数据同步到本地 DuckDB,支持逐杆 GPS、杆数增益、球杆距离及睡眠恢复背景分析。
主要功能
- 01同步 Garmin 球局与击球数据
- 02分析逐杆 GPS 与击球地图
- 03计算杆数增益和表现统计
- 04比较实测球杆距离
- 05关联睡眠与恢复数据
- 06只读 SQL 查询本地缓存
适用场景
- 01分析特定球洞或球杆的表现
- 02绘制球场击球位置图
- 03评估睡眠与成绩的关联
- 04查看实测距离和场地策略
MCP 相关
该 MCP 服务通过工具、提示词和资源向 MCP 客户端开放本地缓存的 Garmin 高尔夫与健康数据。也支持带身份验证的 HTTP 远程服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
13收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
Caddie
真正见过你每一杆的 AI 球童。
Caddie 是一款 MCP 服务,可将 Claude(或任何兼容 MCP 的大模型)连接到你的 Garmin 高尔夫数据——每一场比赛、每一杆 GPS 击球数据、得分增益、真实球杆距离、实际击球距离,以及每个成绩背后的睡眠和恢复情况。想问什么都可以:“为什么我在五杆洞总是打崩?”、“绘制我在主场球场的开球分布图”、“睡眠不好真的会让我多打几杆吗?”
- 本地优先,保护隐私:数据只需同步一次,就会存入你设备上的 DuckDB 文件;凭据和健康数据绝不会离开你的设备。
- 非官方:Caddie 使用与 Garmin Connect 应用相同的私有 API(通过 python-garminconnect)。它仅读取你自己的账户;在生态系统跟上之前,Garmin 一旦更改相关内容,它就可能无法使用。请事先了解这一点。
- 支持:尽力提供支持,欢迎提交问题和 PR。由 OneClub 的制作者打造。
工作原理
Garmin Connect ──sync──► local DuckDB cache ──MCP tools──► your LLM
你的数据只需同步一次,就会存入本地数据库(~/.caddiemcp/golf.duckdb),之后所有问题都会从缓存中获取答案——快速、私密,也不会给 Garmin 的服务器造成负担。凭据绝不会离开你的设备。
设置
从源代码安装(当前目录):
python3 -m venv .venv && .venv/bin/pip install -e .
.venv/bin/caddie-mcp login # one-time; MFA supported
.venv/bin/caddie-mcp sync --max-rounds 50
更喜欢用浏览器而不是终端?caddie-mcp login --web 会打开本地页面(仅限 127.0.0.1),提供标准的邮箱、密码和 MFA 输入框——使用相同的令牌存储方式,操作界面更友好。
从构建好的 wheel 安装(无需检出代码——dist/ 中包含两者):
pipx install ./dist/caddie_mcp-1.0.0-py3-none-any.whl # or pip install
caddie-mcp login && caddie-mcp sync
发布到 PyPI 后,可以通过 uvx caddie-mcp / pipx install caddie-mcp 安装。
Claude Desktop / Claude Code
添加到 claude_desktop_config.json(Claude Code 则添加到 .mcp.json):
{
"mcpServers": {
"caddie-mcp": {
"command": "/ABSOLUTE/PATH/TO/caddie-mcp",
"args": ["serve"]
}
}
}
使用 which caddie-mcp(pipx)或 /path/to/caddie-mcp/.venv/bin/caddie-mcp
(从源代码安装)获取命令路径。本仓库的 .mcp.json 已配置好,可用于在此文件夹中启动的 Claude Code 会话。
远程服务(多用户,HTTP)
同一服务也可通过可流式传输的 HTTP 运行,并使用 bearer-token 身份验证和完整的用户隔离——每位用户都有自己的数据库和 Garmin 令牌存储目录,位于 ~/.caddiemcp/users/<name>/(或 $CADDIEMCP_HOME)下。
caddie-mcp user add marcos # prints the access token (shown once)
caddie-mcp serve-http --host 0.0.0.0 --port 8724
用户可以在浏览器中关联自己的 Garmin 账户,无需管理员使用终端:向他们发送 https://your-host/garmin/login,他们可在此输入访问令牌和 Garmin 凭据(支持两步 MFA);令牌会存入他们各自在服务器上的私有目录。管理员协助登录的方式 caddie-mcp user login <name> 仍可作为备用方案使用。
客户端通过 http://host:8724/mcp 连接,并在标头中携带 Authorization: Bearer <token>——例如,在 Claude Code 中:
claude mcp add --transport http golf http://host:8724/mcp \
--header "Authorization: Bearer <token>"
Docker:
python -m build # wheel must exist in dist/
docker build -t caddie-mcp .
docker run -d -v caddie_data:/data -p 8724:8724 caddie-mcp
docker exec -it <container> caddie-mcp user add marcos
docker exec -it <container> caddie-mcp user login marcos
安全说明:令牌是 256 位密钥,仅以 SHA-256 哈希形式存储,并通过恒定时间比较进行校验;使用 caddie-mcp user rotate-token <name> 轮换令牌。请在 TLS 之后运行(Caddy/nginx/Cloudflare Tunnel)——令牌会通过标头传输。--no-auth 模式适用于仅限本地主机的单用户场景,并且会拒绝绑定到非回环地址。/health 是唯一无需身份验证的路由。/data 卷包含 Garmin 凭据,请妥善处理备份。
claude.ai 自定义连接器(OAuth)
claude.ai 通过 OAuth(动态客户端注册 + PKCE)连接远程 MCP 服务,而不是通过 bearer 标头连接。启用方式如下:
caddie-mcp serve-http --host 0.0.0.0 --oauth \
--public-url https://golf.example.com
然后在 claude.ai 中将 https://golf.example.com/mcp 添加为自定义连接器。首次连接时,用户会进入同意页面,并粘贴一次 caddie-mcp 访问令牌;之后,OAuth 令牌(1 小时访问令牌 + 轮换刷新令牌,以哈希形式存储)会维持连接,并将权限限定在该用户的数据范围内。静态 bearer 令牌仍可与 OAuth 并用。必须使用配置了 TLS 的真实域名——claude.ai 不会连接纯 HTTP 服务。
后台同步
在服务模式下,自动保持所有已关联用户的数据为最新:
caddie-mcp serve-http --host 0.0.0.0 --sync-every 6h
用户将按顺序同步(增量同步,并加入抖动且隔离各用户的错误),避免 Garmin API 遭遇大量请求同时涌入的情况。
Claude Desktop 扩展
python scripts/build_mcpb.py 会生成 dist/caddie-mcp.mcpb——双击即可安装到 Claude Desktop 的安装包,通过 uvx 启动已发布的软件包。机器上需要安装 uv,且该软件包已发布到 PyPI;一次性的 uvx caddie-mcp login 仍需在终端中完成(凭据绝不会经由桌面应用传递)。
发布到 PyPI(维护者)
.venv/bin/python -m build # sdist + wheel into dist/
pipx run twine upload dist/* # needs a PyPI API token
数据质量与修复
caddie-mcp repair 会在整个缓存中重新推导所有计算字段,不会调用 Garmin(球杆名称、球位/击球类型规范化、GPS 到旗杆的距离、GIR/球道命中推断)。每次同步结束时都会自动运行,因此只有在升级连接器后才需要手动运行。
已处理的 Garmin 已知问题:手表会报告 TEEBOX/TEE/UNKNOWN 枚举值;推杆常常是每洞的计数,没有果岭击球数据;击球落点到达果岭时会被吸附到旗杆位置(因此果岭击球后的距离数据会如实标记为 NULL,推杆的杆数增益则使用带标记的估算值)。
工具
| 工具 | 能回答的问题 |
|---|---|
garmin_status | 我已连接吗?缓存中有多少数据,还有多少仍在 Garmin 上? |
sync_garmin_data | 从 Garmin 拉取回合/击球/球杆数据——分批处理(每次调用 25 个,并报告 rounds_remaining),让完整的多年历史数据也能通过聊天安全加载 |
list_rounds | “显示我最近的回合”——简洁摘要 |
get_round | 深入查看单个回合:记分卡、球洞、击球 |
get_shots | 击球级别的 GPS/球杆/球位数据;使用 format="geojson" 获取地图数据 |
get_club_stats | 每支球杆的实际测量距离,与 Garmin 的估算值进行比较 |
get_strokes_gained | 按回合统计 Broadie 杆数增益:开球 / 攻果岭 / 短杆 / 推杆,并与你的差点水平或零差点水平比较 |
get_performance_stats | 约 40 项 PGA 风格的统计数据(开球、按距离统计的 GIR、救球、推杆、得分),可选差点基准 |
get_handicap | WHS 风格的指数、计入的差点差值及趋势 |
get_course_intel | 某个球场各洞的难度和常用开球球杆 |
get_health_context | 某回合日期的睡眠、HRV、Body Battery、准备度和压力 |
correlate_health_performance | “睡眠不好时我的成绩会更差吗?”——配对数据与客观的相关性分析 |
query_golf_data | 任何问题,均以只读 SQL 查询缓存 |
同步还会填充 daily_health(每个回合日期额外调用 Garmin 4 次):
睡眠得分/时长、静息心率、HRV 状态、Body Battery 范围、训练准备度、压力、步数——以及每个回合的时段扩展数据:
开球时的 Body Battery 及打球期间的消耗、回合期间的平均/最高心率和压力,以及通过匹配的 Garmin 活动获取的回合天气(温度、风、湿度、天气状况)。
如果 Garmin 未发送散布数据,系统会根据 GPS 几何关系推导击球偏差(dx/dy):开球相对于开球点→旗杆连线的横向偏差,攻果岭/切杆相对于旗杆的偏差——让任何带有击球 GPS 数据的手表都能提供偏差方向和偏差倾向统计。
每次击球还会计算实际打球距离:击球点和旗杆位置的地形海拔数据来自免费的 Open-Meteo 海拔 API(永久缓存在本地数据库中),plays_like_yds 应用标准的上坡/下坡 1:1 估算方法——因此可以根据“实际打起来相当于多少距离”来分析“我的 150 码击球”。
提示词(打包的工作流):post_round_report、practice_plan、course_strategy、health_check_in、season_review。
资源:schema://data-dictionary(列、单位、枚举值)、docs://metric-definitions(每项统计数据的计算方法)和 docs://getting-started(推荐的工具调用流程)。
约定
- 距离单位为码,坐标使用十进制度数,时间使用 ISO 8601。
- 球位:
tee | fairway | rough | sand | green | recovery | penalty。 - 击球类型:
drive | approach | chip | putt | penalty。 - 未知值为
NULL,绝不伪造——一洞的最后一杆没有测量到的结束距离,工具会明确说明。
安全说明
- Garmin 令牌存储在
~/.garminconnect(权限模式为 0600)——请像对待密码一样妥善保管。 - SQL 工具为只读模式,仅允许执行单条 SELECT 语句,并设有上限。
- 这是一个非官方连接器,仅用于访问你自己的 Garmin 数据。
开发
.venv/bin/python -m pytest tests/ -q
mcp-name: io.github.mbrionesalvarez/caddie-mcp
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。