{
  "schemaVersion": "1.0.0",
  "server": "rack",
  "resource": "mcp.rackstrength.com/mcp",
  "tools": [
    {
      "name": "rack_add_reaction",
      "title": "Add reaction to trainee workout",
      "description": "React to a trainee's completed workout (POST /coaching/reactions) with one\nof thumbs_up | fire | clap | flex. dry_run=True (default) previews with NO\nnetwork call. dry_run=False writes it. Consent-checked server-side (your own\ntrainees only). Duplicate reactions are an idempotent no-op.",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "AddReactionInput": {
            "properties": {
              "trainee_id": {
                "description": "Target trainee UUID (from rack_get_roster_readiness).",
                "title": "Trainee Id",
                "type": "string"
              },
              "workout_id": {
                "description": "The trainee workout UUID to react to (from rack_get_trainee_workouts).",
                "title": "Workout Id",
                "type": "string"
              },
              "reaction_type": {
                "description": "One of: thumbs_up, fire, clap, flex.",
                "title": "Reaction Type",
                "type": "string"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually react.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "trainee_id",
              "workout_id",
              "reaction_type"
            ],
            "title": "AddReactionInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/AddReactionInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_add_reactionArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_assign_program",
      "title": "Assign a program to a trainee",
      "description": "Assign a routine/program to one of your trainees\n(POST /coaching/assignments). dry_run=True (default) returns a preview with NO\nnetwork call. dry_run=False assigns it. Idempotent: re-assigning the SAME\nroutine to the SAME trainee is a safe no-op (the existing assignment is\nreturned, no duplicate). Consent-checked server-side (your own trainees only).",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": true,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "AssignProgramInput": {
            "properties": {
              "trainee_id": {
                "description": "Target trainee UUID (from rack_get_roster_readiness).",
                "title": "Trainee Id",
                "type": "string"
              },
              "routine_name": {
                "description": "Name of the routine/program to assign (1..200 chars).",
                "title": "Routine Name",
                "type": "string"
              },
              "routine_template": {
                "additionalProperties": true,
                "description": "The routine template as a JSON object (exercises, sets, etc.).",
                "title": "Routine Template",
                "type": "object"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually assign. Idempotent: a repeat assign of the same routine to the same trainee is a safe no-op.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "trainee_id",
              "routine_name",
              "routine_template"
            ],
            "title": "AssignProgramInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/AssignProgramInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_assign_programArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_create_custom_exercise",
      "title": "Create custom exercise",
      "description": "Create a custom exercise (POST /exercises). Supplying id makes it idempotent.\nServer enums are passed through; validation 400s come back as actionable text.",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "$defs": {
          "CreateCustomExerciseInput": {
            "properties": {
              "name": {
                "description": "Exercise name, e.g. 'Pendlay Row'.",
                "title": "Name",
                "type": "string"
              },
              "muscle_group": {
                "description": "Primary muscle: chest, back, shoulders, legs, arms, core.",
                "title": "Muscle Group",
                "type": "string"
              },
              "equipment": {
                "description": "barbell, dumbbell, cable, machine, bodyweight, kettlebell, band, smithMachine, trapBar, ezBar, other.",
                "title": "Equipment",
                "type": "string"
              },
              "category": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "compound, isolation, cardio (defaults compound).",
                "title": "Category"
              },
              "sub_muscle_group": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional sub-muscle (e.g. lats, frontDelt).",
                "title": "Sub Muscle Group"
              },
              "instructions": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional how-to.",
                "title": "Instructions"
              },
              "secondary_muscle_groups": {
                "anyOf": [
                  {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional secondary sub-muscles.",
                "title": "Secondary Muscle Groups"
              },
              "id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional client UUID. Supplying it makes the create idempotent (same id = same row across devices).",
                "title": "Id"
              }
            },
            "required": [
              "name",
              "muscle_group",
              "equipment"
            ],
            "title": "CreateCustomExerciseInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/CreateCustomExerciseInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_create_custom_exerciseArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_flag_athlete",
      "title": "Flag an athlete for coach attention",
      "description": "Raise an open coaching flag on one of your trainees\n(POST /coaching/trainees/{trainee_id}/flag) — one of deload | check_in |\nform_review. dry_run=True (default) previews with NO network call.\ndry_run=False raises it. The flag is surfaced (open count) on your trainee\nread. Consent-checked server-side (your own trainees only).",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "FlagAthleteInput": {
            "properties": {
              "trainee_id": {
                "description": "Target trainee UUID (from rack_get_roster_readiness).",
                "title": "Trainee Id",
                "type": "string"
              },
              "flag_type": {
                "description": "One of: deload, check_in, form_review.",
                "title": "Flag Type",
                "type": "string"
              },
              "note": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional context note for the flag (<=2000 chars).",
                "title": "Note"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually raise the flag.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "trainee_id",
              "flag_type"
            ],
            "title": "FlagAthleteInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/FlagAthleteInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_flag_athleteArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_checkin_items",
      "title": "Get check-in items",
      "description": "The coach's check-in queue: trainees who need attention (missed sessions,\nflagged readiness, etc.). Coach-self-scoped — returns only this coach's\ntrainees. READ-ONLY.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_get_checkin_itemsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_exercise",
      "title": "Get exercise",
      "description": "Fetch one exercise by id.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "exercise_id": {
            "title": "Exercise Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "exercise_id"
        ],
        "title": "rack_get_exerciseArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_exercise_progression",
      "title": "Get exercise progression",
      "description": "Progressive-overload history for an exercise (per-session top weight, 1RM,\nvolume). Optional convenience over GET /workouts/exercises/{name}/progression.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "exercise_name": {
            "title": "Exercise Name",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "exercise_name"
        ],
        "title": "rack_get_exercise_progressionArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_messages",
      "title": "Get coach messages",
      "description": "Read the coach<->trainee message thread for one trainee (consent-checked\nserver-side via the coaching pair). trainee_id comes from\nrack_get_roster_readiness. READ-ONLY: this slice does not send messages.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id"
        ],
        "title": "rack_get_messagesArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_program",
      "title": "Get program",
      "description": "Get one program by id with its full weekday slot schedule.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "program_id": {
            "title": "Program Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "program_id"
        ],
        "title": "rack_get_programArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_roster_readiness",
      "title": "Get roster readiness",
      "description": "Coach roster overview: every active trainee with their latest readiness/\nactivity snapshot (War Room). Call this FIRST to discover trainee_ids for the\ntrainee-scoped tools. Coach-only; a non-coach token cannot reach it.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_get_roster_readinessArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_routine",
      "title": "Get routine",
      "description": "Fetch one planned routine by id (full exercise/cardio readback).",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "routine_id": {
            "title": "Routine Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "routine_id"
        ],
        "title": "rack_get_routineArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_trainee_analytics",
      "title": "Get trainee analytics",
      "description": "One trainee's training analytics: weekly volume trend (with moving average),\nper-muscle-group volume, push/pull/legs/arms/core balance, top exercises, and\ntotal/filtered workout counts. `range` windows the derived series (1W/2W/4W/3M/\n6M/all). The server computes the aggregate; this tool only formats it.\n\ntrainee_id comes from rack_get_roster_readiness. Consent-checked server-side\n(a coach only sees their own trainees); a 403 for a non-consented trainee\ncomes back as a readable error, not a crash.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "range": {
            "default": "all",
            "enum": [
              "1W",
              "2W",
              "4W",
              "3M",
              "6M",
              "all"
            ],
            "title": "Range",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id"
        ],
        "title": "rack_get_trainee_analyticsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_trainee_exercise_progression",
      "title": "Get trainee exercise progression",
      "description": "Progressive-overload history for ONE trainee's exercise (per-session top\nweight, reps, e1RM, volume, plus the bodyweight flag). Coach counterpart to\nrack_get_exercise_progression. Returns the latest `limit` sessions (default\n50, server caps at 500) newest-first; raise `limit` to see a longer trend.\n\ntrainee_id comes from rack_get_roster_readiness. Consent-checked server-side;\na 403 for a non-consented trainee comes back as a readable error.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "exercise_name": {
            "title": "Exercise Name",
            "type": "string"
          },
          "limit": {
            "default": 50,
            "title": "Limit",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id",
          "exercise_name"
        ],
        "title": "rack_get_trainee_exercise_progressionArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_trainee_prs",
      "title": "Get trainee PRs",
      "description": "All-time personal records per exercise for ONE trainee (heaviest logged\nweight x reps and when it was set).\n\ntrainee_id comes from rack_get_roster_readiness. Consent-checked server-side;\na 403 for a non-consented trainee comes back as a readable error.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id"
        ],
        "title": "rack_get_trainee_prsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_trainee_summary",
      "title": "Get trainee summary",
      "description": "One trainee's training summary: aggregate stats plus the recent readiness\ntrend. trainee_id comes from rack_get_roster_readiness. Consent-checked\nserver-side (a coach only sees their own trainees); privacy-respecting (hidden\nsections come back empty).",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id"
        ],
        "title": "rack_get_trainee_summaryArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_trainee_workouts",
      "title": "Get trainee workouts",
      "description": "List one trainee's completed workouts (consent-checked server-side).\ntrainee_id comes from rack_get_roster_readiness.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "trainee_id": {
            "title": "Trainee Id",
            "type": "string"
          },
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "trainee_id"
        ],
        "title": "rack_get_trainee_workoutsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_user_context",
      "title": "Get user context",
      "description": "Whoami: report WHICH Rack account this MCP token is connected to and how\nmuch data it holds. Returns email, display_name, subscription_tier, user_id\nand role, plus the total routine and workout counts.\n\nCall this FIRST when routines or workouts come back empty/unexpected: it\nmakes the connected account unmistakable and kills the silent-empty-array\nconfusion (the token may belong to a different account than you expect).\n\nThe workout count is a real server-side total_count. The routine count is\nderived by counting the rows on one large page: the Go RoutineListResponse\n`total` is only the page length (len(routines), NOT a COUNT(*)), so a\nper_page=1 request would always report at most 1. We request the server's\nmax page (per_page=100) and count rows; if the page is full we report\n\"100+\" rather than a false-precise number.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_get_user_contextArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_get_workout",
      "title": "Get workout",
      "description": "Read a completed workout at set level (reps, weight_kg, duration, timestamps,\nrpe, heart rate).\n\nIncludes a `garmin_sync` object reporting whether the workout auto-synced to\nGarmin Connect: status (synced / pending / failed / not_synced), the Garmin\nactivity_id, the connect.garmin.com deep-link url, and the synced_at\ntimestamp. status=\"not_synced\" with null id/url/synced_at when the workout\nwas never uploaded. DETAIL-only — the list tool does not include it.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "workout_id": {
            "title": "Workout Id",
            "type": "string"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "required": [
          "workout_id"
        ],
        "title": "rack_get_workoutArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_list_programs",
      "title": "List programs",
      "description": "List your saved training programs (name, cycle, weekday slots).",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_list_programsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_list_routines",
      "title": "List routines",
      "description": "List planned routines, each with its dashboard edit URL. When the account\nhas zero routines, returns a clear message pointing to rack_get_user_context\n(to confirm the connected account) instead of a silent empty array.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_list_routinesArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_list_workouts",
      "title": "List workouts",
      "description": "List completed workouts with total_count/page/per_page.\n\nDefault is lightweight (one row per workout). Set include_sets=True to also\npull set-level data (reps, weight, set type) per exercise via\n?include=exercises (heavier; opt in only when the set detail is needed).",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "include_sets": {
            "default": false,
            "title": "Include Sets",
            "type": "boolean"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_list_workoutsArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_normalize_exercise_name",
      "title": "Normalize exercise name",
      "description": "Normalize/alias a free-text exercise name to its canonical catalog name.\nPure local, NO API call. Returns input, normalized key, canonical, alias_applied.",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "rack_normalize_exercise_nameArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_save_program",
      "title": "Save program",
      "description": "Create OR update a multi-day training program (weekday slots). dry_run=True\n(default) returns a preview with NO network call. dry_run=False writes via\nPOST /programs (create) or, when program_id is set, PUT /programs/{id} (update).\n\nEach slot's routine_id MUST be a real routine UUID from rack_list_routines (or\ncreate the routine first via rack_save_routine). The server SILENTLY drops an\nunknown routine_id, saving that slot as an empty rest day, so an invented id\nproduces a blank slot, not an error. Use routine_id=null for a real rest day.",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": true,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "ProgramSlotInput": {
            "properties": {
              "id": {
                "description": "Stable slot UUID (client-supplied, required per slot).",
                "title": "Id",
                "type": "string"
              },
              "day_index": {
                "description": "Zero-based position of this slot within the cycle (>=0).",
                "title": "Day Index",
                "type": "integer"
              },
              "session_index": {
                "default": 0,
                "description": "Zero-based session within the day for two-a-days (>=0).",
                "title": "Session Index",
                "type": "integer"
              },
              "routine_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Server routine UUID from rack_list_routines. null => rest day. An unknown id is silently dropped to a rest day server-side.",
                "title": "Routine Id"
              },
              "session_label": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Session Label"
              },
              "label": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Label"
              },
              "weekday": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Lowercase full weekday: sunday..saturday. null => legacy day_index-only scheduling.",
                "title": "Weekday"
              }
            },
            "required": [
              "id",
              "day_index"
            ],
            "title": "ProgramSlotInput",
            "type": "object"
          },
          "SaveProgramInput": {
            "properties": {
              "name": {
                "description": "Program name (required, <=200 chars).",
                "title": "Name",
                "type": "string"
              },
              "cycle_type": {
                "description": "Cycle repeat type: weekly, biweekly, or custom.",
                "enum": [
                  "weekly",
                  "biweekly",
                  "custom"
                ],
                "title": "Cycle Type",
                "type": "string"
              },
              "cycle_length_days": {
                "description": "Length of one cycle in days (1..365).",
                "title": "Cycle Length Days",
                "type": "integer"
              },
              "slots": {
                "description": "The program's scheduled slots (one routine or rest per slot).",
                "items": {
                  "$ref": "#/$defs/ProgramSlotInput"
                },
                "title": "Slots",
                "type": "array"
              },
              "total_weeks": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Total program length in weeks (1..520). null => unlimited.",
                "title": "Total Weeks"
              },
              "is_active": {
                "default": false,
                "description": "Whether this is the athlete's active program.",
                "title": "Is Active",
                "type": "boolean"
              },
              "started_at": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "RFC3339 start timestamp (optional).",
                "title": "Started At"
              },
              "current_slot_index": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Index of the currently active slot (optional).",
                "title": "Current Slot Index"
              },
              "notes": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Program-level note.",
                "title": "Notes"
              },
              "source": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional provenance tag.",
                "title": "Source"
              },
              "program_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Stable program UUID. Present => PUT update; absent => POST create (the tool mints a client UUID, since id is required even on create).",
                "title": "Program Id"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually write.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "name",
              "cycle_type",
              "cycle_length_days",
              "slots"
            ],
            "title": "SaveProgramInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/SaveProgramInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_save_programArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_save_routine",
      "title": "Save routine",
      "description": "Create OR update a planned routine. dry_run=True (default) returns a preview\nwith NO network call. dry_run=False writes via POST /routines (create) or, when\nroutine_id is set, PUT /routines/{id} (update). NEVER uses /import (v2 boundary).",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": true,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "CardioBlockInput": {
            "properties": {
              "modality": {
                "description": "Cardio/timed-carry modality, e.g. 'farmer_carry', 'run'.",
                "title": "Modality",
                "type": "string"
              },
              "sort_order": {
                "description": "Display order.",
                "title": "Sort Order",
                "type": "integer"
              },
              "notes": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional note.",
                "title": "Notes"
              },
              "target_duration_seconds": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Timed carries / durations live here.",
                "title": "Target Duration Seconds"
              },
              "target_distance_meters": {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Target Distance Meters"
              },
              "target_pace_seconds_per_km": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Target Pace Seconds Per Km"
              },
              "interval_count": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Interval Count"
              },
              "interval_duration_seconds": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Interval Duration Seconds"
              },
              "interval_rest_seconds": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Interval Rest Seconds"
              }
            },
            "required": [
              "modality",
              "sort_order"
            ],
            "title": "CardioBlockInput",
            "type": "object"
          },
          "RoutineExerciseInput": {
            "properties": {
              "exercise_id": {
                "description": "Catalog exercise UUID. Resolve names via rack_search_exercises.",
                "title": "Exercise Id",
                "type": "string"
              },
              "sort_order": {
                "description": "Display order within the routine.",
                "title": "Sort Order",
                "type": "integer"
              },
              "target_sets": {
                "description": "Number of working sets.",
                "title": "Target Sets",
                "type": "integer"
              },
              "target_reps": {
                "description": "Target reps (single value).",
                "title": "Target Reps",
                "type": "integer"
              },
              "target_weight": {
                "description": "Target load in kg.",
                "title": "Target Weight",
                "type": "number"
              },
              "rest_seconds": {
                "description": "Rest between sets in seconds.",
                "title": "Rest Seconds",
                "type": "integer"
              },
              "superset_order": {
                "default": 0,
                "description": "Order within a superset.",
                "title": "Superset Order",
                "type": "integer"
              },
              "target_reps_min": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Rep range lower bound.",
                "title": "Target Reps Min"
              },
              "target_reps_max": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Rep range upper bound.",
                "title": "Target Reps Max"
              },
              "notes": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Per-exercise coaching note. Put optional/cut logic here as free text (no structured field exists).",
                "title": "Notes"
              },
              "superset_group_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Superset label. Pass ANY string (e.g. 'A', 'circuit-1') to group exercises into a superset, or omit for a standalone exercise. Exercises sharing the same label are linked; the server normalizes the label into a stable group id, so it need not be a UUID.",
                "title": "Superset Group Id"
              },
              "per_set_reps": {
                "anyOf": [
                  {
                    "items": {
                      "type": "integer"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Per Set Reps"
              },
              "per_set_types": {
                "anyOf": [
                  {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Per Set Types"
              },
              "per_set_weight": {
                "anyOf": [
                  {
                    "items": {
                      "type": "number"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Per Set Weight"
              },
              "per_set_rest_seconds": {
                "anyOf": [
                  {
                    "items": {
                      "type": "integer"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Per Set Rest Seconds"
              },
              "target_rpe": {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Target RPE.",
                "title": "Target Rpe"
              },
              "target_rir": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Target reps in reserve.",
                "title": "Target Rir"
              },
              "effort_type": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Effort Type"
              },
              "rest_type": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Rest-timer mode: 'countdown' (default) or 'countup'. Omit for the countdown default.",
                "title": "Rest Type"
              }
            },
            "required": [
              "exercise_id",
              "sort_order",
              "target_sets",
              "target_reps",
              "target_weight",
              "rest_seconds"
            ],
            "title": "RoutineExerciseInput",
            "type": "object"
          },
          "SaveRoutineInput": {
            "properties": {
              "name": {
                "description": "Routine name (required, <=200 chars).",
                "title": "Name",
                "type": "string"
              },
              "exercises": {
                "description": "Strength exercises in order.",
                "items": {
                  "$ref": "#/$defs/RoutineExerciseInput"
                },
                "title": "Exercises",
                "type": "array"
              },
              "notes": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Routine-level note. Put session-wide optional/cut logic here.",
                "title": "Notes"
              },
              "category": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Category"
              },
              "difficulty": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Difficulty"
              },
              "cardio_blocks": {
                "description": "Timed carries / cardio blocks (durations live here).",
                "items": {
                  "$ref": "#/$defs/CardioBlockInput"
                },
                "title": "Cardio Blocks",
                "type": "array"
              },
              "routine_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Stable routine UUID. Present => PUT update; absent => POST create. POST with an existing id is an idempotent no-op readback.",
                "title": "Routine Id"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually write.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "name",
              "exercises"
            ],
            "title": "SaveRoutineInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/SaveRoutineInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_save_routineArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_search_exercises",
      "title": "Search exercises",
      "description": "Search the Rack exercise library (built-in + custom). Filters: muscle_group,\nequipment, category. The free-text term is sent as `q` (what the server reads).",
      "access": "read",
      "annotations": {
        "readOnly": true,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": false
      },
      "inputSchema": {
        "properties": {
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Query"
          },
          "muscle_group": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Muscle Group"
          },
          "equipment": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Equipment"
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Category"
          },
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "per_page": {
            "default": 50,
            "title": "Per Page",
            "type": "integer"
          },
          "response_format": {
            "default": "markdown",
            "enum": [
              "markdown",
              "json"
            ],
            "title": "Response Format",
            "type": "string"
          }
        },
        "title": "rack_search_exercisesArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_send_message",
      "title": "Send message to trainee",
      "description": "Send a message to one of your trainees (POST /coaching/messages/{trainee_id}).\ndry_run=True (default) returns a preview with NO network call. dry_run=False\nsends it. Consent-checked server-side: you can only message your own trainees.",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": false,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "SendMessageInput": {
            "properties": {
              "trainee_id": {
                "description": "Target trainee UUID (from rack_get_roster_readiness).",
                "title": "Trainee Id",
                "type": "string"
              },
              "content": {
                "description": "Message body (1..5000 chars).",
                "title": "Content",
                "type": "string"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually send.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "trainee_id",
              "content"
            ],
            "title": "SendMessageInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/SendMessageInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_send_messageArguments",
        "type": "object"
      }
    },
    {
      "name": "rack_upsert_coach_note",
      "title": "Upsert private coach note",
      "description": "Create or replace your private note for one trainee\n(PUT /coaching/trainees/{trainee_id}/notes). dry_run=True (default) previews\nwith NO network call. dry_run=False saves it. The note is private to you and\nencrypted at rest; consent-checked server-side (your own trainees only).",
      "access": "write",
      "annotations": {
        "readOnly": false,
        "destructive": false,
        "idempotent": true,
        "dryRunDefault": true
      },
      "inputSchema": {
        "$defs": {
          "UpsertCoachNoteInput": {
            "properties": {
              "trainee_id": {
                "description": "Target trainee UUID (from rack_get_roster_readiness).",
                "title": "Trainee Id",
                "type": "string"
              },
              "content": {
                "description": "Private coach note body (<=10000 chars). Upsert: replaces the existing note for this trainee.",
                "title": "Content",
                "type": "string"
              },
              "dry_run": {
                "default": true,
                "description": "Default true: return a preview and make NO network call. Set false to actually save.",
                "title": "Dry Run",
                "type": "boolean"
              }
            },
            "required": [
              "trainee_id",
              "content"
            ],
            "title": "UpsertCoachNoteInput",
            "type": "object"
          }
        },
        "properties": {
          "input": {
            "$ref": "#/$defs/UpsertCoachNoteInput"
          }
        },
        "required": [
          "input"
        ],
        "title": "rack_upsert_coach_noteArguments",
        "type": "object"
      }
    }
  ]
}
