Note
Your zones were coming from a formula, not from your account. On a live profile the synthesized "Z1" ran 102–122 bpm where the real one tops at 138. This release returns the configured zones and removes the formula.
Your real training zones
icu_get_sport_settings was silently dropping every zone the API returns — the model never declared the fields. HR (absolute bpm), power (%FTP) and pace (% of threshold) zones now come back in full and named, alongside max_hr_bpm, hr_load_type, sweet-spot bounds and default warmup/cooldown. icu_update_sport_settings returns them too, so the effect of recalc_hr_zones is finally visible. icu_get_athlete_profile stays lean — zones cost ~1k tokens per call and a dedicated tool already returns them.
Reported by @jorge-huxley; implementation approach from @nitobosch's #116.
The curve tools no longer invent zones
icu_get_hr_curves built five bands from a value it labelled max_hr_bpm that could never be your max HR: Intervals.icu replaces readings above your configured max at import, so the curve only echoed whatever max was set back then — 198 on the test account, against 204 in raw_heartrate and on the head unit. Both synthesized zone blocks are gone; eFTP stays, since sport settings can't give it. icu_get_activity_streams now documents raw_heartrate, the only way to see a genuine new max that was corrected away.
RPE round-trips again
icu_update_activity wrote perceived_exertion, the Strava mirror the server silently ignores — success responses reported values that were never stored. Writes now target the native icu_rpe, and a fractional Strava import no longer breaks icu_get_activity_details. By @AlexVrg71 (#114) and @tylerjolmstead (#117).
Upgrading from v4.x
No tools were added, removed or renamed — every break is a parameter or a response field.
icu_bulk_create_events: useevent_type,duration_seconds,distance_meters,training_loadinstead of the raw API names, which are now rejected with an error naming the replacement.icu_create_gear/icu_update_gear:brand,modelandprimaryare gone — the API has no such fields. Put those details in the gear name.icu_get_hr_curves: readsummary.peak_hr_bpm(andpeak_hr_duration_seconds), notmax_hr_bpm. For zones, useicu_get_sport_settings.
This drains the whole deferred-breaking-changes list in one go, so consumers migrate once. CHANGELOG.md has the before/after migration table and the full reasoning.
Full Changelog: v4.4.0...v5.0.0