intervals-mcp
Local MCP server for analyzing Intervals.icu accounts, creating AI-assisted training plans, and applying managed drafts to the calendar after explicit confirmation.
README
Intervals MCP
Local Python client and MCP server for analyzing an Intervals.icu account, building AI-assisted training plans, and applying only managed drafts to the calendar after explicit confirmation.
Intervals.icu is the operational source of truth. When an account is connected to Garmin Connect, this MCP can also read the Garmin-derived activities and wellness data exposed by Intervals.icu. It does not call the Garmin API directly.
Quick start
Install the project and create your local configuration:
uv sync --dev
cp .env.example .env
cp PERSONAL.example.md PERSONAL.md
Set INTERVALS_API_KEY in .env, then register the local MCP server with Codex:
codex mcp add intervals_icu -- \
uv run --directory /absolute/path/to/intervals-mcp intervals-mcp
Restart Codex if it was already open, then use /mcp to confirm that intervals_icu is connected. You can now ask Codex things such as:
Read my private training context and list my managed Intervals.icu draft plans.
Read my recent training context and summarize the last two weeks.
Create a draft plan for next week, but show me the preview before writing anything.
The server is local and communicates over stdio. It does not send data to a separate service. Read operations can run immediately; every mutation first returns a preview and requires a second call with confirmed=true after explicit approval. Scheduling can make workouts available for Garmin synchronization, but Garmin delivery must still be verified separately.
For Claude Code, use the equivalent command in Connect to Claude Code. For detailed setup, safety rules, and development commands, continue below.
Codex or Claude Code
│
▼ MCP (stdio)
intervals-mcp ──────── Intervals.icu API
│
▼
Library: [IA] ...
│
athlete review
│
apply plan in Intervals
│
▼
Calendar → Garmin
Why a skill plus MCP
- The skill teaches the LLM the training workflow, workout syntax, and safety guardrails.
- The MCP keeps API access outside the conversation context and exposes typed operations.
PERSONAL.example.mdis the tracked template;PERSONAL.mdstores the active athlete's private context and is ignored by Git.- The Python client verifies that writes belong to the managed namespace.
- Intervals.icu remains the dashboard, calendar, and analysis system.
The MCP provides a deterministic safety boundary around the API: it avoids exposing credentials in prompts and does not provide unrestricted calendar CRUD.
Current capabilities
The server exposes tools for:
- Reading private athlete context with
get_personal_contextandset_personal_fact. - Reading filtered body and health profile metrics with
get_athlete_profile. - Reading activities, wellness, and calendar data with
get_training_contextfor ranges up to 180 days. - Reading power, pace, and heart-rate curves with
get_performance_curves. - Listing and reading managed plans with
list_draft_plansandget_draft_plan. - Creating, cloning, renaming, and editing private managed library plans.
- Adding and updating structured workouts inside managed plans.
- Applying a managed plan to the calendar from an exact future date with
schedule_draft_plan. - Removing only calendar copies from a managed application with
unschedule_draft_plan. - Serving
intervals://safety-policy,intervals://personal-context, andintervals://draft-plansresources. - Serving the
draft_training_weekMCP prompt.
Generic event create, edit, and delete operations are not exposed. Every mutation first returns a preview with confirmed=false; it can only proceed with confirmed=true after explicit approval.
Local personal memory
Copy PERSONAL.example.md to PERSONAL.md and fill it with the active athlete's private memory. The local file is ignored by Git, and the skill requires reading it before analyzing or changing a plan. Durable information can be stored through set_personal_fact; reusing the same key replaces the previous value.
Store only goals, events, recurring availability, preferences, performance markers, equipment, integrations, and training constraints. Never store examples, guesses, API keys, passwords, tokens, payment data, or sensitive health information unless explicitly requested.
Requirements
- Python 3.13 or newer.
uv.- An Intervals.icu account and personal API key.
- Codex or Claude Code to consume the MCP.
Setup
uv sync --dev
cp .env.example .env
Then set INTERVALS_API_KEY in the local .env file. Never commit .env or paste the key into a conversation. Personal Intervals.icu authentication uses HTTP Basic with the literal username API_KEY; the client configures this automatically.
To check read access:
uv run intervals-mcp-cli doctor
The command only lists library containers and does not write anything.
Run and inspect the MCP
uv run intervals-mcp
The process waits for JSON-RPC messages on stdin; this is expected. For visual inspection, use:
uv run mcp dev src/intervals_mcp/mcp_server.py
npx -y @modelcontextprotocol/inspector uv run intervals-mcp
Connect to Codex
codex mcp add intervals_icu -- \
uv run --directory /absolute/path/to/intervals-mcp intervals-mcp
codex mcp list
Use /mcp inside Codex to inspect the server and its tools. The equivalent configuration is:
[mcp_servers.intervals_icu]
command = "uv"
args = ["run", "intervals-mcp"]
cwd = "/absolute/path/to/intervals-mcp"
startup_timeout_sec = 20
tool_timeout_sec = 90
default_tools_approval_mode = "writes"
The writes setting makes Codex request approval for mutating tools. The server also requires its own confirmed=true.
Enable the skill in Codex
mkdir -p .agents/skills
ln -s ../../skills/manage-intervals-icu .agents/skills/manage-intervals-icu
Connect to Claude Code
claude mcp add --transport stdio --scope local intervals_icu -- \
uv run --directory /absolute/path/to/intervals-mcp intervals-mcp
claude mcp list
For a project-shared command, use --scope project, which creates .mcp.json. Do not put the API key in that file; every user must keep a local .env.
Claude Code discovers project skills under .claude/skills:
mkdir -p .claude/skills
ln -s ../../skills/manage-intervals-icu .claude/skills/manage-intervals-icu
Recommended first run
- Run
doctor. - Connect the MCP to Codex or Claude Code.
- Ask it to use the Intervals.icu skill and list managed drafts.
- Request recent training context and verify that no secrets are returned.
- Create an empty plan with
confirmed=falseand inspect the preview. - Approve the second call with
confirmed=true. - Open Intervals.icu and confirm that a private
[IA] ...plan appears. - Add one easy session and verify that Intervals.icu interprets its steps correctly.
- Preview
schedule_draft_plan, review dates and conflicts, and approve only when ready.
Safety model
- A managed plan must have
type == PLANand a description containing[intervals-mcp:managed]. [IA]is only a display prefix; security does not depend on the human-facing name.- Every edit requires the latest remote content hash.
- Only complete managed-plan applications can be scheduled or removed; generic event CRUD is unavailable.
- Scheduling rejects past dates, empty plans, stale hashes, and duplicate applications.
- Existing events in the target dates require additional approval through
allow_calendar_conflicts=true. - Unscheduling resolves IDs by
plan_folder_idand application range, then deletes only those exact events after confirmation. - The server never prints the API key or authentication responses.
- Scheduling may make eligible workouts available for Garmin synchronization; Garmin delivery must be reported as pending until verified.
Development
uv run ruff format --check .
uv run ruff check .
uv run mypy
uv run pytest -q
uv run python scripts/smoke_mcp.py
HTTP tests use a mocked Intervals.icu service. They do not need credentials or modify a real account.
Project status
The client and MCP are implemented and tested against the current public Intervals.icu contract. A manual test with a real API key is still needed to verify exactly how the library displays plans and processes workouts in a specific account.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.