For a coach about their squad: each athlete’s context and sessions, goals, messages and drafting, settings, plans and workouts. Listed to everyone; called from an athlete’s account, each is refused with the athlete tool to use instead.
List the coach's athletes with their current training status, last activity, active goals and unread message count. Start here — it returns the athleteId needed by every other tool. Includes a per-athlete status such as overreaching, monitor, disengaged, quiet, welcome-back or recovering. Quiet means past their own usual gap between sessions with nothing this week — due, not yet disengaged.
Paged: returns up to `limit` athletes (default 50) and a `nextCursor` when there are more. Pass it back as `cursor` to continue; a page can be shorter than the limit and still carry a cursor, so keep going until `nextCursor` is absent. Most rosters fit in one page.
Arguments
status · “active” | “pending” | “inactive”Filter by relationship status. Defaults to all.limit · integerAthletes per page, 1-200. Defaults to 50.cursor · stringThe `nextCursor` from the previous page. Omit for the first page.
The richest single view of an athlete, and the right starting point before writing anything to them. Returns three weeks of activity bucketed by week with per-sport volume, training load with 7-day deltas and trend, per-sport training status, goals with days-to-event, the linked training plan, and pre-computed notable flags.
Every number here was computed by Simma against this athlete's own history. Treat the flags and figures as established fact: do not re-derive averages, recompute percentages, or second-guess a severity. A flag carries a machine name, a severity, the sentence a coach would say, and the values behind it — and sometimes a context line that changes the reading entirely, such as a load spike that is a return from a break rather than overreaching. Read the context line before characterising a flag.
Prefer this over assembling your own picture from list_athlete_activities.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.
Per-sport training status for one athlete: form score and zone, trend, detected pattern, days since last activity, session count and flags. This is Simma's own training-load model — prefer it over inferring load from raw activities.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.
Sleep, HRV, resting heart rate and stress for one athlete. Daily physiology from the athlete's Garmin watch: nightly HRV, sleep (duration, stages, Garmin's sleep score), resting heart rate and all-day stress, one row per calendar date, plus a summary that compares the last 7 days with the athlete's own window. Read `coverage` first: it says how many nights actually carry a reading, and a watch not worn to bed produces nothing. The readings are measurements against the person's own recent days, not medical findings; report them as such and do not diagnose. Garmin's Health API reaches back about 30 days, so the window is capped there in practice.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.days · integerWindow in days, default 28.
Aggregate statistics and training form for one athlete over a window, including fitness/fatigue/form history and active goals. Use for trends over weeks rather than individual sessions.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.activityType · “swimming” | “running” | “cycling” | “combined”Defaults to swimming.weeks · integerWindow in weeks, default 12.system · “metric” | “imperial”
List an athlete's activities, newest first, trimmed to summary fields. Prefer a date window (weeks/months/days) over paging. Use get_activity_detail for the full breakdown of a single session.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.weeks · integerLook back this many weeks.months · integerdays · integeractivityType · stringFilter, e.g. swimming, running, cycling, poolSwim, openWaterSwim.pageSize · integerDefault 25.page · integer
Every session in a window with its pacing shape, plus a roll-up. Answers questions like "which swims faded in the main set this month" or "is she negative-splitting more often" from summaries Simma computed when each activity was saved — no lap data is read or averaged here.
Two views per session. `mainSet` is the longest segment (a swim's main set, the ride itself) and is what a coach means by "did they fade". `session` is every lap including warm-up and cool-down, so a structured swim often reads faded there while the main set was even or negative. Prefer mainSet; mention session only when the two disagree and it matters.
Shapes: negative_split (back half faster by >2%), even (within -2..+3%), faded (+3..8%), faded_hard (>8%). fadePercent is positive when they slowed. paceVariationPercent is lap-to-lap consistency. `lapSource: splits` means the laps were derived from the pace series at the stated distance because no lap button was pressed — say so if you quote a lap number.
Sessions with too few laps to judge are listed with shape null so you can see they existed; do not read anything into them.
`structure: opening_burst` or `two_paced` means the set had two regimes — sprints then steady, or fast/easy alternating — and the shape was judged on the steady block; `rawShape` is what a naive whole-set split would say. Do not describe a two-paced set as fading. `lapsExcludedAsDeviceErrors` counts laps faster than physically possible that were set aside before judging: a miscounting watch, not an athlete.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.weeks · integerWindow, default 12.activityType · stringFilter, e.g. swimming, running, cycling. Default all.shape · “negative_split” | “even” | “faded” | “faded_hard”Only sessions whose main-set shape matches. Default all.
Full detail for one activity, including every lap and the split structure. Large series (GPS traces, heart-rate and pace graphs, elevation profiles, stroke analytics) are summarised rather than inlined. Use this to discuss a specific session.
Values are metric. The document carries an imperial copy of each display tile, which is dropped here because it is the same data converted — it was a third of a ride's payload. Check the coach's or athlete's preferredUnits (get_coach_profile, get_athlete_profile) and convert when speaking to someone who uses imperial; do not report kilometres to a coach who works in miles.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.activityId · string · requiredFrom list_athlete_activities.
An athlete's goals — event name, discipline, date, days until event, target time and notes. Use alongside training status to judge whether load suits the time to race.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.status · “active” | “completed” | “archived”
Edit one of the athlete's goals: rename it, move the date, change the discipline or targets, add notes, or mark it completed or archived. Only the fields you pass change. Read list_athlete_goals first for the goalId and the current values, and confirm the change with the coach before calling this — it writes straight to the athlete's record.
`targets` replaces the whole list, so include every target you want to keep. Distances are metres as a string; times are H:MM:SS.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.goalId · string · requiredFrom list_athlete_goals.eventName · stringeventDate · stringYYYY-MM-DD.discipline · “swimming” | “running” | “cycling”targets · list of objectnotes · stringstatus · “active” | “completed” | “archived”
Recent coach/athlete message thread, newest first. Useful for what has already been said before drafting anything new.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.limit · integerDefault 20.
One athlete's profile and coaching relationship: name, contact, preferred units, pool length, self-rated ability by sport, and threshold values (swim/run pace, cycling power) that Simma's load model scores against. Also returns any linked Google training plan and a summary of the last 12 weeks of activities. Use this for who the athlete is; use get_training_status for how they are going.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.
Every athlete conversation with at least one message, most recent first, with the last message and unread count for each. Answers "who is waiting on me" across the whole roster in one call, rather than get_messages per athlete.
Arguments
Takes no arguments.
The signed-in coach's own record: name, business name, public slug, invite code, and the voice settings Simma applies when drafting athlete emails (tone of voice, coaching instructions, sign-off). Read these before helping write anything so the wording matches what Simma itself would send.
Arguments
Takes no arguments.
Edit the signed-in coach's own profile: business name, public slug, and the voice settings Simma applies when drafting athlete emails (tone of voice, coaching instructions, sign-off). Only the fields you pass change; pass at least one. Read get_coach_profile first for the current values and confirm the change with the coach before calling this — the voice settings shape every draft Simma writes for them from then on.
`signOff` is rendered verbatim at the end of each email; use a newline to separate the closing phrase from the name. The slug must be unique across coaches — a 409 means it is already taken.
Arguments
businessName · stringtoneOfVoice · stringcoachingInstructions · stringsignOff · stringslug · string3-30 chars, lowercase letters, digits and hyphens, starting and ending alphanumeric.
Report which safety gates are active for send_draft in this client. Run it before relying on send_draft: the strongest gate — asking the coach directly before each send — only exists if the client supports MCP elicitation, and the server cannot know that until a client connects.
By default this reads what the client declared, which is a claim rather than proof. Pass `probe: true` to actually raise a throwaway confirmation prompt and find out whether it works. A client can advertise the capability and still fail to show anything, and only a probe catches that.
Arguments
probe · booleanActually raise a harmless test prompt to prove the gate works. Sends no email and changes nothing. Answer it either way.
Set an athlete's thresholds, ability levels, units, pool length, name, body mass or date of birth. Only the fields you pass change. Thresholds are what every training-load number is scored against, so a wrong one reshapes the athlete's whole history: read get_athlete_profile first, state the old and new value to the coach, and confirm before calling this.
Units are the ones a coach speaks in — pace as M:SS, speed in km/h — and are converted to what Simma stores. Cycling threshold power comes from a power meter (95% of best 20-minute power is the usual estimate); threshold speed is the fallback for riders without one and is the whole basis of their load, so set it with care. Body mass only affects the climbing term of the speed-based cycling estimate; it is safe to ask the athlete for. `ftpLocked` stops Simma's own auto-estimation from overwriting a threshold the coach has set deliberately. Birthdate is worth asking for: without it every heart-rate zone is derived from a default age of 40. It changes zones on activities processed from now on, not ones already stored.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.birthdate · stringDate of birth as YYYY-MM-DD. Sets the age that heart-rate zones are derived from; activities processed after the change use the new zones, earlier ones keep the zones they were scored with.firstName · stringlastName · stringpreferredUnits · “metric” | “imperial”lapLength · numberPool length, in lapUnit.lapUnit · “m” | “yd”swimmingLevel · integer1 learning, 2 beginner/casual, 3 intermediate, 4 advanced.runningLevel · integer1 learning, 2 beginner/casual, 3 intermediate, 4 advanced.cyclingLevel · integer1 learning, 2 beginner/casual, 3 intermediate, 4 advanced.swimThresholdPace · string | numberCritical swim speed pace per 100m, as M:SS or seconds (e.g. 1:45).runThresholdPace · string | numberThreshold run pace per km, as M:SS or seconds (e.g. 4:30).cyclingThresholdPowerWatts · numbercyclingThresholdSpeedKmh · numberbodyMassKg · numberftpLocked · boolean
Set the coach's private notes on an athlete, or the specialty the coach works with them on. Notes are the coach's own memory of the athlete — training background, constraints, what they respond to — and are included in get_athlete_context, so what you write here shapes future drafts. `notes` replaces the whole text: read get_athlete_profile first and carry forward what should stay.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.notes · stringspecialty · “general” | “swimming” | “running” | “cycling” | “triathlon”
Add a goal for the athlete: an event with a date and one target per discipline. A goal with one target takes that discipline; more than one makes it a multi-discipline goal. Each target needs a distance or a time. Confirm with the coach before calling this.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.eventName · string · requiredeventDate · stringYYYY-MM-DD.targets · list of object · requirednotes · string
Remove a goal permanently. Prefer update_goal with status `completed` or `archived` when the goal happened or was abandoned — that keeps the history the context builder reads. Delete only for mistakes, and confirm with the coach first.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.goalId · string · requiredFrom list_athlete_goals.
Attach a Google Docs or Sheets URL as the athlete's training plan. Simma reads it (read-only) when building coaching context, so plan-versus-actual comparison becomes possible. The document must first be shared with Simma's service account; if it is not, this returns the address to share it with — relay that to the coach rather than retrying. Replaces any plan already linked.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.docUrl · string · requiredA docs.google.com document or spreadsheet URL.
Detach the linked Google Doc or Sheet. Simma stops reading it; the document itself is untouched. Confirm with the coach first.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.
Store a message you have written to an athlete as a draft. Nothing is sent — the draft appears in Simma where the coach can read, edit and send it, and it is what send_draft takes.
Read get_coach_profile first: the coach's tone of voice, coaching instructions and sign-off are what Simma itself writes with, and a draft that ignores them will not sound like them. Ground the content in get_athlete_context rather than in your own reading of the raw numbers.
Returns the stored draft including the `sk` that send_draft needs.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.subject · string · requiredEmail subject line.body · string · requiredPlain text body. Simma renders the HTML email at send time.
End the coaching relationship with an athlete. They keep every activity and goal and land on Simma's house coach account; what goes is this coach's access to their training, the coach's private notes on them, and any training plan linked for them. The message thread stays stored but is no longer reachable from this roster.
Cannot be undone from here: the athlete would need to join again with the coach's invite code. Get the coach's explicit agreement naming the athlete first; where the client supports it the coach is also asked directly and the call stops if they decline. Never remove several athletes from one approval.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.
Delete a draft that was never sent. Use it to clear a draft the coach decided against, or one you created and no longer need — otherwise it stays in the thread indefinitely.
Drafts only. A message that has been sent cannot be deleted, and should not be: removing it would not unsend the email, but it would break the routing that delivers the athlete's reply back into the thread and erase the record of what was actually said.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.sk · string · requiredThe draft's sort key, from save_draft or get_messages.
Send a saved draft to the athlete as a real email, immediately. This cannot be undone or recalled, and it arrives under the coach's name — the athlete has no way to tell it was written with an assistant.
Show the coach the exact subject and body and get their explicit agreement before calling. Do not send on a vague instruction, and never batch sends across several athletes from a single approval. Where the client supports it, the coach is also asked to confirm directly and the send stops if they decline.
`confirmSubject` and `confirmBody` must match the stored draft exactly, so a stale or mistaken `sk` cannot send a different message than the one that was approved. Take all three values from save_draft or get_messages rather than from memory.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.sk · string · requiredThe draft's sort key, from save_draft or get_messages.confirmSubject · string · requiredThe draft's exact subject, as shown to the coach.confirmBody · string · requiredThe draft's exact body, as shown to the coach.
Check a workout written in Simma's workout format against one athlete's pool and thresholds. Returns each mistake with the path to it, or the workout read back as plain lines with its totals and whether it can be sent to that athlete's watch. Changes nothing.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.workout · object · requiredA workout in Simma's workout format, version 1. Call get_workout_format first for the fields, rules and examples.
Send a workout in Simma's workout format to one athlete's Garmin watch, on the coach's instruction. The workout is added to the athlete's Garmin workout library, where they pick it on the watch; it is not scheduled on a date, and nothing already in Garmin is changed. Check it first and read the outline back to the person in plain words. Where the client supports it they are also asked directly, and the call stops if they decline. If Garmin refuses, its own message is returned.
Arguments
athleteId · string · requiredThe athlete's userId, from list_athletes.workout · object · requiredA workout in Simma's workout format, version 1. Call get_workout_format first for the fields, rules and examples.