Labsco
leewnsdud logo

Garmin Connect

โ˜… 4

from leewnsdud

Access Garmin Connect running data and training plan information.

๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅโœ“ VerifiedAccount requiredNeeds API keys

garmin-mcp

Garmin Connect ๋Ÿฌ๋‹ ๋ฐ์ดํ„ฐ๋ฅผ LLM์— ์ œ๊ณตํ•˜๋Š” MCP(Model Context Protocol) ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.

Claude Desktop ๋“ฑ MCP ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๋™ํ•˜์—ฌ ๋Ÿฌ๋‹ ํ›ˆ๋ จ ๋ถ„์„, ๊ณ„ํš ์ˆ˜๋ฆฝ, ์›Œํฌ์•„์›ƒ ์ƒ์„ฑ ๋“ฑ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ

  • ๋Ÿฌ๋‹ ํ™œ๋™ ์กฐํšŒ - ์ตœ๊ทผ ํ™œ๋™, ๋‚ ์งœ๋ณ„ ์กฐํšŒ, ์ƒ์„ธ ๋ถ„์„, ์Šคํ”Œ๋ฆฟ ๋ฐ์ดํ„ฐ (47๊ฐœ ํ•„๋“œ: ํŽ˜์ด์Šค, ์‹ฌ๋ฐ•, ์ผ€์ด๋˜์Šค, ๋Ÿฌ๋‹ ๋‹ค์ด๋‚˜๋ฏน์Šค, ํŒŒ์›Œ, HR์กด, GAP, ๊ฒฝ์‚ฌ๋„, ์Šคํƒœ๋ฏธ๋‚˜, ์˜จ๋„ ๋“ฑ)
  • ํŠธ๋ ˆ์ผ๋Ÿฌ๋‹ ๋ถ„์„ - ClimbPro ๊ฒฝ์‚ฌ ๊ตฌ๊ฐ„ ๋ถ„์„, ๋“ฑ๊ธ‰๋ณ„ ๋‚œ์ด๋„, Grade Adjusted Pace, Run/Walk Detection, ๋‚ ์”จ ์กฐ๊ฑด
  • ์ฃผ๊ฐ„/์›”๊ฐ„ ์š”์•ฝ - ๋ณผ๋ฅจ ํŠธ๋ Œ๋“œ, ์ „์›” ๋Œ€๋น„ ๋น„๊ต
  • ํ›ˆ๋ จ ์ง€ํ‘œ - VO2max, ํ›ˆ๋ จ ์ƒํƒœ, ํ›ˆ๋ จ ์ค€๋น„๋„, ๋ ˆ์ด์Šค ์˜ˆ์ธก, ์ –์‚ฐ์—ญ์น˜
  • ์‹ฌ๋ฐ•/HRV - ์ผ๊ฐ„ ์‹ฌ๋ฐ•, ์‹ฌ๋ฐ•๋ณ€์ด๋„, ํ™œ๋™๋ณ„ ์‹ฌ๋ฐ•์กด ๋ถ„ํฌ
  • ์›ฐ๋‹ˆ์Šค - ์ˆ˜๋ฉด, ์ŠคํŠธ๋ ˆ์Šค, ๋ฐ”๋””๋ฐฐํ„ฐ๋ฆฌ, SpO2
  • ๊ฐœ์ธ ๊ธฐ๋ก/๋ชฉํ‘œ - PR, ํ”ผํŠธ๋‹ˆ์Šค ๋ชฉํ‘œ
  • ์›Œํฌ์•„์›ƒ ์ƒ์„ฑ - ์‹œ๊ฐ„/๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ์ธํ„ฐ๋ฒŒ, ํ…œํฌ ๋“ฑ ๊ตฌ์กฐํ™”๋œ ์›Œํฌ์•„์›ƒ์„ Garmin ์›Œ์น˜์— ์ „์†ก (ํŽ˜์ด์Šค/์‹ฌ๋ฐ•/์ผ€์ด๋˜์Šค/ํŒŒ์›Œ ํƒ€๊ฒŸ)
  • ๋Ÿฌ๋‹ํ™” ๊ด€๋ฆฌ - ์‹ ๋ฐœ๋ณ„ ๋ˆ„์  ๊ฑฐ๋ฆฌ + ๋งˆ๋ชจ์œจ ์ถ”์ 
  • ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ - ๋ชจ๋“  API ์‘๋‹ต์—์„œ PII(์†Œ์œ ์ž ์ด๋ฆ„, ํ”„๋กœํ•„ ID, GPS ์ขŒํ‘œ) ์ž๋™ ํ•„ํ„ฐ๋ง

