{"$schema":"https://verifymcp.io/schemas/trust-report.json","schemaVersion":1,"license":{"name":"CC BY-NC 4.0","url":"https://creativecommons.org/licenses/by-nc/4.0/"},"generatedAt":"2026-11-05T16:35:03.131Z","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp","markdownUrl":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp.md","server":{"slug":"app-durely-garmin-insights-mcp","name":"durely insights MCP for Garmin","registryName":"app.durely/garmin-insights-mcp","description":"Your full Garmin history, kept locally, analysed down to the second, via the official Personal API.","registryStatus":"active","deletedAt":null,"statusMessage":null,"liveness":"live","publisher":{"class":"unknown","claimed":false}},"component":{"slug":"ghcr-io-durely-garmin-insights-mcp","type":"oci","identifier":"ghcr.io/durely/garmin-insights-mcp","withdrawn":false,"url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp","version":"0.5.2","transport":"stdio","scoredAt":"2026-11-05T08:35:57.380Z"},"score":{"total":44,"tier":"low","status":"scored","weekDelta":3,"history":[{"date":"2026-11-05","total":44},{"date":"2026-11-04","total":44},{"date":"2026-11-03","total":43},{"date":"2026-11-02","total":43},{"date":"2026-11-01","total":42},{"date":"2026-10-31","total":42},{"date":"2026-10-30","total":41},{"date":"2026-10-29","total":41}]},"categories":[{"name":"Supply Chain Security","score":0,"verdict":"unverified","reasons":["No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.","Known CVEs could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.","Install-script risk not yet assessed.","Dependency health could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read."],"codes":[{"code":"supplychain.malware_inconclusive","args":{"reason":"ecosystem_unsupported"}},{"code":"cve.inconclusive","args":{"reason":"no_sbom_attached"}},{"code":"installscript.inconclusive","args":{"reason":"no_install_concept"}},{"code":"dephealth.inconclusive","args":{"reason":"no_sbom_attached"}}]},{"name":"Provenance & Transparency","score":48,"verdict":"fail","reasons":["Source repository is publicly reachable at the declared URL.","Provenance check failed: no build-provenance attestation is published.","Clear OSI-approved license (Apache-2.0).","Actively maintained (last published 6 days ago).","Publishes a security disclosure policy (SECURITY.md)."],"codes":[{"code":"provenance.repo_verified","args":{}},{"code":"provenance.none","args":{}},{"code":"license.osi","args":{"spdx":"Apache-2.0"}},{"code":"maintenance.recent","args":{"age_days":"6"}},{"code":"disclosure.present","args":{}}]},{"name":"Schema Quality & AI Usability","score":75,"verdict":"fail","reasons":["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 5250 tokens (~238/item across 22 items; 21 tools + 1 resources), over budget; trim descriptions and params.","Usage-examples check failed: none of the tools include examples."],"codes":[{"code":"schema.descriptions","args":{"pct":"100"}},{"code":"schema.ai_quality","args":{"band":"good"}},{"code":"schema.footprint_heavy","args":{"avg":"238","items":"22","tools":"21","tokens":"5250","resources":"1"}},{"code":"schema.examples_absent","args":{}}]},{"name":"Stability & Change Management","score":23,"verdict":"partial","reasons":["Stability observed for 7 of 30 days with no destabilising changes; credit accrues until the full window elapses."],"codes":[{"code":"stability.building_history","args":{"days":"7"}}]},{"name":"Tool Coverage","score":97,"verdict":"partial","reasons":["100% of tools have a non-trivial description (not blank, and not just the tool's name).","92% of tool parameters carry a description."],"codes":[{"code":"toolquality.descriptions","args":{"pct":"100"}},{"code":"toolquality.param_docs","args":{"pct":"92"}}]},{"name":"Tool Safety","score":100,"verdict":"pass","reasons":["No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.","We read all 21 captured tool definition(s), and no name or description among them implies an irreversible operation.","An AI judge read all 23 captured unit(s) of tool text and found none that tries to manipulate the model reading it."],"codes":[{"code":"toolsafety.injection_clean","args":{}},{"code":"toolsafety.destructive_none","args":{"tools":"21"}},{"code":"toolsafety.manipulation_clean","args":{"units":"23","judged":"23"}}]},{"name":"Capabilities","score":100,"verdict":"pass","reasons":["Implements a current MCP spec version (2026-07-28)."],"codes":[{"code":"protocol.current","args":{"version":"2026-07-28"}}]}],"inconclusive":["No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.","Known CVEs could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.","Install-script risk not yet assessed.","Dependency health could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read."],"malware":[],"components":[{"slug":"durely-garmin-insights-mcp","type":"npm","identifier":"@durely/garmin-insights-mcp","withdrawn":false,"score":81,"current":false,"url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/durely-garmin-insights-mcp","markdownUrl":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/durely-garmin-insights-mcp.md"},{"slug":"ghcr-io-durely-garmin-insights-mcp","type":"oci","identifier":"ghcr.io/durely/garmin-insights-mcp","withdrawn":false,"score":44,"current":true,"url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp","markdownUrl":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp.md"}],"facts":[{"label":"Registry","value":"oci"},{"label":"Package","value":"ghcr.io/durely/garmin-insights-mcp"},{"label":"Version","value":"0.5.2"},{"label":"Transport","value":"stdio"}],"install":{"available":true,"bundleSha256":null},"tools":[{"name":"garmin_status","title":"Garmin connection status","description":"Check that the Garmin Personal API connection works and report its configuration.\n\nReports: where the API key comes from, whether a token could be obtained and when it expires, the API key's expiry (if GARMIN_API_KEY_EXPIRES is set), the time zone used for calendar dates, and the server version.\n\nUse this first when another garmin_* tool fails with an authentication error, or when the user asks whether their Garmin connection is set up.","inputs":[{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":124},{"name":"garmin_get_profile","title":"Get Garmin profile and zones","description":"Get the user's Garmin profile settings, heart rate zones per sport, and fitness age.\n\nReturns: units and locale, time zone, preferred training days, HR zone floors per sport (with the max HR / LTHR / resting HR used to compute them), and the latest fitness age.\n\nUse this before interpreting heart rate data (to know the user's zones), or when the user asks about their zones, max HR, lactate threshold or fitness age.","inputs":[{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":125},{"name":"garmin_list_activities","title":"List Garmin activities","description":"Search the user's Garmin activities (all history, from the local cache), newest first by default.\n\nReturns one page of compact summaries plus the total number of matches: id, date, type, name, duration, distance, pace/speed, HR, power, elevation, training effect, training load, TSS/IF and VO2max where available, plus time in HR/power zones (JSON mode).\n\nExamples:\n  - \"My runs this month\" -> activity_type=\"running\", start_date=\"2026-10-01\"\n  - \"Longest rides ever\" -> activity_type=\"cycling\", sort_by=\"distance\"\n  - \"Zwift sessions\" -> activity_type=\"virtual_ride\"\n  - \"Triathlon bike legs\" -> include_multisport_legs=true, activity_type=\"road_biking\"\n\nThe cache refreshes automatically when it's more than an hour old. Use garmin_get_activity for one activity's full details (splits, FTP, workout).","inputs":[{"name":"activity_type","type":"string","required":false,"description":"Garmin activity type or parent type. Parent types include their subtypes: running (trail_running, treadmill_running, track_running, virtual_run), cycling (road_biking, virtual_ride, indoor_cycling, m…"},{"name":"end_date","type":"string","required":false,"description":"Only activities on or before this local date, yyyy-MM-dd"},{"name":"include_multisport_legs","type":"boolean","required":false,"description":"false (default): multisport activities appear once, as the parent. true: show their individual legs (swim/bike/run/transitions) instead of the parent, e.g. so triathlon bike legs count as cycling vol…"},{"name":"limit","type":"integer","required":false,"description":"Maximum activities to return (1-100)"},{"name":"max_distance_km","type":"number","required":false,"description":"Maximum distance in km"},{"name":"max_duration_min","type":"number","required":false,"description":"Maximum duration in minutes"},{"name":"min_distance_km","type":"number","required":false,"description":"Minimum distance in km"},{"name":"min_duration_min","type":"number","required":false,"description":"Minimum duration in minutes"},{"name":"offset","type":"integer","required":false,"description":"Number of activities to skip, for pagination"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"search","type":"string","required":false,"description":"Text to match in the activity name (case-insensitive)"},{"name":"sort_by","type":"string","required":false,"description":"Sort field"},{"name":"sort_order","type":"string","required":false,"description":"desc = newest/largest first"},{"name":"start_date","type":"string","required":false,"description":"Only activities on or after this local date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":563},{"name":"garmin_get_activity","title":"Get Garmin activity details","description":"Get full details for one Garmin activity by ID.\n\nReturns: name, description, type, start time and time zone, device, summary metrics (duration, distance, speeds, HR min/avg/max, power avg/max/NP/20-min, FTP, cadence, stride, calories, training effect + message, training load, TSS, IF, temperature, intensity minutes), split summaries (e.g. run/walk/stand intervals), the structured workout if one was followed, and multisport parent/child IDs.\n\nGet IDs from garmin_list_activities. Example: \"Tell me about yesterday's run\" -> list activities for that date, then call this with its id.","inputs":[{"name":"activity_id","type":"integer","required":true,"description":"Garmin activity ID from garmin_list_activities, e.g. 12345678901"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":198},{"name":"garmin_get_activity_laps","title":"Get activity laps","description":"Get the laps (and sessions, swim lengths and Garmin's physiological metrics) of one activity, from its original FIT file.\n\nReturns per lap: start offset, duration (elapsed and timer), distance, pace/speed, avg/max HR, avg/max/normalized power, cadence, ascent/descent, intensity (active/rest/warmup/cooldown) and lap trigger; for swims, stroke and lengths. Also: device, multisport sessions, and FIT-only metrics when the device recorded them (VO2max, recovery time, lactate threshold HR/power).\n\nUse it for interval sessions, splits and pacing. Downloads the FIT file on first use (one request), then it's cached. For a multisport leg ID, returns only that leg's laps.","inputs":[{"name":"activity_id","type":"integer","required":true,"description":"Garmin activity ID from garmin_list_activities"},{"name":"lap_offset","type":"integer","required":false,"description":"Skip this many laps (for activities with very many laps)"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":225},{"name":"garmin_get_activity_streams","title":"Get activity time series","description":"Get second-by-second data from one activity's FIT file, downsampled to fit in context.\n\nReturns per field min/avg/max over the window, plus columnar series: t (seconds from the start of the activity, or of the leg for a multisport leg) and one array per field. Units: heart_rate bpm, power W, speed m/s, cadence steps/min (running) or rpm (cycling) or strokes/min, altitude m, distance m (cumulative), temperature °C, respiration_rate breaths/min, performance_condition (Garmin's -20..+20 score), vertical_oscillation mm, stance_time ms. Cadence averages leave out zeros.\n\nDefaults to heart_rate, power, speed, cadence, altitude (whichever the activity has) at 10 s resolution, at most 500 points; the resolution coarsens automatically for long activities. Zoom in with start_s/end_s (e.g. one interval from garmin_get_activity_laps' start offsets) and a smaller resolution_s.\n\n\"position\" adds GPS latitude/longitude and reveals where the user was: only request it when the user asks for location or route analysis. Developer fields (e.g. running power from a Connect IQ app) can be requested by the name listed in available_fields, like \"dev_RP_Power\".","inputs":[{"name":"activity_id","type":"integer","required":true,"description":"Garmin activity ID from garmin_list_activities"},{"name":"end_s","type":"number","required":false,"description":"Window end, seconds from the start"},{"name":"fields","type":"array","required":false,"description":"Fields to return: heart_rate, power, speed, cadence, altitude, distance, temperature, respiration_rate, performance_condition, vertical_oscillation, stance_time, position, or a dev_* field"},{"name":"max_points","type":"integer","required":false,"description":"Upper bound on points returned"},{"name":"resolution_s","type":"integer","required":false,"description":"Seconds per point (minimum)"},{"name":"response_format","type":"string","required":false,"description":"'json' (default) for the full series, 'markdown' for stats and a short preview table"},{"name":"start_s","type":"number","required":false,"description":"Window start, seconds from the start"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":431},{"name":"garmin_download_activity_fit","title":"Export activity FIT file","description":"Save the original FIT file of an activity to the server's exports folder and return its path, e.g. to import it into another tool (Intervals.icu, Golden Cheetah, a spreadsheet converter).\n\nThe file is exactly what the device recorded. Saved as <data dir>/exports/<activity_id>.fit; an existing export is kept, not overwritten. For a multisport leg, exports the whole multisport file.","inputs":[{"name":"activity_id","type":"integer","required":true,"description":"Garmin activity ID from garmin_list_activities"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":114},{"name":"garmin_get_daily_health","title":"Daily health and recovery","description":"Get day-by-day wellness and recovery data, from the local cache (all history).\n\nPer day: steps (+ goal), floors, resting/min/max heart rate, stress (average, max, % of the day at rest/low/medium/high), Body Battery (min, max, charged, drained), intensity minutes (moderate, vigorous), calories (total, active), respiration, hydration, plus that night's sleep (duration, score) and HRV (last-night average, status).\n\ngroup_by=\"week\" (Monday-based) or \"month\" aggregates: averages per day, minimums/maximums for min_hr/max_hr/stress_max, and totals plus per-day averages for steps and intensity minutes.\n\nDefaults to the last 14 days. Daily rows are limited to 92 days per call; use group_by=\"week\" or \"month\" for longer periods (e.g. a year by week). Today's values are partial.\n\nExamples: \"How's my recovery this week?\" → defaults. \"Resting HR trend this year\" → start_date=\"2026-01-01\", group_by=\"week\".","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"group_by","type":"string","required":false,"description":null},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":295},{"name":"garmin_get_sleep","title":"Sleep","description":"Get nightly sleep from the local cache: bed and wake time, total sleep, deep/light/REM/awake time, naps, sleep score with quality and Garmin's feedback, awake count, average respiration and sleep stress. JSON mode adds the sleep score's components (duration, stress, deep/light/REM %, restlessness, awake count) with Garmin's rating each.\n\nA night belongs to the date you woke up. Defaults to the last 14 nights, at most 92 per call.","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":159},{"name":"garmin_get_hrv","title":"Heart rate variability","description":"Get nightly HRV (heart rate variability, in ms) from the local cache: last-night average, highest 5-minute value, 7-day average, the personal baseline range (balanced low/high) and Garmin's status (BALANCED, UNBALANCED, LOW, POOR).\n\nWith readings_date, also returns that night's 5-minute HRV readings (fetched from Garmin if older than the synced detail window).\n\nDefaults to the last 28 nights, at most 366 per call. HRV needs a compatible watch worn overnight; history starts when that began.","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"readings_date","type":"string","required":false,"description":"Night (wake-up date) to include 5-minute readings for"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":197},{"name":"garmin_get_intraday","title":"Intraday health data","description":"Get one day's health data through the day, averaged into intervals: heart rate (bpm), Body Battery (0-100), overnight HRV readings (ms) and SpO2 (pulse ox, %).\n\nReturns per metric: min/avg/max, the day's summary values (e.g. resting HR, Body Battery charged/drained, SpO2 averages), and a columnar series (local times \"HH:MM\" + values). Synced for the last 150 days; older days are fetched from Garmin on demand. Garmin itself keeps intraday heart rate and HRV readings for only about 4–5 months (Body Battery longer), so older days may have just the day summary.\n\nDefaults to today, all four metrics, 15-minute intervals. HRV and SpO2 need a compatible watch (SpO2 also needs pulse ox enabled).","inputs":[{"name":"date","type":"string","required":false,"description":"Defaults to today"},{"name":"interval_min","type":"integer","required":false,"description":"Minutes per point"},{"name":"metrics","type":"array","required":false,"description":null},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":238},{"name":"garmin_get_body_composition","title":"Weight and body composition","description":"Get weigh-ins from the local cache: weight (kg), BMI, body fat %, body water %, muscle and bone mass (kg), visceral fat, and where each came from (scale, manual, linked app). Includes the change over the period and the weight goal if one is set.\n\nOnly days with a weigh-in appear. Defaults to the last 365 days.","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":136},{"name":"garmin_get_nutrition","title":"Nutrition and hydration","description":"Get food logged in Garmin Connect (or a linked app such as MyFitnessPal) per day: calories, carbs, protein and fat against the day's goals, and meals; plus hydration (ml) from the daily summary.\n\nFood logs are fetched from Garmin on demand and cached. Defaults to the last 7 days, at most 31 per call.","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":133},{"name":"garmin_get_womens_health","title":"Menstrual cycle","description":"Get menstrual cycle tracking from Garmin Connect for a date: cycle day, current phase and days until the next, period and cycle length, predicted next cycle, fertile window and ovulation date, plus that day's logged symptoms and notes (day view). Fetched live from Garmin.\n\nReturns a clear \"not tracked\" message when cycle tracking isn't set up. Defaults to today.","inputs":[{"name":"date","type":"string","required":false,"description":"Defaults to today"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":120},{"name":"garmin_analyze_activity","title":"Analyze an activity","description":"Compute training metrics for one activity from its second-by-second FIT data:\n- time in heart rate zones (the user's Garmin zones for that sport) and, with an FTP, in power zones (Coggan)\n- power: average, normalized power (NP), variability index, intensity factor and TSS (needs FTP)\n- aerobic decoupling: drift of power or pace per heartbeat between the first and second half (<5% is good for steady efforts of 45+ min)\n- first vs second half (negative/positive split)\n- best efforts: power over 5 s–60 min, heart rate over 1–60 min, fastest 400 m–marathon (running), 5–90 km (cycling), 100 m–3.8 km (swimming)\n- Edwards TRIMP (zone-weighted minutes) and detected work intervals with their consistency\n\nFTP comes from ftp_w, else from the activity's own record (Garmin cycling FTP). Works for multisport legs too.","inputs":[{"name":"activity_id","type":"integer","required":true,"description":"Garmin activity ID from garmin_list_activities"},{"name":"ftp_w","type":"integer","required":false,"description":"Functional threshold power in watts, for power zones, IF and TSS"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":278},{"name":"garmin_training_summary","title":"Training summary","description":"Summarize training per week or month: sessions, hours, distance, elevation and training load, per sport; intensity distribution (share of time in low = HR zones 1–2, moderate = zone 3, high = zones 4–5, with a rough pattern: polarized, pyramidal, threshold-heavy); and the load trend at the end of each period: fitness (CTL, 42-day), fatigue (ATL, 7-day), form (TSB = CTL − ATL) and the acute:chronic ratio (ACWR; above ~1.5 is a commonly cited risk zone).\n\nLoad is Garmin's training load per activity; activities without it (older devices, some third-party uploads) get an estimate from average heart rate (Banister TRIMP) scaled to Garmin's load using the user's own activities. The response says how much is estimated. Multisport legs count toward their sport; walking is included as its own sport.\n\nDefaults to the last 12 weeks by week. Filter with sport (e.g. running, cycling, or a type like virtual_ride).","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"group_by","type":"string","required":false,"description":null},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"sport","type":"string","required":false,"description":"Only this sport (parent type) or activity type"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":310},{"name":"garmin_recovery_trends","title":"Recovery trends","description":"Relate training load to recovery markers, day by day: resting HR, overnight HRV, sleep score and duration, Body Battery max and stress, each against the user's own rolling 28-day baseline.\n\nReturns: a status (last 7 days vs the previous 28: HRV, resting HR, sleep, load; plus current fitness/fatigue/form), days flagged for low HRV, elevated resting HR or poor sleep, weekly averages, and correlations such as \"previous day's load vs next morning's HRV\" with their strength. Correlation is not causation, and short periods give noisy results.\n\nDefaults to the last 8 weeks; at most 180 days.","inputs":[{"name":"end_date","type":"string","required":false,"description":"Defaults to today"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"},{"name":"start_date","type":"string","required":false,"description":"Local calendar date, yyyy-MM-dd"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":200},{"name":"garmin_compare_activities","title":"Compare activities","description":"Compare 2–6 activities side by side: date, type, duration, distance, pace/speed, heart rate, power (avg/NP), elevation, training effect and load, cadence, and efficiency factor (speed or NP per heartbeat; higher means more output for the same heart rate, a classic way to track aerobic progress on similar sessions).\n\nWith deep=true, also analyzes each one's FIT data (downloads files if needed): aerobic decoupling, time in low/moderate/high HR zones and best efforts.\n\nExample: \"Am I getting fitter on my Tuesday interval run?\" → list those runs, then compare them.","inputs":[{"name":"activity_ids","type":"array","required":true,"description":null},{"name":"deep","type":"boolean","required":false,"description":"Also run FIT-based analysis for each activity"},{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":185},{"name":"garmin_query","title":"Query the Garmin cache with SQL","description":"Run one read-only SQLite query against the local Garmin cache, for analyses the other tools don't cover (custom aggregations, correlations, records, comparisons across years).\n\nViews (one row per item; use these first):\n- activities(id, parent_id, is_multisport_parent, type_key, sport, name, start_local, start_date, duration_s, moving_s, distance_m, elevation_gain_m, avg_speed_mps, avg_hr, max_hr, avg_power_w, norm_power_w, calories, aerobic_te, anaerobic_te, training_load, tss, vo2max)\n  sport = Garmin parent type (running, cycling, swimming, walking, ...); type_key = exact type (road_biking, virtual_ride, lap_swimming, ...). Multisport: parent rows have is_multisport_parent=1, legs have parent_id; to count volume use is_multisport_parent = 0.\n- daily(date, steps, step_goal, walk_distance_m, floors_up, resting_hr, min_hr, max_hr, stress_avg, stress_max, stress_rest_pct, stress_low_pct, stress_medium_pct, stress_high_pct, body_battery_min, body_battery_max, body_battery_charged, body_battery_drained, intensity_moderate_min, intensity_vigorous_min, calories_total, calories_active, respiration_avg, hydration_ml)\n- sleep(date, start_local, end_local, sleep_s, deep_s, light_s, rem_s, awake_s, nap_s, score, quality, feedback, awake_count, respiration_avg, sleep_stress_avg)  -- date = the morning you woke up\n- hrv(date, last_night_avg, last_night_5min_high, weekly_avg, baseline_low, baseline_high, status)\n- weight(date, weight_kg, bmi, body_fat_pct, body_water_pct, muscle_mass_kg, bone_mass_kg, visceral_fat, source, entries)\nRaw JSON (for fields not in the views, via json_extract):\n- activity(id, ..., raw_json)  -- Garmin's full activity summary, e.g. json_extract(raw_json, '$.maxAvgPower_1200'), '$.hrTimeInZone_2', '$.fastestSplit_5000', '$.avgStrideLength'\n- daily_raw(domain, date, json)  -- domains: daily_summaries, sleep, hrv, weight, body_battery, hrv_readings, heart_rate, spo2, food_logs\nDates are 'yyyy-MM-dd' text in the user's local calendar; durations in seconds…","inputs":[{"name":"max_rows","type":"integer","required":false,"description":null},{"name":"response_format","type":"string","required":false,"description":null},{"name":"sql","type":"string","required":true,"description":"A single SELECT or WITH query"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":716},{"name":"garmin_sync","title":"Sync Garmin data","description":"Start downloading Garmin data into the local cache. Runs in the background and returns immediately; follow progress with garmin_sync_status.\n\nYou rarely need this: other tools sync automatically on first use and when the cache is over an hour old. Use it to:\n  - fetch the latest data right now (e.g. \"I just finished a run\"),\n  - extend history further back (from=\"2019-01-01\"),\n  - re-download everything (mode=\"full\"), e.g. after editing many activities in Garmin Connect.\n\nDomains (default: all except fit_files): activities, daily_summaries, sleep, hrv, weight, body_battery, hrv_readings, heart_rate, spo2.\n\"fit_files\" downloads the original FIT file of every activity (one request each, ~2 activities/s). That's optional: FIT files are otherwise fetched on demand by garmin_get_activity_laps and garmin_get_activity_streams.","inputs":[{"name":"domains","type":"array","required":false,"description":"Only sync these domains. Defaults to all except \"fit_files\"."},{"name":"from","type":"string","required":false,"description":"Extend history back to this date (yyyy-MM-dd). History starts at your first activity by default; an earlier date fetches older wellness data. A later date has no effect: history is never narrowed."},{"name":"mode","type":"string","required":false,"description":"auto: new data plus any history still missing. full: forget what's cached and re-download."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":292},{"name":"garmin_sync_status","title":"Garmin sync status","description":"Show what's in the local Garmin cache and the progress of the current or last sync.\n\nReturns: the running/last sync (progress, errors), and per data domain the date range covered, number of days, whether all history is in, and the last successful sync.","inputs":[{"name":"response_format","type":"string","required":false,"description":"'markdown' for readable text (default), 'json' for complete structured data"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":88}],"toolsTruncatedAtCapture":false,"diagnostics":{"capturedAt":"2026-11-05T08:35:57.000Z","track":"package","endpoint":null,"declaredUrl":null,"truncated":false,"tls":null,"dnssec":null,"auth":null,"httpsRedirect":null,"transports":[],"provenance":{"outcome":"none","label":"No attestation","reason":"no_attestation","reasonLabel":"No attestation published","discovery":null,"discoveryLabel":null,"sourceRepo":null,"attestationSkipped":null,"attestationSkippedLabel":null},"installScripts":[],"installScriptsTotal":null,"vulnerabilities":[],"vulnerabilitiesTotal":null,"dependencies":null},"mismatches":[],"changelog":{"trackingSince":"2026-10-29","recent":[{"id":"chg_01a1aad9-b754-73a0-b49a-b9bc4496fa5a","kind":"check.reverified","summary":"Provenance (unverified → fail)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-11-05","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a1aad9-b754-73a0-b49a-b9bc4496fa5a"},{"id":"chg_01a1a5af-76a4-7d09-a87f-7fa4bdefba15","kind":"score.total_changed","summary":"Trust score (43 → 44)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-04","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a1a5af-76a4-7d09-a87f-7fa4bdefba15"},{"id":"chg_01a1a5af-769f-7ae6-b198-5e36a01bf968","kind":"check.unverifiable","summary":"Provenance (fail → unverified)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-11-04","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a1a5af-769f-7ae6-b198-5e36a01bf968"},{"id":"chg_01a19b61-d1ea-7f30-a891-962088939429","kind":"score.total_changed","summary":"Trust score (42 → 43)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-02","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a19b61-d1ea-7f30-a891-962088939429"},{"id":"chg_01a19114-f73d-7a1f-8b9d-2d49beb2f8fd","kind":"score.total_changed","summary":"Trust score (41 → 42)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a19114-f73d-7a1f-8b9d-2d49beb2f8fd"},{"id":"chg_01a18999-322e-7c57-9440-a9057e83596c","kind":"score.first_scored","summary":"First indexed and scored","materiality":"functional","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-29","url":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp#chg-chg_01a18999-322e-7c57-9440-a9057e83596c"}],"truncated":false,"feedUrl":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp/changelog.json"},"links":{"html":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp","markdown":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp.md","changelogJson":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp/changelog.json","changelogRss":"https://verifymcp.io/servers/app-durely-garmin-insights-mcp/ghcr-io-durely-garmin-insights-mcp.xml","external":[{"label":"GitHub Container Registry","href":"https://ghcr.io/durely/garmin-insights-mcp"},{"label":"Repository","href":"https://github.com/durely/garmin-insights-mcp"}]}}