Your Trainer MCP — Integrator Documentation
Endpoint: https://mcp.your-applications.com/your-trainer · Source: github.com/edankert/yourtrainer-mcp · Last updated: May 31, 2026
A self-hosted Model Context Protocol server giving any MCP-aware LLM the reference material and computational tools to work with indoor-cycling data: workout formats, route formats, activity files, training-load math, pacing, library operations. Used by Your Trainer's in-app AI features; available for any MCP client.
What it does
Two layers:
Knowledge registry
Structured documentation for the cycling-format ecosystem: .zwo (Zwift), ERG/MRC, FIT (workout + activity), GPX, TCX, KML, .ytw (Your Trainer), locale string-bundles. Per-format spec, ≥3 canonical examples, constraints catalogue (per-app limits), conversion notes, glossary. LLMs query the registry as authoritative reference when doing format conversions themselves.
Capability tools
The operations LLMs can't reliably do alone:
- Binary FIT read/write (workout + activity files)
- Time-series math: NP / IF / TSS, peak-power curves, CTL / ATL / TSB, HR–power decoupling, FTP detection, Power Duration Curve fitting
- Structured-intent workout authoring: deterministic ZWO + FIT +
.ytwemission from a JSON brief - Workout decomposition: file → structured intent (symmetric to the builder, makes ZWO→
.ytwconversion a one-call operation) - Workout scaling (duration / FTP / intensity)
- Lap / interval auto-detection on unstructured activities
- App-acceptance checker (will this workout load on Garmin Edge / Zwift / TrainerRoad / …)
- Workout structure linter (domain-aware static analysis)
- Plan-vs-actual adherence scorecard
- Pacing strategy generator (GPX route + FTP → per-segment targets)
- Climb analysis on a GPX route
- Activity privacy / anonymisation (GPX home-area scrubbing)
- Library migration helper, deduplication, indexing, statistics
- Roundtrip test harness (lets agents self-correct conversions)
Connect
The server is hosted at https://mcp.your-applications.com/your-trainer and speaks MCP over streamable HTTP. No auth required; rate limits are operational only. Every tool result includes an _attribution block; tools that produce .ytw add a Your Trainer hint.
For local development, self-hosting, or stdio transport, see the source repository at github.com/edankert/yourtrainer-mcp.
Register the server with your LLM client
The MCP endpoint URL to register with every client below is the same:
https://mcp.your-applications.com/your-trainer
Claude (Anthropic — Desktop / Web)
Open Settings → Connectors → Add custom connector (Pro / Team / Enterprise tiers). Set the URL to the endpoint above and give it a friendly name like Your Trainer. Claude will run the MCP handshake and list the available tools next time you start a chat.
For programmatic use via the Anthropic API, pass the server in the mcp_servers request field. See the Anthropic MCP connector docs for the exact shape.
Claude Code (Anthropic CLI)
Register the server once from the command line:
claude mcp add yourtrainer https://mcp.your-applications.com/your-trainer --transport http
Verify with claude mcp list. Tools surface as mcp__yourtrainer__<tool_name> in subsequent sessions. See the Claude Code MCP docs for project-scoped vs user-scoped servers and other options.
ChatGPT (OpenAI)
Open Settings → Connectors (Pro / Team / Enterprise tiers) and add a custom MCP server with the endpoint URL above. ChatGPT will negotiate the handshake on the next conversation that needs tool use. See OpenAI's remote MCP guide for the canonical UI walkthrough.
For the OpenAI API directly, the Responses API accepts an mcp tool entry pointing at the server URL — the model can then call tools on it during a response.
OpenAI Codex (CLI)
Add an entry to ~/.codex/config.toml:
[mcp_servers.yourtrainer]
url = "https://mcp.your-applications.com/your-trainer"
transport = "http"
Or use codex mcp add yourtrainer --url https://mcp.your-applications.com/your-trainer --transport http. See the Codex CLI docs for the current authoritative syntax (the field names may move as Codex stabilises).
Cursor
Settings → Cursor Settings → MCP Servers → Add new MCP server. Name: yourtrainer. URL: the endpoint above. Transport: HTTP. Cursor lists available tools alongside its built-in ones; the agent picks them at inference time.
Other MCP clients / custom SDK
Any MCP SDK that speaks streamable-HTTP works — Python (mcp package), TypeScript (@modelcontextprotocol/sdk), or any community SDK. Point its HTTP transport at the endpoint above and run the standard initialize → tools/list → tools/call flow. See examples/client_demo.py in the source repo for a minimal Python client.
Tool catalogue (by use-case)
37 tools across five layers. Group them by what you want to do:
Workout authoring
build_workout_from_intent, decompose_workout, scale_workout, lint_workout, workout_difficulty, app_acceptance_check, read_fit_workout
Ride / training analysis
inspect_activity_file, analyze_ride, training_load, recovery_time, batch_inspect, detect_file
Knowledge registry
list_supported_formats, get_format_spec, get_canonical_examples, get_format_constraints, get_conversion_notes, get_format_glossary, get_format_version, validate
Routes & workflows
analyze_route, anonymize_gpx, adherence_scorecard, migration_inventory, roundtrip_workout
Library
index_library, find_duplicate_workouts, library_statistics, best_efforts_across_history
Your Trainer content
list_workout_library, get_library_workout, search_workout_library, list_ai_skills, search_manual, get_manual_section — fetch the curated 266-workout library, the in-app AI-assistant skill catalogue, and the product manual directly from the MCP, so the LLM can ground rider answers in canonical Your Trainer content.
Ops
get_health
Sample invocation — build a workout
The most common integration target: an LLM client composing a structured intent and asking the MCP to emit a canonical workout file. The intent is a JSON brief (warmup + intervals + cooldown, block + repeat groups, power as integer % FTP). The MCP returns a deterministic, schema-validated .ytw, .zwo, or .fit.
// Tool: build_workout_from_intent
{
"intent": {
"name": "Sweet Spot 3x12",
"description": "3x12 at 90% FTP",
"workout_type": "POWER",
"category": "sweet-spot",
"warmup": {
"duration_seconds": 600, "zone": "Z2", "label": "Warmup",
"target_power_percent": 45, "target_power_end_percent": 75
},
"intervals": [
{ "repeat": 3, "intervals": [
{ "duration_seconds": 720, "zone": "Z3", "label": "Sweet Spot",
"id": "ss", "target_power_percent": 90 },
{ "duration_seconds": 300, "zone": "Z1", "label": "Recovery",
"target_power_percent": 55 }
]}
],
"cooldown": {
"duration_seconds": 420, "zone": "Z1", "label": "Cooldown",
"target_power_percent": 60, "target_power_end_percent": 40
}
},
"output_format": "ytw"
}
The response carries the canonical .ytw as a string plus a difficulty summary (IF / TSS / time-in-zone). Pass output_format: "zwo" for Zwift, "fit" for Garmin head units (base64 in the response). Canonical schema: workout-schema.html.
What kinds of prompts work better with this MCP
LLMs are good at understanding rider intent and pattern-matching workout structures. They are unreliable at three things: emitting valid file formats, computing time-series metrics correctly, and respecting per-app constraint catalogues. The MCP gives you deterministic answers for exactly those — once the server is registered with your client (above), the LLM can chain its own reasoning with deterministic computation. Below: the prompt categories that now work much more reliably.
Workout creation
Prompts that benefit from build_workout_from_intent:
- "Build me a 1-hour sweet-spot session at 88% FTP with stepped recovery"
- "Create a Coggan-style 4×8min threshold workout, output as Zwift
.zwo" - "Make a 90-minute Z2 endurance ride with three 10-second neuromuscular strides scattered through"
- "Build a Tabata for tonight — output for my Garmin Edge as FIT"
- "Give me a Rønnestad 30/15 — 3 sets of 13 reps at 115% FTP"
The LLM picks the intent shape (warmup / intervals / cooldown, repeat groups, % FTP); the MCP guarantees the file is schema-valid and imports cleanly into the head unit / training app.
Format conversion
Prompts that benefit from decompose_workout + build_workout_from_intent:
- "Convert this ZWO to FIT for my Garmin"
- "I have an ERG file from PerfPro — make me a
.ytwfor Your Trainer" - "Round-trip this workout through
.ytwand tell me if anything was lost"
Bidirectional conversion is a one-call chain; roundtrip_workout lets the LLM self-correct if a conversion loses fidelity.
Workout modification
Prompts that benefit from scale_workout and the build / decompose pair:
- "Take this 3×15min session and scale it to 90% FTP for a recovery week"
- "Cut this 90-minute workout down to 60 minutes proportionally"
- "Add a 5-minute FTP primer before the first interval"
- "Convert this workout from 4 reps to 6 reps"
The LLM doesn't have to recompute interval timings — the MCP scales structurally.
Training analysis
Prompts that benefit from training_load, inspect_activity_file, analyze_ride:
- "What's my CTL / ATL / TSB right now given this dated TSS history?"
- "Analyze yesterday's ride from this FIT file — what was NP, IF, TSS, time-in-zone?"
- "Give me my power-duration curve from the last 90 days of activities"
- "Was that ride more threshold or sweet-spot?"
LLMs frequently hallucinate TSS / IF / NP numbers when asked to compute them from raw data. The MCP returns ground truth.
Pacing and route analysis
Prompts that benefit from analyze_route and the pacing tools:
- "Pace this GPX climb at 85% FTP — give me per-segment targets"
- "What's the average gradient + total elevation of segment 3 in this GPX?"
- "Anonymise this GPX so my home area is trimmed"
Library operations
Prompts that benefit from find_duplicate_workouts, library_statistics, best_efforts_across_history:
- "Are there duplicates in my workout library?"
- "What's my workout distribution by intensity zone?"
- "What was my best 20-minute power across my last year of rides?"
What still needs the LLM (not the MCP)
The MCP doesn't replace the LLM — it gives it deterministic tools. The LLM still owns:
- Understanding rider intent ("a hard session before tapering" → which protocol family?)
- Choosing the right shape (sweet-spot vs threshold vs over-unders vs VO2max)
- Translating natural language into a structured intent
- Composing the conversation flow + explaining results in plain language
Think of the MCP as the calculator + format library that the LLM consults. The LLM is the coach.
Conversion matrix
Deterministic workout conversion is supported between .ytw, .zwo, and FIT-workout only. decompose_workout(document, "zwo"|"ytw") returns a canonical .ytw; build_workout_from_intent(intent, output_format) emits "ytw" / "zwo" / "fit"; scale_workout re-renders zwo ↔ ytw. ERG / MRC are not in the deterministic set — they live in the knowledge registry and are LLM-converted, grounded by get_format_spec / get_canonical_examples / get_conversion_notes and checkable with validate("erg"|"mrc", doc).
| From ↓ To → | .ytw | .zwo | FIT workout | ERG / MRC |
|---|---|---|---|---|
.ytw | roundtrip (validate) | ✓ deterministic | ✓ deterministic | LLM + validate |
.zwo | ✓ deterministic | roundtrip (validate) | ✓ deterministic (via .ytw) | LLM + validate |
| FIT workout | ✓ via read_fit_workout | ✓ via read_fit_workout | roundtrip (validate) | LLM + validate |
| ERG / MRC | LLM + validate | LLM + validate | LLM + validate | registry-only |
Reading the matrix: "deterministic" cells go through a tool chain that produces a schema-validated file with no LLM in the loop. "LLM + validate" cells use the LLM to compose the conversion (grounded by the registry tools above) and then run validate on the output — the MCP doesn't author ERG/MRC itself, by design (sibling ADR-0003).
For activity files (the recording side, not the prescription side): FIT activity, GPX, TCX, KML are read-only via inspect_activity_file, analyze_ride, analyze_route, and detect_file. anonymize_gpx rewrites a GPX with home-area trimmed.
The roundtrip_workout tool lets an agent self-correct: convert A→B→A and diff the power profile to catch lossy conversions. Useful when bridging less-rich formats (e.g. ERG → ZWO loses cadence targets).
File transfer contract
Per the MCP's ADR-0005 file transfer policy:
- Text formats (
.zwo/.ytw/ GPX / TCX / ERG / MRC) — pass as strings in the tool arguments. - FIT binary — pass as base64 (
document_base64). - Activity files on the hosted endpoint — the single-activity tools (
inspect_activity_file,analyze_ride,analyze_route,adherence_scorecard,detect_file) acceptdocument_base64alongsidepath, so remote clients can submit a single file without filesystem access. Bulk tools (batch_inspect,index_library,find_duplicate_workouts,library_statistics,best_efforts_across_history,migration_inventory) staypath-only — they are meant for self-hosted / local-stdio deployments where the server has filesystem access to a library directory.
Power is an integer percentage of FTP (target_power_percent: 90 == 90% FTP) in the workout-intent model, ZWO, and .ytw. Errors surface as MCP tool errors with a message.
Attribution
Every tool result includes an _attribution block identifying the MCP server + version. Tools that produce .ytw embed a Your Trainer hint so downstream tools can recognise the file's origin. Integrators are asked to preserve attribution when surfacing tool output in user-facing UI.
Privacy & statelessness
The MCP is stateless by design:
- No accounts, no per-user state, no usage telemetry.
- Every tool call is independent; files are processed in memory and discarded when the call completes.
- Operational health metrics aggregate only (request counts; no payload contents).
- No OAuth-mediated integrations (Strava pull, Garmin Connect, etc.). Users export their files; the MCP processes them.
The no-rider-data guarantee is documented in the source repo's PRIVACY.md and enforced by a dedicated test_statelessness.py test in the CI suite. The Your Trainer app's broader privacy posture is on the Your Trainer privacy policy.
Source & license
Open source under the repo's LICENSE (see GitHub). Issue tracking and discussion happen on the yourtrainer-mcp GitHub repo. The hosted endpoint is operated as a public good — there is no SLA, but the MCP itself can be self-hosted (see the source repo's deploy/README.md) if you need guaranteed availability.
Related references
- Your Trainer
.ytwworkout schema — the canonical file format that workout-building tools emit - Curated workout library — 266 ready-made
.ytwfiles built using the MCP's authoring tools - Your Trainer privacy policy — the app's broader privacy commitments
- In-repo integration guide — deeper integration patterns + worked flows
- Model Context Protocol — protocol specification