create_workout
Log a completed workout to Hevy with exercises, sets, notes, and timing.
Instructions
Log a completed workout to Hevy.
workout shape:
{ title, description?, start_time, end_time, is_private?, exercises: [
{ exercise_template_id, notes?, superset_id?, sets: [
{ type, weight_kg?, reps?, rpe?, distance_meters?, duration_seconds? }
] }
] }
Resolve exercise_template_id values via search_exercise_templates before
calling this tool — never invent IDs.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| workout | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/hevy_mcp/tools/workouts.py:86-103 (handler)The main handler for the 'create_workout' tool. Validates the input workout dict using the Workout Pydantic model, posts it to the Hevy API via POST /workouts, and returns a confirmation message with the API response data.
@mcp.tool() @tool_guard async def create_workout(workout: dict[str, Any]) -> dict[str, Any]: """Log a completed workout to Hevy. `workout` shape: { title, description?, start_time, end_time, is_private?, exercises: [ { exercise_template_id, notes?, superset_id?, sets: [ { type, weight_kg?, reps?, rpe?, distance_meters?, duration_seconds? } ] } ] } Resolve `exercise_template_id` values via `search_exercise_templates` *before* calling this tool — never invent IDs. """ validated = Workout.model_validate(workout).model_dump(exclude_none=True) data = await client.post("/workouts", json={"workout": validated}) return {"text": "Workout logged.", "data": data} - src/hevy_mcp/schemas.py:41-48 (schema)Pydantic schema/model for the Workout resource, used to validate and deserialize the input to create_workout. Models fields like title, description, start_time, end_time, is_private, and exercises (list of WorkoutExercise).
class Workout(_Base): id: str | None = None title: str description: str | None = None start_time: datetime | None = None end_time: datetime | None = None is_private: bool = False exercises: list[WorkoutExercise] = Field(default_factory=list) - src/hevy_mcp/schemas.py:34-38 (schema)Pydantic schema for a workout exercise, referenced in create_workout input. Contains exercise_template_id, superset_id, notes, and a list of WorkoutSet.
class WorkoutExercise(_Base): exercise_template_id: str superset_id: int | None = None notes: str | None = None sets: list[WorkoutSet] = Field(default_factory=list) - src/hevy_mcp/schemas.py:23-31 (schema)Pydantic schema for an individual set within a workout exercise, used in the create_workout input validation chain.
class WorkoutSet(_Base): index: int | None = None type: SetType = "normal" weight_kg: float | None = None reps: int | None = None distance_meters: float | None = None duration_seconds: int | None = None rpe: float | None = None custom_metric: float | None = None - src/hevy_mcp/tools/workouts.py:20-21 (registration)Registration via the @mcp.tool() decorator inside the register() function. The create_workout tool is registered as an MCP tool on the mcp server instance when register() is called.
def register(mcp, ctx) -> None: client = ctx.client