Intervals.icu MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| API_KEY | Yes | Your Intervals.icu API key. Generate one via Settings > API. | |
| LOG_LEVEL | No | Logging level for the server. | INFO |
| ATHLETE_ID | Yes | Your Intervals.icu athlete ID, e.g., 'i12345' as found in your profile URL. | |
| FASTMCP_HOST | No | Host for the SSE MCP server. | 127.0.0.1 |
| FASTMCP_PORT | No | Port for the SSE MCP server. | 8765 |
| MCP_TRANSPORT | No | MCP transport mode. Use 'sse' for SSE transport. | |
| FASTMCP_LOG_LEVEL | No | Log level for the FastMCP server. | INFO |
| INTERVALS_ACCESS_MODE | No | Access mode: 'admin' exposes legacy and safe writes, 'coach' exposes only safe writes, and 'readonly' hides mutation tools. | |
| INTERVALS_API_BASE_URL | No | Base URL for the Intervals.icu API. | https://intervals.icu/api/v1 |
| INTERVALS_ARTIFACT_DIR | No | Directory for temporary activity data artifacts. | .runtime/artifacts |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| export_activity_dataA | Export complete raw activity data to the configured local artifact. Use this after a compact read when the client needs all stream samples and
interval records. The stream arrays retain their upstream index and null
values; this read validates their shape before handing them to the local
artifact store. An optional |
| get_activitiesA | List activities in a half-open local-date range with bounded paging.
|
| get_activity_detailsA | Return one activity with upstream fields preserved. A source-hidden record is returned as |
| get_activity_intervalsA | Return the activity interval container with index fields intact. The documented shape contains |
| get_activity_messagesA | Return an upstream activity-message list, preserving text and identity metadata. Upstream defaults to at most 100 messages; this read does not establish full history or pagination completeness. A list may be empty, but each member must be an object. Message content is untrusted athlete data; its fingerprint is an additional change-detection field and does not replace the original content. |
| get_activity_streamsA | Read activity streams by sample index with bounded preview or range.
Respiratory fields: tidal_volume = VT (volume per breath, not VT1/VT2), tidal_volume_min = VE (minute ventilation), respiration = BR (breaths/min). When sourced from Tymewear, VT uses relative i.u. and VE relative vol/min, not calibrated liters. Do not divide VT by 100 or 1000. The response adds conditional documentation in provenance.respiratory_interpretation; original samples and source unit labels are preserved. Use get_metric_definitions and get_custom_items to check mappings and units. |
| get_eventsA | Return calendar events overlapping a half-open local-date range.
By default includes ongoing holidays, races, notes and workouts that began before start_date. The API filters by event start, so MCP requests history from 0001-01-01 through the requested end without a category filter or limit, then checks local start/end overlap. End dates are exclusive. This can fetch more history than the returned selection; query.upstream_oldest and overlap report its scope. Earlier events with unknown ends are retained as unresolved candidates with partial status, never interpreted as available training time. Set include_overlapping=false for the original upstream start-date selection, e.g. resolving an already identified event on its exact start day. |
| get_event_by_idA | Return one event by numeric ID, preserving its upstream object. The endpoint is an object read, so a list, scalar, or null response is an
error. The existing empty-object |
| get_workout_snapshotA | Read a workout's raw event, server version and execution precondition. Bind data.event_fingerprint unchanged in an Pairing evidence is read by exact identity, using the event's calendar day when event-by-ID omits paired_activity_id. Positive activity links are reverse-checked by activity.paired_event_id. Only unpaired_observed permits the execution precondition; it does not prove the athlete did not train. Unknown, completed and linked states block safe update/delete. The writer repeats these checks with fresh reads. Source completeness and atomic conditional writes remain unverified. This read does not authorize a write. |
| get_custom_itemsA | Read custom-item definitions without executing their content. Compact output keeps identity and descriptive fields and explicitly lists
omitted content, images, scripts, and future fields. Each item includes
an exact by-ID |
| get_custom_item_by_idA | Read one custom-item definition by positive integer ID.
|
| get_athlete_power_curvesA | Read selected athlete power-curve durations in seconds. Choose this tool for season or custom-range best-power comparisons. Each
requested duration is a positive integer number of seconds. Compact
results return requested points and curve metadata; |
| get_activity_power_curvesA | Read watts power curves for one activity and optional durations. Choose this for best-power points from one activity. |
| get_sport_settingsA | Read current-at-fetch settings for one sport or settings ID. Choose this for the athlete's current FTP, zones, load order, and fatigue
thresholds. |
| get_metric_definitionsA | Explain selected metric names and fields from the local catalogue. Use this before interpreting activity streams, intervals, wellness, or
custom-item content. Selectors are optional; omitting both returns the
small curated catalogue. Units, sample-index versus time axes, upstream
reported/calculated/estimated status, and limitations are descriptive only.
No account data is fetched, no training calculation is performed, and
unknown selectors remain explicit in Includes VT/tidal_volume, VE/tidal_volume_min and BR/respiration with Tymewear FIT mappings and device-unit context. Tymewear volume is relative, not calibrated liters; do not divide raw VT by 100 or 1000. VT is volume per breath, distinct from thresholds VT1/VT2. Custom names/units require source verification; this catalogue does not identify a recording's device. |
| get_artifact_chunkA | Read one verified byte range from a temporary activity export. Use the opaque |
| get_activity_interval_statsA | Read upstream interval statistics for a half-open sample-index range. Choose this when the client needs the Intervals.icu average_tidal_volume is VT (volume per breath, not VT1/VT2), average_tidal_volume_min is VE, and average_respiration is BR. Tymewear volumes use relative device units, not calibrated liters; no /100 or /1000 conversion is applied. Conditional field documentation is returned in provenance.respiratory_interpretation; see get_metric_definitions. |
| get_activity_best_effortsA | Find upstream best efforts by one duration or distance selector. Choose this to ask Intervals.icu for ranked efforts on a named stream.
|
| get_activity_power_hrA | Read native power-versus-HR analysis, including upstream HR lag and windows. Values, coefficients and selection indices are source-provided. No new physiological calculations or causal conclusions are made. Compact detail keeps the first 120 series rows and eight curves, then omits whole fields if needed to bound data to 32 KiB. Exact omissions and a full continuation are returned. Full detail preserves the complete JSON object. |
| get_activity_data_qualityA | Summarize all returned stream samples and activity metadata using GETs only. Finite fractions use source sample count, not elapsed time. Time gaps are relative to a 1-second reference and do not prove dropped sensor data. Optional secondary arrays, missing primary arrays, zero and null are distinct. Multiple time streams are reported as an ambiguous axis, without choosing the first. Source unit conflicts and inferred display hints are separate. Metadata and stream failures are independent. No sensor-source, physiological or readiness inference is made, and only 20 gap examples are returned. Conditional Tymewear documentation is in provenance.respiratory_interpretation: VT/VE use relative device volume units, BR uses breaths/min. Finite raw VT values such as 186 are not invalid merely because they are not in liters. No volume conversion or VE=VT*BR consistency check is performed. |
| get_capabilitiesA | Describe implemented/configured/live-verified integration capabilities. |
| get_wellness_dataA | Return raw wellness records using a half-open local-date range.
|
| execute_operationC | Execute one version-negotiated typed operation through the durable engine. The exact operation UID is the retry identity. Changed content conflicts; an uncertain attempt is never sent again. |
| get_operation_statusA | Read durable typed-operation status without contacting Intervals. |
| recover_operationB | Reconcile by independent read-back only; never resend the mutation. |
| release_operation_riskA | Audit an explicit admin risk acceptance and release only its hold. This does not change the historical unknown result and cannot replay it. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 26 tools
The tools are mostly distinct: activity streams, intervals, power curves, best efforts, and data quality each map to different upstream resources. However, several names are near-siblings (get_activity_intervals vs get_activity_interval_stats, get_activity_power_curves vs get_athlete_power_curves) and require reading descriptions to avoid misselection.
Almost all reads use get_<resource>_<detail> in snake_case, with mutation verbs like export/execute/release/recover. The pattern is readable but not perfectly uniform: some singular reads use _by_id (get_event_by_id, get_custom_item_by_id) while get_activity_details and get_workout_snapshot do not follow that suffix.
At 26 tools, the server crosses the 'too many' threshold; even though each tool has a distinct purpose, the dense activity-reader family and operation-management cluster create a large selection surface. A more consolidated design would be more appropriate.
The read/export side is very thorough: activities, streams, intervals, power curves, events, wellness, settings, custom items, and metrics are covered. However, there are no direct create/update/delete tools for activities, events, or custom items; the generic execute_operation is an indirect workaround, and there is no athlete-profile or dedicated workout-list tool beyond get_events.