# io.github.endurancetools/garmin-mcp (npm · garmin-mcp-server)

Unofficial Garmin Connect server: training load, form, HRV readiness and workouts for your watch

- Trust score: 71/100 (medium)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-10-24

## Components

- npm · `garmin-mcp-server`: 71/100 (this document), [markdown](https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server.md), [page](https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server)

## Channel facts

- Registry: `npm`
- Package: `garmin-mcp-server`
- Version: `0.4.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-10-24.

- **Supply Chain Security**: 90/100
  - No malware found by supply-chain analysis.
  - CVE check failed: a known high-severity CVE affects tar 7.4.3, reached via garmin-mcp-auth > cuimp > tar. A fixed version is available.
  - No install/post-install scripts declared.
  - 9 of 37 dependencies flagged as unhealthy (1 deprecated).
- **Provenance & Transparency**: 48/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 7 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 74/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 4351 tokens (~174/item across 25 items; 20 tools + 5 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 33/100
  - Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 85/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 49% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 20 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 22 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

## Install

### How do I install the io.github.endurancetools/garmin-mcp server?

io.github.endurancetools/garmin-mcp runs locally as an npm package, launched with npx -y garmin-mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add endurancetools-garmin-mcp -- npx -y garmin-mcp-server
```

### Cursor

```json
{
  "mcpServers": {
    "endurancetools-garmin-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "garmin-mcp-server"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "endurancetools-garmin-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "garmin-mcp-server"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add endurancetools-garmin-mcp -- npx -y garmin-mcp-server
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "endurancetools-garmin-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "garmin-mcp-server"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add endurancetools-garmin-mcp --command npx --arg -y --arg garmin-mcp-server
```

### Hermes

```yaml
mcp_servers:
  endurancetools-garmin-mcp:
    command: "npx"
    args: ["-y", "garmin-mcp-server"]
```

### Netclaw

```json
{
  "McpServers": {
    "endurancetools-garmin-mcp": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "garmin-mcp-server"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add endurancetools-garmin-mcp -t stdio -c npx -a -y garmin-mcp-server
```

### Other

