update-workout
Modify workout details such as title, description, start/end times, privacy settings, and exercise data. Provides the updated workout with all changes applied for accurate tracking.
Instructions
Update an existing workout by ID. You can modify the title, description, start/end times, privacy setting, and exercise data. Returns the updated workout with all changes applied.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | No | ||
| endTime | Yes | ||
| exercises | Yes | ||
| isPrivate | No | ||
| startTime | Yes | ||
| title | Yes | ||
| workoutId | Yes |
Implementation Reference
- src/tools/workouts.ts:277-322 (handler)The core handler function for the 'update-workout' tool. It maps input parameters to the Hevy API request format, calls the updateWorkout method on the Hevy client, handles errors, formats the response using formatWorkout, and returns JSON.async ({ workoutId, title, description, startTime, endTime, isPrivate, exercises, }) => { const requestBody: PostWorkoutsRequestBody = { workout: { title, description: description || null, startTime, endTime, isPrivate, exercises: exercises.map((exercise: ExerciseInput) => ({ exerciseTemplateId: exercise.exerciseTemplateId, supersetId: exercise.supersetId || null, notes: exercise.notes || null, sets: exercise.sets.map((set: ExerciseSetInput) => ({ type: set.type, weightKg: set.weightKg || null, reps: set.reps || null, distanceMeters: set.distanceMeters || null, durationSeconds: set.durationSeconds || null, rpe: set.rpe || null, customMetric: set.customMetric || null, })), })), }, }; const data = await hevyClient.updateWorkout(workoutId, requestBody); if (!data) { return createEmptyResponse( `Failed to update workout with ID ${workoutId}`, ); } const workout = formatWorkout(data); return createJsonResponse(workout, { pretty: true, indent: 2, });
- src/tools/workouts.ts:248-275 (schema)Zod schema defining the input parameters for the 'update-workout' tool, including workoutId, title, optional description, required ISO timestamps, privacy flag, and array of exercises with detailed set data.{ workoutId: z.string().min(1), title: z.string().min(1), description: z.string().optional().nullable(), startTime: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/), endTime: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/), isPrivate: z.boolean().default(false), exercises: z.array( z.object({ exerciseTemplateId: z.string().min(1), supersetId: z.coerce.number().nullable().optional(), notes: z.string().optional().nullable(), sets: z.array( z.object({ type: z .enum(["warmup", "normal", "failure", "dropset"]) .default("normal"), weightKg: z.coerce.number().optional().nullable(), reps: z.coerce.number().int().optional().nullable(), distanceMeters: z.coerce.number().int().optional().nullable(), durationSeconds: z.coerce.number().int().optional().nullable(), rpe: z.coerce.number().optional().nullable(), customMetric: z.coerce.number().optional().nullable(), }), ), }), ), },
- src/tools/workouts.ts:246-326 (registration)Registers the 'update-workout' tool with the MCP server using server.tool(), providing name, description, input schema, and error-handling wrapped handler."update-workout", "Update an existing workout by ID. You can modify the title, description, start/end times, privacy setting, and exercise data. Returns the updated workout with all changes applied.", { workoutId: z.string().min(1), title: z.string().min(1), description: z.string().optional().nullable(), startTime: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/), endTime: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/), isPrivate: z.boolean().default(false), exercises: z.array( z.object({ exerciseTemplateId: z.string().min(1), supersetId: z.coerce.number().nullable().optional(), notes: z.string().optional().nullable(), sets: z.array( z.object({ type: z .enum(["warmup", "normal", "failure", "dropset"]) .default("normal"), weightKg: z.coerce.number().optional().nullable(), reps: z.coerce.number().int().optional().nullable(), distanceMeters: z.coerce.number().int().optional().nullable(), durationSeconds: z.coerce.number().int().optional().nullable(), rpe: z.coerce.number().optional().nullable(), customMetric: z.coerce.number().optional().nullable(), }), ), }), ), }, withErrorHandling( async ({ workoutId, title, description, startTime, endTime, isPrivate, exercises, }) => { const requestBody: PostWorkoutsRequestBody = { workout: { title, description: description || null, startTime, endTime, isPrivate, exercises: exercises.map((exercise: ExerciseInput) => ({ exerciseTemplateId: exercise.exerciseTemplateId, supersetId: exercise.supersetId || null, notes: exercise.notes || null, sets: exercise.sets.map((set: ExerciseSetInput) => ({ type: set.type, weightKg: set.weightKg || null, reps: set.reps || null, distanceMeters: set.distanceMeters || null, durationSeconds: set.durationSeconds || null, rpe: set.rpe || null, customMetric: set.customMetric || null, })), })), }, }; const data = await hevyClient.updateWorkout(workoutId, requestBody); if (!data) { return createEmptyResponse( `Failed to update workout with ID ${workoutId}`, ); } const workout = formatWorkout(data); return createJsonResponse(workout, { pretty: true, indent: 2, }); }, "update-workout-operation", ), );
- src/index.ts:40-40 (registration)Top-level call to register all workout tools, including 'update-workout', on the main MCP server instance.registerWorkoutTools(server, hevyClient);