์š”๊ตฌ ์‚ฌํ•ญ

  • Python 3.10+
  • uv ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €
  • Garmin Connect ๊ณ„์ •

์„ค์น˜

git clone https://github.com/leewnsdud/garmin-connect-mcp.git
cd garmin-connect-mcp
uv sync

์ธ์ฆ

์ตœ์ดˆ 1ํšŒ ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

uv run python scripts/auth.py

์ด๋ฉ”์ผ, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด OAuth ํ† ํฐ์ด ~/.garminconnect/์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. MFA ์‚ฌ์šฉ ์‹œ ์ฝ”๋“œ ์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, .env ํŒŒ์ผ์— ์ž๊ฒฉ์ฆ๋ช…์„ ์„ค์ •ํ•˜๋ฉด ์ž๋™ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.

Claude Desktop ์—ฐ๋™

~/Library/Application Support/Claude/claude_desktop_config.json์— ์ถ”๊ฐ€:

{
  "mcpServers": {
    "garmin-mcp": {
      "command": "/Users/<username>/.local/bin/uv",
      "args": [
        "--directory",
        "/path/to/garmin-mcp",
        "run",
        "garmin-mcp"
      ]
    }
  }
}

uv์˜ ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. which uv๋กœ ํ™•์ธํ•˜์„ธ์š”.

์„ค์ • ํ›„ Claude Desktop์„ ์žฌ์‹œ์ž‘ํ•˜๋ฉด ๋„๊ตฌ๊ฐ€ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜ (์„ ํƒ)

.env.example์„ ์ฐธ๊ณ ํ•˜์—ฌ .env ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜์„ค๋ช…๊ธฐ๋ณธ๊ฐ’
GARMIN_EMAILGarmin Connect ์ด๋ฉ”์ผ-
GARMIN_PASSWORDGarmin Connect ๋น„๋ฐ€๋ฒˆํ˜ธ-
GARMIN_TOKEN_DIRํ† ํฐ ์ €์žฅ ๊ฒฝ๋กœ~/.garminconnect
GARMINTOKENSBase64 ์ธ์ฝ”๋”ฉ ํ† ํฐ (CI/Docker์šฉ)-

์ œ๊ณต ๋„๊ตฌ (24๊ฐœ)

Activities

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_recent_activities์ตœ๊ทผ ๋Ÿฌ๋‹ ํ™œ๋™ ๋ชฉ๋ก (GAP, RWD ํฌํ•จ)count (๊ธฐ๋ณธ 20, ์ตœ๋Œ€ 100)
get_activities_by_date๋‚ ์งœ ๋ฒ”์œ„๋กœ ๋Ÿฌ๋‹ ํ™œ๋™ ์กฐํšŒstart_date, end_date
get_activity_detailํ™œ๋™ ์ƒ์„ธ ์ •๋ณด (์Šคํƒœ๋ฏธ๋‚˜, ์ž„ํŒฉํŠธ ๋กœ๋“œ ํฌํ•จ)activity_id
get_activity_splitskm๋ณ„ ์Šคํ”Œ๋ฆฟ ๋ฐ์ดํ„ฐactivity_id
get_activity_weatherํ™œ๋™ ์ค‘ ๋‚ ์”จ ์กฐ๊ฑด (์˜จ๋„, ์Šต๋„, ํ’์†)activity_id
get_activity_typed_splitsClimbPro ๊ฒฝ์‚ฌ ๊ตฌ๊ฐ„ ๋ถ„์„ (๋“ฑ๊ธ‰, GAP)activity_id

