{"service":"MyoAmigo MCP tools","endpoint":"https://api.myoamigo.com/mcp","transport":"JSON-RPC 2.0 over HTTP POST","protocolVersion":"2025-06-18","authentication":{"oauth":"https://api.myoamigo.com/.well-known/oauth-protected-resource/mcp","apiKeyFallback":"Authorization: Bearer myo_sk_… — issue one at https://api.myoamigo.com/connect"},"docs":"https://api.myoamigo.com/connect","tools":[{"name":"log_set","title":"Log set","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Log one completed set onto the user's synced workout (the app sees it). The `exercise` must EXACTLY match a catalog exercise name/id or one of the user's custom exercises — call get_user_context first if unsure. Nothing is created for an unknown exercise. For a normal set pass `reps` (with `weight`). For a TIMED HOLD (plank, wall sit, dead hang) pass `durationSeconds` and omit `reps` (weight 0 unless it's a weighted hold). To avoid double-logging on a retry, pass a stable `idempotencyKey` and REUSE the same value if you call again for the same set.","inputSchema":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id, e.g. 'Barbell Deadlift' or 'Barbell_Deadlift'"},"weight":{"type":"number","minimum":0,"description":"Weight in lb (≥ 0; use 0 for bodyweight movements and unweighted holds)"},"reps":{"type":"integer","minimum":1,"description":"Reps completed (≥ 1). Omit for a timed hold — pass durationSeconds instead."},"durationSeconds":{"type":"number","exclusiveMinimum":0,"description":"Hold duration in seconds for a timed isometric exercise (plank/wall sit/dead hang). Provide this OR reps."},"rir":{"type":"integer","minimum":0,"description":"Reps in reserve (optional, ≥ 0)"},"isWarmup":{"type":"boolean","description":"Whether this was a warmup set (optional, default false)"},"idempotencyKey":{"type":"string","description":"Optional stable key identifying this logical set; reuse the exact same value when retrying so a duplicate call doesn't log a second set."}},"required":["exercise","weight"]}},{"name":"get_history","title":"Get exercise history","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Recent logged sets for an exercise (exact name/id), most recent first.","inputSchema":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id"},"limit":{"type":"integer","minimum":1,"maximum":100,"description":"Max rows (default 10, max 100)"}},"required":["exercise"]}},{"name":"get_pr","title":"Get personal record","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Personal record for an exercise (exact name/id): heaviest working set and best Epley e1RM.","inputSchema":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id"}},"required":["exercise"]}},{"name":"get_user_context","title":"Get user context","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"A dense snapshot of the user so you can act correctly: recent workouts, the user's exercise vocabulary (the exact ids/names valid for log_set), and per-exercise estimated 1RM, recent working ranges, and PRs. Call this before logging if you're unsure of the exact exercise identifier.","inputSchema":{"type":"object","properties":{}}},{"name":"search_exercises","title":"Search exercise catalog","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Browse the built-in exercise catalog (879 movements) to find the EXACT id/name to pass to create_routine / log_set. Fuzzy `query` matches name, alternate names (aliases like 'skull crusher' → 'Lying Dumbbell Tricep Extension'), equipment, and muscles, tolerating typos and word order. Filter by target `muscle` (e.g. 'chest', 'quadriceps') and/or `equipment` (e.g. 'barbell', 'dumbbell', 'cable'). Use this whenever you want to program a movement the user hasn't logged before — get_user_context only covers what they've already done. Returns id | name | equipment | primary muscles (+ aka aliases when present).","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Name substring, e.g. 'press' or 'romanian deadlift'"},"muscle":{"type":"string","description":"Filter by a primary muscle, e.g. 'chest', 'hamstrings', 'lats'"},"equipment":{"type":"string","description":"Filter by equipment, e.g. 'barbell', 'dumbbell', 'cable', 'body only'"},"limit":{"type":"integer","description":"Max results (default 20, max 100)"}}}},{"name":"create_exercise","title":"Create a custom exercise","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Create a CUSTOM exercise when the movement you want isn't in the built-in catalog. ALWAYS call search_exercises first — if it's already in the catalog, use that instead (this tool rejects a name that matches a catalog exercise, and a name matching one of the user's existing customs). Only `name` is required; everything else is optional with sensible defaults (level=beginner, category=strength, trackingType=weightReps). Once created it syncs to the app and is immediately usable by log_set / create_routine (pass its name or id exactly). For non-weight movements set `trackingType`: reps (bodyweight), duration (timed hold), or distanceDuration (cardio).","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, e.g. 'Spoto Press', 'Copenhagen Plank'"},"primaryMuscles":{"type":"array","items":{"type":"string"},"description":"Primary muscles worked, e.g. ['chest','triceps'] (optional)"},"secondaryMuscles":{"type":"array","items":{"type":"string"},"description":"Secondary muscles, e.g. ['shoulders'] (optional)"},"equipment":{"type":"string","description":"Equipment, e.g. 'barbell', 'dumbbell', 'cable', 'body only' (optional)"},"force":{"type":"string","description":"'push', 'pull', or 'static' (optional)"},"mechanic":{"type":"string","description":"'compound' or 'isolation' (optional)"},"level":{"type":"string","description":"'beginner', 'intermediate', or 'expert' (optional, default 'beginner')"},"category":{"type":"string","description":"e.g. 'strength', 'cardio', 'stretching' (optional, default 'strength')"},"instructions":{"type":"array","items":{"type":"string"},"description":"Step-by-step instructions (optional)"},"trackingType":{"type":"string","enum":["weightReps","reps","duration","distanceDuration"],"description":"How the movement is tracked (optional, default 'weightReps')"}},"required":["name"]}},{"name":"list_workouts","title":"List workouts","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"List the user's COMPLETED workouts (most recent first) with full per-exercise set detail (weight × reps, RIR, warmups). Use this to analyze training history before programming. Defaults to completed sessions only; pass includeInProgress to also see a session still being logged.","inputSchema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"description":"Max workouts (default 10, max 100)"},"includeInProgress":{"type":"boolean","description":"Include the in-progress session too (default false)"}}}},{"name":"finish_workout","title":"Finish workout","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"description":"Mark a workout session as COMPLETED (stamps its finishedAt). Use this after logging the final set of a session you built with log_set, so it counts as a completed workout in the app's history and stats (and fires the workout.completed webhook). Get the session id from a log_set response (the `session …` it returns) or from list_workouts({ includeInProgress: true }). Idempotent: finishing an already-finished session is a no-op.","inputSchema":{"type":"object","properties":{"sessionId":{"type":"string","description":"The workout session id (from a log_set response or list_workouts)"}},"required":["sessionId"]}},{"name":"delete_workout","title":"Delete workout","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Delete a workout session and everything in it — its exercises and sets (soft delete, same cascade as deleting a workout in the app). History, PRs, and stats drop the sets immediately, and the deletion syncs to the app/watch. Use to remove a mis-logged or test session. Get the id from list_workouts({ includeInProgress: true }) or a log_set response. Irreversible from this surface — there is no undelete tool.","inputSchema":{"type":"object","properties":{"sessionId":{"type":"string","description":"The workout session id (from list_workouts or a log_set response)"}},"required":["sessionId"]}},{"name":"update_set","title":"Edit a logged set","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"description":"Correct a previously logged set — change its weight, reps, RIR, and/or warmup flag. Provide at least one field; omitted fields keep their current value (pass `rir: null` to clear an RIR). The set keeps its identity, exercise, and place in the session; only the numbers change, and the edit syncs to the app/watch and re-counts in history/PRs/stats. Get the `setId` from list_workouts (each set renders as \"…×… [set <id>]\") or from a log_set response. To change which exercise a set belongs to, delete it and log_set under the right exercise instead.","inputSchema":{"type":"object","properties":{"setId":{"type":"string","description":"The set id (from list_workouts — shown as \"[set <id>]\" — or a log_set response)"},"weight":{"type":"number","minimum":0,"description":"New weight in lb (≥ 0; optional)"},"reps":{"type":"integer","minimum":1,"description":"New rep count (≥ 1; optional)"},"rir":{"type":["integer","null"],"minimum":0,"description":"New reps-in-reserve (≥ 0), or null to clear it (optional)"},"isWarmup":{"type":"boolean","description":"New warmup flag (optional)"}},"required":["setId"]}},{"name":"delete_set","title":"Delete a logged set","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Delete a single mis-logged set (soft delete, same as removing one set in the app). History, PRs, and stats drop it immediately and the deletion syncs to the app/watch; the rest of the workout is untouched. Get the `setId` from list_workouts (each set renders as \"…×… [set <id>]\") or a log_set response. To remove an entire session, use delete_workout instead. Irreversible from this surface — there is no undelete tool.","inputSchema":{"type":"object","properties":{"setId":{"type":"string","description":"The set id (from list_workouts — shown as \"[set <id>]\" — or a log_set response)"}},"required":["setId"]}},{"name":"log_cardio","title":"Log cardio activity","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Log a cardio session (run/ride/swim/…) onto the user's synced model (the app sees it). `activityType` is a name (Cycling, Elliptical, Hiking, Rowing, Running, Stair Climbing, Swimming, Walking, HIIT, Other) or a raw HKWorkoutActivityType integer. Distance is in METERS and duration in SECONDS (canonical; the app converts to mi/km for display) — both optional, but provide at least one. To avoid double-logging on a retry, pass a stable `idempotencyKey` and REUSE it if you call again for the same activity.","inputSchema":{"type":"object","properties":{"activityType":{"type":"string","description":"Activity type name (e.g. 'running', 'cycling') or a raw HK integer"},"distanceMeters":{"type":"number","exclusiveMinimum":0,"description":"Distance in meters (optional, > 0)"},"durationSeconds":{"type":"number","exclusiveMinimum":0,"description":"Duration in seconds (optional, > 0)"},"notes":{"type":"string","description":"Optional notes"},"date":{"type":"string","description":"ISO-8601 date/time of the activity (optional, defaults to now)"},"idempotencyKey":{"type":"string","description":"Stable key; reuse on retry so a duplicate call doesn't log twice."}},"required":["activityType"]}},{"name":"get_cardio","title":"List cardio activities","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"List the user's logged cardio activities (runs/rides/swims…), newest first — date | type | distance (m) | duration. Distance is meters, duration seconds (canonical).","inputSchema":{"type":"object","properties":{"limit":{"type":"integer","description":"Max rows (default 30, max 500)"}}}},{"name":"get_body_metrics","title":"Get body metrics","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Read the user's logged body metrics (bodyweight, body-fat %, and custom measurements), newest first — the coaching context the workout tools can't see (relative strength, cut/bulk progress). Optionally filter by `type` (e.g. 'bodyweight'). Returns date | type | value unit.","inputSchema":{"type":"object","properties":{"type":{"type":"string","description":"Filter to one metric type, e.g. 'bodyweight' (optional — omit for all)"},"limit":{"type":"integer","description":"Max rows, newest first (default 30, max 500)"}}}},{"name":"log_body_metric","title":"Log body metric","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Log a body metric onto the user's synced model (the app sees it): `type` 'bodyweight' (unit lb or kg) or 'measurement' (a tape measurement, unit in or cm, with a `name` for the site — e.g. 'Waist', 'Chest', 'Hips', 'Left Bicep'; reuse the user's existing names from get_body_metrics so trends stay on one chart). The value is stored verbatim in its entered unit. The coach and strength standards prefer a logged bodyweight, so log one when the user tells you their weight. To avoid double-logging on a retry, pass a stable `idempotencyKey` and REUSE it if you call again for the same sample.","inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["bodyweight","measurement"],"description":"'bodyweight' or 'measurement'"},"value":{"type":"number","exclusiveMinimum":0,"description":"The reading, in `unit` (stored verbatim)"},"unit":{"type":"string","enum":["lb","kg","in","cm"],"description":"lb/kg for bodyweight; in/cm for measurements"},"name":{"type":"string","description":"Measurement site (required for type 'measurement', e.g. 'Waist'); omit for bodyweight"},"date":{"type":"string","description":"ISO-8601 date/time of the sample (optional, defaults to now)"},"idempotencyKey":{"type":"string","description":"Stable key; reuse on retry so a duplicate call doesn't log twice."}},"required":["type","value","unit"]}},{"name":"get_stats","title":"Get training stats","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Aggregate training stats across all the user's logged working sets: per-exercise estimated 1RM / heaviest / total volume, total volume by muscle, and a weekly volume trend (all weights normalized to lb). The dense analytics view for spotting progress, imbalances, and fatigue before programming.","inputSchema":{"type":"object","properties":{}}},{"name":"list_routines","title":"List routines","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"List the user's training routines (programs) with each routine's id, name, and ordered exercises (exact exercise id/name + target sets, rep range, and rest). Call before update_routine to get the routine id and the current item list.","inputSchema":{"type":"object","properties":{}}},{"name":"create_routine","title":"Create routine","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Author a NEW training routine (program) for the user — the agent's primary write capability. Each exercise must EXACTLY match a catalog name/id or one of the user's customs (call get_user_context if unsure); an unknown exercise rejects the whole call (nothing is created). Per-exercise prescription is optional and defaults to 3 sets × 8–12 reps, 90s rest. The routine syncs to the app and watch, ready to start. To avoid duplicate routines on a retry, pass a stable `idempotencyKey` and REUSE the same value if you call again for the same routine.","inputSchema":{"type":"object","properties":{"name":{"type":"string","maxLength":200,"description":"Routine name, e.g. 'Push Day A' (max 200 chars)"},"notes":{"type":"string","description":"Optional coaching notes for the routine"},"idempotencyKey":{"type":"string","description":"Optional stable key identifying this logical routine; reuse the exact same value when retrying so a duplicate call doesn't create a second copy."},"exercises":{"type":"array","description":"Ordered exercises in the routine (at least one).","items":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id, e.g. 'Barbell Bench Press'"},"targetSets":{"type":"integer","minimum":1,"description":"Working sets (default 3)"},"repLow":{"type":"integer","minimum":1,"description":"Low end of the rep range (default 8; ≤ repHigh)"},"repHigh":{"type":"integer","minimum":1,"description":"High end of the rep range (default 12; ≥ repLow)"},"restSeconds":{"type":"integer","minimum":0,"description":"Rest between sets in seconds (default 90)"}},"required":["exercise"]}}},"required":["name","exercises"]}},{"name":"update_routine","title":"Update routine","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Revise an existing routine (get its id from list_routines). Optionally rename (`name`) and/or re-note (`notes`). If `exercises` is given it REPLACES the routine's full exercise list (old items removed, new ordered list written) — use it to reprogram a block. Same exact-match rule as create_routine: an unknown exercise rejects the whole call.","inputSchema":{"type":"object","properties":{"routineId":{"type":"string","description":"The routine's id (from list_routines)"},"name":{"type":"string","maxLength":200,"description":"New name (optional, max 200 chars)"},"notes":{"type":"string","description":"New notes (optional)"},"exercises":{"type":"array","description":"Optional FULL replacement of the routine's ordered exercises.","items":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id"},"targetSets":{"type":"integer","minimum":1,"description":"Working sets (default 3)"},"repLow":{"type":"integer","minimum":1,"description":"Low end of the rep range (default 8; ≤ repHigh)"},"repHigh":{"type":"integer","minimum":1,"description":"High end of the rep range (default 12; ≥ repLow)"},"restSeconds":{"type":"integer","minimum":0,"description":"Rest between sets in seconds (default 90)"}},"required":["exercise"]}}},"required":["routineId"]}},{"name":"delete_routine","title":"Delete routine","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Delete a routine and its exercise list (soft delete, same as deleting a routine in the app — past workouts logged from it are untouched). Get the id from list_routines. If a weekly plan still schedules the routine, the plan keeps the slot and the response names the affected plans so you can revise them with update_plan. Irreversible from this surface — there is no undelete tool.","inputSchema":{"type":"object","properties":{"routineId":{"type":"string","description":"The routine's id (from list_routines)"}},"required":["routineId"]}},{"name":"list_plans","title":"List weekly plans","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"List the user's weekly plans (which routine runs on which weekday). At most one plan is ACTIVE — it steers the app's Train tab, widget, and nudges. Each plan shows its id, weekday→routine schedule, missed-day policy, and — when it was produced by the app's plan generator — the generating request (goal, days/week, experience, equipment). Call before update_plan/delete_plan to get ids.","inputSchema":{"type":"object","properties":{}}},{"name":"create_plan","title":"Create weekly plan","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Put a weekly schedule on the user's calendar: map routines onto weekdays (1 = Monday … 7 = Sunday). Each routine must be the user's own — pass a routine id or exact name from list_routines (create routines first with create_routine if needed). Activates by default, replacing whatever plan was steering the app (pass activate: false to save without scheduling). Syncs to the app and watch; missed days default to catching up. `name` is capped at 200 characters and `notes` at 2000. To avoid duplicate plans on a retry, pass a stable `idempotencyKey` and REUSE the same value if you call again for the same plan.","inputSchema":{"type":"object","properties":{"name":{"type":"string","maxLength":200,"description":"Plan name, e.g. 'Push/Pull/Legs' (max 200 chars)"},"days":{"type":"array","description":"The weekday→routine slots (at least one). Unlisted weekdays are rest days.","items":{"type":"object","properties":{"weekday":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday: 1 = Monday … 7 = Sunday"},"routine":{"type":"string","description":"Routine id or exact name (from list_routines)"}},"required":["weekday","routine"]}},"missedPolicy":{"type":"string","enum":["catchUp","skip"],"description":"What a missed day becomes: 'catchUp' (default — it leads the week until done) or 'skip' (strict calendar)."},"activate":{"type":"boolean","description":"Make this the active plan (default true; deactivates any other)."},"notes":{"type":"string","maxLength":2000,"description":"Optional coaching notes for the plan (max 2000 chars)"},"idempotencyKey":{"type":"string","description":"Optional stable key identifying this logical plan; reuse the exact same value when retrying so a duplicate call doesn't create a second copy."}},"required":["name","days"]}},{"name":"update_plan","title":"Update weekly plan","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Revise a weekly plan (get its id from list_plans). Optionally rename, re-note, change the missed-day policy, REPLACE the full weekday→routine schedule (`days` swaps the whole week), and/or flip `isActive` (activating deactivates every other plan; deactivating leaves the app on rotation inference). `name` is capped at 200 characters and `notes` at 2000.","inputSchema":{"type":"object","properties":{"planId":{"type":"string","description":"The plan's id (from list_plans)"},"name":{"type":"string","maxLength":200,"description":"New name (optional, max 200 chars)"},"notes":{"type":"string","maxLength":2000,"description":"New notes (optional, max 2000 chars)"},"missedPolicy":{"type":"string","enum":["catchUp","skip"],"description":"New missed-day policy (optional)"},"days":{"type":"array","description":"Optional FULL replacement of the weekday→routine slots.","items":{"type":"object","properties":{"weekday":{"type":"integer","minimum":1,"maximum":7,"description":"ISO weekday: 1 = Monday … 7 = Sunday"},"routine":{"type":"string","description":"Routine id or exact name (from list_routines)"}},"required":["weekday","routine"]}},"isActive":{"type":"boolean","description":"Activate (true) or deactivate (false) this plan (optional)"}},"required":["planId"]}},{"name":"delete_plan","title":"Delete weekly plan","annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"description":"Delete a weekly plan (soft delete — the routines it scheduled stay in the user's list, only the weekly schedule goes). Get the id from list_plans.","inputSchema":{"type":"object","properties":{"planId":{"type":"string","description":"The plan's id (from list_plans)"}},"required":["planId"]}},{"name":"generate_plan","title":"Generate a training plan","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"PROPOSE a multi-day training plan for the user with the app's own plan generator — the same engine onboarding uses. Read-only: it returns a suggested week (day names, exercise picks, sets × rep range, rest) tailored to `goal` and `daysPerWeek`, ranking the catalog against the user's own history (so familiar lifts and sensible progressions surface), and persists NOTHING. For lifts the user has never logged it includes a provenance-labelled starting weight band (in kg). Use it to draft a program to discuss; to actually schedule it, persist the routines with create_routine and the weekly schedule with create_plan.","inputSchema":{"type":"object","properties":{"goal":{"type":"string","enum":["strength","hypertrophy","general"],"description":"Training goal (drives set/rep/rest scheme)."},"daysPerWeek":{"type":"integer","minimum":1,"maximum":6,"description":"Training days per week (1–6); sets the split."},"equipment":{"type":"array","items":{"type":"string"},"description":"Lowercased equipment the user can access, e.g. ['barbell','dumbbell','cable']. Omit/empty = unconstrained ('body only' is always allowed)."},"experience":{"type":"string","enum":["beginner","intermediate","advanced"],"description":"Training experience (optional, defaults to beginner)."},"avoidExerciseIds":{"type":"array","items":{"type":"string"},"description":"Exercise ids to exclude (optional), e.g. from search_exercises."},"avoidMuscles":{"type":"array","items":{"type":"string"},"description":"Primary-muscle strings to avoid for injury (optional), e.g. ['lower back']."},"preferFullBody":{"type":"boolean","description":"Force Full Body A/B/C at 1–3 days/week instead of the default split (optional)."}},"required":["goal","daysPerWeek"]}},{"name":"get_strength_standards","title":"Get strength standards","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Rate the user's big barbell lifts (squat / bench / deadlift / overhead press) against sex-specific population strength standards: bodyweight-relative ratio, percentile (1–99), and a Beginner→Elite level — the same assessment the app's Progress screen shows. Needs a logged bodyweight (see get_body_metrics). Sex isn't synced, so pass `sex` for accuracy; it defaults to male with a note. Only clean competition-style barbell variants count (an incline bench / RDL won't).","inputSchema":{"type":"object","properties":{"sex":{"type":"string","enum":["male","female"],"description":"Biological sex for the standard (defaults to male if omitted)."}}}},{"name":"get_muscle_balance","title":"Get muscle balance","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Per-muscle weekly working-set volume vs evidence-based hypertrophy target bands (à la Renaissance Periodization MEV–MAV), plus days since each muscle was last trained — for ALL muscle groups, so neglected ones surface too. Each muscle is labeled untrained / under / optimal / high. The coaching view for spotting imbalances and under/over-training before programming.","inputSchema":{"type":"object","properties":{}}},{"name":"get_training_consistency","title":"Get training consistency","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Training cadence at a glance: sessions this week and this month, the current consecutive-week streak, average sessions/week, and the last 8 weeks' session counts. Use to coach consistency ('you've trained 4 weeks straight' vs 'let's rebuild the habit').","inputSchema":{"type":"object","properties":{}}},{"name":"get_progress","title":"Get progress","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Progress over time, computed from history: recent PRs (sessions that beat a lift's prior best), stalls (lifts whose estimated 1RM peaked several sessions ago — plateau/regression), and a per-exercise trend snapshot (current e1RM, all-time best, and up/down/flat vs ~28 days ago). The signal for spotting what's moving and what's stuck.","inputSchema":{"type":"object","properties":{}}},{"name":"get_week_review","title":"Get week review","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"The coach's week-in-review digest for one training week (Monday–Sunday): sessions / working sets / tonnage with the prior-week trend, adherence to the active weekly plan (which scheduled days slipped), PR events that landed in the week, per-muscle weekly working sets vs the evidence bands, and 1–3 dry, evidence-cited focus pointers for next week. Honest by design — it reports what the log shows and never cheers. `week`: 'last' (default — the most recently completed week, the natural Monday read) or 'current' (the in-flight week; open days are not counted as missed and a clean read is explicitly provisional).","inputSchema":{"type":"object","properties":{"week":{"type":"string","enum":["last","current"],"description":"'last' (default) = the most recently completed Mon–Sun week; 'current' = the week in progress."}}}},{"name":"assess_session","title":"Assess session","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"An honest, evidence-based verdict on a finished session — measured against the user's OWN history (their bests, their last session, their personal volume norm). Returns a tier (breakthrough / strong / solid / light / empty), a headline + subtext, and the evidence behind it. Deliberately not generic praise: a PR is celebrated, a light/sandbagged day gets a candid nudge. Defaults to the most recent finished session; pass `sessionId` (from list_workouts) for a specific one.","inputSchema":{"type":"object","properties":{"sessionId":{"type":"string","description":"A specific session id (from list_workouts). Omit for the most recent finished session."}}}},{"name":"estimate_starting_weight","title":"Estimate starting weight","annotations":{"readOnlyHint":true,"openWorldHint":false},"description":"Estimate a sensible STARTING working weight + rep range for an exercise the user has NEVER logged, by transferring strength from the most similar lift they HAVE logged. Returns the band (lb), an estimated 1RM, the donor lift it's based on, and a confidence — an estimate with provenance, deliberately conservative (warm up toward it, never auto-load). For a lift the user already trains, use get_history / get_pr instead. `exercise` must EXACTLY match a catalog name/id or one of the user's customs.","inputSchema":{"type":"object","properties":{"exercise":{"type":"string","description":"Exact exercise name or id of the un-logged target, e.g. 'Incline Dumbbell Press'"}},"required":["exercise"]}},{"name":"set_profile","title":"Set profile","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"description":"Set the user's profile inputs for strength standards — biological `sex` ('male'/'female') and/or `bodyweightLb` — on their synced cloud profile. Use this when standards can't be computed because sex or bodyweight is missing (e.g. get_strength_standards reports no bodyweight), or to correct them. IMPORTANT: this writes only to the cloud profile used here for analytics. It does NOT write to Apple Health, and it does not change what the iOS app displays; the app pushes its own sex from the device and a logged bodyweight syncs separately, either of which can later supersede what you set. Prefer values the user explicitly states.","inputSchema":{"type":"object","properties":{"sex":{"type":"string","enum":["male","female"],"description":"Biological sex for sex-specific standards."},"bodyweightLb":{"type":"number","exclusiveMinimum":0,"description":"Bodyweight in lb (> 0). Stored in kg on the profile."}}}},{"name":"submit_feedback","title":"Submit feedback","annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"description":"Send feedback, a bug report, a feature request, or a support question to the MyoAmigo team on the user's behalf. Use this only when the user explicitly asks to send feedback or report a problem — relay their words; do not invent feedback. The message is saved and the team is notified by email. Returns a reference id.","inputSchema":{"type":"object","properties":{"message":{"type":"string","description":"The feedback / report / question, in the user's words (required, ≤ 5000 chars)."},"category":{"type":"string","enum":["bug","feature","question","other"],"description":"What kind of feedback this is (default 'other')."},"subject":{"type":"string","description":"Optional short subject line (≤ 200 chars)."},"contactEmail":{"type":"string","description":"Optional reply-to address if the user wants a response somewhere other than their account email."}},"required":["message"]}}]}