Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

Runspector — AI running coach for Garmin

PYPI · RUNSPECTOR

AI running coach for Garmin: HRV, readiness and VO2max explained, workouts on your watch

Available components

67 Trust /100

Last scanned (18 hours ago)

Scores higher than 63% of PyPI servers

Category Health and Science

Trust breakdown (7 categories)

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. How we score → Why this is hard to score →

Supply Chain Security50
  • Malware scan not yet available for this package.Unverified
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
  • 0 of 37 dependencies flagged as unhealthy. View diagnostics → Pass
Provenance & Transparency100
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to edxleon/runspector). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 1 days ago).Pass
  • Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability67
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 3462 tokens (~192/item across 18 items; 18 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management17
  • Stability observed for 5 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage98
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 93% of tool parameters carry a description.Partial
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 18 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 19 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 4 Nov 26 −14
    • Malware scan: pass → unverified ▼ security
    • Security disclosure: fail → pass ▲ functional
  • 3 Nov 26 +15
    • Malware scan: unverified → pass ▲ security
  • 2 Nov 26 +1
    • Stability: 0.07 → unverified ▼ security
    • Tool safety: pass → unverified ▼ security
    • Malware scan: unverified → pass ▲ security
    • Capabilities: pass → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • First check of Schema quality: unverified functional
    • Package version: 0.7.0 → 0.10.0 functional
    • Package version: 0.7.0 → 0.9.0 functional
    • Package version: 0.7.0 → 0.8.0 functional
  • 1 Nov 26 0
    • Schema quality: 2775 → 3217 ▼ functional
    • Package version: 0.6.0 → 0.7.0 functional
  • 31 Oct 26 +1
    • Stability: unverified → 0.03 ▲ functional
    • Package version: 0.5.1 → 0.6.0 functional
  • 30 Oct 26 64

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 4 Nov 2026 · Analysed pypi/runspector@0.10.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem pypi
Reason Verified
Discovered via Registry attestation endpoint
Source repo edxleon/runspector
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/edxleon/runspector/.github/workflows/release.yml@refs/tags/v0.10.0
Rekor log index 3650456682
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:2665883d3176235613b5c22951ae3586f92a532ed4da06f2447ccc7904321d04

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted hatchling.build

Background: Why install scripts are a supply-chain risk →

Dependencies 37 packages
Packages resolved 37
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 18 exposed · ~2,895 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
analyze_workout ~108

Deep dive into ONE run: time in each HR zone, interval structure (rep count, rep length, work vs recovery HR), weather, performance condition, plus rule-based notes. Default: the latest run with detail. The interval structure is Garmin's auto-detection — if the athlete states a different structure, the athlete is right.

NameTypeReqDescription
activity_id––Garmin activity id; wins over `day`.
day––ISO date YYYY-MM-DD. Omit for the latest.
NameTypeReqDescription
resultstringyes–

No examples provided.

apply_workout ~169

WRITE a proposed session to the athlete's Garmin account: upload the workout, schedule it on the proposal's day, push it to the watch, then read it back and verify structure and targets. Call ONLY after the athlete has seen the preview and explicitly agreed - a request ("plan me 10 km") is not agreement, "yes, put it on the watch" is. Not available to the app's own card runs; there the athlete clicks. Returns what is now on Garmin, with any warning (not pushed because the watch is offline; a mismatch found on read-back). A proposal can be applied once; an unknown or used id says so and lists the open ones.

NameTypeReqDescription
proposal_idstringyesThe id propose_workout returned.
NameTypeReqDescription
resultstringyes–

No examples provided.

check_in ~387

Record what the athlete SAYS about themselves today: ill, in pain, sore or stressed - or that it is over. Call it when they tell you, in their own words ("I have a cold", "my calf hurts", "legs are heavy from Sunday", "rough week at work"); never from the data alone - a low HRV is not a cold. It changes today's decision in code: ill or pain rest the day whatever the watch says, and after they end it, as many easy days follow as it lasted; sore or stressed take the hard session away. It holds until they say it is over, or runs out after a few days without a new word; saying it again keeps it open. Returns what was recorded and the app's decision for today now. Local only, nothing goes to Garmin; not available to the app's own card runs.

NameTypeReqDescription
kindstringyesill: a cold, fever, flu, stomach bug. pain: something hurts (a calf, a knee, a foot) - not muscle soreness. sore: muscle soreness, heavy legs. stressed: work or life stress.
note––Where or what, in the athlete's words: "left calf", "sore throat". Optional.
overboolean–True when the athlete says it is OVER ("the cold is gone", "no more pain"). "Better" is not over - ask.
since––The day it began, YYYY-MM-DD, when the athlete says so ("since yesterday", "since Monday") - at most 7 days back. Default: today.
undoboolean–True only when the athlete says today's check-in was recorded by mistake ("no, my friend is ill"): it is taken back as if never said. Not for "it is gone" - that is over.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_athlete_profile ~158

What the app has learned about THIS athlete from their own data, each with its evidence: how many days they run and on which weekdays, their long-run day, a weekly other sport, how consistent they are, their intensity pattern over 28 days, the VO2max trend and whether a measurement is due, Garmin's load focus, resting-HR baseline and zones - and, where a value moved and held, since when. Call it once per conversation after `get_coaching_reference`, and use it to make the advice theirs. It is context, not today's numbers: those come from the other tools, and the decision stays the app's. Read-only; no Garmin call.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

get_coaching_reference ~91

The coach's full rule set: how to read the data, today's decision, the planning rules, zones and intensity distribution, the energy boundary and the sources behind each threshold - the same text the app's own coach works from. Call it ONCE per conversation, before the first training advice, and follow it. No arguments, no Garmin call; it reads nothing of the athlete.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

get_daily_metrics ~54

Every recorded recovery value for ONE day (default: latest day with data). Use when a single night/day is in question, not for trends.

NameTypeReqDescription
day––ISO date YYYY-MM-DD. Omit for the latest.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_intensity_distribution ~81

Time in heart-rate zones across all runs (easy Z1-2 / moderate Z3 / hard Z4-5 / Z5) with percentages — the basis for the 80/20 polarisation question. States how many runs have zone detail, so an incomplete picture is visible.

NameTypeReqDescription
period_daysinteger–Window length in days.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_recent_activities ~64

Workout digest: totals per sport plus the latest workouts, each run classified Quality / Long Run / Easy (from training effect and duration). Use to see what was actually trained before recommending the next session.

NameTypeReqDescription
period_daysinteger–Window length in days.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_recovery_summary ~74

Averages of sleep, HRV, resting HR, stress, Body Battery and steps over the last N days plus a snapshot of the latest day. Use for "how has my recovery been?". Aggregates only — never a day-by-day list.

NameTypeReqDescription
period_daysinteger–Window length in days.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_training_load ~88

Training-load picture: ACWR with its SOURCE (Garmin's EWMA ratio, or a self-computed fallback that is less reliable), Garmin training status, VO2max with change, and weekly load buckets. VO2max change is only reported when the value actually varied (Garmin carries the last value forward).

NameTypeReqDescription
period_daysinteger–Window length in days.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_training_readiness ~195

Today's readiness verdict GO / EASY / REST with the signals behind it (HRV status, sleep score, Body Battery, resting HR vs 27-day baseline, ACWR, days since the last hard workout). Rule-based and conservative. START HERE for "should I train today?". Carries the app's own decision for today and, on a hard day, WHICH hard session the history calls for (VO2max intervals, threshold reps, or the steady block Garmin measures VO2max from) - explain that, do not pick another; the athlete's goal from their profile when set; the Garmin calendar for the next 14 days, each entry with its weekday, date and schedule id (what propose_change names). Flags stale data explicitly. When the last Garmin sync is older than 30 minutes it syncs first (10-40 s) and says so on top.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

get_trend ~58

Weekly averages of ONE recovery metric over the last N days — for "is my HRV / resting HR / sleep trending up or down?".

NameTypeReqDescription
metricstringyes–
period_daysinteger–Window length in days.
NameTypeReqDescription
resultstringyes–

No examples provided.

get_vo2max_history ~85

VO2max over the last 8 weeks as STEPS (only the days the value really changed — Garmin carries it forward in between) plus a descriptive comparison of the last 28 days with the 28 before (distance, Z5 minutes, easy share, temperature). Use for "why is my VO2max moving?". Descriptive, not causal.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

propose_change ~222

File the athlete's OWN change to their planned week as a proposal: "Friday instead of Saturday", "Tuesday shorter", "no intervals this week", "add an easy run on Thursday". The athlete decides: the change is kept as asked even where the rules disagree - more than the plan's step, two hard days in a row, a hard session in a return week, a run on a rest day or while they said they are in pain. What the rules think of it comes back as `coach:` lines; say them to the athlete in your own words, and suggest a better change in your answer instead of making one they did not ask for. A workout this app did not make can be removed or replaced, not moved. Returns the change with its days and a proposal id. NOTHING is written to Garmin: apply_workout with the id after the athlete's yes; undo_workout takes it back.

NameTypeReqDescription
changesarrayyesExactly the changes the athlete asked for - nothing they did not ask for.
NameTypeReqDescription
resultstringyes–

No examples provided.

propose_week ~432

Build a polarised training week and file it as ONE proposal: a VO2max session and a threshold session 48 h apart, the long run on its weekday, easy runs between, nothing hard the day before or after the long run, at least one rest day. The sessions go on the days the athlete usually runs, and the quality sessions keep clear of a weekly other sport - read from their history, each an `assumption:` line. Sized from the athlete's own running weeks and read against their history, in code: +10 % by default, held or unloaded on the load ratio, a down week after three weeks up, a return week after a pause, and a measurement week (a steady block in the threshold slot) when VO2max has had no new value for 28 days - each one an `assumption:` line in the preview; explain the line, do not override it. Targets from their own zones, pace from Garmin's race predictions when no threshold is measured. Use when the athlete asks for their week ("plan my week", "what should next week look like"). The calendar wins: a day that already has an entry gets nothing, and a quality session too close to a hard calendar day becomes an easy run - each change is a `calendar:` line. Returns every session with its day and one proposal id; apply_workout with that id puts the package on Garmin after the athlete's yes. Nothing is written here.

NameTypeReqDescription
days_per_week––Running days. Default: the athlete's profile, else their history (the days they usually run), else 4 - the last two listed as an assumption.
long_run_day––Weekday of the long run. Default: the profile, else the weekday of their usual long run, else sun - the last two listed as an assumption.
start_day––First day of the week to plan, YYYY-MM-DD, today or up to 8 days ahead. Default: the coming Monday (today, if today is Monday).
NameTypeReqDescription
resultstringyes–

No examples provided.

propose_workout ~394

Build a structured session for the athlete's route or time budget and file it as a PROPOSAL - warm-up, work reps with targets, recovery jogs, cool-down - sized so the whole thing adds up to the route. Targets come from the athlete's own Garmin zones; anything not measured is listed as an assumption. Use when the athlete asks for a workout ("plan me intervals for my 10 km", "an easy 45 minutes", "a threshold session") or when the readiness verdict calls for a different session than the one on the calendar. Kinds: easy/long (one capped step), threshold (Z4 reps), vo2max (Z5 reps), steady (>= 12 min even effort at threshold - the only shape Garmin measures VO2max from). `day` defaults to today. Returns the preview and a proposal id. NOTHING is written to Garmin: show the preview, and only if the athlete says yes call apply_workout with the id. On an impossible request (route too short) returns why, not a session.

NameTypeReqDescription
day––ISO date YYYY-MM-DD. Omit for the latest.
distance_km––Route length in km, e.g. 10 for a fixed 10 km loop. Give this OR duration_min.
duration_min––Session length in minutes. Give this OR distance_km.
kindstringyes–
name––Workout name on the watch. Default: kind and structure, e.g. 'VO2max 4x4 min'.
replaces_schedule_id––A calendar entry this session REPLACES (the number after 'schedule' in get_training_readiness). Applying unschedules it first; the workout stays in the library. Use for the readiness swap: an easy ru…
NameTypeReqDescription
resultstringyes–

No examples provided.

sync_garmin ~70

Pull the latest days and workouts from Garmin Connect NOW. Call this first when today's run or last night's sleep is missing. Takes 10-40 s. Read-only towards Garmin; writes only to the local database.

NameTypeReqDescription
daysinteger–How many days back to re-fetch.
NameTypeReqDescription
resultstringyes–

No examples provided.

undo_workout ~165

Take a session (or a whole applied week) back OFF the athlete's Garmin calendar. The counterpart of apply_workout: use it when the athlete says the session should not be there after all, or after trying the write path out. It unschedules - the workout stays in their Garmin library, so applying the same proposal again puts it back on a day without building or uploading anything a second time. Only sessions this app uploaded and scheduled are touched; a calendar entry that has changed hands since is left alone and reported. Like apply_workout it needs the athlete's explicit yes, and it is not available to the app's own card runs.

NameTypeReqDescription
proposal_idstringyesThe id of a proposal that was applied.
NameTypeReqDescription
resultstringyes–

No examples provided.

Install

How do I install the Runspector — AI running coach for Garmin MCP server?

Runspector — AI running coach for Garmin runs locally as a PyPI package, launched with uvx runspector. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · runspector

# add to Claude Code
claude mcp add edxleon-runspector -- uvx runspector
Common questions

What is the Runspector — AI running coach for Garmin MCP server?

Runspector — AI running coach for Garmin is an MCP server listed in the public MCP registry as io.github.edxleon/runspector. AI running coach for Garmin: HRV, readiness and VO2max explained, workouts on your watch. This page covers its PyPI package (runspector).

Is the Runspector — AI running coach for Garmin MCP server safe to use?

Runspector — AI running coach for Garmin scores 67 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 4 November 2026. Its build provenance is signed and verified. 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 Runspector — AI running coach for Garmin MCP server expose?

Runspector — AI running coach for Garmin exposes 18 tools: get_athlete_profile, get_coaching_reference, get_training_readiness, get_recovery_summary, get_daily_metrics, and 13 more. Their descriptions and schemas cost roughly 2,895 tokens of context every time the server is loaded.

Is the Runspector — AI running coach for Garmin MCP server still maintained?

Runspector — AI running coach for Garmin is still listed as active in the MCP registry. We last reached this channel on 4 November 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 Runspector — AI running coach for Garmin MCP server under?

Runspector — AI running coach for Garmin declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.