Repository navigation
[intervals-mcp-server] Expose custom activity fields, all streams and per-interval stream metrics - #153
Open
futureweb wants to merge 1 commit into
Open
[intervals-mcp-server] Expose custom activity fields, all streams and per-interval stream metrics#153futureweb wants to merge 1 commit into
futureweb wants to merge 1 commit into
Conversation
…trics - get_activity_details lists every custom activity field (name, code, value, units, select label) resolved from the athlete's custom item definitions; include_all_fields adds the remaining payload fields - get_activity_streams accepts any stream type (standard or custom) or "all" and adds full-resolution CSV/JSON output with index/time slicing, downsampling and paging via max_points - new list_activity_streams tool lists the standard and custom streams of an activity with names, units, descriptions and optional statistics - get_activity_intervals lists custom interval fields and, with stream_types, evaluates streams per interval and group (start/end/min/max/mean/delta, non-null sample count) from the raw samples between start_index/end_index - get_wellness_data(include_all_fields=True) labels custom wellness fields with name, units and select label - custom item definitions are cached per process (tools/custom_items.py) and invalidated when items are created, updated or deleted - null/NaN (including the API's "NaN" string) is reported as "no value"; a 0 in a field filled from the device file is marked as possibly missing Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Intervals.icu stores the values of custom items (ACTIVITY_FIELD, INTERVAL_FIELD, ACTIVITY_STREAM, INPUT_FIELD) as plain keys of the activity, interval, stream and wellness payloads, named by the item's
content.code. Until now the MCP server rendered a fixed set of standard fields, requested a fixed set of stream types and only previewed the first/last five samples, so an assistant could not see metrics that devices write into custom fields and streams (e.g. Garmin training effect, EPOC, recovery time, VO2max, performance condition, stamina, sweat loss, grade adjusted speed, gear selection, a second power meter). This PR makes all of that available, read-only and data-driven: whatever the athlete has defined is resolved against/athlete/{id}/custom-item; nothing device-specific is hard-coded.Changes
get_activity_details: new section Custom Activity Fields listing every custom activity field with a value: display name, technical code, value, units and (select fields) option label; definitions without a value are named. New optional argsinclude_custom_fields(defaultTrue) andinclude_all_fields(defaultFalse, appends every other non-empty payload field such as time in zones or running dynamics).null/NaN(the API serialises NaN as the string"NaN") is reported as no value; a0in a field filled from the device file is marked as possibly missing, because Intervals.icu stores0when the source field is absent from the file.get_activity_streams:stream_typesaccepts any stream type, custom codes included, or"all". New optional argsoutput_format(summaryas before,full= CSV with one row per sample,json),start_index/end_index,start_time/end_time,downsample(keeps every n-th recorded sample, never averages) andmax_points(paging with a note on how to continue). The summary now shows units, custom flag, description and start/end/min/max/mean statistics per stream. Thetimestream is always included in full/json output because recording pauses appear as jumps in it.list_activity_streams(new): lists the standard and custom streams an activity has, with names, units and descriptions from the definitions;include_stats=Trueadds per-stream statistics.get_activity_intervals: custom interval fields are listed per interval; new optionalstream_typesevaluates the raw samples betweenstart_indexandend_indexof every interval and over all member intervals of a group (start, end, min, max, mean, delta, non-null sample count)."custom"selects every custom stream plussecondary_power,"all"every stream.get_wellness_data(include_all_fields=True): custom wellness fields are annotated with name, units and select label.tools/custom_items.py: per-process cache of the custom item definitions (errors are not cached), invalidated bycreate_custom_item/update_custom_item/delete_custom_item.utils/custom_fields.py(definition index, value rendering) andutils/streams.py(range statistics, index/time range resolution, CSV/JSON rendering).format_intervalswas split into per-interval/per-group blocks; the legacy text is unchanged.All existing tool signatures and their default behaviour are unchanged (new arguments are optional); only read-only endpoints are used.
Testing
uv run --locked pytest: 99 passed (38 new tests intests/test_custom_fields.py,tests/test_streams.py,tests/test_custom_streams_tools.py).ruff check .: no new findings (one pre-existing unused import intools/power_curves.py).mypy src tests: success.pylint --disable=C0301 $(git ls-files '*.py'): no new findings apart from the usual duplicate-code note for the test boilerplate.🤖 Generated with Claude Code