Summary

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_weekly_running_summary์ฃผ๊ฐ„ ๋Ÿฌ๋‹ ์š”์•ฝend_date, weeks (์ตœ๋Œ€ 12)
get_monthly_running_summary์›”๊ฐ„ ๋Ÿฌ๋‹ ์š”์•ฝ + ์ „์›” ๋น„๊ตyear, month

Training

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_training_statusํ›ˆ๋ จ ์ƒํƒœdate
get_training_readinessํ›ˆ๋ จ ์ค€๋น„๋„ ์ ์ˆ˜date
get_vo2max_and_fitnessVO2max + ํ”ผํŠธ๋‹ˆ์Šค ๋‚˜์ดdate
get_race_predictions5K/10K/ํ•˜ํ”„/ํ’€ ์˜ˆ์ƒ ๊ธฐ๋ก์—†์Œ
get_lactate_threshold์ –์‚ฐ์—ญ์น˜ ์‹ฌ๋ฐ•/ํŽ˜์ด์Šคstart_date, end_date

Heart Rate

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_heart_rate_data์ผ๊ฐ„ ์‹ฌ๋ฐ• ๋ฐ์ดํ„ฐdate
get_hrv_data์‹ฌ๋ฐ•๋ณ€์ด๋„ (HRV)date
get_activity_hr_zonesํ™œ๋™๋ณ„ ์‹ฌ๋ฐ•์กด ๋ถ„ํฌactivity_id

Wellness

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_sleep_data์ˆ˜๋ฉด ๋ฐ์ดํ„ฐdate
get_daily_wellness์ŠคํŠธ๋ ˆ์Šค/๋ฐ”๋””๋ฐฐํ„ฐ๋ฆฌ/SpO2/ํ˜ธํก์ˆ˜date
get_weekly_wellness_summary์ฃผ๊ฐ„ ์›ฐ๋‹ˆ์Šค ํŠธ๋ Œ๋“œend_date, weeks (์ตœ๋Œ€ 4)

Records & Goals

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_personal_records๊ฐœ์ธ ๊ธฐ๋ก (1K~๋งˆ๋ผํ†ค)์—†์Œ
get_goalsํ”ผํŠธ๋‹ˆ์Šค ๋ชฉํ‘œstatus (active/completed/all)

Workout

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
create_running_workout์›Œํฌ์•„์›ƒ ์ƒ์„ฑ ๋ฐ Garmin์— ์—…๋กœ๋“œ (์‹œ๊ฐ„/๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜, ํŽ˜์ด์Šค/์‹ฌ๋ฐ•/์ผ€์ด๋˜์Šค/ํŒŒ์›Œ ํƒ€๊ฒŸ)name, steps, description
get_workouts์ €์žฅ๋œ ์›Œํฌ์•„์›ƒ ๋ชฉ๋กcount (๊ธฐ๋ณธ 20, ์ตœ๋Œ€ 100)

Gear

๋„๊ตฌ์„ค๋ช…์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ
get_running_gear๋Ÿฌ๋‹ํ™” ๋ชฉ๋ก + ๋ˆ„์  ๊ฑฐ๋ฆฌ + ๋งˆ๋ชจ์œจ์—†์Œ

์›Œํฌ์•„์›ƒ ์ƒ์„ฑ ๊ฐ€์ด๋“œ

create_running_workout์œผ๋กœ ๊ตฌ์กฐํ™”๋œ ๋Ÿฌ๋‹ ์›Œํฌ์•„์›ƒ์„ ์ƒ์„ฑํ•˜๊ณ  Garmin ์›Œ์น˜์— ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Step ํƒ€์ž…

ํƒ€์ž…์„ค๋ช…
warmup์›Œ๋ฐ์—…
interval์ธํ„ฐ๋ฒŒ (๊ณ ๊ฐ•๋„)
recoveryํšŒ๋ณต ์กฐ๊น…
rest์™„์ „ ํœด์‹ (์„œ์„œ ์‰ฌ๊ธฐ)
cooldown์ฟจ๋‹ค์šด
repeat๋ฐ˜๋ณต ๊ทธ๋ฃน

