Skip to main content
Glama

create-routine

Design and save a personalized workout routine in Hevy by specifying title, exercises, sets, and optional folder assignment. Returns the complete routine details with a unique ID for tracking.

Instructions

Create a new workout routine in your Hevy account. Requires title and at least one exercise with sets. Optionally assign to a specific folder. Returns the complete routine details upon successful creation including the newly assigned routine ID.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
exercisesYes
folderIdNo
notesNo
titleYes

Implementation Reference

  • The execution logic for the 'create-routine' tool. Handles input parameters, maps them to the Hevy API request format, calls the API to create the routine, formats the response, and returns it as JSON.
    withErrorHandling(async (args) => { if (!hevyClient) { throw new Error( "API client not initialized. Please provide HEVY_API_KEY.", ); } const { title, folderId, notes, exercises } = args as CreateRoutineParams; const data = await hevyClient.createRoutine({ routine: { title, folder_id: folderId ?? null, notes: notes ?? "", exercises: exercises.map( (exercise): PostRoutinesRequestExercise => ({ exercise_template_id: exercise.exerciseTemplateId, superset_id: exercise.supersetId ?? null, rest_seconds: exercise.restSeconds ?? null, notes: exercise.notes ?? null, sets: exercise.sets.map( (set): PostRoutinesRequestSet => ({ type: set.type as PostRoutinesRequestSetTypeEnumKey, weight_kg: set.weightKg ?? null, reps: set.reps ?? null, distance_meters: set.distanceMeters ?? null, duration_seconds: set.durationSeconds ?? null, custom_metric: set.customMetric ?? null, }), ), }), ), }, }); if (!data) { return createEmptyResponse( "Failed to create routine: Server returned no data", ); } const routine = formatRoutine(data); return createJsonResponse(routine, { pretty: true, indent: 2, }); }, "create-routine"),
  • Zod input schema defining the parameters for the 'create-routine' tool: title, optional folderId, notes, and array of exercises with sets.
    { title: z.string().min(1), folderId: z.coerce.number().nullable().optional(), notes: z.string().optional(), exercises: z.array( z.object({ exerciseTemplateId: z.string().min(1), supersetId: z.coerce.number().nullable().optional(), restSeconds: z.coerce.number().int().min(0).optional(), notes: z.string().optional(), sets: z.array( z.object({ type: z .enum(["warmup", "normal", "failure", "dropset"]) .default("normal"), weightKg: z.coerce.number().optional(), reps: z.coerce.number().int().optional(), distanceMeters: z.coerce.number().int().optional(), durationSeconds: z.coerce.number().int().optional(), customMetric: z.coerce.number().optional(), }), ), }), ), },
  • The server.tool() call that registers the 'create-routine' tool with the MCP server, providing name, description, input schema, and handler function.
    server.tool( "create-routine", "Create a new workout routine in your Hevy account. Requires a title and at least one exercise with sets. Optionally assign to a folder. Returns the full routine details including the new routine ID.", { title: z.string().min(1), folderId: z.coerce.number().nullable().optional(), notes: z.string().optional(), exercises: z.array( z.object({ exerciseTemplateId: z.string().min(1), supersetId: z.coerce.number().nullable().optional(), restSeconds: z.coerce.number().int().min(0).optional(), notes: z.string().optional(), sets: z.array( z.object({ type: z .enum(["warmup", "normal", "failure", "dropset"]) .default("normal"), weightKg: z.coerce.number().optional(), reps: z.coerce.number().int().optional(), distanceMeters: z.coerce.number().int().optional(), durationSeconds: z.coerce.number().int().optional(), customMetric: z.coerce.number().optional(), }), ), }), ), }, withErrorHandling(async (args) => { if (!hevyClient) { throw new Error( "API client not initialized. Please provide HEVY_API_KEY.", ); } const { title, folderId, notes, exercises } = args as CreateRoutineParams; const data = await hevyClient.createRoutine({ routine: { title, folder_id: folderId ?? null, notes: notes ?? "", exercises: exercises.map( (exercise): PostRoutinesRequestExercise => ({ exercise_template_id: exercise.exerciseTemplateId, superset_id: exercise.supersetId ?? null, rest_seconds: exercise.restSeconds ?? null, notes: exercise.notes ?? null, sets: exercise.sets.map( (set): PostRoutinesRequestSet => ({ type: set.type as PostRoutinesRequestSetTypeEnumKey, weight_kg: set.weightKg ?? null, reps: set.reps ?? null, distance_meters: set.distanceMeters ?? null, duration_seconds: set.durationSeconds ?? null, custom_metric: set.customMetric ?? null, }), ), }), ), }, }); if (!data) { return createEmptyResponse( "Failed to create routine: Server returned no data", ); } const routine = formatRoutine(data); return createJsonResponse(routine, { pretty: true, indent: 2, }); }, "create-routine"),
  • TypeScript type definition for CreateRoutineParams used in the handler to type-check the input arguments.
    type CreateRoutineParams = { title: string; folderId?: number | null; notes?: string; exercises: Array<{ exerciseTemplateId: string; supersetId?: number | null; restSeconds?: number; notes?: string; sets: Array<{ type: "warmup" | "normal" | "failure" | "dropset"; weightKg?: number; reps?: number; distanceMeters?: number; durationSeconds?: number; customMetric?: number; }>; }>; };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chrisdoc/hevy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server