```json
{
  "mcpServers": {
    "endurancetools-garmin-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "garmin-mcp-server"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-22 (score 71, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-20 (score 70, +1)

No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-18 (score 69, +1)

No change was recorded against any check on this day. Stability & Change Management went from 10 to 13. That category is still filling its 30-day observation window: 3 days of observed history at the previous scan, 4 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-16 (score 68, +16)

- [security regression] Stability: 0.03 → unverified
- [security regression] Tool safety: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional] Package version: 0.4.0 → 0.4.1

### 2026-10-15 (score 52, −15)

- [security regression] Malware scan: pass → unverified
- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.3.1 → 0.4.0

### 2026-10-14 (score 67, +31)

- [security improvement] Injection markers: unverified → pass
- [security] First check of Judged manipulation: pass
- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [functional improvement] Tool coverage: unverified → 100
- [functional improvement] Schema quality: unverified → 100
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Security disclosure: fail → pass
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 49
- [functional] First check of Destructive annotations: pass
- [functional] First check of Schema quality: fail
- [functional] First check of Schema quality: good
- [functional] First check of Tool coverage: 100
- [functional] Package version: 0.3.0 → 0.3.1

### 2026-10-13 (score 36, +8)

- [security regression] CVE-2026-59871 affects this package: high
- [security regression] CVE-2026-53655 affects this package: high
- [security regression] CVE-2026-59873 affects this package: high
- [security regression] CVE-2026-24842 affects this package: high
- [security regression] CVE-2026-29786 affects this package: high
- [security regression] CVE-2026-23950 affects this package: high
- [security regression] CVE-2026-73566 affects this package: high
- [security regression] CVE-2026-59874 affects this package: high
- [security regression] CVE-2026-59875 affects this package: high
- [security regression] CVE-2026-26960 affects this package: high
- [security regression] CVE-2026-23745 affects this package: high
- [security regression] CVE-2026-31802 affects this package: high
- [security regression] Known CVEs: unverified → fail
- [functional improvement] Dependency health: unverified → 0.91
- [functional] Package version: 0.2.0 → 0.3.0

### 2026-10-12 (score 28)

First indexed and scored.

## MCP tools (20)

### `garmin_sync` (~253 tokens)

Sync Garmin data

Download data from Garmin Connect into the local cache. Read tools already download missing data by themselves, so call this only when the user asks to sync/refresh or to pre-load a range, or when a tool returned meta.sync_hint (auto fetch turned off) and the user agreed; pass the hint's scope/from/to. Days already stored are skipped. Long ranges run in the background in 7-day chunks with pauses and a daily request cap to stay gentle with Garmin; this waits at most 20 s and reports progress (also in garmin://sync-status). Example: {"scope":"health","from":"2026-09-01","to":"2026-09-30"}.

Input parameters:

- `force` (boolean): Re-download days that are already stored
- `from` (string): Start date; default: 7 days before `to`
- `scope` (string): all | activities | health (daily summary, sleep, HRV, weight) | training (status, readiness, VO2max) | reference (profile, gear, devices, activity types, workouts, calendar months of from..to, also i…
- `to` (string): End date; default: today

Output parameters:

- `data` (object)
- `meta`

### `get_activities` (~186 tokens)

List activities

List workouts/activities (runs, rides, swims, strength...) as dense summaries: id, date, type, name, duration, distance, pace or speed, HR, training load. Use for "what did I do last week", finding an activity id, or comparing sessions. For one activity in depth use get_activity; for weekly/monthly totals use get_period_summary. Example: {"from":"2026-10-01","type":"running","limit":10}.

Input parameters:

- `cursor` (string): next_cursor from the previous page
- `from` (string)
- `limit` (integer)
- `sort` (string)
- `to` (string)
- `type` (string): Garmin type key, e.g. running, trail_running, cycling, lap_swimming, strength_training; partial match. All keys: resource garmin://activity-types

Output parameters:

- `data` (object)
- `meta`

### `get_activity` (~174 tokens)

Get one activity

Details of one activity by id. detail="summary" (default) for the overview incl. description, RPE and feel; "splits" adds laps; "hr_zones" adds time in HR zones; "power_zones" adds time in power zones (power meter); "weather" adds temperature, wind and conditions during the activity; "exercise_sets" adds strength sets (exercise, reps, weight, rest); "full" adds all of these plus the raw second-by-second stream (HR, pace, GPS...) paginated with next_cursor, 50 KB per page - only when the user needs raw samples.

Input parameters:

- `cursor` (string): For detail="full": next_cursor of the previous page
- `detail` (string)
- `id` (integer, required): Activity id from get_activities

Output parameters:

- `data` (object)
- `meta`

### `update_activity` (~149 tokens)

Edit an activity

Change an activity in Garmin Connect: name, type (Garmin type key such as "trail_running"; valid keys in resource garmin://activity-types), description (notes), rpe (0-10 perceived effort) or feel (0 very weak, 25 weak, 50 normal, 75 strong, 100 very strong). Only call when the user asked for the change. Returns the activity after the edit.

Input parameters:

- `description` (string)
- `feel`
- `id` (integer, required)
- `name` (string)
- `rpe` (number)
- `type` (string): Garmin type key from garmin://activity-types, e.g. trail_running

Output parameters:

- `data` (object)
- `meta`

### `download_activity_file` (~118 tokens)

Download activity file

Save an activity as a file on this machine and return its path: fit (original device file), gpx, tcx, kml or csv (laps). Use when the user wants the file itself, e.g. to import elsewhere.

Input parameters:

- `format` (string)
- `id` (integer, required)
- `output_dir` (string): Subdirectory of the download directory (GARMIN_FIT_DOWNLOAD_DIR or <data dir>/downloads), e.g. "races"; default the download directory itself. Paths outside it are rejected

Output parameters:

- `data` (object)
- `meta`

### `query_health` (~267 tokens)

Query daily health metrics

For "how did I sleep this week", "calories and intensity minutes this week", "steps yesterday" or any single health metric over days: a table per day or per ISO week plus summary with averages, totals, min/max and 7/28-day trend. Metrics: steps, resting_hr, hrv, sleep, stress, body_battery, respiration, spo2, intensity_minutes, calories, floors. steps also returns the daily distance in km, resting_hr the daily min/max HR, hrv the Garmin HRV status and baseline range, floors the floors climbed, calories the kcal burned (total, active) and eaten (calories_consumed_kcal, absent without food log entries). Ask for several metrics in one call (e.g. calories and intensity_minutes together). Use get_sleep for sleep stages of particular nights. Example: {"metrics":["hrv","resting_hr","sleep"],"from":"2026-07-01","to":"2026-09-30","granularity":"week"}.

Input parameters:

- `from` (string): Default: 7 days before `to`
- `granularity` (string): "week" for ranges longer than ~3 weeks
- `metrics` (array, required)
- `to` (string): Default: today

Output parameters:

- `data` (object)
- `meta`

### `get_sleep` (~82 tokens)

Get sleep

Sleep for one night ({"date":"2026-10-08"}, the morning date) with stages, score, SpO2, respiration and overnight HRV; or for a range ({"from","to"}) a per-night table with averages and trends.

Input parameters:

- `date` (string)
- `from` (string)
- `to` (string)

Output parameters:

- `data` (object)
- `meta`

### `get_training_status` (~184 tokens)

Get training status

Fitness and fatigue: VO2max (running/cycling) with trend, training readiness, remaining recovery time, Garmin training status (productive, maintaining, ...), Garmin acute/chronic load and load focus (aerobic low/high, anaerobic vs. targets), and `garmin_load_model`: CTL/ATL/TSB from Garmin's daily training load (EPOC); the own TSS model (power, pace, HR) is get_load. `metrics` holds race predictions (5k to marathon), endurance and hill score, fitness age, personal records and heat/altitude acclimation as of the newest training sync on or before `to`. Set include_series for the daily load curve.

Input parameters:

- `from` (string): Default: 28 days before `to`
- `include_series` (boolean)
- `to` (string)

Output parameters:

- `data` (object)
- `meta`

### `get_body_composition` (~54 tokens)

Get body composition

Weigh-ins (kg, body fat %, muscle mass, BMI) in a range with change and trend. Default range: last 90 days.

Input parameters:

- `from` (string)
- `to` (string)

Output parameters:

- `data` (object)
- `meta`

### `get_period_summary` (~326 tokens)

Summarise a week, month or range

Training week or month at a glance: sessions and volume per sport, time in the Garmin HR zones 1-5 (for the 3-zone Z1/Z2/Z3 split against LT1/LTHR, e.g. time below LT1 or polarisation, use get_load), active vs rest days, longest and hardest session, `garmin_load_model` at the end (CTL/ATL/TSB from Garmin's daily training load (EPOC); the own TSS model is get_load), and only avg/min/max of sleep, HRV, resting HR, steps, stress and body battery plus average daily kcal. Day-by-day values and other metrics (calorie totals, intensity minutes, floors, respiration, SpO2) come from query_health, weight from get_body_composition. Weeks run Monday-Sunday. Period "range" gives the same for any from..to up to 366 days, e.g. a training block: {"period":"range","from":"2026-08-04","to":"2026-09-28"}. `complete` is true when the period is over and all its data is in the cache; `training` is left out while its activities are not. Example: {"period":"week","anchor_date":"2026-10-08"}.

Input parameters:

- `anchor_date` (string): week/month: any date inside the period; default today
- `from` (string): range only, required
- `period` (string)
- `to` (string): range only, required

Output parameters:

- `data` (object)
- `meta`

### `list_workouts` (~234 tokens)

Workouts and calendar

For "my next race", "what is planned this week" or "which workouts do I have": the saved workout library (`workouts`), scheduled workouts (`upcoming_schedule`) and races or events the user added or subscribed to (`upcoming_events`: date, title, distance, start time, location; `race`/`primary` present only when true, `primary` marks the goal race of an active training plan). The calendar covers `from` to `to` (default: today and the next 60 days); any range works, past or future, and months not in the cache yet are downloaded on the way. Example: {"from":"2027-03-01","to":"2027-05-31"} for races next spring.

Input parameters:

- `from` (string): Calendar start; default today (or 60 days before `to` when `to` is in the past)
- `limit` (integer)
- `sport` (string): e.g. running, cycling, strength_training
- `to` (string): Calendar end; default 60 days after `from`

Output parameters:

- `data` (object)
- `meta`

### `get_workout` (~38 tokens)

Get a planned workout

Steps of a saved workout in readable form (warm-up, repeats, targets in pace/HR/power).

Input parameters:

- `id` (integer, required)

Output parameters:

- `data` (object)
- `meta`

### `create_workout` (~442 tokens)

Create a workout

Save a new structured workout to Garmin Connect (then use schedule_workouts to put it on the calendar so it syncs to the watch). Pass exactly one of: `preset` for a standard session from a few parameters (run_intervals, walk_run, easy_z2, strength_circuit); `definition` for anything else (typed steps with duration and target, nestable repeats); `garmin_json` only to copy an existing Garmin workout JSON. Errors name the bad field, e.g. steps[2].steps[0].target. Call with dry_run: true first, show the steps to the user and save only after they agree. dry_run saves nothing and does not contact Garmin: it returns the readable steps and the estimated duration (time steps, plus distance steps at the middle of their pace range; steps with neither are listed in estimate_note, and for garmin_json that carries its own estimate the note says it was taken from there).

Input parameters:

- `definition` (object): Typed workout. Example: {"name":"6x400m","sport":"running","steps":[{"kind":"warmup","duration":{"type":"time","seconds":600}},{"kind":"repeat","count":6,"steps":[{"kind":"interval","duration":{"type…
- `dry_run` (boolean): true: only show the steps and estimated duration, save nothing
- `garmin_json` (object): Raw Garmin workout JSON with workoutName, sportType and workoutSegments
- `preset`: Ready-made workout filled in from a few parameters. Example: {"name":"run_intervals","params":{"repeats":6,"work_meters":400,"work_target":{"type":"pace","min_per_km_fast":"3:50","min_per_km_slow":"4…

Output parameters:

- `data` (object)
- `meta`

### `schedule_workouts` (~147 tokens)

Schedule workouts

Put saved workouts on the Garmin calendar (they then sync to the watch), or take them off it. `unschedule` takes schedule_id values (from list_workouts upcoming_schedule or an earlier schedule_workouts result); the workout stays in the library, only the calendar entry goes. Unschedule only what the user asked to remove. Unscheduling runs first, so moving a workout is one call. Returns a result per item. Examples: {"items":[{"date":"2026-10-10","workout_id":123}]}, {"unschedule":[456]}.

Input parameters:

- `items` (array)
- `unschedule` (array): schedule_id values of calendar entries to remove

Output parameters:

- `data` (object)
- `meta`

### `get_gear` (~47 tokens)

Get gear

Shoes, bikes and other gear with total distance, usage since, notes and status. include_activities adds the last 10 activities per item.

Input parameters:

- `include_activities` (boolean)

Output parameters:

- `data` (object)
- `meta`

### `get_devices` (~53 tokens)

Get devices

Garmin devices on the account with model, firmware, last sync time and settings (time/date format, units, tones, move and heart-rate alerts, pulse ox during sleep, number of alarms). Comes from the reference sync.

Output parameters:

- `data` (object)
- `meta`

### `get_load` (~512 tokens)

Get training load (own model)

Own transparent load model (TSS per activity from power, else pace, else heart rate, else session RPE, with date-dependent thresholds), not Garmin's EPOC load; for Garmin's status and CTL/ATL/TSB from Garmin's load (`garmin_load_model`) use get_training_status. Returns CTL/ATL/TSB, ACWR, monotony and strain on `to` (`latest`), warning `flags`, ISO weeks per sport (sessions, hours, km, TSS, hrTSS, Garmin load, hours in Z1-2/Z3/Z4-5), the 3-zone intensity split against LT1/LTHR of the last 28 days (Z1/Z2/Z3 minutes and %; answers time below LT1, % in Z1, polarisation) and the thresholds used. include_series adds the daily curve, include_activities TSS/IF/load_source/EF per activity, include_efficiency the monthly EF trend, both with aerobic decoupling (Pa:Hr/Pw:Hr, % EF drop from first to second half) of sessions of 60+ min below LTHR with downloaded laps, include_by_sport CTL/ATL/TSB/ACWR per sport group (`by_sport`, plus run_ctl… columns in the series) next to the total, which stays the default. Example: {"from":"2026-09-01","to":"2026-09-30","include_activities":true}.

Input parameters:

- `flags` (object): Own flag thresholds, any of (default): acwr_high 1.5, acwr_warn 1.3, acwr_low 0.8, monotony_high 2, tsb_low -30, tsb_fresh 15, week_jump_pct 15, z1_min_pct 75, rpe_calibration 0.23, hr_method zones,…
- `from` (string): Default: 27 days before `to`
- `include_activities` (boolean)
- `include_by_sport` (boolean)
- `include_efficiency` (boolean)
- `include_series` (boolean)
- `source` (string): auto: power, pace, HR, then RPE per activity; hrtss: HR only; garmin_load: Garmin activity training load
- `to` (string): Default: today

Output parameters:

- `data` (object)
- `meta`

### `get_readiness` (~315 tokens)

Morning readiness

Morning GO/MODIFY/REST decision from HRV, resting HR, sleep hours and load; pass `rules` to use your own thresholds. Each signal has its value, reference, rating (ok, yellow, red; unknown when data is missing) and a readable detail; plus rules_used and a recommendation. Garmin's own scores (Training Readiness, Body Battery, stress; sleep score in the sleep value) are shown as info, not counted. REST needs a red pair (hrv with rhr or sleep, load with hrv, rhr or sleep), a single red or 2 yellow give MODIFY; decision_rule "count" instead gives REST at decision_red_min reds. Use for "how am I today" or "can I do a hard session". Example: {"date":"2026-10-12"}.

Input parameters:

- `date` (string): Morning to judge; default today
- `rules` (object): Own thresholds, any of (default): hrv_red_base_factor 0.9, hrv_red_mean28_factor 0.85, hrv_yellow_weekly_factor 0.9, rhr_red_delta 5, rhr_yellow_delta 3, sleep_h_red 6, sleep_h_yellow 7, acwr_red 1.5…

Output parameters:

- `data` (object)
- `meta`

### `get_thresholds` (~162 tokens)

Get training thresholds

Thresholds the analytics use on `date` (default today): per param its value, the date it applies since and its source (garmin-auto from the Garmin profile, test, manual, import), by_sport (run, bike, swim: LTHR and LT1 with a note when a fallback, default or approximation), HRmax and the 28-day resting HR. zones has the HR and power zone floors per sport from the Garmin profile (method, HRmax/rest/LTHR or FTP used, fetched date; current, not historical). history adds every recorded row. Example: {"param":"lthr_run","history":true}.

Input parameters:

- `date` (string)
- `history` (boolean)
- `param` (string)

Output parameters:

- `data` (object)
- `meta`

### `set_threshold` (~219 tokens)

Record a threshold

Record a field test result (LTHR, LT1, HRmax, FTP…) effective from a date; ask the user before saving. Stored in the local database only, never sent to Garmin; a row with the same date, param and source stays as it is (added false). A backdated row recomputes earlier activities from its date on (the first garmin-auto row is the Garmin profile as of its first download). Returns the row and the value in effect today. Example: {"date":"2026-10-11","param":"lthr_run","value":171,"note":"30 min TT"}.

Input parameters:

- `date` (string, required): Day of the test, not in the future
- `note` (string)
- `param` (string, required): Heart rates in bpm, ftp_w/run_ftp_w in W, css_s_per_100m in s per 100 m, run_threshold_pace_s_per_km in s per km
- `source` (string)
- `value` (number, required)

Output parameters:

- `data` (object)
- `meta`

## Diagnostics

Captured diagnostic sections: Provenance, Vulnerabilities, Dependencies. The full working is on the page: https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server#diagnostics

## Score history

- 2026-10-24: 71
- 2026-10-23: 71
- 2026-10-22: 71
- 2026-10-21: 70
- 2026-10-20: 70
- 2026-10-19: 69
- 2026-10-18: 69
- 2026-10-17: 68
- 2026-10-16: 68
- 2026-10-15: 52
- 2026-10-14: 67
- 2026-10-13: 36
- 2026-10-12: 28

## Common questions

### What is the io.github.endurancetools/garmin-mcp server?

io.github.endurancetools/garmin-mcp is listed in the public MCP registry as io.github.endurancetools/garmin-mcp. Unofficial Garmin Connect server: training load, form, HRV readiness and workouts for your watch. This page covers its npm package (garmin-mcp-server).

### Is the io.github.endurancetools/garmin-mcp server safe to use?

io.github.endurancetools/garmin-mcp scores 71 out of 100 on VerifyMCP. We recorded 12 known advisories against it as of 24 October 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the io.github.endurancetools/garmin-mcp server expose?

io.github.endurancetools/garmin-mcp exposes 20 tools: garmin_sync, get_activities, get_activity, update_activity, download_activity_file, and 15 more. Their descriptions and schemas cost roughly 3,962 tokens of context every time the server is loaded.

### Is the io.github.endurancetools/garmin-mcp server still maintained?

io.github.endurancetools/garmin-mcp is still listed as active in the MCP registry. We last reached this channel on 24 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the io.github.endurancetools/garmin-mcp server under?

io.github.endurancetools/garmin-mcp declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/garmin-mcp-server
- Socket report: https://socket.dev/npm/package/garmin-mcp-server
- Repository: https://github.com/endurancetools/garmin-mcp
- Changelog RSS feed: https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server.xml
- Changelog JSON feed: https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server.json
- HTML version of this page: https://verifymcp.io/servers/endurancetools-garmin-mcp/garmin-mcp-server