์ข…๋ฃŒ ์กฐ๊ฑด (Step ๊ธฐ๊ฐ„)

ํ•„๋“œํƒ€์ž…์„ค๋ช…์˜ˆ์‹œ
duration_secondsint์‹œ๊ฐ„ ๊ธฐ๋ฐ˜"duration_seconds": 300 (5๋ถ„)
distance_metersint๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜"distance_meters": 1000 (1km)

ํ•˜๋‚˜์˜ ์›Œํฌ์•„์›ƒ์—์„œ ์‹œ๊ฐ„/๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ step์„ ํ˜ผํ•ฉ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Target ํƒ€์ž…

ํƒ€์ž…๊ฐ’ ํ˜•์‹์˜ˆ์‹œ
pacemin:sec/km"min": "4:30", "max": "4:50"
heart_ratebpm"min": 140, "max": 155
cadencespm"min": 170, "max": 185
powerwatts"min": 280, "max": 320

์˜ต์…˜

  • ์›Œํฌ์•„์›ƒ ๋ฉ”๋ชจ: description ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „์ฒด ์„ค๋ช… ์ถ”๊ฐ€
  • Step ๋ฉ”๋ชจ: ๊ฐ step์— "description": "๋ฉ”๋ชจ" ์ถ”๊ฐ€
  • ๋งˆ์ง€๋ง‰ ํšŒ๋ณต ๊ฑด๋„ˆ๋›ฐ๊ธฐ: repeat step์— "skip_last_rest": true ์ถ”๊ฐ€

์˜ˆ์‹œ: 4x1km ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ์ธํ„ฐ๋ฒŒ

{
  "name": "4x1km Intervals @4:30",
  "description": "10K ๋ ˆ์ด์Šค ๋Œ€๋น„ VO2max ์ธํ„ฐ๋ฒŒ",
  "steps": [
    {
      "type": "warmup",
      "duration_seconds": 600,
      "description": "๊ฐ€๋ณ๊ฒŒ ์กฐ๊น…"
    },
    {
      "type": "repeat",
      "count": 4,
      "skip_last_rest": true,
      "steps": [
        {
          "type": "interval",
          "distance_meters": 1000,
          "target": { "type": "pace", "min": "4:20", "max": "4:40" },
          "description": "๋ชฉํ‘œ ํŽ˜์ด์Šค ์œ ์ง€"
        },
        {
          "type": "recovery",
          "duration_seconds": 120,
          "description": "์ฒœ์ฒœํžˆ ์กฐ๊น…์œผ๋กœ ํšŒ๋ณต"
        }
      ]
    },
    {
      "type": "cooldown",
      "duration_seconds": 600,
      "description": "๋งˆ๋ฌด๋ฆฌ ์กฐ๊น…"
    }
  ]
}

์ƒ์„ธ ์›Œํฌ์•„์›ƒ ์ƒ์„ฑ ๊ฐ€์ด๋“œ๋Š” AGENTS.md๋ฅผ, ์ „์ฒด ๋„๊ตฌ ์š”์ฒญ/์‘๋‹ต ๊ทœ๊ฒฉ์€ TOOL_SPEC.md๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

ํ™œ์šฉ ์˜ˆ์‹œ

