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.

io.github.hhopke/intervals-icu-mcp

PYPI · INTERVALS-ICU-MCP

Read/write Intervals.icu MCP server: activities, wellness, calendar, gear, and workouts.

Available components

+21 this week 96 Trust /100

Last scanned (19 hours ago)

Scores higher than 98% 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 Security100
  • No malware found by supply-chain analysis.Pass
  • 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
  • 1 of 25 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to hhopke/intervals-icu-mcp). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 3 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability81
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 15057 tokens (~206/item across 73 items; 69 tools + 4 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 Management98
  • Stability check failed: the tool surface changed between 5.5.0 and 5.8.0: 1 tool removals, 0 breaking changes, 4 additions. See how to fix → Fail
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • 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
  • All 6 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 70 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (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.

  • 1 Nov 26 +15
    • Malware scan: unverified → pass ▲ security
  • 31 Oct 26 +6
    • CVE-2026-69247 no longer affects this package ▲ security
    • CVE-2026-69248 no longer affects this package ▲ security
    • CVE-2026-69249 no longer affects this package ▲ security
    • Malware scan: unverified → pass ▲ security
    • Known CVEs: fail → pass ▲ security
    • Package version: 5.7.1 → 5.8.0 functional
  • 25 Oct 26 −15
    • Malware scan: pass → unverified ▼ security
  • 22 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 18 Oct 26 −21
    • CVE-2026-69248 affects this package: high ▼ security
    • CVE-2026-69247 affects this package: high ▼ security
    • CVE-2026-69249 affects this package: high ▼ security
    • Malware scan: pass → unverified ▼ security
    • Stability: pass → fail ▼ security
    • Known CVEs: pass → fail ▼ security
    • Package version: 5.6.0 → 5.7.1 functional
  • 17 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 16 Oct 26 0
    • Stability: 0.97 → pass security
  • 15 Oct 26 +1

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

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/intervals-icu-mcp@5.8.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 hhopke/intervals-icu-mcp
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/hhopke/intervals-icu-mcp/.github/workflows/publish.yml@refs/tags/v5.8.0
Rekor log index 3614626329
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:9575f1320b92326182cba86c8dde829532ba04c94794806c31072fffa3a32bda

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 25 packages
Packages resolved 25
Stale 1
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 69 exposed · ~14,705 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
icu_get_wellness_data ~122

Fetch wellness records over a RANGE of recent days (default last 7). Use for trends, weekly summaries, "how has my sleep been this week?", recovery curves. For PMC/fitness chart CTL/ATL/TSB series use icu_get_fitness_chart. For a single specific date use icu_get_wellness_for_date instead — this tool always returns a multi-day list.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
days_backinteger–Number of days to look back
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_get_wellness_for_date ~103

Fetch the wellness record for ONE specific date. Use when the user names a date — "show my HRV for Monday", "wellness on 2026-03-15", "how did I sleep last Thursday?". For ranges, weeks, or trends use icu_get_wellness_data.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
datestringyesDate in YYYY-MM-DD format
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_get_workout_library ~82

List all workout-library folders + training plans the athlete has access to (personal, shared, and followed plans). Each folder ID can be passed to icu_get_workouts_in_folder to see its contents, or to icu_apply_training_plan to schedule it onto the calendar.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_get_workouts_in_folder ~66

List the workouts stored in one specific library folder or training plan — name, type, structure, training load, intensity factor.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
folder_idintegeryesFolder ID to get workouts from
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_list_athletes ~115

List the athletes this account can access — the caller plus anyone they follow or coach. Call this FIRST whenever a request concerns someone other than the default athlete, to resolve a name to the athlete_id that other tools take. Returns each athlete's access level, so you know before calling whether a write will be permitted, plus any tags and a short preview of the athlete notes. Entries with notes_truncated=true have longer notes; icu_get_athlete_profile returns the full text.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

icu_search_activities ~121

Search activities by name or tag, returning a LIGHT result list — id, name, type, date, distance, time only. Use this first for "find my X" queries. Only escalate to search_activities_full when you specifically need power, HR, training load, or intensity-factor data on the matches (heavier payload).

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
limitinteger–Maximum number of results to return
querystringyesSearch query (activity name or tag)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_search_activities_full ~119

Search activities by name or tag, returning FULL Activity objects with power, HR, training load, intensity factor, normalized power, weather — every metric per result. Heavy payload. Use only when the lighter search_activities won't tell you what you need (e.g. "find my threshold rides with NP above 250W").

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
limitinteger–Maximum number of results to return
querystringyesSearch query (activity name or tag)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_search_intervals ~224

Search intervals ACROSS ALL the athlete's activities (cross-activity). Different from icu_get_activity_intervals (single-activity). Use to track progress on a workout type ("all my threshold intervals over the last year") or find comparable historical sessions. Returns the activities containing matching intervals, each with an `interval_summary` like "2x 8m 162w" (reps x duration at target).

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
interval_type––Interval target type: AUTO, POWER, HR, or PACE (what the interval targeted — not the sport and not a workout-step label)
limitinteger–Maximum number of matching activities to return
max_duration––Maximum interval duration in seconds
max_intensity––Maximum interval intensity in percent of threshold (e.g. 105)
min_duration––Minimum interval duration in seconds
min_intensity––Minimum interval intensity in percent of threshold (e.g. 80)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_activity ~316

Update an existing activity's metadata (name, type, distance, sub-type, RPE, etc.). Only fields you pass are sent; everything else stays unchanged. Strava-imported activities cannot be updated. Moving, elapsed and recording time cannot be changed after an activity exists (neither here nor in the web UI); they can only be set when a manual activity is created. Keys passed via `fields` are sent as-is and are not echoed back in the response.

NameTypeReqDescription
activity_idstringyesActivity ID to update
activity_type––Updated activity type (e.g., Ride, Run, Swim)
carbs_ingested––Carbohydrates ingested during the session (g)
commute––Mark as commute
description––Updated description
distance––Distance in meters (e.g. for indoor rides whose file lacks it)
feel––How you felt (1-5 scale)
fields––Any other writable Activity API field, sent as-is (e.g. {'icu_ignore_hr': true}). Named parameters win on conflict.
name––Updated activity name
perceived_exertion––RPE rating (1-10 scale)
race––Mark as race
sub_type––Activity sub-type: NONE, COMMUTE, WARMUP, COOLDOWN or RACE
tags––Tags; replaces the existing tag list
trainer––Mark as trainer/indoor workout
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_activity_message ~152

REPLACE the text of an existing note on an activity (edit, not add). Use when the user wants to fix or rewrite a note they already left: "correct my note on that ride", "change the comment to say...". Only the author's own notes can be changed. Returns the old and the new text — the old text is not recoverable otherwise. To post an additional note use icu_add_activity_message.

NameTypeReqDescription
activity_idstringyesThe Intervals.icu activity ID
contentstringyesNew note text; replaces the old text entirely
message_idintegeryesID of the note to change (from icu_get_activity_messages)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_activity_streams ~103

Upload raw time-series streams (power, HR, cadence, etc.) onto an existing activity. Destructive — overwrites existing stream data. Accepts JSON array or CSV. Different from get_activity_streams (READ).

NameTypeReqDescription
activity_idstringyesActivity ID to update
formatstring–Format of the payload: 'json' or 'csv'
payload_stringstringyesJSON array of stream dictionaries or raw CSV data
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_athlete_notes ~157

REPLACE the free-text notes kept on an athlete's own record — not an activity comment or a calendar note. Use for standing context about the athlete: "note on my profile that I'm injured", "update my athlete notes". The whole text is overwritten, so to add to existing notes read them first with icu_get_athlete_profile and send the combined text. For a comment on one activity use icu_add_activity_message; for a dated calendar note use icu_create_event.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
notesstringyesFull new notes text (Markdown). Replaces the existing notes; pass an empty string to clear them.
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_custom_item ~206

Modify an existing custom chart/field/zones/panel. Use when the user wants to change one of their existing customizations: "rename my custom field", "make this chart public". Usually need icu_get_custom_items first to find the right `item_id`. Only fields you pass are sent — others are left unchanged. For `content` schema, see intervals-icu://custom-item-schemas.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
content––Updated configuration content (replaces existing wholesale). Same schema as create_custom_item.content — see intervals-icu://custom-item-schemas for the per-item_type shape.
description––Updated description
item_idintegeryesCustom item ID to update
item_type––Updated type (see icu_create_custom_item for values)
name––Updated name
visibility––Updated visibility: PRIVATE, FOLLOWERS, or PUBLIC
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_event ~838

Update an existing calendar event. Only fields you pass are sent — other fields remain unchanged. For category and training_availability semantics, see intervals-icu://event-categories. For WORKOUT `description` syntax, see intervals-icu://workout-syntax.

NameTypeReqDescription
athlete_cannot_edit––Lock this event so the athlete cannot move or edit it (the web UI's 'Athlete cannot edit' checkbox). For coaches managing an athlete via athlete_id
athlete_id––Athlete ID (for coaches managing multiple athletes)
color––Updated color (hex string)
description––Updated description. For WORKOUT events the server parses this into structured, device-syncable steps with zones and a training load. Use Intervals.icu workout syntax: one step per line as '- <durati…
distance_meters––Updated distance in meters
duration_seconds––Updated duration in seconds
end_date––Updated end date (YYYY-MM-DD)
event_idintegeryesEvent ID to update
event_type––Updated activity type
hide_from_athlete––Hide this event from the athlete's calendar (the web UI's 'Hide from athlete' checkbox). For coaches managing an athlete via athlete_id
name––Updated event name
not_on_fitness_chart––Hide event from the fitness chart
show_as_note––Show event as a note on the fitness chart
show_on_ctl_line––Render event on the CTL line
start_date––Updated start date (YYYY-MM-DD)
tags––Replacement tag list, without the leading # — overwrites existing tags, so include any to keep. [] clears
training_availability––Updated training availability: NORMAL, LIMITED, or UNAVAILABLE
training_load––Updated training load
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_gear ~101

Update an existing gear item. Only fields you pass are sent.

NameTypeReqDescription
active––False retires the gear (dated today); True un-retires it
athlete_id––Athlete ID (for coaches managing multiple athletes)
gear_idstringyesID of the gear item to update
gear_type––Updated type, case-insensitive (Bike, Shoes, Trainer, Chain, ...)
name––Updated name
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_gear_reminder ~98

Update an existing gear maintenance reminder. Only fields you pass are sent.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
distance_alert––Updated distance alert in kilometers
gear_idstringyesID of the gear item
reminder_idintegeryesID of the reminder to update
text––Updated reminder text
time_alert––Updated time alert in hours
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_sport_settings ~444

Update sport settings: FTP, FTHR, pace/swim thresholds, or explicit HR/power zones. Explicit zones replace the threshold-derived ones (e.g. to match a lab test). Changes apply from now on; past activities keep the zones they were analysed with. To re-zone past activities, tell the user to use Update zones in the Intervals.icu activity list view (not in the API).

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
fthr––Functional Threshold Heart Rate in bpm
ftp––Functional Threshold Power in watts (for cycling)
hr_zone_names––One name per hr_zones bound
hr_zones––Explicit HR zone upper bounds in bpm, strictly increasing (e.g. lab VT1/VT2). The last bound is the max HR: Intervals.icu sets max_hr to it
indoor_ftp––Indoor Functional Threshold Power in watts (for cycling)
max_hr––Max HR in bpm. Optional with hr_zones (taken from the last bound); if sent, it must equal that bound
pace_threshold––Threshold pace in min/km (e.g., 4.5 for 4:30/km)
power_zone_names––One name per power_zones_percent_ftp bound
power_zones_percent_ftp––Explicit power zone upper bounds as % of FTP (not watts), strictly increasing, each <= 200; a final 999 makes the top zone open-ended
recalc_hr_zonesboolean–Rescale HR zones when fthr changes. Explicit lab zones are rescaled too; pass false to keep them. Zones sent in the same call are kept either way
sport_idintegeryesID of the sport settings to update
sweet_spot_max––Sweet spot upper bound, % of FTP
sweet_spot_min––Sweet spot lower bound, % of FTP
swim_threshold––Swim threshold in min/100m (e.g., 1.5 for 1:30/100m)
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_wellness ~534

Upsert wellness data for ONE specific date — creates the record if missing, otherwise updates the fields you pass. Only provided fields are sent. Subjective scales (fatigue, soreness, stress, mood, motivation, injury) are 1-5. Pass `locked=True` to stop device sync from overwriting manual entries. Writes to the authenticated athlete unless athlete_id names a managed athlete.

NameTypeReqDescription
abdomen––Abdominal circumference in cm
athlete_id––Athlete ID (for coaches managing multiple athletes)
blood_glucose––Blood glucose in mmol/L
body_fat––Body fat percentage
calories_consumed––Calories consumed (kcal)
carbohydrates––Carbohydrates consumed (grams)
comments––Comments or notes
datestringyesDate in YYYY-MM-DD format
diastolic––Diastolic blood pressure in mmHg
fat_total––Total fat consumed (grams)
fatigue––Fatigue level (1-5 scale)
hrv––HRV (rMSSD) value
hydration––Subjective hydration rating (1-4: 1=well hydrated, 4=very dehydrated)
hydration_liters––Hydration volume (liters)
injury––Injury severity (1-5 scale: 1=none, 5=severe)
lactate––Blood lactate in mmol/L — lab result
locked––Lock record to prevent device sync from overwriting manual entries
menstrual_phase––Menstrual phase (e.g. FOLLICULAR, OVULATING, LUTEAL, MENSTRUAL)
mood––Mood level (1-5 scale)
motivation––Motivation level (1-5 scale)
protein––Protein consumed (grams)
readiness––Readiness score (0-100)
respiration––Respiration rate in breaths per minute
resting_hr––Resting heart rate in bpm
sleep_quality––Sleep quality (1-5 scale)
sleep_secs––Sleep duration in seconds
soreness––Soreness level (1-5 scale)
spo2––Blood oxygen saturation percentage (SpO2)
stress––Stress level (1-5 scale)
systolic––Systolic blood pressure in mmHg
vo2max––VO2max (ml/kg/min) — lab result or device estimate
weight––Weight in kg
NameTypeReqDescription
resultstringyes–

No examples provided.

icu_update_workout ~752

Change fields on an EXISTING library workout — only the fields you pass are sent. To save a new workout use icu_create_workout. This edits the library workout only; calendar events are separate records changed with icu_update_event.

NameTypeReqDescription
athlete_id––Athlete ID (for coaches managing multiple athletes)
color––Updated color (hex string)
day––PLAN folders only: updated day offset from plan start
description––Updated workout steps. For WORKOUT events the server parses this into structured, device-syncable steps with zones and a training load. Use Intervals.icu workout syntax: one step per line as '- <dura…
distance_meters––Updated distance in meters
duration_seconds––Updated duration in seconds
folder_id––Move the workout to this folder or plan
indoor––Mark as an indoor workout
name––Updated workout name
tags––Replacement tag list
target––Updated device target type: AUTO, POWER, HR, or PACE
training_load––Updated training load
workout_idintegeryesLibrary workout ID (from icu_get_workouts_in_folder)
workout_type––Updated activity discipline: Ride, Run, Swim, Walk, Hike, WeightTraining, Workout, VirtualRide, VirtualRun, Other (full discipline list: intervals-icu://event-categories resource)
NameTypeReqDescription
resultstringyes–

No examples provided.

Install

How do I install the io.github.hhopke/intervals-icu-mcp server?

io.github.hhopke/intervals-icu-mcp runs locally as a PyPI package, launched with uvx intervals-icu-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · intervals-icu-mcp

# add to Claude Code
claude mcp add hhopke-intervals-icu-mcp -- uvx intervals-icu-mcp
Common questions

What is the io.github.hhopke/intervals-icu-mcp server?

io.github.hhopke/intervals-icu-mcp is listed in the public MCP registry as io.github.hhopke/intervals-icu-mcp. Read/write Intervals.icu MCP server: activities, wellness, calendar, gear, and workouts. This page covers its PyPI package (intervals-icu-mcp).

Is the io.github.hhopke/intervals-icu-mcp server safe to use?

io.github.hhopke/intervals-icu-mcp scores 96 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 io.github.hhopke/intervals-icu-mcp server expose?

io.github.hhopke/intervals-icu-mcp exposes 69 tools: icu_get_recent_activities, icu_get_activities_by_date, icu_get_activity_details, icu_search_activities, icu_search_activities_full, and 64 more. Their descriptions and schemas cost roughly 14,705 tokens of context every time the server is loaded.

Is the io.github.hhopke/intervals-icu-mcp server still maintained?

io.github.hhopke/intervals-icu-mcp 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 io.github.hhopke/intervals-icu-mcp server under?

io.github.hhopke/intervals-icu-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.