intervals-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@intervals-mcp How was my training load this week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Intervals MCP
A self-hosted, read-only MCP server that gives AI assistants access to an athlete's Intervals.icu training data.
Connect a sports watch, bike computer, trainer, Strava, or another supported source to Intervals.icu. Intervals MCP then exposes the normalized training data to ChatGPT, Claude, Claude Code, Cursor, VS Code, and other MCP clients. See Intervals.icu for its current integrations; the list changes over time.
The server only makes GET requests. It cannot create, edit, or delete anything
in an athlete's Intervals.icu account.
What an assistant can read
Athlete profile, timezone, sport settings, zones, FTP, LTHR, and max HR.
Activities, details, laps, intervals, and downsampled streams.
Wellness, fitness, fatigue, HRV, sleep, mood, and weight when available.
A coach-style training readiness assessment: form (TSB) classified into a band, a ramp-rate read, and whether recent HRV has dropped below baseline.
PNG charts: CTL/ATL/TSB over time, and best-effort curves (HR, pace, power) by duration or distance -- for when the shape says more than the numbers.
Planned events, best-effort curves, gear, and the workout library.
Additional Intervals.icu v1
GETendpoints through a read-only raw tool, which redacts anything that looks like a credential or an email address.
Large responses are compacted before they reach the model. Empty fields are dropped, streams are downsampled, and summaries use the full data series.
Related MCP server: intervals.mcp
Quick start
You need an Ubuntu or Debian VPS with a public hostname. Point the hostname's DNS record at the server and allow inbound TCP ports 80 and 443. The installer adds Docker, Compose, Git, and uv when they are missing:
curl -fsSL https://raw.githubusercontent.com/VictorForV/intervals-mcp/master/install.sh | sudo bashReview install.sh before running it if you prefer not to pipe a
remote script to a privileged shell. Manual installation remains available by
cloning the repository and running ./manage.sh after installing the
prerequisites.
Choose Initial setup. The manager asks for the public hostname, a short athlete name, and the Intervals.icu athlete ID and API key. The ID and key are available under Settings → Developer Settings in Intervals.icu. The API key uses hidden input.
The manager creates owner-only configuration, generates a strong random URL
token, starts the service, and prints the connector URLs. Run ./manage.sh later
to add, list, edit, or remove athletes, rotate URLs, rebuild, restart, or inspect
the service.
Connecting an AI client
Each athlete receives two secret URLs:
https://mcp.example.com/<secret>/mcp # Streamable HTTP, preferred
https://mcp.example.com/<secret>/sse # legacy SSE compatibilityTreat the complete URL like a password. It grants read access to that athlete's training and wellness data.
Claude and Claude Desktop
Open Settings → Connectors → Add custom connector and enter the /mcp URL.
Availability and organization permissions depend on the Claude plan. See the
current Anthropic instructions.
Claude Code
The manager prints a ready-to-run command:
claude mcp add --transport http intervals-alex https://mcp.example.com/<secret>/mcpChatGPT
Add the server as a custom app/connector and use the URL accepted by your current ChatGPT workspace. Availability, UI, and administrator requirements vary by plan and can change. See the current OpenAI apps documentation. The manager shows both URL formats for compatibility.
Other clients
Use /mcp with remote Streamable HTTP clients and /sse with older SSE clients.
Follow the client's current documentation and never commit a secret URL to a
shared configuration.
Administration
The interactive panel is the recommended interface:
./manage.shFor automation, the same interface has subcommands:
uv run intervals-mcp-admin add
uv run intervals-mcp-admin list
uv run intervals-mcp-admin show alex
uv run intervals-mcp-admin edit alex
uv run intervals-mcp-admin rotate alex
uv run intervals-mcp-admin remove alexAvoid --api-key in an interactive shell because command arguments can be saved
in shell history or exposed in the process list. Omit it for hidden input.
Local stdio mode
For one athlete and a client that launches local processes, copy .env.example
to .env, configure the Intervals.icu credentials, and run:
uv run intervals-mcpSecurity model
Intervals.icu requests are read-only (
GET).Each athlete gets a separate API client and independent random path token.
.envandusers.tomlare gitignored and written with mode0600.API keys and path tokens are excluded from application and proxy access logs.
The public service uses HTTPS through Caddy.
users.tomlis mounted read-only into the container.
The path token is bearer authentication: anyone with the URL can read that
athlete's data. Rotate it from ./manage.sh if exposed. See
SECURITY.md for reporting issues.
Development
uv sync
uv run pytestTests use fully synthetic, API-shaped fixtures and make no network requests.
Regenerate them with uv run python scripts/generate_fixtures.py.
See CONTRIBUTING.md for development guidelines.
License
MIT — see LICENSE.
Available Tools
15 toolsget_activityA
One activity by id, in the same shape as a list_activities entry.
Use it when you already have an id (from list_activities, an event,
or the athlete) and want that one activity without re-listing a whole
window. It does not currently surface fields list_activities omits.
Inputs: activity_id (required).
get_activity_intervalsA
Laps and detected intervals inside one activity.
Use it to see how a session was structured: per-lap distance, duration,
pace, heart rate, power and zone. This is where interval execution shows
up, such as whether reps faded.
Inputs: activity_id (required).
get_activity_streamsA
Time series inside one activity, downsampled.
types is a comma-separated list, for example heartrate, velocity_smooth,
altitude, cadence, watts, temp, latlng. Returns `points` evenly spaced
samples per series plus min/mean/max over the whole series. points must
be between 2 and 2000. The raw data can exceed ten thousand samples per
series, so pass full=true only when the shape of every second genuinely
matters -- not a small `points` value, which is rejected rather than
silently answered with the full series.
latlng sometimes comes back from intervals.icu as latitude only rather
than [lat, lon] pairs; when that happens the series carries a note
saying so instead of a silently wrong coordinate.
Inputs: activity_id (required), full, types, points.
get_athlete_profileA
The athlete's profile: name, location, timezone, sex.
Read this first when you need to interpret local times or address the
athlete by name.
Inputs: no named parameters.
get_best_effort_chartA
A PNG of the best-effort curve for a sport: HR, pace or power against duration or distance, log-scaled since a curve spans seconds to hours.
kind is hr, pace or power, same as get_best_efforts. Use this when the
shape of the curve -- a plateau, a cliff past some duration -- says
more than the ten named points get_best_efforts returns.
Inputs: kind (required), newest, oldest, sport_type.
get_best_effortsA
Best-effort curve for a sport: the athlete's peak sustained values.
kind is hr, pace or power. Returns the best value held for 5s, 15s, 30s,
1m, 5m, 10m, 20m, 30m, 1h and 1h30m over the window, which defaults to
the last 12 months. Use it to compare current form against past peaks.
Inputs: kind (required), newest, oldest, sport_type.
get_eventsA
Planned calendar entries: future workouts, races and goals.
Defaults to today through 28 days ahead. Pass an earlier oldest to see
what was planned in the past. An empty list means nothing is scheduled.
Inputs: newest, oldest.
get_gearA
Registered gear such as shoes and bikes, with accumulated distance.
Useful for mileage on a given pair of shoes. An empty list means the athlete tracks no gear.
Inputs: no named parameters.
get_sport_settingsA
Training zones and thresholds per sport: FTP, LTHR, max HR, power, heart-rate and pace zones, sweet spot range.
Read this before judging whether a session was easy or hard; zone
boundaries differ per sport.
Inputs: no named parameters.
get_training_load_chartA
A PNG chart of CTL (fitness), ATL (fatigue) and TSB (form) over time.
Defaults to the last 90 days, the usual window for seeing a build and a taper. Use this when a shape -- a spike, a plateau, a steady climb -- says more than the numbers would on their own.
Inputs: newest, oldest.
get_training_readinessA
Assess current form from CTL/ATL/ramp rate and recent HRV, coach-style.
Defaults to a six-week window so recent HRV has a real baseline to
compare against. Returns TSB (fitness minus fatigue) classified into a
band -- high_risk, overreaching, neutral, fresh, very_fresh -- each
with a plain-language note, plus a ramp-rate read (declining,
maintaining, building, aggressive) and, when HRV is logged, the last
7 days against the rest of the window with a flag if it has dropped
more than 10% below baseline.
Inputs: newest, oldest.
get_wellnessB
Daily wellness and training-load history.
Defaults to the last 30 days. Per day: CTL (fitness), ATL (fatigue),
ramp rate, plus whatever the athlete logs — weight, resting HR, HRV,
sleep, soreness, fatigue, stress, mood, motivation. This is the record
to read before judging whether load is sustainable.
Inputs: newest, oldest.
intervals_get_rawA
Escape hatch: GET any intervals.icu v1 path and return it unshaped.
Use only when a dedicated tool cannot answer the question, since raw
payloads are large. path is relative to https://intervals.icu/api/v1,
for example "athlete/{athlete}/activities"; "{athlete}" expands to the
configured athlete id. Pass query arguments in params, not in the path.
This is still read-only.
Field names are returned as-is, but values that look like credentials
or personal contact info -- email, API keys, tokens, invitation links
-- are replaced with "[redacted]" wherever they appear in the payload.
Inputs: path (required), params.
list_activitiesB
Completed activities in a date range, newest first.
Defaults to the last 30 days. Filter by activity_type such as Run,
TrailRun, Ride, Swim, Hike, Workout, WeightTraining, Yoga. Each entry
carries distance, duration, pace, heart rate, elevation, training load
and the CTL/ATL standing at the time. The response reports how many
activities matched versus how many were returned.
Inputs: limit, newest, oldest, activity_type.
list_workoutsA
The athlete's saved workout library and its folders.
These are workout templates, not completed sessions; use list_activities
for what was actually done.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 15 tools
Every tool targets a distinct resource: profile, wellness, settings, activities (list vs single), intervals, streams, readiness, charts, events, best efforts, gear, workouts, and a raw fallback. Even closely related tools like get_activity_intervals and get_activity_streams are clearly separated by their descriptions.
The naming is mostly consistent with a get_/list_ + noun pattern. The notable outlier is intervals_get_raw, which reverses the convention, and minor singular/plural inconsistency between get_best_efforts and get_best_effort_chart, but the pattern is otherwise predictable.
15 tools sits right at the upper bound of a well-scoped set, and each tool maps cleanly to a meaningful part of the intervals.icu API. No redundant or filler tools; even the raw escape hatch serves a clear fallback role.
The surface thoroughly covers the read-only athlete analytics domain: profile, training load, wellness, activities with multiple detail levels, best efforts, charts, events, gear, and workout templates. The raw escape hatch closes any remaining gaps, making dead ends unlikely.
Maintenance
Related MCP Connectors
Connect Intervals.icu to Claude and ChatGPT: read training, plan workouts. Training never stored.
Your own cycling data for your AI assistant: rides, power, climbs and routes. Read-only.
Your swim, bike and run training: readiness, HRV, sleep, workouts and race predictions. Read-only.
Your endurance training data in your AI assistant: activities, recovery, plan, workout edits.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI assistants to interact with Intervals.icu fitness tracking and wellness data, allowing users to fetch, filter, and group activities or health metrics. It provides structured summaries of workouts and physical well-being through natural language queries.4-
- FlicenseAqualityDmaintenanceEnables AI assistants to access and analyze intervals.icu training data including activities, fitness metrics (CTL/ATL/TSB), wellness stats, and calendar events. Supports natural language querying of athletic performance for training insights and workout planning.6-
- AlicenseAqualityBmaintenanceEnables Claude and ChatGPT to access and manage Intervals.icu data, including activities, events, wellness metrics, power curves, and custom items through natural language.26GPL 3.0
- AlicenseAqualityBmaintenanceEnables natural-language access to Intervals.icu training data, wellness metrics, activities, events, and workout management through MCP-compatible clients.64MIT