Claude Desktop์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • "์ด๋ฒˆ ์ฃผ ๋Ÿฌ๋‹ ์š”์•ฝํ•ด์ค˜"
  • "์ตœ๊ทผ 3๊ฐœ์›” ์ฃผ๊ฐ„ ๋ณผ๋ฅจ ํŠธ๋ Œ๋“œ ๋ถ„์„ํ•ด์ค˜"
  • "๋‚ด VO2max ๊ธฐ์ค€์œผ๋กœ Jack Daniels VDOT ํ›ˆ๋ จ ํŽ˜์ด์Šค ๊ณ„์‚ฐํ•ด์ค˜"
  • "์ตœ๊ทผ ํ™œ๋™๋“ค์˜ ์‹ฌ๋ฐ•์กด ๋ถ„ํฌ๋ฅผ ๋ณด๊ณ  80/20 ๋น„์œจ์„ ์ง€ํ‚ค๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์ค˜"
  • "๋‚ด์ผ 4x1km ์ธํ„ฐ๋ฒŒ ์›Œํฌ์•„์›ƒ ๋งŒ๋“ค์–ด์ค˜"
  • "๋‚ด ๋Ÿฌ๋‹ํ™” ์ค‘ ๊ต์ฒด ์‹œ๊ธฐ๊ฐ€ ๋œ ๊ฒƒ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์ค˜"
  • "์ˆ˜๋ฉด๊ณผ ํ›ˆ๋ จ ์ค€๋น„๋„์˜ ์ƒ๊ด€๊ด€๊ณ„๋ฅผ ๋ถ„์„ํ•ด์ค˜"
  • "์ตœ๊ทผ ํŠธ๋ ˆ์ผ๋Ÿฌ๋‹์˜ ๊ฒฝ์‚ฌ ๊ตฌ๊ฐ„๋ณ„ ์„ฑ๊ณผ๋ฅผ ๋ถ„์„ํ•ด์ค˜"
  • "ํŠธ๋ ˆ์ผ๋Ÿฌ๋‹์—์„œ ๊ฑท๊ธฐ/๋‹ฌ๋ฆฌ๊ธฐ ๋น„์œจ์„ ํ™•์ธํ•ด์ค˜"

์ง€์›ํ•˜๋Š” ๋Ÿฌ๋‹ ํ›ˆ๋ จ ๋ฐฉ๋ฒ•๋ก 

๋ฐฉ๋ฒ•๋ก ํ™œ์šฉ ๋ฐ์ดํ„ฐ
Jack Daniels VDOTVO2max, PR, ๋ ˆ์ด์Šค ์˜ˆ์ธก
Norwegian Double Threshold์ –์‚ฐ์—ญ์น˜, ์‹ฌ๋ฐ•์กด
80/20 Training์‹ฌ๋ฐ•์กด ๋ถ„ํฌ
Hanson's Method์ฃผ๊ฐ„/์›”๊ฐ„ ๋ณผ๋ฅจ, ํŽ˜์ด์Šค ํŠธ๋ Œ๋“œ
Pfitzinger์ฃผ๊ฐ„ ๋ณผ๋ฅจ, ์žฅ๊ฑฐ๋ฆฌ ๋Ÿฐ ๋ถ„์„
ํŠธ๋ ˆ์ผ/์šธํŠธ๋ผ ๋ถ„์„ClimbPro ๊ฒฝ์‚ฌ ๊ตฌ๊ฐ„, ๋‚ ์”จ, RWD, GAP

๊ฐœ๋ฐœ

# ์ฝ”๋“œ ์ˆ˜์ • ํ›„ ํŒจํ‚ค์ง€ ์žฌ์„ค์น˜
uv sync --reinstall-package garmin-mcp

# Claude Desktop ์žฌ์‹œ์ž‘์œผ๋กœ MCP ์„œ๋ฒ„ ๋ฐ˜์˜

๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ

๋ชจ๋“  Garmin API ์‘๋‹ต์—์„œ ๋‹ค์Œ ๊ฐœ์ธ์ •๋ณด ํ•„๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค:

  • ์†Œ์œ ์ž ์ •๋ณด: ownerId, ownerFullName, ownerDisplayName, userId, ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL
  • ํ”„๋กœํ•„ ID: userProfilePK, userProfileId, profileId, profileNumber
  • ์‚ฌ์šฉ์ž ์ •๋ณด: displayName, fullName, userPro, userRoles
  • GPS ์ขŒํ‘œ: startLatitude, startLongitude, endLatitude, endLongitude

์ด ํ•„ํ„ฐ๋ง์€ src/garmin_mcp/sanitize.py์˜ strip_pii() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์žฌ๊ท€์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ์ˆ  ์Šคํƒ

  • python-garminconnect - Garmin Connect API ํด๋ผ์ด์–ธํŠธ
  • FastMCP - MCP ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ
  • uv - Python ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €
  • garth - OAuth ํ† ํฐ ๊ด€๋ฆฌ

๋ผ์ด์„ ์Šค

MIT