apple-workouts-mcp
Builds structured runs, strength sessions, and multi-week training plans, then publishes and schedules them on Apple Watch through WorkoutKit and the HoodaRun companion app.
Uses iCloud Drive as the default workout feed location and private CloudKit records for web-saved plans, enabling sync of planned workouts into HoodaRun.
Reads recent Strava activities and training history to assess fitness and estimate the gap to a goal time, using the user's own Strava API credentials.
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., "@apple-workouts-mcpPut a 3x2mi tempo at 6:20 on Tuesday and a 12-miler on Sunday"
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.
apple-workouts-mcp
An MCP server that lets Claude (or any MCP client) build structured runs, strength sessions and multi-week training plans and put them on your Apple Watch — the Apple counterpart to mcp-garmin.
"Put a 3×2mi tempo at 6:15–6:25 on Tuesday, Strength B on Thursday,
and a 12-miler with the last 3 at half-marathon pace on Sunday."
→ built, published, scheduled on the Watch by HoodaRun.How it reaches the Watch
Apple has no cloud API that writes to a Watch. Structured workouts get there through WorkoutKit, which only runs on the iPhone. So the work is split:
Claude ──MCP──▶ apple-workouts-mcp ──writes──▶ workouts.json
│ (iCloud Drive, or GET /feed.json)
▼
HoodaRun (iPhone) ── WorkoutKit ──▶ Apple Watch
│
status.json ◀──writes─────┘ (what actually landed)The server compiles each workout into JSON that maps 1:1 onto WorkoutKit (
CustomWorkout→ warmup /IntervalBlocks / cooldown,HeartRateZoneAlert,SpeedRangeAlert, time / distance / open goals).HoodaRun reads the feed, schedules new or changed workouts with
WorkoutScheduler, removes ones that left the feed, and writesstatus.jsonback — solist_scheduledcan tell you what's really on your wrist.Completed runs reach Strava through Strava's own Apple Health sync; the server reads them back (read-only, your own Strava API app) for fitness assessment.
Nothing third-party sits in the middle: iCloud Drive for local use, or your own HTTP host.
Related MCP server: garmin-claude-mcp
Quick start (Mac + iCloud Drive)
git clone https://github.com/yashhooda1/mcp-apple-workouts
cd mcp-apple-workouts
pip install -e ".[dev]"
pytest -q # offline: compiles workouts + feed round-tripsAdd to Claude Desktop's MCP config (see examples/claude_desktop_config.json):
{ "mcpServers": { "apple-workouts": { "command": "apple-workouts-mcp" } } }On a Mac the feed defaults to iCloud Drive › HoodaRun › MCP
(WORKOUT_FEED_DIR overrides). In HoodaRun: Settings › Claude plans ›
Choose feed folder… and pick that folder once. HoodaRun syncs on launch and
from Sync now.
Optional: Strava history
Create an API app at https://www.strava.com/settings/api (callback domain
localhost) and setSTRAVA_CLIENT_ID/STRAVA_CLIENT_SECRET.Run
apple-workouts-strava-authonce. The rotating refresh token is saved toSTRAVA_TOKENS(default~/.hooda-workouts/strava_tokens.json, mode 600).
Without Strava, pass current_weekly_miles to the plan tools.
Remote (claude.ai custom connector)
Deploy with the Dockerfile / railway.toml, attach a volume at /data, set
MCP_AUTH_TOKEN (openssl rand -hex 32). The same bearer token gates all three
routes:
Route | Who | |
| Claude | MCP streamable HTTP |
| HoodaRun | the workout feed |
| HoodaRun | what's scheduled on the Watch |
In HoodaRun use Remote server (HTTP) with your https:// host and token
(stored in the Keychain).
Tools
Tool | Access | Description |
| read | Recent Strava activities |
| read | Summarise recent training; size the gap to a goal time |
| read | Feed workouts, each flagged |
| read | Last HoodaRun sync: scheduled, pending, errors |
| read | The exact WorkoutKit-shaped JSON for a spec |
| read | Race catalogue |
| write | Structured run on a date (optional time, indoor/outdoor) |
| write | Guided strength/core session on a date |
| write | Remove one workout by id |
| write | Remove a date range (dry-run first) |
| plan | Publish a plan you wrote — runs and lifts, by date |
| plan | Any race, any goal — built from your actual fitness |
| plan | High-school 800 / 1600 / 3200 / 5K blocks |
Every generated plan schedules two strength/core sessions a week and returns per-week nutrition, hydration and recovery guidance.
Workout spec
Same schema as mcp-garmin, so prompts and plans port unchanged:
{"name": "4x1mi threshold", "location": "outdoor", "steps": [
{"kind": "warmup", "duration": "15:00", "target": "hr:2"},
{"repeat": 4, "steps": [
{"kind": "run", "duration": "1mi", "target": "pace:6:35-6:55"},
{"kind": "recovery", "duration": "2:30", "target": "hr:2"}]},
{"kind": "cooldown", "duration": "10:00", "target": "hr:2"}]}Durations:
"15:00","90s","1mi","400m","1km","open"(lap button)Targets:
"hr:2"→HeartRateZoneAlert,"pace:M:SS-M:SS"(per mile) →SpeedRangeAlert, or noneStrength:
{"name": …, "exercises": [{"category": "PLANK", "exercise": "SIDE_PLANK", "sets": 3, "hold": "30s", "rest_s": 30}]}— rep sets are open steps you end with the Action button; holds and rest are timed
Things WorkoutKit decides, not us
Scheduled-workout cap. WorkoutKit only holds
WorkoutScheduler.maxAllowedScheduledWorkoutCountworkouts at once (shared with anything HoodaRun schedules itself). HoodaRun fills free slots with the soonest sessions and reports the rest aspending; each sync rolls forward, so open the app every few days during a long block.One warmup and one cooldown. A leading
warmupand trailingcooldownbecome WorkoutKit's; everything else becomes interval blocks, in order.Strength is scheduled as Traditional Strength Training, falling back to Functional Strength if the Watch doesn't support it as a custom workout.
Building on the web (yashhooda.ai + CloudKit)
The HoodaRun section on yashhooda.ai is a workout builder that saves to the
visitor's own private CloudKit database after they sign in with their Apple
ID (CloudKit JS). HoodaRun reads those records alongside the MCP feed, schedules
them with the same code path, and writes scheduledRev back so the site shows
On Watch. Web workouts use the identical hooda.workouts.custom/v1 JSON.
One-time setup in CloudKit Console:
Container
iCloud.ai.yashhooda.HoodaRun(or changecontainerIDinCloudKitPlanStore.swiftandCK.containerin the site section to match HoodaRun's real container). Add it under HoodaRun › Signing & Capabilities › iCloud › CloudKit.Record type
PlannedWorkoutwith String fieldsdate,time,name,sport,workoutJSON,rev,source,scheduledRev, and Date/TimesyncedAt.Indexes:
dateQueryable + Sortable,recordNameQueryable.Deploy the schema to Production.
API Access › new web API token, sign-in callback/allowed origin
https://yashhooda.ai. Paste it intoCK.apiTokenin the site section; until then the builder runs in preview mode (build + copy JSON, no sign-in).
HoodaRun integration
Add the three files in ios/HoodaRun/ to the HoodaRun target (iOS 18+ /
watchOS 11+, WorkoutKit, CloudKit):
MCPPlanSync.swift— feed models, JSON →CustomWorkout, the sync actorCloudKitPlanStore.swift— reads/marks workouts saved from yashhooda.aiMCPSyncSettingsView.swift— source picker + Sync now
Then two insertions in the app:
// In HoodaRun's settings list:
NavigationLink("Claude plans") { MCPSyncSettingsView() }
// In the App struct, sync whenever HoodaRun comes to the foreground:
@Environment(\.scenePhase) private var scenePhase
// ...on the root WindowGroup content:
.onChange(of: scenePhase) { _, phase in
if phase == .active { Task { try? await MCPPlanSync.shared.sync() } }
}The sync only ever removes workouts it scheduled itself (tracked by id), so workouts made in HoodaRun's own builder are never touched.
License
MIT
Available Tools
14 toolsassess_fitnessB
Read-only: summarise recent training (from Strava), and size the gap to a marathon goal.
With goal_time ('3:15:00') and race_date ('2027-04-19') also returns what
the goal asks for, what a safe ramp reaches, and — when those disagree — the
goal this runway does support.
| Name | Required | Description | Default |
|---|---|---|---|
| goal_time | No | ||
| race_date | No | ||
| weeks_of_history | No | ||
| current_weekly_miles | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It helpfully states 'Read-only' and explains that optional inputs produce additional comparative outputs, but it omits key operational context such as authentication requirements for Strava, failure modes if data is unavailable, and how the assessment is computed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loads the read-only nature and core purpose. The second paragraph conditionally explains the richer output when goal and race inputs are supplied. Minor formatting awkwardness aside, every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex analytical tool with no output schema, no annotations, and 0% schema parameter coverage. The description only partially compensates: it explains the high-level inputs/outputs for goal_time and race_date but does not account for default behavior when they are omitted, the roles of weeks_of_history and current_weekly_miles, or the exact shape of the assessment.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for four parameters. The description only adds meaning for two of them, including useful format examples for goal_time ('3:15:00') and race_date ('2027-04-19'). It says nothing about weeks_of_history or current_weekly_miles, leaving half the parameters undocumented anywhere.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('summarise recent training') and a concrete analytical outcome ('size the gap to a marathon goal'). It clearly differentiates the tool's assessment purpose from sibling tools like list_activities or create_marathon_plan, though it does not explicitly name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: run this to assess current fitness and evaluate a marathon goal, and optionally supply goal_time/race_date for a more detailed comparison. However, there is no explicit guidance on when to choose this tool over list_activities or create_marathon_plan, nor any stated exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clear_scheduledA
Remove every feed workout in [start_date, end_date] inclusive.
Destructive. Defaults to dry_run=True — call again with dry_run=False to commit. Only touches workouts this server published; workouts made in HoodaRun's own builder are never removed.
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | ||
| end_date | Yes | ||
| start_date | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so well: it declares the operation destructive, describes the dry-run default and commit step, and limits deletion to workouts published by this server. It also explicitly excludes workouts made in HoodaRun's own builder.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the action, then immediately flags destructiveness, dry-run behavior, and scope. Every sentence adds operational value with no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive bulk-clear tool with no annotations, no output schema, and undocumented parameters, the description covers the critical safety and scope details. It is nearly complete, missing only lower-level details such as date format expectations and what a dry run returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It clarifies that start_date and end_date form an inclusive interval and fully explains dry_run's default and commit behavior, though it does not specify date string format or timezone handling.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: remove every feed workout within an inclusive date range. It also scopes the operation to workouts this server published, which helps distinguish it from single-item or unrelated scheduled-workout operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains the safe usage pattern: defaults to dry_run=True and must be called again with dry_run=False to commit. It does not explicitly compare itself with siblings like unschedule_workout, but the range-based bulk-clear context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_hs_track_planB
Build a high-school track block: 800 / 1600 / 3200 / 5k.
goal_time defaults to the barrier — sub-2:00 800, sub-4:30 1600, sub-10:00
3200, sub-15:00 5K. With current_pr the report sizes the gap honestly.
training_age ('new' | 'developing' | 'experienced') sets a hard mileage
ceiling; Sunday is always rest; no doubles; nutrition guidance is
adequacy-only. Take it to the athlete's school coach before running it.
dry_run=True validates without publishing.
| Name | Required | Description | Default |
|---|---|---|---|
| time | No | ||
| event | No | 1600 | |
| weeks | No | ||
| dry_run | No | ||
| replace | No | ||
| goal_time | No | ||
| meet_days | No | ||
| current_pr | No | ||
| start_date | No | ||
| training_age | No | developing | |
| current_weekly_miles | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does well: it discloses mileage ceilings by training_age, Sunday rest, no doubles, adequacy-only nutrition, and the meaning of dry_run. It omits a significant behavior — that `replace` defaults to true, so an existing plan may be overwritten, and there is no note on permissions or what publishing entails.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Compact and front-loaded — the core behavior and defaults come first, caveats after. The line-broken phrasing and added defaults table are a little repetitive ('goal_time defaults to the barrier' plus the enumerated barriers), but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter mutation tool with no annotations and no output schema, much is covered (defaults, constraints, dry_run), but the omission of `replace`'s overwrite semantics and the meaning of half the parameters leaves real gaps an agent would need filled before invoking it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 11 parameters, so the description must compensate. It explains goal_time defaults, training_age's three values, and dry_run, but leaves `time`, `weeks`, `meet_days`, `start_date`, `current_weekly_miles`, `event`, and especially `replace` completely undefined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Build a high-school track block') and enumerates supported events (800/1600/3200/5k). This distinguishes it in spirit from create_training_plan and create_marathon_plan, though it never names those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real usage context: coach review before running the plan, and dry_run=True to validate without publishing. However, it never says when to choose this over create_training_plan/create_marathon_plan, which is the key routing decision an agent faces among these siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_marathon_planA
Build a marathon block for ANY race and ANY goal, scaled to current fitness.
Reads recent Strava history (unless use_strava_history=False or
current_weekly_miles is supplied), compares it to what the goal asks for,
and ramps from where the runner actually is — 8%/week ceiling,
3-up-1-down, 3-week taper, ending on race day. If the goal doesn't fit the
runway, the plan targets the goal that does and says so; force_goal=True
overrides. Two strength sessions a week; weekly fuelling/recovery guidance
in the report. dry_run=True validates without publishing.
| Name | Required | Description | Default |
|---|---|---|---|
| time | No | ||
| dry_run | No | ||
| replace | No | ||
| goal_time | Yes | ||
| race_date | Yes | ||
| race_name | Yes | ||
| force_goal | No | ||
| start_date | No | ||
| days_per_week | No | ||
| use_strava_history | No | ||
| current_weekly_miles | No | ||
| heat_penalty_s_per_mile | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden well by disclosing the ramp ceiling, 3-up-1-down structure, taper, fallback goal behavior, Strava dependency, and dry_run validation. It still omits important side-effect details, especially what replace=True does and whether publishing is destructive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and then packs the most important behavioral details into a short, dense block. Despite covering a complex tool, it avoids filler and keeps each sentence functional.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter, unannotated mutation tool, the description is behaviorally informative but incomplete. It does not fully explain all parameters or the return/report structure, and it omits important publishing/replacement semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains use_strava_history, current_weekly_miles, force_goal, and dry_run, but leaves replace, start_date, days_per_week, heat_penalty_s_per_mile, and the distinction between time and goal_time undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: "Build a marathon block." The scope is clear ("ANY race and ANY goal, scaled to current fitness"), and it is distinct from sibling tools like create_strength_workout or create_hs_track_plan, though it does not explicitly contrast with create_training_plan.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context for when the tool applies (marathon planning) and explains key conditional behavior such as reading Strava history unless overridden, force_goal, and dry_run. However, it does not explicitly state when to use this versus create_training_plan or other plan-creation siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_strength_workoutB
Create a guided strength/core workout and schedule it for a date.
Each exercise takes reps (an open set you end with the Action button) or
hold ('45s', timed), plus sets and rest_s. Each set shows on the Watch by
name, e.g. 'Romanian Deadlift · 8 reps', with a timed rest between sets.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | ||
| time | No | ||
| schedule_date | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose real runtime behavior: an open rep set terminated by the Action button, timed holds, per-set naming on the Watch, and timed rest between sets. It omits mutation consequences and requirements — scheduling side effects, whether an existing workout on that date is overwritten, and validation or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The action and scoping sentence comes first, followed by two short supporting sentences about exercise shape and Watch rendering. The 'Romanian Deadlift · 8 reps' example earns its place by showing the output format, though the phrasing is slightly wordy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a nested-object, no-annotation, no-output-schema creation tool, the description covers the exercise payload well but leaves the scheduling half thin: date/time format, timezone, conflict behavior with existing scheduled workouts, and differentiation from create_workout are all absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Top-level schema coverage is 0% (spec, time, and schedule_date are undocumented), so the description must compensate. It usefully clarifies the reps-vs-hold distinction and confirms sets/rest_s semantics inside each exercise, but says nothing about schedule_date format, the time field, or the workout name/description/estimated_minutes fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a guided strength/core workout') plus the scheduling side effect, which is more than the name alone conveys. However, it never distinguishes this tool from the sibling create_workout or preview_workout, leaving the agent to guess which creator applies to strength work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: you reach for this when you want a guided strength/core session placed on a date. There is no explicit 'use this instead of create_workout when...' guidance, no prerequisites, and no indication of whether preview_workout should be called first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_training_planA
Publish a multi-week plan you wrote yourself.
items is a list of {"date": "YYYY-MM-DD", "spec": } — a spec with exercises is strength, otherwise running.
Re-pushing the same plan name updates it in place, and (replace=True) drops
sessions from the earlier push that are no longer in the plan.
dry_run=True validates and reports without publishing.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| time | No | ||
| items | Yes | ||
| dry_run | No | ||
| replace | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does well: it discloses that re-pushing the same name updates in place, that replace=True drops sessions no longer present, and that dry_run=True validates without publishing. It does not cover permissions, visibility of published plans, or error behavior, but the key mutation and destructive semantics are surfaced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, front-loaded with the purpose, and each subsequent sentence adds distinct value about item format, update semantics, or validation. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations, no output schema, and 5 params at 0% schema coverage, the description gives important semantics but leaves meaningful gaps. It omits the `time` parameter, publication visibility, and return/error behavior, so an agent still lacks some information needed to invoke it confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains `items` in useful detail (date + WorkoutSpec/StrengthSpec, with exercises signalling strength), and explains `replace` and `dry_run`, but it never mentions the `time` parameter or fully clarifies `name` beyond update-by-name behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'Publish a multi-week plan you wrote yourself.' The phrase 'you wrote yourself' implicitly distinguishes it from sibling tools like create_marathon_plan and create_hs_track_plan, though it does not name those alternatives explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The self-authored qualifier implies this tool is for custom multi-week plans rather than preset plans or single workouts. However, it never explicitly compares itself to siblings such as create_workout or create_marathon_plan, and there are no stated exclusions or selection conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_workoutA
Create a structured running workout and schedule it for a date.
schedule_date is 'YYYY-MM-DD'; time is optional 24h 'HH:MM'. The same name on the same date overwrites instead of duplicating. Targets: 'hr:2' (HR zone) or 'pace:6:35-6:55' (min/mi window); durations '15:00', '1mi', '400m', 'open'. Set spec.location='indoor' for treadmill sessions.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | ||
| time | No | ||
| schedule_date | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full behavioral load. It does disclose the key side effect ('same name on the same date overwrites instead of duplicating'), which is genuinely valuable, but omits whether the workout is pushed to a device/Watch, any sync or connectivity requirements, and whether repeats are supported despite RepeatSpec existing in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, then terse, semicolon-separated clauses each carrying a distinct constraint. No filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers formats, overwrite semantics and treadmill mode, which is adequate for a mutation tool. It leaves out the RepeatSpec/repeat-step capability the schema exposes, and with no output schema it says nothing about what the call returns or whether the agent should preview first.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The top-level schedule_date and time parameters have no schema descriptions, and the description supplies their exact formats ('YYYY-MM-DD', 24h 'HH:MM'). It also spells out target and duration token syntax, which reinforces rather than merely repeats the nested schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a structured running workout') plus the scheduling side effect. The word 'running' implicitly separates it from create_strength_workout, but no sibling is named explicitly, so differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied — you would call this to build a new scheduled workout — and the overwrite rule tells the agent how duplicates behave. However, it never says when to use preview_workout first, when create_training_plan is the better choice, or when to unschedule instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_activitiesB
Recent activities from Strava (read-only): id, name, type, start, distance, HR.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description does useful work by declaring '(read-only)' and naming the returned fields (id, name, type, start, distance, HR). However, it omits ordering, the effective time window, and how the default days/limit values interact, which matters for a tool whose whole behavior is a filtered fetch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the field list is worth including. Minor cost is the abbreviation 'HR' and the field enumeration crowding out parameter explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with no output schema, listing the returned fields covers the return-value burden and 'read-only' covers safety. Still missing are the two parameters' meaning and the default/ordering behavior, which an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description never explains 'days' or 'limit' — the only hint is the adjective 'Recent', which is far too loose to convey that days defaults to 30 and limit caps result count. The description must compensate here and does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (activities) plus the source (Strava), which distinguishes it from siblings like list_scheduled and list_marathons. It also enumerates the returned fields, but never says explicitly that this is a Strava-activity listing versus other activity types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Only the word 'Recent' implies a use case; there is no statement of when to prefer this over list_scheduled or the fitness-assessment tools, and no mention of prerequisites such as a connected Strava account. The agent must infer the scenario entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_marathonsC
Marathons in the catalogue whose next running falls inside the window. Dates come from each race's scheduling rule — confirm with the organiser.
| Name | Required | Description | Default |
|---|---|---|---|
| max_weeks_out | No | ||
| min_weeks_out | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden. It usefully discloses the data provenance (dates derived from each race's scheduling rule) and warns that dates are unreliable, which no annotation or schema field conveys. It says nothing about return shape, ordering, or whether the window is inclusive, so the disclosure is partial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the filtered resource and scope. The second sentence carries the provenance caveat, which is genuinely informative rather than filler; only the 'confirm with the organiser' tail is arguably padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations, no output schema and 0% parameter coverage, the description must explain both the window semantics and what a returned marathon entry contains. It explains neither, leaving an agent unable to map min/max weeks to real dates or know what fields each race will carry.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so both parameters depend on the description, which only gestures at them with the word 'window'. It never states that the bounds are in weeks, that max_weeks_out=104 spans two years, that min_weeks_out=0 means including imminent/recent races, or how the two bounds interact.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It names the resource (marathons in the catalogue) and the exact filtering criterion (next running inside the window), which is specific enough to separate it from pick_random_marathon or create_marathon_plan. The verb 'list' is only implicit in the sentence fragment, and no sibling is named as a contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this versus pick_random_marathon or create_marathon_plan, and no prerequisites or exclusions. The only guidance is a data-quality caveat ('confirm with the organiser'), which is not usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_scheduledB
Workouts in the feed (optionally within [start_date, end_date]), each marked with whether HoodaRun has confirmed it's scheduled on the Watch.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | ||
| start_date | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that returned workouts are marked with whether HoodaRun has confirmed Watch scheduling, but it does not mention read-only nature, permissions, pagination, ordering, or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no redundant content. Every clause contributes either the resource, the optional filter, or the per-item scheduling marker.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter list tool with no output schema and no annotations, the description gives a basic but incomplete picture. It explains the core return content and optional date range, but omits date format, ordering, pagination, defaults, and whether calling it has any side effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It identifies both parameters by naming the optional [start_date, end_date] range, which adds meaning beyond the bare schema, but it does not specify date format, inclusivity, ordering, or default behavior when omitted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource as workouts in the feed and notes the optional date range and scheduled-on-Watch marker. It does not explicitly distinguish this tool from sibling list_activities or other listing tools, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus alternatives such as list_activities or sync_status. It only states what is returned and that a date range is optional, leaving selection entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pick_random_marathonC
Pick a marathon at random from the catalogue — the 'surprise me' path.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | ||
| max_weeks_out | No | ||
| min_weeks_out | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It says selection is random from the catalogue but does not disclose whether the seed makes selection deterministic, how min_weeks_out/max_weeks_out filter the catalogue, or what the tool returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted wording. It is efficient, though its brevity leaves necessary invocation details unaddressed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three parameters, no annotations, no output schema, and zero schema-description coverage, the description is not complete enough to invoke correctly. The core purpose is clear, but the filtering and seeding behavior are opaque.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not mention any of the three parameters. It adds no meaning for seed, max_weeks_out, or min_weeks_out, leaving an agent unable to infer their effect.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Pick a marathon at random from the catalogue.' It distinguishes the operation from listing tools through the 'surprise me' framing, though it does not explicitly name list_marathons as the alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase "the 'surprise me' path" implies when to use it, but there is no explicit guidance on when not to use it or which sibling tool to choose instead, such as list_marathons for deliberate browsing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_workoutA
Compile a workout or strength spec and return the exact WorkoutKit-shaped JSON HoodaRun would receive, without publishing anything.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the key behavioral trait: it produces output but publishes nothing, so there are no side effects. It also characterizes the return value as the exact payload HoodaRun would receive. It omits validation/error behavior and whether the spec is checked against constraints before compilation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and the return value, ending with the key safety clause. There is no filler and nothing that could be cut without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the output concept (WorkoutKit-shaped JSON), which partly compensates for the absent output schema. But for a tool whose only parameter is an opaque nested object, leaving the spec structure entirely undocumented leaves a critical gap in an otherwise self-contained definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single `spec` parameter is a free-form object with additionalProperties:true and 0% schema description coverage, and the description adds nothing about its expected fields, nesting, or required keys. An agent is told it may be a 'workout or strength spec' but must guess the entire structure, which is the tool's core input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Compile') and names the resource ('a workout or strength spec') plus the concrete return form ('exact WorkoutKit-shaped JSON'). It implicitly covers both create_workout and create_strength_workout by accepting 'workout or strength spec', but it never names those siblings, so differentiation is by inference rather than explicit routing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'without publishing anything' implies a dry-run use case, letting an agent infer it should preview before calling create_workout or create_strength_workout. However, the description never states that context explicitly, nor does it give any when-not condition (e.g., skip preview for trivial specs).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_statusA
What HoodaRun last reported: when it synced, what's on the Watch, what's waiting for a free slot (WorkoutKit caps scheduled workouts), and errors.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses what data is returned (sync time, Watch contents, pending queue due to WorkoutKit caps, errors) which is helpful behavioral context. However, it does not explicitly state that it is a read-only operation, nor does it mention any side effects or authentication requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the core purpose and then enumerates the key return values. Every phrase earns its place, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description provides a good summary of what the tool reports. It covers the main data points (sync time, Watch contents, pending items, errors) which is sufficient for an agent to decide to call it. Minor gaps like return format are acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline score is 4. The description does not need to explain parameters, and it adds value by describing the return contents instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a status reporter: 'What HoodaRun last reported' and lists the specific data returned (sync time, Watch contents, pending items, errors). It doesn't use a direct verb like 'Get' and doesn't explicitly contrast with siblings, but the resource and scope are unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance or alternatives are stated. However, the context of siblings (all action tools) and the description's focus on reporting imply this is the tool to check sync state. Usage is implied but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unschedule_workoutA
Remove one workout from the feed by id; HoodaRun removes it from the Watch at its next sync.
| Name | Required | Description | Default |
|---|---|---|---|
| workout_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden. It does disclose one genuinely valuable trait — removal propagates to the Watch only at the next sync, not immediately — but omits whether the removal is reversible, what permissions are needed, and what happens for an unknown or already-unscheduled id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, two clauses, front-loaded with the action and selector, with the sync behavior as supporting detail. Nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter removal tool with no output schema and no annotations, the description covers the essential operational surprise (delayed Watch sync). Missing only id provenance and failure behavior, which are minor for this shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single parameter has no title or description beyond 'Workout Id'. The description only adds that the id selects the workout to remove; it does not say where the id comes from (e.g. list_scheduled) or its format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Remove) plus resource (one workout from the feed) and the selector (by id). The phrase 'one workout' implicitly separates it from the sibling clear_scheduled, which presumably clears the whole feed, but the differentiation is by implication rather than explicit contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: 'Remove one workout' suggests single-item removal versus clear_scheduled's bulk clearing, but the description never names that alternative or states the condition for choosing it. No prerequisites or error cases (e.g. unknown id) are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v0.1.0- First observed
assess_fitness - First observed
clear_scheduled - First observed
create_hs_track_plan - First observed
create_marathon_plan - First observed
create_strength_workout - First observed
create_training_plan - First observed
create_workout - First observed
list_activities - First observed
list_marathons - First observed
list_scheduled - First observed
pick_random_marathon - First observed
preview_workout - First observed
sync_status - First observed
unschedule_workout
TDQS
Scored across 14 tools
Most tools have clearly distinct purposes: feed reads (list_scheduled, sync_status), feed mutations (unschedule_workout, clear_scheduled), and creation tools are well separated. The only real overlap is among the plan builders (create_training_plan vs create_marathon_plan vs create_hs_track_plan) — an agent could plausibly reach for the generic plan publisher when a marathon or track block is wanted, though the descriptions do clarify.
Almost all names are snake_case verb_noun (create_workout, list_scheduled, preview_workout, clear_scheduled). Minor deviations: sync_status is noun-only and pick_random_marathon is verb_adj_noun, but overall the pattern is predictable.
14 tools sit comfortably in the ideal band for a workout scheduling/generation server. Each tool covers a genuine capability — read feed, mutate feed, preview, sync, plan generation, catalogue — with no filler.
Lifecycle coverage is strong: create, preview/validate, list, unschedule single, clear range, plus sync status and plan publishing. Gaps are minor — no explicit get-by-id or update-existing-workout tool, though same-name/date overwrite and unschedule-then-recreate provide workarounds.
Maintenance
Related MCP Connectors
Your AI writes training plans that arrive as structured workouts on iPhone and Apple Watch.
Your triathlon training in Claude: activities, PMC load, plans pushed to Garmin, races, recovery.
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
AI coach for Garmin: builds training plans and structured workouts, synced straight to your watch.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceStrength-training app Claude can write to: reads real workout history (planned vs actual) and writes planned workouts back into the Tally iOS app. First-party hosted remote MCP server secured with OAuth 2.1 (PKCE + dynamic client registration).MIT
- AlicenseNot gradedqualityCmaintenanceLets Claude read your recent Garmin activities and wellness data through intervals.icu, then design, create, update, or delete structured workouts that sync to your watch. Read tools cover training history, sleep, HRV, and upcoming calendar events.MIT
- AlicenseNot gradedqualityCmaintenanceLets Claude read a runner's recent activities and wellness signals — sleep, HRV, resting heart rate — and then design, schedule, edit, or delete structured workouts. Planned sessions are written to an intervals.icu calendar that syncs through Garmin Connect onto the user's watch, without exposing Garmin credentials.MIT
- AlicenseNot gradedqualityCmaintenanceLets Claude read recent Garmin training activities and wellness signals such as sleep, HRV, and resting heart rate, then design and push structured workouts onto the user's calendar for syncing to their watch. Workouts can also be listed, edited, and deleted through natural language.MIT