hevy-mcp 1.21.19 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
(function() {
|
|
5
5
|
try {
|
|
6
6
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
|
|
7
|
-
e.SENTRY_RELEASE = { id: "1.21.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "1.21.20" };
|
|
8
8
|
var n = new e.Error().stack;
|
|
9
9
|
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "03cf150f-6466-4ca3-9cf1-e423cc0e3cd2", e._sentryDebugIdIdentifier = "sentry-dbid-03cf150f-6466-4ca3-9cf1-e423cc0e3cd2");
|
|
10
10
|
} catch (e) {}
|
|
11
11
|
})();
|
|
12
|
-
import { r as runServer } from "./src-
|
|
12
|
+
import { r as runServer } from "./src-B4g1Mwm2.mjs";
|
|
13
13
|
//#region src/cli.ts
|
|
14
14
|
runServer().catch((error) => {
|
|
15
15
|
console.error("Fatal error in main():", error);
|
package/dist/index.mjs
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
(function() {
|
|
5
5
|
try {
|
|
6
6
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
|
|
7
|
-
e.SENTRY_RELEASE = { id: "1.21.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "1.21.20" };
|
|
8
8
|
var n = new e.Error().stack;
|
|
9
9
|
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "a23492d3-dc93-45b6-9c01-6c2fef1c843d", e._sentryDebugIdIdentifier = "sentry-dbid-a23492d3-dc93-45b6-9c01-6c2fef1c843d");
|
|
10
10
|
} catch (e) {}
|
|
11
11
|
})();
|
|
12
|
-
import { n as createServer, r as runServer, t as configSchema } from "./src-
|
|
12
|
+
import { n as createServer, r as runServer, t as configSchema } from "./src-B4g1Mwm2.mjs";
|
|
13
13
|
export { configSchema, createServer as default, runServer };
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
(function() {
|
|
5
5
|
try {
|
|
6
6
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
|
|
7
|
-
e.SENTRY_RELEASE = { id: "1.21.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "1.21.20" };
|
|
8
8
|
var n = new e.Error().stack;
|
|
9
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
9
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "bb2b5971-1f60-4460-ae1a-40d8fc6d0bba", e._sentryDebugIdIdentifier = "sentry-dbid-bb2b5971-1f60-4460-ae1a-40d8fc6d0bba");
|
|
10
10
|
} catch (e) {}
|
|
11
11
|
})();
|
|
12
12
|
import * as Sentry from "@sentry/node";
|
|
@@ -20,17 +20,6 @@ import fetch from "@kubb/plugin-client/clients/axios";
|
|
|
20
20
|
* Centralized error handling utility for MCP tools
|
|
21
21
|
*/
|
|
22
22
|
/**
|
|
23
|
-
* Specific error types for better categorization
|
|
24
|
-
*/
|
|
25
|
-
let ErrorType = /* @__PURE__ */ function(ErrorType) {
|
|
26
|
-
ErrorType["API_ERROR"] = "API_ERROR";
|
|
27
|
-
ErrorType["VALIDATION_ERROR"] = "VALIDATION_ERROR";
|
|
28
|
-
ErrorType["NOT_FOUND"] = "NOT_FOUND";
|
|
29
|
-
ErrorType["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
30
|
-
ErrorType["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
31
|
-
return ErrorType;
|
|
32
|
-
}({});
|
|
33
|
-
/**
|
|
34
23
|
* Create a standardized error response for MCP tools
|
|
35
24
|
*
|
|
36
25
|
* @param error - The error object or message
|
|
@@ -67,11 +56,11 @@ function createErrorResponse(error, context) {
|
|
|
67
56
|
function determineErrorType(error, message) {
|
|
68
57
|
const messageLower = message.toLowerCase();
|
|
69
58
|
const nameLower = error instanceof Error ? error.name.toLowerCase() : "";
|
|
70
|
-
if (nameLower.includes("network") || messageLower.includes("network") || nameLower.includes("fetch") || messageLower.includes("fetch") || nameLower.includes("timeout") || messageLower.includes("timeout")) return
|
|
71
|
-
if (nameLower.includes("validation") || messageLower.includes("validation") || messageLower.includes("invalid") || messageLower.includes("required")) return
|
|
72
|
-
if (messageLower.includes("not found") || messageLower.includes("404") || messageLower.includes("does not exist")) return
|
|
73
|
-
if (nameLower.includes("api") || messageLower.includes("api") || messageLower.includes("server error") || messageLower.includes("500")) return
|
|
74
|
-
return
|
|
59
|
+
if (nameLower.includes("network") || messageLower.includes("network") || nameLower.includes("fetch") || messageLower.includes("fetch") || nameLower.includes("timeout") || messageLower.includes("timeout")) return "NETWORK_ERROR";
|
|
60
|
+
if (nameLower.includes("validation") || messageLower.includes("validation") || messageLower.includes("invalid") || messageLower.includes("required")) return "VALIDATION_ERROR";
|
|
61
|
+
if (messageLower.includes("not found") || messageLower.includes("404") || messageLower.includes("does not exist")) return "NOT_FOUND";
|
|
62
|
+
if (nameLower.includes("api") || messageLower.includes("api") || messageLower.includes("server error") || messageLower.includes("500")) return "API_ERROR";
|
|
63
|
+
return "UNKNOWN_ERROR";
|
|
75
64
|
}
|
|
76
65
|
/**
|
|
77
66
|
* Wrap an async function with standardized error handling
|
|
@@ -346,9 +335,9 @@ const zOptionalRepRange = z.preprocess((value) => value === null ? void 0 : valu
|
|
|
346
335
|
}).optional());
|
|
347
336
|
function buildRepRange(repRange) {
|
|
348
337
|
if (!repRange) return null;
|
|
349
|
-
const start = repRange.start ??
|
|
350
|
-
const end = repRange.end ??
|
|
351
|
-
if (start ===
|
|
338
|
+
const start = repRange.start ?? void 0;
|
|
339
|
+
const end = repRange.end ?? void 0;
|
|
340
|
+
if (start === void 0 && end === void 0) return null;
|
|
352
341
|
return {
|
|
353
342
|
start,
|
|
354
343
|
end
|
|
@@ -1297,7 +1286,7 @@ function getPostV1RoutineFoldersUrl() {
|
|
|
1297
1286
|
* @summary Create a new routine folder. The folder will be created at index 0, and all other folders will have their indexes incremented.
|
|
1298
1287
|
* {@link /v1/routine_folders}
|
|
1299
1288
|
*/
|
|
1300
|
-
async function postV1RoutineFolders(
|
|
1289
|
+
async function postV1RoutineFolders(data, headers, config = {}) {
|
|
1301
1290
|
const { client: request = fetch, ...requestConfig } = config;
|
|
1302
1291
|
const requestData = data;
|
|
1303
1292
|
return (await request({
|
|
@@ -1327,7 +1316,7 @@ function getPostV1RoutinesUrl() {
|
|
|
1327
1316
|
* @summary Create a new routine
|
|
1328
1317
|
* {@link /v1/routines}
|
|
1329
1318
|
*/
|
|
1330
|
-
async function postV1Routines(
|
|
1319
|
+
async function postV1Routines(data, headers, config = {}) {
|
|
1331
1320
|
const { client: request = fetch, ...requestConfig } = config;
|
|
1332
1321
|
const requestData = data;
|
|
1333
1322
|
return (await request({
|
|
@@ -1357,7 +1346,7 @@ function getPostV1WorkoutsUrl() {
|
|
|
1357
1346
|
* @summary Create a new workout
|
|
1358
1347
|
* {@link /v1/workouts}
|
|
1359
1348
|
*/
|
|
1360
|
-
async function postV1Workouts(
|
|
1349
|
+
async function postV1Workouts(data, headers, config = {}) {
|
|
1361
1350
|
const { client: request = fetch, ...requestConfig } = config;
|
|
1362
1351
|
const requestData = data;
|
|
1363
1352
|
return (await request({
|
|
@@ -1387,7 +1376,7 @@ function getPutV1RoutinesRoutineidUrl(routineId) {
|
|
|
1387
1376
|
* @summary Update an existing routine
|
|
1388
1377
|
* {@link /v1/routines/:routineId}
|
|
1389
1378
|
*/
|
|
1390
|
-
async function putV1RoutinesRoutineid(routineId,
|
|
1379
|
+
async function putV1RoutinesRoutineid(routineId, data, headers, config = {}) {
|
|
1391
1380
|
const { client: request = fetch, ...requestConfig } = config;
|
|
1392
1381
|
const requestData = data;
|
|
1393
1382
|
return (await request({
|
|
@@ -1417,7 +1406,7 @@ function getPutV1WorkoutsWorkoutidUrl(workoutId) {
|
|
|
1417
1406
|
* @summary Update an existing workout
|
|
1418
1407
|
* {@link /v1/workouts/:workoutId}
|
|
1419
1408
|
*/
|
|
1420
|
-
async function putV1WorkoutsWorkoutid(workoutId,
|
|
1409
|
+
async function putV1WorkoutsWorkoutid(workoutId, data, headers, config = {}) {
|
|
1421
1410
|
const { client: request = fetch, ...requestConfig } = config;
|
|
1422
1411
|
const requestData = data;
|
|
1423
1412
|
return (await request({
|
|
@@ -1453,20 +1442,20 @@ function createClient$1(apiKey, baseUrl = "https://api.hevyapp.com") {
|
|
|
1453
1442
|
return {
|
|
1454
1443
|
getWorkouts: (params) => wrapApi(getV1Workouts)(headers, params, { client }),
|
|
1455
1444
|
getWorkout: (workoutId) => wrapApi(getV1WorkoutsWorkoutid)(workoutId, headers, { client }),
|
|
1456
|
-
createWorkout: (data) => wrapApi(postV1Workouts)(
|
|
1457
|
-
updateWorkout: (workoutId, data) => wrapApi(putV1WorkoutsWorkoutid)(workoutId,
|
|
1445
|
+
createWorkout: (data) => wrapApi(postV1Workouts)(data, headers, { client }),
|
|
1446
|
+
updateWorkout: (workoutId, data) => wrapApi(putV1WorkoutsWorkoutid)(workoutId, data, headers, { client }),
|
|
1458
1447
|
getWorkoutCount: () => wrapApi(getV1WorkoutsCount)(headers, { client }),
|
|
1459
1448
|
getWorkoutEvents: (params) => wrapApi(getV1WorkoutsEvents)(headers, params, { client }),
|
|
1460
1449
|
getRoutines: (params) => wrapApi(getV1Routines)(headers, params, { client }),
|
|
1461
1450
|
getRoutineById: (routineId) => wrapApi(getV1RoutinesRoutineid)(routineId, headers, { client }),
|
|
1462
|
-
createRoutine: (data) => wrapApi(postV1Routines)(
|
|
1463
|
-
updateRoutine: (routineId, data) => wrapApi(putV1RoutinesRoutineid)(routineId,
|
|
1451
|
+
createRoutine: (data) => wrapApi(postV1Routines)(data, headers, { client }),
|
|
1452
|
+
updateRoutine: (routineId, data) => wrapApi(putV1RoutinesRoutineid)(routineId, data, headers, { client }),
|
|
1464
1453
|
getExerciseTemplates: (params) => wrapApi(getV1ExerciseTemplates)(headers, params, { client }),
|
|
1465
1454
|
getExerciseTemplate: (templateId) => wrapApi(getV1ExerciseTemplatesExercisetemplateid)(templateId, headers, { client }),
|
|
1466
1455
|
getExerciseHistory: (exerciseTemplateId, params) => wrapApi(getV1ExerciseHistoryExercisetemplateid)(exerciseTemplateId, headers, params, { client }),
|
|
1467
1456
|
createExerciseTemplate: (data) => wrapApi(postV1ExerciseTemplates)(data, headers, { client }),
|
|
1468
1457
|
getRoutineFolders: (params) => wrapApi(getV1RoutineFolders)(headers, params, { client }),
|
|
1469
|
-
createRoutineFolder: (data) => wrapApi(postV1RoutineFolders)(
|
|
1458
|
+
createRoutineFolder: (data) => wrapApi(postV1RoutineFolders)(data, headers, { client }),
|
|
1470
1459
|
getRoutineFolder: (folderId) => wrapApi(getV1RoutineFoldersFolderid)(folderId, headers, { client }),
|
|
1471
1460
|
getWebhookSubscription: async () => {
|
|
1472
1461
|
throw new Error("Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.");
|
|
@@ -1487,7 +1476,7 @@ function createClient(apiKey, baseUrl) {
|
|
|
1487
1476
|
//#endregion
|
|
1488
1477
|
//#region src/index.ts
|
|
1489
1478
|
const name = "hevy-mcp";
|
|
1490
|
-
const version = "1.21.
|
|
1479
|
+
const version = "1.21.20";
|
|
1491
1480
|
const sentryConfig = {
|
|
1492
1481
|
dsn: "https://ce696d8333b507acbf5203eb877bce0f@o4508975499575296.ingest.de.sentry.io/4509049671647312",
|
|
1493
1482
|
release: process.env.SENTRY_RELEASE ?? `${name}@${version}`,
|
|
@@ -1528,4 +1517,4 @@ async function runServer() {
|
|
|
1528
1517
|
//#endregion
|
|
1529
1518
|
export { createServer as n, runServer as r, configSchema as t };
|
|
1530
1519
|
|
|
1531
|
-
//# sourceMappingURL=src-
|
|
1520
|
+
//# sourceMappingURL=src-B4g1Mwm2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-B4g1Mwm2.mjs","names":["createClient","api.getV1Workouts","api.getV1WorkoutsWorkoutid","api.postV1Workouts","api.putV1WorkoutsWorkoutid","api.getV1WorkoutsCount","api.getV1WorkoutsEvents","api.getV1Routines","api.getV1RoutinesRoutineid","api.postV1Routines","api.putV1RoutinesRoutineid","api.getV1ExerciseTemplates","api.getV1ExerciseTemplatesExercisetemplateid","api.getV1ExerciseHistoryExercisetemplateid","api.postV1ExerciseTemplates","api.getV1RoutineFolders","api.postV1RoutineFolders","api.getV1RoutineFoldersFolderid","createKubbClient"],"sources":["../src/utils/error-handler.ts","../src/utils/formatters.ts","../src/utils/response-formatter.ts","../src/tools/folders.ts","../src/utils/json-parser.ts","../src/tools/routines.ts","../src/tools/templates.ts","../src/tools/webhooks.ts","../src/tools/workouts.ts","../src/utils/config.ts","../src/generated/client/api/getV1ExerciseHistoryExercisetemplateid.ts","../src/generated/client/api/getV1ExerciseTemplates.ts","../src/generated/client/api/getV1ExerciseTemplatesExercisetemplateid.ts","../src/generated/client/api/getV1RoutineFolders.ts","../src/generated/client/api/getV1RoutineFoldersFolderid.ts","../src/generated/client/api/getV1Routines.ts","../src/generated/client/api/getV1RoutinesRoutineid.ts","../src/generated/client/api/getV1Workouts.ts","../src/generated/client/api/getV1WorkoutsCount.ts","../src/generated/client/api/getV1WorkoutsEvents.ts","../src/generated/client/api/getV1WorkoutsWorkoutid.ts","../src/generated/client/api/postV1ExerciseTemplates.ts","../src/generated/client/api/postV1RoutineFolders.ts","../src/generated/client/api/postV1Routines.ts","../src/generated/client/api/postV1Workouts.ts","../src/generated/client/api/putV1RoutinesRoutineid.ts","../src/generated/client/api/putV1WorkoutsWorkoutid.ts","../src/utils/hevyClientKubb.ts","../src/utils/hevyClient.ts","../src/index.ts"],"sourcesContent":["/**\n * Centralized error handling utility for MCP tools\n */\n\n// Import the McpToolResponse type from response-formatter to ensure consistency\nimport { isAxiosError } from \"axios\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\n/**\n * Standard error response interface\n */\nexport interface ErrorResponse {\n\tmessage: string;\n\tcode?: string;\n\tdetails?: unknown;\n}\n\n/**\n * Specific error types for better categorization\n */\nexport enum ErrorType {\n\tAPI_ERROR = \"API_ERROR\",\n\tVALIDATION_ERROR = \"VALIDATION_ERROR\",\n\tNOT_FOUND = \"NOT_FOUND\",\n\tNETWORK_ERROR = \"NETWORK_ERROR\",\n\tUNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\n/**\n * Enhanced error response with type categorization\n */\nexport interface EnhancedErrorResponse extends ErrorResponse {\n\ttype: ErrorType;\n}\n\n/**\n * Create a standardized error response for MCP tools\n *\n * @param error - The error object or message\n * @param context - Optional context information about where the error occurred\n * @returns A formatted MCP tool response with error information\n */\nexport function createErrorResponse(\n\terror: unknown,\n\tcontext?: string,\n): McpToolResponse {\n\t// Extract axios response data if available\n\tlet errorMessage = error instanceof Error ? error.message : String(error);\n\n\t// Check for axios error with response data\n\tif (isAxiosError(error) && error.response?.data) {\n\t\tconst { data } = error.response;\n\t\tif (typeof data === \"string\") {\n\t\t\terrorMessage = data;\n\t\t} else if (data && typeof data === \"object\") {\n\t\t\ttry {\n\t\t\t\terrorMessage = JSON.stringify(data);\n\t\t\t} catch (_e) {\n\t\t\t\terrorMessage = String(data);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract error code if available (for logging purposes)\n\tconst errorCode =\n\t\terror instanceof Error && \"code\" in error\n\t\t\t? (error as { code?: string }).code\n\t\t\t: undefined;\n\n\t// Determine error type based on error characteristics\n\tconst errorType = determineErrorType(error, errorMessage);\n\n\t// Include error code in logs if available\n\tif (errorCode) {\n\t\tconsole.debug(`Error code: ${errorCode}`);\n\t}\n\n\tconst contextPrefix = context ? `[${context}] ` : \"\";\n\tconst formattedMessage = `${contextPrefix}Error: ${errorMessage}`;\n\n\t// Log the error for server-side debugging with type information\n\tconsole.error(`${formattedMessage} (Type: ${errorType})`, error);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: formattedMessage,\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\n/**\n * Determine the type of error based on error characteristics\n */\nfunction determineErrorType(error: unknown, message: string): ErrorType {\n\tconst messageLower = message.toLowerCase();\n\tconst nameLower = error instanceof Error ? error.name.toLowerCase() : \"\";\n\n\tif (\n\t\tnameLower.includes(\"network\") ||\n\t\tmessageLower.includes(\"network\") ||\n\t\tnameLower.includes(\"fetch\") ||\n\t\tmessageLower.includes(\"fetch\") ||\n\t\tnameLower.includes(\"timeout\") ||\n\t\tmessageLower.includes(\"timeout\")\n\t) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"invalid\") ||\n\t\tmessageLower.includes(\"required\")\n\t) {\n\t\treturn ErrorType.VALIDATION_ERROR;\n\t}\n\n\tif (\n\t\tmessageLower.includes(\"not found\") ||\n\t\tmessageLower.includes(\"404\") ||\n\t\tmessageLower.includes(\"does not exist\")\n\t) {\n\t\treturn ErrorType.NOT_FOUND;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"server error\") ||\n\t\tmessageLower.includes(\"500\")\n\t) {\n\t\treturn ErrorType.API_ERROR;\n\t}\n\n\treturn ErrorType.UNKNOWN_ERROR;\n}\n\n/**\n * Wrap an async function with standardized error handling\n *\n * This function preserves the parameter types of the wrapped function while\n * providing error handling. The returned function accepts Record<string, unknown>\n * (as required by MCP SDK) but internally casts to the original parameter type.\n *\n * @param fn - The async function to wrap\n * @param context - Context information for error messages\n * @returns A function that catches errors and returns standardized error responses\n */\nexport function withErrorHandling<TParams extends Record<string, unknown>>(\n\tfn: (args: TParams) => Promise<McpToolResponse>,\n\tcontext: string,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\treturn async (args: Record<string, unknown>) => {\n\t\ttry {\n\t\t\treturn await fn(args as TParams);\n\t\t} catch (error) {\n\t\t\treturn createErrorResponse(error, context);\n\t\t}\n\t};\n}\n","import type {\n\tExerciseHistoryEntry,\n\tExerciseTemplate,\n\tRoutine,\n\tRoutineFolder,\n\tWorkout,\n} from \"../generated/client/types/index.js\";\n\n/**\n * Formatted workout set interface\n */\nexport interface FormattedWorkoutSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n}\n\n/**\n * Formatted workout exercise interface\n */\nexport interface FormattedWorkoutExercise {\n\tindex: number | undefined;\n\tname: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetsId: number | undefined | null;\n\tsets: FormattedWorkoutSet[] | undefined;\n}\n\n/**\n * Formatted workout interface\n */\nexport interface FormattedWorkout {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tdescription: string | undefined | null;\n\tstartTime: string | number | undefined;\n\tendTime: string | number | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\tduration: string;\n\texercises: FormattedWorkoutExercise[] | undefined;\n}\n\n/**\n * Formatted routine set interface\n */\nexport interface FormattedRoutineSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\trepRange?: { start?: number | null; end?: number | null } | undefined | null;\n\trpe?: number | undefined | null;\n}\n\n/**\n * Formatted routine exercise interface\n */\nexport interface FormattedRoutineExercise {\n\tname: string | undefined;\n\tindex: number | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetId: number | undefined | null;\n\trestSeconds: string | undefined;\n\tsets: FormattedRoutineSet[] | undefined;\n}\n\n/**\n * Formatted routine interface\n */\nexport interface FormattedRoutine {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tfolderId: number | undefined | null;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\texercises: FormattedRoutineExercise[] | undefined;\n}\n\n/**\n * Formatted routine folder interface\n */\nexport interface FormattedRoutineFolder {\n\tid: number | undefined;\n\ttitle: string | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n}\n\n/**\n * Formatted exercise template interface\n */\nexport interface FormattedExerciseTemplate {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\ttype: string | undefined;\n\tprimaryMuscleGroup: string | undefined;\n\tsecondaryMuscleGroups: string[] | undefined;\n\tisCustom: boolean | undefined;\n}\n\nexport interface FormattedExerciseHistoryEntry {\n\tworkoutId: string | undefined;\n\tworkoutTitle: string | undefined;\n\tworkoutStartTime: string | undefined;\n\tworkoutEndTime: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\tsetType: string | undefined;\n}\n\n/**\n * Format a workout object for consistent presentation\n *\n * @param workout - The workout object from the API\n * @returns A formatted workout object with standardized properties\n */\nexport function formatWorkout(workout: Workout): FormattedWorkout {\n\treturn {\n\t\tid: workout.id,\n\t\ttitle: workout.title,\n\t\tdescription: workout.description,\n\t\tstartTime: workout.start_time,\n\t\tendTime: workout.end_time,\n\t\tcreatedAt: workout.created_at,\n\t\tupdatedAt: workout.updated_at,\n\t\tduration: calculateDuration(workout.start_time, workout.end_time),\n\t\texercises: workout.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tindex: exercise.index,\n\t\t\t\tname: exercise.title,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetsId: exercise.supersets_id,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\trpe: set.rpe,\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine object for consistent presentation\n *\n * @param routine - The routine object from the API\n * @returns A formatted routine object with standardized properties\n */\nexport function formatRoutine(routine: Routine): FormattedRoutine {\n\treturn {\n\t\tid: routine.id,\n\t\ttitle: routine.title,\n\t\tfolderId: routine.folder_id,\n\t\tcreatedAt: routine.created_at,\n\t\tupdatedAt: routine.updated_at,\n\t\texercises: routine.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tname: exercise.title,\n\t\t\t\tindex: exercise.index,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetId: exercise.supersets_id,\n\t\t\t\trestSeconds: exercise.rest_seconds,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\t...(set.rep_range !== undefined && { repRange: set.rep_range }),\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\t...(set.rpe !== undefined && { rpe: set.rpe }),\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine folder object for consistent presentation\n *\n * @param folder - The routine folder object from the API\n * @returns A formatted routine folder object with standardized properties\n */\nexport function formatRoutineFolder(\n\tfolder: RoutineFolder,\n): FormattedRoutineFolder {\n\treturn {\n\t\tid: folder.id,\n\t\ttitle: folder.title,\n\t\tcreatedAt: folder.created_at,\n\t\tupdatedAt: folder.updated_at,\n\t};\n}\n\n/**\n * Calculate duration between two ISO timestamp strings\n *\n * @param startTime - The start time as ISO string or timestamp\n * @param endTime - The end time as ISO string or timestamp\n * @returns A formatted duration string (e.g. \"1h 30m 45s\") or \"Unknown duration\" if inputs are invalid\n */\nexport function calculateDuration(\n\tstartTime: string | number | null | undefined,\n\tendTime: string | number | null | undefined,\n): string {\n\tif (!startTime || !endTime) return \"Unknown duration\";\n\n\ttry {\n\t\tconst start = new Date(startTime);\n\t\tconst end = new Date(endTime);\n\n\t\t// Validate dates\n\t\tif (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) {\n\t\t\treturn \"Unknown duration\";\n\t\t}\n\n\t\tconst durationMs = end.getTime() - start.getTime();\n\n\t\t// Handle negative durations\n\t\tif (durationMs < 0) {\n\t\t\treturn \"Invalid duration (end time before start time)\";\n\t\t}\n\n\t\tconst hours = Math.floor(durationMs / (1000 * 60 * 60));\n\t\tconst minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60));\n\t\tconst seconds = Math.floor((durationMs % (1000 * 60)) / 1000);\n\n\t\treturn `${hours}h ${minutes}m ${seconds}s`;\n\t} catch (error) {\n\t\tconsole.error(\"Error calculating duration:\", error);\n\t\treturn \"Unknown duration\";\n\t}\n}\n\n/**\n * Format an exercise template object for consistent presentation\n *\n * @param template - The exercise template object from the API\n * @returns A formatted exercise template object with standardized properties\n */\nexport function formatExerciseTemplate(\n\ttemplate: ExerciseTemplate,\n): FormattedExerciseTemplate {\n\treturn {\n\t\tid: template.id,\n\t\ttitle: template.title,\n\t\ttype: template.type,\n\t\tprimaryMuscleGroup: template.primary_muscle_group,\n\t\tsecondaryMuscleGroups: template.secondary_muscle_groups,\n\t\tisCustom: template.is_custom,\n\t};\n}\n\nexport function formatExerciseHistoryEntry(\n\tentry: ExerciseHistoryEntry,\n): FormattedExerciseHistoryEntry {\n\treturn {\n\t\tworkoutId: entry.workout_id,\n\t\tworkoutTitle: entry.workout_title,\n\t\tworkoutStartTime: entry.workout_start_time,\n\t\tworkoutEndTime: entry.workout_end_time,\n\t\texerciseTemplateId: entry.exercise_template_id,\n\t\tweight: entry.weight_kg,\n\t\treps: entry.reps,\n\t\tdistance: entry.distance_meters,\n\t\tduration: entry.duration_seconds,\n\t\trpe: entry.rpe,\n\t\tcustomMetric: entry.custom_metric,\n\t\tsetType: entry.set_type,\n\t};\n}\n","/**\n * MCP Tool Response type\n */\nexport interface McpToolResponse {\n\t[x: string]: unknown;\n\tcontent: Array<{\n\t\ttype: \"text\";\n\t\ttext: string;\n\t}>;\n}\n\n/**\n * Format options for JSON responses\n */\nexport interface JsonFormatOptions {\n\t/** Whether to pretty-print the JSON with indentation */\n\tpretty?: boolean;\n\t/** Indentation spaces for pretty-printing (default: 2) */\n\tindent?: number;\n}\n\n/**\n * Create a standardized success response with JSON data\n *\n * @param data - The data to include in the response\n * @param options - Formatting options\n * @returns A formatted MCP tool response with the data as JSON\n */\nexport function createJsonResponse(\n\tdata: unknown,\n\toptions: JsonFormatOptions = { pretty: true, indent: 2 },\n): McpToolResponse {\n\tconst jsonString = options.pretty\n\t\t? JSON.stringify(data, null, options.indent)\n\t\t: JSON.stringify(data);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: jsonString,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response with text data\n *\n * @param message - The text message to include in the response\n * @returns A formatted MCP tool response with the text message\n */\nexport function createTextResponse(message: string): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response for empty or null results\n *\n * @param message - Optional message to include (default: \"No data found\")\n * @returns A formatted MCP tool response for empty results\n */\nexport function createEmptyResponse(\n\tmessage = \"No data found\",\n): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1RoutineFolders200,\n\tGetV1RoutineFoldersFolderid200,\n\tPostV1RoutineFolders201,\n\tRoutineFolder,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutineFolder } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the folder operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n/**\n * Register all routine folder-related tools with the MCP server\n */\nexport function registerFolderTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routine folders\n\tconst getRoutineFoldersSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutineFoldersParams = InferToolParams<\n\t\ttypeof getRoutineFoldersSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-routine-folders\",\n\t\t\"Get a paginated list of your routine folders, including both default and custom folders. Useful for organizing and browsing your workout routines.\",\n\t\tgetRoutineFoldersSchema,\n\t\twithErrorHandling(async (args: GetRoutineFoldersParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1RoutineFolders200 = await hevyClient.getRoutineFolders({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routine folders to extract relevant information\n\t\t\tconst folders =\n\t\t\t\tdata?.routine_folders?.map((folder: RoutineFolder) =>\n\t\t\t\t\tformatRoutineFolder(folder),\n\t\t\t\t) || [];\n\n\t\t\tif (folders.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routine folders found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(folders);\n\t\t}, \"get-routine-folders\"),\n\t);\n\n\t// Get single routine folder by ID\n\tconst getRoutineFolderSchema = {\n\t\tfolderId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineFolderParams = InferToolParams<typeof getRoutineFolderSchema>;\n\n\tserver.tool(\n\t\t\"get-routine-folder\",\n\t\t\"Get complete details of a specific routine folder by its ID, including name, creation date, and associated routines.\",\n\t\tgetRoutineFolderSchema,\n\t\twithErrorHandling(async (args: GetRoutineFolderParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { folderId } = args;\n\t\t\tconst data: GetV1RoutineFoldersFolderid200 =\n\t\t\t\tawait hevyClient.getRoutineFolder(folderId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Routine folder with ID ${folderId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder);\n\t\t}, \"get-routine-folder\"),\n\t);\n\n\t// Create new routine folder\n\tconst createRoutineFolderSchema = {\n\t\tname: z.string().min(1),\n\t} as const;\n\ttype CreateRoutineFolderParams = InferToolParams<\n\t\ttypeof createRoutineFolderSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-routine-folder\",\n\t\t\"Create a new routine folder in your Hevy account. Requires a name for the folder. Returns the full folder details including the new folder ID.\",\n\t\tcreateRoutineFolderSchema,\n\t\twithErrorHandling(async (args: CreateRoutineFolderParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { name } = args;\n\t\t\tconst data: PostV1RoutineFolders201 =\n\t\t\t\tawait hevyClient.createRoutineFolder({\n\t\t\t\t\troutine_folder: {\n\t\t\t\t\t\ttitle: name,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine folder: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-routine-folder\"),\n\t);\n}\n","/**\n * Preprocessor to handle MCP clients that send JSON-stringified arrays\n * instead of native arrays for complex parameters.\n *\n * This is used with Zod's z.preprocess to handle cases where MCP clients\n * serialize complex nested structures as JSON strings.\n *\n * @param val - The value to potentially parse\n * @returns The parsed array if val is a valid JSON string, otherwise returns val unchanged\n */\nexport function parseJsonArray(val: unknown): unknown {\n\t// Handle case where MCP client sends JSON string instead of array\n\tif (typeof val === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(val);\n\t\t} catch {\n\t\t\t// Let Zod validation handle the error\n\t\t\treturn val;\n\t\t}\n\t}\n\treturn val;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1Routines200,\n\tGetV1RoutinesRoutineid200,\n\tPostRoutinesRequestExercise,\n\tPostRoutinesRequestSet,\n\tPostRoutinesRequestSetTypeEnumKey,\n\tPostV1Routines201,\n\tPutRoutinesRequestExercise,\n\tPutRoutinesRequestSet,\n\tPutRoutinesRequestSetTypeEnumKey,\n\tPutV1RoutinesRoutineid200,\n\tRoutine,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutine } from \"../utils/formatters.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the routine operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nfunction coerceNullishNumberInput(value: unknown): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\n\tif (typeof value !== \"string\") {\n\t\treturn value;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed === \"\") {\n\t\treturn undefined;\n\t}\n\n\tconst lowered = trimmed.toLowerCase();\n\tif (lowered === \"null\") {\n\t\treturn null;\n\t}\n\tif (lowered === \"undefined\") {\n\t\treturn undefined;\n\t}\n\n\tconst asNumber = Number(trimmed);\n\tif (Number.isNaN(asNumber)) {\n\t\treturn value;\n\t}\n\n\treturn asNumber;\n}\n\nconst zNullableInt = z.preprocess(\n\tcoerceNullishNumberInput,\n\tz.number().int().nullable().optional(),\n);\n\nconst zOptionalRepRange = z.preprocess(\n\t(value) => (value === null ? undefined : value),\n\tz\n\t\t.object({\n\t\t\tstart: zNullableInt,\n\t\t\tend: zNullableInt,\n\t\t})\n\t\t.optional(),\n);\n\nfunction buildRepRange(repRange?: {\n\tstart?: number | null;\n\tend?: number | null;\n}): { start?: number; end?: number } | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? undefined;\n\tconst end = repRange.end ?? undefined;\n\tif (start === undefined && end === undefined) {\n\t\treturn null;\n\t}\n\n\treturn { start, end };\n}\n\n/**\n * Returns a fixed rep count when `repRange` is a fixed range (start and end are\n * both non-null and equal). Otherwise returns null.\n */\nfunction getFixedRepsFromRepRange(\n\trepRange:\n\t\t| {\n\t\t\t\tstart?: number | null;\n\t\t\t\tend?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): number | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? null;\n\tconst end = repRange.end ?? null;\n\tif (start === null || end === null) {\n\t\treturn null;\n\t}\n\tif (start !== end) {\n\t\treturn null;\n\t}\n\n\treturn start;\n}\n\nconst repRangeDisplayWarningText =\n\t\"Note: Hevy's public API stores rep ranges (rep_range), but the Hevy apps may \" +\n\t\"not display them because they rely on an internal-only exercise field \" +\n\t\"(input_modifier). See https://github.com/chrisdoc/hevy-mcp/issues/261 for \" +\n\t\"details/workarounds.\";\n\n/**\n * Register all routine-related tools with the MCP server\n */\nexport function registerRoutineTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routines\n\tconst getRoutinesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutinesParams = InferToolParams<typeof getRoutinesSchema>;\n\n\tserver.tool(\n\t\t\"get-routines\",\n\t\t\"Get a paginated list of your workout routines, including custom and default routines. Useful for browsing or searching your available routines.\",\n\t\tgetRoutinesSchema,\n\t\twithErrorHandling(async (args: GetRoutinesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Routines200 = await hevyClient.getRoutines({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routines to extract relevant information\n\t\t\tconst routines =\n\t\t\t\tdata?.routines?.map((routine: Routine) => formatRoutine(routine)) || [];\n\n\t\t\tif (routines.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routines found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(routines);\n\t\t}, \"get-routines\"),\n\t);\n\n\t// Get single routine by ID (new, direct endpoint)\n\tconst getRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineParams = InferToolParams<typeof getRoutineSchema>;\n\n\tserver.tool(\n\t\t\"get-routine\",\n\t\t\"Get a routine by its ID using the direct endpoint. Returns all details for the specified routine.\",\n\t\tgetRoutineSchema,\n\t\twithErrorHandling(async (args: GetRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { routineId } = args;\n\t\t\tconst data: GetV1RoutinesRoutineid200 = await hevyClient.getRoutineById(\n\t\t\t\tString(routineId),\n\t\t\t);\n\t\t\tif (!data || !data.routine) {\n\t\t\t\treturn createEmptyResponse(`Routine with ID ${routineId} not found`);\n\t\t\t}\n\t\t\tconst routine = formatRoutine(data.routine);\n\t\t\treturn createJsonResponse(routine);\n\t\t}, \"get-routine\"),\n\t);\n\n\t// Create new routine\n\tconst createRoutineSchema = {\n\t\ttitle: z.string().min(1),\n\t\tfolderId: z.coerce.number().nullable().optional(),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateRoutineParams = InferToolParams<typeof createRoutineSchema>;\n\n\tserver.tool(\n\t\t\"create-routine\",\n\t\t\"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.\",\n\t\tcreateRoutineSchema,\n\t\twithErrorHandling(async (args: CreateRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { title, folderId, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PostV1Routines201 = await hevyClient.createRoutine({\n\t\t\t\troutine: {\n\t\t\t\t\ttitle,\n\t\t\t\t\tfolder_id: folderId ?? null,\n\t\t\t\t\tnotes: notes ?? \"\",\n\t\t\t\t\texercises: exercises.map((exercise): PostRoutinesRequestExercise => {\n\t\t\t\t\t\tconst sets = exercise.sets.map((set): PostRoutinesRequestSet => {\n\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\tconst reps = typeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttype: set.type as PostRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"create-routine\"),\n\t);\n\n\t// Update existing routine\n\tconst updateRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateRoutineParams = InferToolParams<typeof updateRoutineSchema>;\n\n\tserver.tool(\n\t\t\"update-routine\",\n\t\t\"Update an existing routine by ID. You can modify the title, notes, and exercise configurations. Returns the updated routine with all changes applied.\",\n\t\tupdateRoutineSchema,\n\t\twithErrorHandling(async (args: UpdateRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { routineId, title, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PutV1RoutinesRoutineid200 = await hevyClient.updateRoutine(\n\t\t\t\troutineId,\n\t\t\t\t{\n\t\t\t\t\troutine: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\tnotes: notes ?? null,\n\t\t\t\t\t\texercises: exercises.map((exercise): PutRoutinesRequestExercise => {\n\t\t\t\t\t\t\tconst sets = exercise.sets.map((set): PutRoutinesRequestSet => {\n\t\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\t\tconst reps =\n\t\t\t\t\t\t\t\t\ttypeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\ttype: set.type as PutRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update routine with ID ${routineId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"update-routine\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tExerciseTemplate,\n\tGetV1ExerciseHistoryExercisetemplateid200,\n\tGetV1ExerciseTemplates200,\n\tGetV1ExerciseTemplatesExercisetemplateid200,\n\tPostV1ExerciseTemplates200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tformatExerciseHistoryEntry,\n\tformatExerciseTemplate,\n} from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the template operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n// Shared muscle group values used by both create and search tools\nconst MUSCLE_GROUPS = [\n\t\"abdominals\",\n\t\"shoulders\",\n\t\"biceps\",\n\t\"triceps\",\n\t\"forearms\",\n\t\"quadriceps\",\n\t\"hamstrings\",\n\t\"calves\",\n\t\"glutes\",\n\t\"abductors\",\n\t\"adductors\",\n\t\"lats\",\n\t\"upper_back\",\n\t\"traps\",\n\t\"lower_back\",\n\t\"chest\",\n\t\"cardio\",\n\t\"neck\",\n\t\"full_body\",\n\t\"other\",\n] as const;\n\n// Module-level cache for all exercise templates\nlet exerciseTemplateCache: ExerciseTemplate[] | null = null;\n// In-flight promise to prevent concurrent duplicate fetches\nlet exerciseTemplateFetch: Promise<ExerciseTemplate[]> | null = null;\n\n/** Reset the exercise template cache (exposed for testing). */\nexport function resetExerciseTemplateCache(): void {\n\texerciseTemplateCache = null;\n\texerciseTemplateFetch = null;\n}\n\n/**\n * Register all exercise template-related tools with the MCP server\n */\nexport function registerTemplateTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get exercise templates\n\tconst getExerciseTemplatesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(100).default(5),\n\t} as const;\n\ttype GetExerciseTemplatesParams = InferToolParams<\n\t\ttypeof getExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-templates\",\n\t\t\"Get a paginated list of exercise templates (default and custom) with details like name, category, equipment, and muscle groups. Useful for browsing or searching available exercises.\",\n\t\tgetExerciseTemplatesSchema,\n\t\twithErrorHandling(async (args: GetExerciseTemplatesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\t\tpage,\n\t\t\t\t\tpageSize,\n\t\t\t\t});\n\n\t\t\t// Process exercise templates to extract relevant information\n\t\t\tconst templates =\n\t\t\t\tdata?.exercise_templates?.map((template: ExerciseTemplate) =>\n\t\t\t\t\tformatExerciseTemplate(template),\n\t\t\t\t) || [];\n\n\t\t\tif (templates.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No exercise templates found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(templates);\n\t\t}, \"get-exercise-templates\"),\n\t);\n\n\t// Get single exercise template by ID\n\tconst getExerciseTemplateSchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t} as const;\n\ttype GetExerciseTemplateParams = InferToolParams<\n\t\ttypeof getExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-template\",\n\t\t\"Get complete details of a specific exercise template by its ID, including name, category, equipment, muscle groups, and notes.\",\n\t\tgetExerciseTemplateSchema,\n\t\twithErrorHandling(async (args: GetExerciseTemplateParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { exerciseTemplateId } = args;\n\t\t\tconst data: GetV1ExerciseTemplatesExercisetemplateid200 =\n\t\t\t\tawait hevyClient.getExerciseTemplate(exerciseTemplateId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Exercise template with ID ${exerciseTemplateId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst template = formatExerciseTemplate(data);\n\t\t\treturn createJsonResponse(template);\n\t\t}, \"get-exercise-template\"),\n\t);\n\n\t// Get exercise history for a template\n\tconst getExerciseHistorySchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t\tstartDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 start date for filtering history\")\n\t\t\t.optional(),\n\t\tendDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 end date for filtering history\")\n\t\t\t.optional(),\n\t} as const;\n\ttype GetExerciseHistoryParams = InferToolParams<\n\t\ttypeof getExerciseHistorySchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-history\",\n\t\t\"Get past sets for a specific exercise template, optionally filtered by start and end dates.\",\n\t\tgetExerciseHistorySchema,\n\t\twithErrorHandling(async (args: GetExerciseHistoryParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { exerciseTemplateId, startDate, endDate } = args;\n\t\t\tconst data: GetV1ExerciseHistoryExercisetemplateid200 =\n\t\t\t\tawait hevyClient.getExerciseHistory(exerciseTemplateId, {\n\t\t\t\t\t...(startDate ? { start_date: startDate } : {}),\n\t\t\t\t\t...(endDate ? { end_date: endDate } : {}),\n\t\t\t\t});\n\n\t\t\tconst history =\n\t\t\t\tdata?.exercise_history?.map((entry) =>\n\t\t\t\t\tformatExerciseHistoryEntry(entry),\n\t\t\t\t) || [];\n\n\t\t\tif (history.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise history found for template ${exerciseTemplateId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(history);\n\t\t}, \"get-exercise-history\"),\n\t);\n\n\t// Create a custom exercise template\n\tconst createExerciseTemplateSchema = {\n\t\ttitle: z.string().min(1),\n\t\texerciseType: z.enum([\n\t\t\t\"weight_reps\",\n\t\t\t\"reps_only\",\n\t\t\t\"bodyweight_reps\",\n\t\t\t\"bodyweight_assisted_reps\",\n\t\t\t\"duration\",\n\t\t\t\"weight_duration\",\n\t\t\t\"distance_duration\",\n\t\t\t\"short_distance_weight\",\n\t\t]),\n\t\tequipmentCategory: z.enum([\n\t\t\t\"none\",\n\t\t\t\"barbell\",\n\t\t\t\"dumbbell\",\n\t\t\t\"kettlebell\",\n\t\t\t\"machine\",\n\t\t\t\"plate\",\n\t\t\t\"resistance_band\",\n\t\t\t\"suspension\",\n\t\t\t\"other\",\n\t\t]),\n\t\tmuscleGroup: z.enum(MUSCLE_GROUPS),\n\t\totherMuscles: z.array(z.enum(MUSCLE_GROUPS)).default([]),\n\t} as const;\n\ttype CreateExerciseTemplateParams = InferToolParams<\n\t\ttypeof createExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-exercise-template\",\n\t\t\"Create a custom exercise template with title, type, equipment, and muscle groups.\",\n\t\tcreateExerciseTemplateSchema,\n\t\twithErrorHandling(async (args: CreateExerciseTemplateParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst {\n\t\t\t\ttitle,\n\t\t\t\texerciseType,\n\t\t\t\tequipmentCategory,\n\t\t\t\tmuscleGroup,\n\t\t\t\totherMuscles,\n\t\t\t} = args;\n\n\t\t\tconst response: PostV1ExerciseTemplates200 =\n\t\t\t\tawait hevyClient.createExerciseTemplate({\n\t\t\t\t\texercise: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\texercise_type: exerciseType,\n\t\t\t\t\t\tequipment_category: equipmentCategory,\n\t\t\t\t\t\tmuscle_group: muscleGroup,\n\t\t\t\t\t\tother_muscles: otherMuscles,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\treturn createJsonResponse({\n\t\t\t\tid: response?.id,\n\t\t\t\tmessage: \"Exercise template created successfully\",\n\t\t\t});\n\t\t}, \"create-exercise-template\"),\n\t);\n\n\t// Search exercise templates (cached)\n\tconst searchExerciseTemplatesSchema = {\n\t\tquery: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.describe(\n\t\t\t\t\"Case-insensitive substring to match against exercise template titles\",\n\t\t\t),\n\t\tprimaryMuscleGroup: z\n\t\t\t.enum(MUSCLE_GROUPS)\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional filter to restrict results to a specific primary muscle group\",\n\t\t\t),\n\t\trefresh: z\n\t\t\t.boolean()\n\t\t\t.optional()\n\t\t\t.default(false)\n\t\t\t.describe(\n\t\t\t\t\"Set to true to bust the in-memory cache and re-fetch all templates from the API\",\n\t\t\t),\n\t} as const;\n\ttype SearchExerciseTemplatesParams = InferToolParams<\n\t\ttypeof searchExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"search-exercise-templates\",\n\t\t\"Search exercise templates by name with optional muscle group filter. Fetches all templates from the Hevy API on first call and caches them in memory for subsequent searches. Use refresh:true to force a re-fetch.\",\n\t\tsearchExerciseTemplatesSchema,\n\t\twithErrorHandling(async (args: SearchExerciseTemplatesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { query, primaryMuscleGroup, refresh } = args;\n\n\t\t\t// Populate cache if empty or refresh requested.\n\t\t\t// Use an in-flight promise to prevent concurrent duplicate fetches.\n\t\t\tif (exerciseTemplateCache === null || refresh) {\n\t\t\t\tif (refresh) exerciseTemplateFetch = null;\n\n\t\t\t\tif (exerciseTemplateFetch === null) {\n\t\t\t\t\texerciseTemplateFetch = (async () => {\n\t\t\t\t\t\tconst allTemplates: ExerciseTemplate[] = [];\n\t\t\t\t\t\tlet page = 1;\n\t\t\t\t\t\tlet pageCount = 1;\n\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\t\t\t\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\t\t\t\t\t\tpage,\n\t\t\t\t\t\t\t\t\tpageSize: 100,\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst templates = data?.exercise_templates ?? [];\n\t\t\t\t\t\t\tallTemplates.push(...templates);\n\t\t\t\t\t\t\tpageCount = data?.page_count ?? 1;\n\t\t\t\t\t\t\tpage++;\n\t\t\t\t\t\t} while (page <= pageCount);\n\n\t\t\t\t\t\texerciseTemplateCache = allTemplates;\n\t\t\t\t\t\texerciseTemplateFetch = null;\n\t\t\t\t\t\treturn allTemplates;\n\t\t\t\t\t})();\n\t\t\t\t}\n\n\t\t\t\tawait exerciseTemplateFetch;\n\t\t\t}\n\n\t\t\t// Filter by query (case-insensitive title substring match)\n\t\t\tconst queryLower = query.toLowerCase();\n\t\t\tif (exerciseTemplateCache === null) {\n\t\t\t\tthrow new Error(\"Failed to populate exercise template cache.\");\n\t\t\t}\n\t\t\tlet results = exerciseTemplateCache.filter((t) =>\n\t\t\t\t(t.title ?? \"\").toLowerCase().includes(queryLower),\n\t\t\t);\n\n\t\t\t// Optional primary muscle group filter\n\t\t\tif (primaryMuscleGroup !== undefined) {\n\t\t\t\tresults = results.filter(\n\t\t\t\t\t(t) => t.primary_muscle_group === primaryMuscleGroup,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise templates found matching \"${query}\"${primaryMuscleGroup ? ` with primary muscle group \"${primaryMuscleGroup}\"` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(results.map(formatExerciseTemplate));\n\t\t}, \"search-exercise-templates\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n> & {\n\tgetWebhookSubscription?: () => Promise<unknown>;\n\tcreateWebhookSubscription?: (data: {\n\t\twebhook: {\n\t\t\turl: string;\n\t\t\tauthToken: string | null;\n\t\t};\n\t}) => Promise<unknown>;\n\tdeleteWebhookSubscription?: () => Promise<unknown>;\n};\n\n// Enhanced webhook URL validation\nconst webhookUrlSchema = z\n\t.string()\n\t.url()\n\t.refine(\n\t\t(url) => {\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(url);\n\t\t\t\treturn parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tmessage: \"Webhook URL must be a valid HTTP or HTTPS URL\",\n\t\t},\n\t)\n\t.refine(\n\t\t(url) => {\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(url);\n\t\t\t\treturn (\n\t\t\t\t\tparsed.hostname !== \"localhost\" && !parsed.hostname.startsWith(\"127.\")\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tmessage: \"Webhook URL cannot be localhost or loopback address\",\n\t\t},\n\t);\n\nexport function registerWebhookTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get webhook subscription\n\tconst getWebhookSubscriptionSchema = {} as const;\n\ttype GetWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof getWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-webhook-subscription\",\n\t\t\"Get the current webhook subscription for this account. Returns the webhook URL and auth token if a subscription exists.\",\n\t\tgetWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (_args: GetWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!hevyClient.getWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.getWebhookSubscription();\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No webhook subscription found for this account\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"get-webhook-subscription\"),\n\t);\n\n\t// Create webhook subscription\n\tconst createWebhookSubscriptionSchema = {\n\t\turl: webhookUrlSchema.describe(\n\t\t\t\"The webhook URL that will receive POST requests when workouts are created\",\n\t\t),\n\t\tauthToken: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional auth token that will be sent as Authorization header in webhook requests\",\n\t\t\t),\n\t} as const;\n\ttype CreateWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof createWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-webhook-subscription\",\n\t\t\"Create a new webhook subscription for this account. The webhook will receive POST requests when workouts are created. Your endpoint must respond with 200 OK within 5 seconds.\",\n\t\tcreateWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (args: CreateWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { url, authToken } = args;\n\t\t\tif (!hevyClient.createWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.createWebhookSubscription({\n\t\t\t\twebhook: {\n\t\t\t\t\turl,\n\t\t\t\t\tauthToken: authToken || null,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create webhook subscription - please check your URL and try again\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"create-webhook-subscription\"),\n\t);\n\n\t// Delete webhook subscription\n\tconst deleteWebhookSubscriptionSchema = {} as const;\n\ttype DeleteWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof deleteWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"delete-webhook-subscription\",\n\t\t\"Delete the current webhook subscription for this account. This will stop all webhook notifications.\",\n\t\tdeleteWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (_args: DeleteWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!hevyClient.deleteWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.deleteWebhookSubscription();\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to delete webhook subscription - no subscription may exist or there was a server error\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"delete-webhook-subscription\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tGetV1Workouts200,\n\tGetV1WorkoutsCount200,\n\tGetV1WorkoutsEvents200,\n\tGetV1WorkoutsWorkoutid200,\n\tPostV1Workouts201,\n\tPostWorkoutsRequestBody,\n\tPostWorkoutsRequestExercise,\n\tPostWorkoutsRequestSetRpeEnumKey,\n\tPostWorkoutsRequestSetTypeEnumKey,\n\tPutV1WorkoutsWorkoutid200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatWorkout } from \"../utils/formatters.js\";\nimport type { HevyClient } from \"../utils/hevyClient.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n/**\n * Register all workout-related tools with the MCP server\n */\nexport function registerWorkoutTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get workouts\n\tconst getWorkoutsSchema = {\n\t\tpage: z.coerce.number().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetWorkoutsParams = InferToolParams<typeof getWorkoutsSchema>;\n\n\tserver.tool(\n\t\t\"get-workouts\",\n\t\t\"Get a paginated list of workouts. Returns workout details including title, description, start/end times, and exercises performed. Results are ordered from newest to oldest.\",\n\t\tgetWorkoutsSchema,\n\t\twithErrorHandling(async (args: GetWorkoutsParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Workouts200 = await hevyClient.getWorkouts({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst workouts =\n\t\t\t\tdata?.workouts?.map((workout) => formatWorkout(workout)) || [];\n\n\t\t\tif (workouts.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No workouts found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(workouts);\n\t\t}, \"get-workouts\"),\n\t);\n\n\t// Get single workout by ID\n\tconst getWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t} as const;\n\ttype GetWorkoutParams = InferToolParams<typeof getWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"get-workout\",\n\t\t\"Get complete details of a specific workout by ID. Returns all workout information including title, description, start/end times, and detailed exercise data.\",\n\t\tgetWorkoutSchema,\n\t\twithErrorHandling(async (args: GetWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { workoutId } = args;\n\t\t\tconst data: GetV1WorkoutsWorkoutid200 =\n\t\t\t\tawait hevyClient.getWorkout(workoutId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(`Workout with ID ${workoutId} not found`);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout);\n\t\t}, \"get-workout\"),\n\t);\n\n\t// Get workout count\n\tserver.tool(\n\t\t\"get-workout-count\",\n\t\t\"Get the total number of workouts on the account. Useful for pagination or statistics.\",\n\t\t{},\n\t\twithErrorHandling(async () => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data: GetV1WorkoutsCount200 = await hevyClient.getWorkoutCount();\n\t\t\tconst count = data?.workout_count ?? 0;\n\t\t\treturn createJsonResponse({ count });\n\t\t}, \"get-workout-count\"),\n\t);\n\n\t// Get workout events (updates/deletes)\n\tconst getWorkoutEventsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t\tsince: z.string().default(\"1970-01-01T00:00:00Z\"),\n\t} as const;\n\ttype GetWorkoutEventsParams = InferToolParams<typeof getWorkoutEventsSchema>;\n\n\tserver.tool(\n\t\t\"get-workout-events\",\n\t\t\"Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\",\n\t\tgetWorkoutEventsSchema,\n\t\twithErrorHandling(async (args: GetWorkoutEventsParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize, since } = args;\n\t\t\tconst data: GetV1WorkoutsEvents200 = await hevyClient.getWorkoutEvents({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t\tsince,\n\t\t\t});\n\n\t\t\tconst events = data?.events || [];\n\n\t\t\tif (events.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No workout events found for the specified parameters since ${since}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(events);\n\t\t}, \"get-workout-events\"),\n\t);\n\n\t// Create workout\n\tconst createWorkoutSchema = {\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateWorkoutParams = InferToolParams<typeof createWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"create-workout\",\n\t\t\"Create a new workout in your Hevy account. Requires title, start/end times, and at least one exercise with sets. Returns the complete workout details upon successful creation including the newly assigned workout ID.\",\n\t\tcreateWorkoutSchema,\n\t\twithErrorHandling(async (args: CreateWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { title, description, startTime, endTime, isPrivate, exercises } =\n\t\t\t\targs;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PostV1Workouts201 =\n\t\t\t\tawait hevyClient.createWorkout(requestBody);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create workout: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-workout\"),\n\t);\n\n\t// Update workout\n\tconst updateWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateWorkoutParams = InferToolParams<typeof updateWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"update-workout\",\n\t\t\"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.\",\n\t\tupdateWorkoutSchema,\n\t\twithErrorHandling(async (args: UpdateWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tworkoutId,\n\t\t\t\ttitle,\n\t\t\t\tdescription,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisPrivate,\n\t\t\t\texercises,\n\t\t\t} = args;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PutV1WorkoutsWorkoutid200 = await hevyClient.updateWorkout(\n\t\t\t\tworkoutId,\n\t\t\t\trequestBody,\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update workout with ID ${workoutId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"update-workout-operation\"),\n\t);\n}\n","export interface HevyConfig {\n\tapiKey?: string;\n}\n\n/**\n * Parse CLI arguments and environment to derive configuration.\n * Priority order for API key: CLI flag forms > environment variable.\n * Supported CLI arg forms:\n * --hevy-api-key=KEY\n * --hevyApiKey=KEY\n * hevy-api-key=KEY (bare, e.g. when passed after npm start -- )\n */\nexport function parseConfig(\n\targv: string[],\n\tenv: NodeJS.ProcessEnv,\n): HevyConfig {\n\tlet apiKey = \"\";\n\tconst apiKeyArgPatterns = [\n\t\t/^--hevy-api-key=(.+)$/i,\n\t\t/^--hevyApiKey=(.+)$/i,\n\t\t/^hevy-api-key=(.+)$/i,\n\t];\n\tfor (const raw of argv) {\n\t\tfor (const pattern of apiKeyArgPatterns) {\n\t\t\tconst m = raw.match(pattern);\n\t\t\tif (m) {\n\t\t\t\tapiKey = m[1];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (apiKey) break;\n\t}\n\tif (!apiKey) {\n\t\tapiKey = env.HEVY_API_KEY || \"\";\n\t}\n\n\treturn {\n\t\tapiKey,\n\t};\n}\n\nexport function assertApiKey(\n\tapiKey: string | undefined,\n): asserts apiKey is string {\n\tif (!apiKey) {\n\t\tconsole.error(\n\t\t\t\"Hevy API key is required. Provide it via the HEVY_API_KEY environment variable or the --hevy-api-key=YOUR_KEY command argument.\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1ExerciseHistoryExercisetemplateidQueryResponse, GetV1ExerciseHistoryExercisetemplateidPathParams, GetV1ExerciseHistoryExercisetemplateidQueryParams, GetV1ExerciseHistoryExercisetemplateidHeaderParams, GetV1ExerciseHistoryExercisetemplateid400 } from \"../types/GetV1ExerciseHistoryExercisetemplateid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseHistoryExercisetemplateidUrl(exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"]) {\n const res = { method: 'GET', url: `/v1/exercise_history/${exerciseTemplateId}` as const }\n return res\n}\n\n/**\n * @summary Get exercise history for a specific exercise template\n * {@link /v1/exercise_history/:exerciseTemplateId}\n */\nexport async function getV1ExerciseHistoryExercisetemplateid(exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"], headers: GetV1ExerciseHistoryExercisetemplateidHeaderParams, params?: GetV1ExerciseHistoryExercisetemplateidQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1ExerciseHistoryExercisetemplateidQueryResponse, ResponseErrorConfig<GetV1ExerciseHistoryExercisetemplateid400>, unknown>({ method : \"GET\", url : getGetV1ExerciseHistoryExercisetemplateidUrl(exerciseTemplateId).url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1ExerciseTemplatesQueryResponse, GetV1ExerciseTemplatesQueryParams, GetV1ExerciseTemplatesHeaderParams, GetV1ExerciseTemplates400 } from \"../types/GetV1ExerciseTemplates.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseTemplatesUrl() {\n const res = { method: 'GET', url: `/v1/exercise_templates` as const }\n return res\n}\n\n/**\n * @summary Get a paginated list of exercise templates available on the account.\n * {@link /v1/exercise_templates}\n */\nexport async function getV1ExerciseTemplates(headers: GetV1ExerciseTemplatesHeaderParams, params?: GetV1ExerciseTemplatesQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1ExerciseTemplatesQueryResponse, ResponseErrorConfig<GetV1ExerciseTemplates400>, unknown>({ method : \"GET\", url : getGetV1ExerciseTemplatesUrl().url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1ExerciseTemplatesExercisetemplateidQueryResponse, GetV1ExerciseTemplatesExercisetemplateidPathParams, GetV1ExerciseTemplatesExercisetemplateidHeaderParams, GetV1ExerciseTemplatesExercisetemplateid404 } from \"../types/GetV1ExerciseTemplatesExercisetemplateid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseTemplatesExercisetemplateidUrl(exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"]) {\n const res = { method: 'GET', url: `/v1/exercise_templates/${exerciseTemplateId}` as const }\n return res\n}\n\n/**\n * @summary Get a single exercise template by id.\n * {@link /v1/exercise_templates/:exerciseTemplateId}\n */\nexport async function getV1ExerciseTemplatesExercisetemplateid(exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"], headers: GetV1ExerciseTemplatesExercisetemplateidHeaderParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1ExerciseTemplatesExercisetemplateidQueryResponse, ResponseErrorConfig<GetV1ExerciseTemplatesExercisetemplateid404>, unknown>({ method : \"GET\", url : getGetV1ExerciseTemplatesExercisetemplateidUrl(exerciseTemplateId).url.toString(), ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1RoutineFoldersQueryResponse, GetV1RoutineFoldersQueryParams, GetV1RoutineFoldersHeaderParams, GetV1RoutineFolders400 } from \"../types/GetV1RoutineFolders.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutineFoldersUrl() {\n const res = { method: 'GET', url: `/v1/routine_folders` as const }\n return res\n}\n\n/**\n * @summary Get a paginated list of routine folders available on the account.\n * {@link /v1/routine_folders}\n */\nexport async function getV1RoutineFolders(headers: GetV1RoutineFoldersHeaderParams, params?: GetV1RoutineFoldersQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1RoutineFoldersQueryResponse, ResponseErrorConfig<GetV1RoutineFolders400>, unknown>({ method : \"GET\", url : getGetV1RoutineFoldersUrl().url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1RoutineFoldersFolderidQueryResponse, GetV1RoutineFoldersFolderidPathParams, GetV1RoutineFoldersFolderidHeaderParams, GetV1RoutineFoldersFolderid404 } from \"../types/GetV1RoutineFoldersFolderid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutineFoldersFolderidUrl(folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"]) {\n const res = { method: 'GET', url: `/v1/routine_folders/${folderId}` as const }\n return res\n}\n\n/**\n * @summary Get a single routine folder by id.\n * {@link /v1/routine_folders/:folderId}\n */\nexport async function getV1RoutineFoldersFolderid(folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"], headers: GetV1RoutineFoldersFolderidHeaderParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1RoutineFoldersFolderidQueryResponse, ResponseErrorConfig<GetV1RoutineFoldersFolderid404>, unknown>({ method : \"GET\", url : getGetV1RoutineFoldersFolderidUrl(folderId).url.toString(), ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1RoutinesQueryResponse, GetV1RoutinesQueryParams, GetV1RoutinesHeaderParams, GetV1Routines400 } from \"../types/GetV1Routines.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutinesUrl() {\n const res = { method: 'GET', url: `/v1/routines` as const }\n return res\n}\n\n/**\n * @summary Get a paginated list of routines\n * {@link /v1/routines}\n */\nexport async function getV1Routines(headers: GetV1RoutinesHeaderParams, params?: GetV1RoutinesQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1RoutinesQueryResponse, ResponseErrorConfig<GetV1Routines400>, unknown>({ method : \"GET\", url : getGetV1RoutinesUrl().url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1RoutinesRoutineidQueryResponse, GetV1RoutinesRoutineidPathParams, GetV1RoutinesRoutineidHeaderParams, GetV1RoutinesRoutineid400 } from \"../types/GetV1RoutinesRoutineid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutinesRoutineidUrl(routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"]) {\n const res = { method: 'GET', url: `/v1/routines/${routineId}` as const }\n return res\n}\n\n/**\n * @summary Get a routine by its Id\n * {@link /v1/routines/:routineId}\n */\nexport async function getV1RoutinesRoutineid(routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"], headers: GetV1RoutinesRoutineidHeaderParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1RoutinesRoutineidQueryResponse, ResponseErrorConfig<GetV1RoutinesRoutineid400>, unknown>({ method : \"GET\", url : getGetV1RoutinesRoutineidUrl(routineId).url.toString(), ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1WorkoutsQueryResponse, GetV1WorkoutsQueryParams, GetV1WorkoutsHeaderParams, GetV1Workouts400 } from \"../types/GetV1Workouts.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsUrl() {\n const res = { method: 'GET', url: `/v1/workouts` as const }\n return res\n}\n\n/**\n * @summary Get a paginated list of workouts\n * {@link /v1/workouts}\n */\nexport async function getV1Workouts(headers: GetV1WorkoutsHeaderParams, params?: GetV1WorkoutsQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1WorkoutsQueryResponse, ResponseErrorConfig<GetV1Workouts400>, unknown>({ method : \"GET\", url : getGetV1WorkoutsUrl().url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1WorkoutsCountQueryResponse, GetV1WorkoutsCountHeaderParams } from \"../types/GetV1WorkoutsCount.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsCountUrl() {\n const res = { method: 'GET', url: `/v1/workouts/count` as const }\n return res\n}\n\n/**\n * @summary Get the total number of workouts on the account\n * {@link /v1/workouts/count}\n */\nexport async function getV1WorkoutsCount(headers: GetV1WorkoutsCountHeaderParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1WorkoutsCountQueryResponse, ResponseErrorConfig<Error>, unknown>({ method : \"GET\", url : getGetV1WorkoutsCountUrl().url.toString(), ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1WorkoutsEventsQueryResponse, GetV1WorkoutsEventsQueryParams, GetV1WorkoutsEventsHeaderParams, GetV1WorkoutsEvents500 } from \"../types/GetV1WorkoutsEvents.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsEventsUrl() {\n const res = { method: 'GET', url: `/v1/workouts/events` as const }\n return res\n}\n\n/**\n * @description Returns a paginated array of workout events, indicating updates or deletions.\n * @summary Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\n * {@link /v1/workouts/events}\n */\nexport async function getV1WorkoutsEvents(headers: GetV1WorkoutsEventsHeaderParams, params?: GetV1WorkoutsEventsQueryParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1WorkoutsEventsQueryResponse, ResponseErrorConfig<GetV1WorkoutsEvents500>, unknown>({ method : \"GET\", url : getGetV1WorkoutsEventsUrl().url.toString(), params, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { GetV1WorkoutsWorkoutidQueryResponse, GetV1WorkoutsWorkoutidPathParams, GetV1WorkoutsWorkoutidHeaderParams, GetV1WorkoutsWorkoutid404 } from \"../types/GetV1WorkoutsWorkoutid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsWorkoutidUrl(workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"]) {\n const res = { method: 'GET', url: `/v1/workouts/${workoutId}` as const }\n return res\n}\n\n/**\n * @summary Get a single workout’s complete details by the workoutId\n * {@link /v1/workouts/:workoutId}\n */\nexport async function getV1WorkoutsWorkoutid(workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"], headers: GetV1WorkoutsWorkoutidHeaderParams, config: Partial<RequestConfig> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n\n\n const res = await request<GetV1WorkoutsWorkoutidQueryResponse, ResponseErrorConfig<GetV1WorkoutsWorkoutid404>, unknown>({ method : \"GET\", url : getGetV1WorkoutsWorkoutidUrl(workoutId).url.toString(), ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PostV1ExerciseTemplatesMutationRequest, PostV1ExerciseTemplatesMutationResponse, PostV1ExerciseTemplatesHeaderParams, PostV1ExerciseTemplates400, PostV1ExerciseTemplates403 } from \"../types/PostV1ExerciseTemplates.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1ExerciseTemplatesUrl() {\n const res = { method: 'POST', url: `/v1/exercise_templates` as const }\n return res\n}\n\n/**\n * @summary Create a new custom exercise template.\n * {@link /v1/exercise_templates}\n */\nexport async function postV1ExerciseTemplates(data: PostV1ExerciseTemplatesMutationRequest, headers: PostV1ExerciseTemplatesHeaderParams, config: Partial<RequestConfig<PostV1ExerciseTemplatesMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PostV1ExerciseTemplatesMutationResponse, ResponseErrorConfig<PostV1ExerciseTemplates400 | PostV1ExerciseTemplates403>, PostV1ExerciseTemplatesMutationRequest>({ method : \"POST\", url : getPostV1ExerciseTemplatesUrl().url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PostV1RoutineFoldersMutationRequest, PostV1RoutineFoldersMutationResponse, PostV1RoutineFoldersHeaderParams, PostV1RoutineFolders400 } from \"../types/PostV1RoutineFolders.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1RoutineFoldersUrl() {\n const res = { method: 'POST', url: `/v1/routine_folders` as const }\n return res\n}\n\n/**\n * @summary Create a new routine folder. The folder will be created at index 0, and all other folders will have their indexes incremented.\n * {@link /v1/routine_folders}\n */\nexport async function postV1RoutineFolders(data: PostV1RoutineFoldersMutationRequest, headers: PostV1RoutineFoldersHeaderParams, config: Partial<RequestConfig<PostV1RoutineFoldersMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PostV1RoutineFoldersMutationResponse, ResponseErrorConfig<PostV1RoutineFolders400>, PostV1RoutineFoldersMutationRequest>({ method : \"POST\", url : getPostV1RoutineFoldersUrl().url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PostV1RoutinesMutationRequest, PostV1RoutinesMutationResponse, PostV1RoutinesHeaderParams, PostV1Routines400, PostV1Routines403 } from \"../types/PostV1Routines.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1RoutinesUrl() {\n const res = { method: 'POST', url: `/v1/routines` as const }\n return res\n}\n\n/**\n * @summary Create a new routine\n * {@link /v1/routines}\n */\nexport async function postV1Routines(data: PostV1RoutinesMutationRequest, headers: PostV1RoutinesHeaderParams, config: Partial<RequestConfig<PostV1RoutinesMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PostV1RoutinesMutationResponse, ResponseErrorConfig<PostV1Routines400 | PostV1Routines403>, PostV1RoutinesMutationRequest>({ method : \"POST\", url : getPostV1RoutinesUrl().url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PostV1WorkoutsMutationRequest, PostV1WorkoutsMutationResponse, PostV1WorkoutsHeaderParams, PostV1Workouts400 } from \"../types/PostV1Workouts.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1WorkoutsUrl() {\n const res = { method: 'POST', url: `/v1/workouts` as const }\n return res\n}\n\n/**\n * @summary Create a new workout\n * {@link /v1/workouts}\n */\nexport async function postV1Workouts(data: PostV1WorkoutsMutationRequest, headers: PostV1WorkoutsHeaderParams, config: Partial<RequestConfig<PostV1WorkoutsMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PostV1WorkoutsMutationResponse, ResponseErrorConfig<PostV1Workouts400>, PostV1WorkoutsMutationRequest>({ method : \"POST\", url : getPostV1WorkoutsUrl().url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PutV1RoutinesRoutineidMutationRequest, PutV1RoutinesRoutineidMutationResponse, PutV1RoutinesRoutineidPathParams, PutV1RoutinesRoutineidHeaderParams, PutV1RoutinesRoutineid400, PutV1RoutinesRoutineid404 } from \"../types/PutV1RoutinesRoutineid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPutV1RoutinesRoutineidUrl(routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"]) {\n const res = { method: 'PUT', url: `/v1/routines/${routineId}` as const }\n return res\n}\n\n/**\n * @summary Update an existing routine\n * {@link /v1/routines/:routineId}\n */\nexport async function putV1RoutinesRoutineid(routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"], data: PutV1RoutinesRoutineidMutationRequest, headers: PutV1RoutinesRoutineidHeaderParams, config: Partial<RequestConfig<PutV1RoutinesRoutineidMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PutV1RoutinesRoutineidMutationResponse, ResponseErrorConfig<PutV1RoutinesRoutineid400 | PutV1RoutinesRoutineid404>, PutV1RoutinesRoutineidMutationRequest>({ method : \"PUT\", url : getPutV1RoutinesRoutineidUrl(routineId).url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type { PutV1WorkoutsWorkoutidMutationRequest, PutV1WorkoutsWorkoutidMutationResponse, PutV1WorkoutsWorkoutidPathParams, PutV1WorkoutsWorkoutidHeaderParams, PutV1WorkoutsWorkoutid400 } from \"../types/PutV1WorkoutsWorkoutid.ts\";\nimport type { Client, RequestConfig, ResponseErrorConfig } from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPutV1WorkoutsWorkoutidUrl(workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"]) {\n const res = { method: 'PUT', url: `/v1/workouts/${workoutId}` as const }\n return res\n}\n\n/**\n * @summary Update an existing workout\n * {@link /v1/workouts/:workoutId}\n */\nexport async function putV1WorkoutsWorkoutid(workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"], data: PutV1WorkoutsWorkoutidMutationRequest, headers: PutV1WorkoutsWorkoutidHeaderParams, config: Partial<RequestConfig<PutV1WorkoutsWorkoutidMutationRequest>> & { client?: Client } = {}) {\n const { client: request = fetch, ...requestConfig } = config\n\n const requestData = data\n\n const res = await request<PutV1WorkoutsWorkoutidMutationResponse, ResponseErrorConfig<PutV1WorkoutsWorkoutid400>, PutV1WorkoutsWorkoutidMutationRequest>({ method : \"PUT\", url : getPutV1WorkoutsWorkoutidUrl(workoutId).url.toString(), data : requestData, ... requestConfig, headers : { ...headers, ...requestConfig.headers } })\n return res.data\n}","import type {\n\tRequestConfig,\n\tResponseConfig,\n} from \"@kubb/plugin-client/clients/axios\";\nimport axios from \"axios\";\nimport * as api from \"../generated/client/api\";\nimport type {\n\tGetV1ExerciseHistoryExercisetemplateidQueryParams,\n\tGetV1ExerciseTemplatesQueryParams,\n\tGetV1RoutineFoldersQueryParams,\n\tGetV1RoutinesQueryParams,\n\tGetV1WorkoutsEventsQueryParams,\n\tGetV1WorkoutsQueryParams,\n\tPostV1ExerciseTemplatesMutationRequest,\n\tPostV1RoutineFoldersMutationRequest,\n\tPostV1RoutinesMutationRequest,\n\tPostV1WorkoutsMutationRequest,\n\tPutV1RoutinesRoutineidMutationRequest,\n\tPutV1WorkoutsWorkoutidMutationRequest,\n} from \"../generated/client/types\";\n\n// Define a proper client type that matches the Kubb client interface\ntype KubbClient = {\n\t<TData, _TError = unknown, TVariables = unknown>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>>;\n\tgetConfig: () => Partial<RequestConfig<unknown>>;\n\tsetConfig: (config: RequestConfig) => Partial<RequestConfig<unknown>>;\n};\n\n/**\n * Type-safe wrapper helper that enforces parameter types match the generated API.\n * This prevents arg-order regressions by using Parameters<> to extract expected types.\n *\n * Usage: wrapApi(api.postV1ExerciseTemplates)(data, headers, { client })\n * TypeScript will error if arguments don't match the generated signature.\n */\nfunction wrapApi<T extends (...args: Parameters<T>) => ReturnType<T>>(\n\tfn: T,\n): (...args: Parameters<T>) => ReturnType<T> {\n\treturn fn;\n}\n\ntype CreateWebhookSubscriptionRequest = {\n\twebhook: {\n\t\turl: string;\n\t\tauthToken: string | null;\n\t};\n};\n\nexport function createClient(\n\tapiKey: string,\n\tbaseUrl = \"https://api.hevyapp.com\",\n) {\n\t// Create an axios instance with the API key\n\tconst axiosInstance = axios.create({\n\t\tbaseURL: baseUrl,\n\t\theaders: {\n\t\t\t\"api-key\": apiKey,\n\t\t},\n\t});\n\n\t// Create headers object with API key\n\tconst headers = {\n\t\t\"api-key\": apiKey,\n\t};\n\n\t// Cast axios instance to the expected client type\n\tconst client = axiosInstance as unknown as KubbClient;\n\n\t// Return an object with all the API methods using ReturnType for automatic type inference\n\t// All API calls use wrapApi to ensure TypeScript validates arg order matches generated API\n\treturn {\n\t\t// Workouts\n\t\tgetWorkouts: (\n\t\t\tparams?: GetV1WorkoutsQueryParams,\n\t\t): ReturnType<typeof api.getV1Workouts> =>\n\t\t\twrapApi(api.getV1Workouts)(headers, params, { client }),\n\t\tgetWorkout: (\n\t\t\tworkoutId: string,\n\t\t): ReturnType<typeof api.getV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.getV1WorkoutsWorkoutid)(workoutId, headers, { client }),\n\t\tcreateWorkout: (\n\t\t\tdata: PostV1WorkoutsMutationRequest,\n\t\t): ReturnType<typeof api.postV1Workouts> =>\n\t\t\twrapApi(api.postV1Workouts)(data, headers, { client }),\n\t\tupdateWorkout: (\n\t\t\tworkoutId: string,\n\t\t\tdata: PutV1WorkoutsWorkoutidMutationRequest,\n\t\t): ReturnType<typeof api.putV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.putV1WorkoutsWorkoutid)(workoutId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\t\tgetWorkoutCount: (): ReturnType<typeof api.getV1WorkoutsCount> =>\n\t\t\twrapApi(api.getV1WorkoutsCount)(headers, { client }),\n\t\tgetWorkoutEvents: (\n\t\t\tparams?: GetV1WorkoutsEventsQueryParams,\n\t\t): ReturnType<typeof api.getV1WorkoutsEvents> =>\n\t\t\twrapApi(api.getV1WorkoutsEvents)(headers, params, { client }),\n\n\t\t// Routines\n\t\tgetRoutines: (\n\t\t\tparams?: GetV1RoutinesQueryParams,\n\t\t): ReturnType<typeof api.getV1Routines> =>\n\t\t\twrapApi(api.getV1Routines)(headers, params, { client }),\n\t\tgetRoutineById: (\n\t\t\troutineId: string,\n\t\t): ReturnType<typeof api.getV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.getV1RoutinesRoutineid)(routineId, headers, { client }),\n\t\tcreateRoutine: (\n\t\t\tdata: PostV1RoutinesMutationRequest,\n\t\t): ReturnType<typeof api.postV1Routines> =>\n\t\t\twrapApi(api.postV1Routines)(data, headers, { client }),\n\t\tupdateRoutine: (\n\t\t\troutineId: string,\n\t\t\tdata: PutV1RoutinesRoutineidMutationRequest,\n\t\t): ReturnType<typeof api.putV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.putV1RoutinesRoutineid)(routineId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Exercise Templates\n\t\tgetExerciseTemplates: (\n\t\t\tparams?: GetV1ExerciseTemplatesQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplates> =>\n\t\t\twrapApi(api.getV1ExerciseTemplates)(headers, params, { client }),\n\t\tgetExerciseTemplate: (\n\t\t\ttemplateId: string,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplatesExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseTemplatesExercisetemplateid)(\n\t\t\t\ttemplateId,\n\t\t\t\theaders,\n\t\t\t\t{\n\t\t\t\t\tclient,\n\t\t\t\t},\n\t\t\t),\n\t\tgetExerciseHistory: (\n\t\t\texerciseTemplateId: string,\n\t\t\tparams?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseHistoryExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseHistoryExercisetemplateid)(\n\t\t\t\texerciseTemplateId,\n\t\t\t\theaders,\n\t\t\t\tparams,\n\t\t\t\t{ client },\n\t\t\t),\n\t\tcreateExerciseTemplate: (\n\t\t\tdata: PostV1ExerciseTemplatesMutationRequest,\n\t\t): ReturnType<typeof api.postV1ExerciseTemplates> =>\n\t\t\twrapApi(api.postV1ExerciseTemplates)(data, headers, { client }),\n\n\t\t// Routine Folders\n\t\tgetRoutineFolders: (\n\t\t\tparams?: GetV1RoutineFoldersQueryParams,\n\t\t): ReturnType<typeof api.getV1RoutineFolders> =>\n\t\t\twrapApi(api.getV1RoutineFolders)(headers, params, { client }),\n\t\tcreateRoutineFolder: (\n\t\t\tdata: PostV1RoutineFoldersMutationRequest,\n\t\t): ReturnType<typeof api.postV1RoutineFolders> =>\n\t\t\twrapApi(api.postV1RoutineFolders)(data, headers, { client }),\n\t\tgetRoutineFolder: (\n\t\t\tfolderId: string,\n\t\t): ReturnType<typeof api.getV1RoutineFoldersFolderid> =>\n\t\t\twrapApi(api.getV1RoutineFoldersFolderid)(folderId, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\tgetWebhookSubscription: async (): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t\tcreateWebhookSubscription: async (\n\t\t\t_data: CreateWebhookSubscriptionRequest,\n\t\t): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t\tdeleteWebhookSubscription: async (): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Type representing the Hevy API client returned by createClient.\n * Useful for typing variables that hold the client instance.\n */\nexport type HevyApiClient = ReturnType<typeof createClient>;\n","// Import the Kubb-based client\nimport { createClient as createKubbClient } from \"./hevyClientKubb.js\";\n\nexport function createClient(apiKey: string, baseUrl: string) {\n\treturn createKubbClient(apiKey, baseUrl);\n}\n\n// Export the HevyClient type for use in other modules\nexport type HevyClient = ReturnType<typeof createClient>;\n","import * as Sentry from \"@sentry/node\";\n\ndeclare const __HEVY_MCP_NAME__: string | undefined;\ndeclare const __HEVY_MCP_VERSION__: string | undefined;\ndeclare const __HEVY_MCP_BUILD__: boolean | undefined;\n\nconst isBuiltArtifact =\n\ttypeof __HEVY_MCP_BUILD__ === \"boolean\" ? __HEVY_MCP_BUILD__ : false;\nif (\n\tisBuiltArtifact &&\n\t(typeof __HEVY_MCP_NAME__ !== \"string\" ||\n\t\ttypeof __HEVY_MCP_VERSION__ !== \"string\")\n) {\n\tthrow new Error(\n\t\t\"Build-time variables __HEVY_MCP_NAME__ and __HEVY_MCP_VERSION__ must be defined.\",\n\t);\n}\n\nconst name =\n\ttypeof __HEVY_MCP_NAME__ === \"string\" ? __HEVY_MCP_NAME__ : \"hevy-mcp\";\nconst version =\n\ttypeof __HEVY_MCP_VERSION__ === \"string\" ? __HEVY_MCP_VERSION__ : \"dev\";\n\n// Environment variables are loaded via Node.js native --env-file flag (Node.js 20.6+)\n// or set directly in the environment. No dotenv dependency needed.\n// This avoids stdout pollution that corrupts MCP JSON-RPC communication in stdio mode.\n\n// Sentry monitoring is baked into the built MCP server so usage and errors\n// from users of the published package are captured for observability.\nconst sentryRelease = process.env.SENTRY_RELEASE ?? `${name}@${version}`;\nconst sentryConfig = {\n\tdsn: \"https://ce696d8333b507acbf5203eb877bce0f@o4508975499575296.ingest.de.sentry.io/4509049671647312\",\n\trelease: sentryRelease,\n\t// Tracing must be enabled for MCP monitoring to work\n\ttracesSampleRate: 1.0,\n\tsendDefaultPii: false,\n} as const;\n\nSentry.init(sentryConfig);\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { registerFolderTools } from \"./tools/folders.js\";\nimport { registerRoutineTools } from \"./tools/routines.js\";\nimport { registerTemplateTools } from \"./tools/templates.js\";\nimport { registerWebhookTools } from \"./tools/webhooks.js\";\nimport { registerWorkoutTools } from \"./tools/workouts.js\";\nimport { assertApiKey, parseConfig } from \"./utils/config.js\";\nimport { createClient } from \"./utils/hevyClient.js\";\n\nconst HEVY_API_BASEURL = \"https://api.hevyapp.com\";\n\nconst serverConfigSchema = z.object({\n\tapiKey: z\n\t\t.string()\n\t\t.min(1, \"Hevy API key is required\")\n\t\t.describe(\"Your Hevy API key (available in the Hevy app settings).\"),\n});\n\nexport const configSchema = serverConfigSchema;\ntype ServerConfig = z.infer<typeof serverConfigSchema>;\n\nfunction buildServer(apiKey: string) {\n\tconst baseServer = new McpServer({\n\t\tname,\n\t\tversion,\n\t});\n\tconst server = Sentry.wrapMcpServerWithSentry(baseServer);\n\n\tconst hevyClient = createClient(apiKey, HEVY_API_BASEURL);\n\tconsole.error(\"Hevy client initialized with API key\");\n\n\tregisterWorkoutTools(server, hevyClient);\n\tregisterRoutineTools(server, hevyClient);\n\tregisterTemplateTools(server, hevyClient);\n\tregisterFolderTools(server, hevyClient);\n\tregisterWebhookTools(server, hevyClient);\n\n\treturn server;\n}\n\nexport default function createServer({ config }: { config: ServerConfig }) {\n\tconst { apiKey } = serverConfigSchema.parse(config);\n\tconst server = buildServer(apiKey);\n\treturn server;\n}\n\nexport async function runServer() {\n\tconst args = process.argv.slice(2);\n\tconst cfg = parseConfig(args, process.env);\n\tconst apiKey = cfg.apiKey;\n\tassertApiKey(apiKey);\n\n\tconst server = buildServer(apiKey);\n\tconsole.error(\"Starting MCP server in stdio mode\");\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hevy-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "A Model Context Protocol (MCP) server implementation that interfaces with the Hevy fitness tracking app and its API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -80,9 +80,9 @@
|
|
|
80
80
|
"abstract-syntax-tree": "^2.22.0",
|
|
81
81
|
"cross-env": "^10.1.0",
|
|
82
82
|
"lefthook": "^2.1.4",
|
|
83
|
-
"oxfmt": "^0.
|
|
83
|
+
"oxfmt": "^0.46.0",
|
|
84
84
|
"oxlint": "^1.58.0",
|
|
85
|
-
"oxlint-tsgolint": "^0.
|
|
85
|
+
"oxlint-tsgolint": "^0.21.1",
|
|
86
86
|
"semantic-release": "^25.0.3",
|
|
87
87
|
"semantic-release-unsquash": "^0.4.0",
|
|
88
88
|
"tsdown": "^0.21.7",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-DDICz5UO.mjs","names":["createClient","api.getV1Workouts","api.getV1WorkoutsWorkoutid","api.postV1Workouts","api.putV1WorkoutsWorkoutid","api.getV1WorkoutsCount","api.getV1WorkoutsEvents","api.getV1Routines","api.getV1RoutinesRoutineid","api.postV1Routines","api.putV1RoutinesRoutineid","api.getV1ExerciseTemplates","api.getV1ExerciseTemplatesExercisetemplateid","api.getV1ExerciseHistoryExercisetemplateid","api.postV1ExerciseTemplates","api.getV1RoutineFolders","api.postV1RoutineFolders","api.getV1RoutineFoldersFolderid","createKubbClient"],"sources":["../src/utils/error-handler.ts","../src/utils/formatters.ts","../src/utils/response-formatter.ts","../src/tools/folders.ts","../src/utils/json-parser.ts","../src/tools/routines.ts","../src/tools/templates.ts","../src/tools/webhooks.ts","../src/tools/workouts.ts","../src/utils/config.ts","../src/generated/client/api/getV1ExerciseHistoryExercisetemplateid.ts","../src/generated/client/api/getV1ExerciseTemplates.ts","../src/generated/client/api/getV1ExerciseTemplatesExercisetemplateid.ts","../src/generated/client/api/getV1RoutineFolders.ts","../src/generated/client/api/getV1RoutineFoldersFolderid.ts","../src/generated/client/api/getV1Routines.ts","../src/generated/client/api/getV1RoutinesRoutineid.ts","../src/generated/client/api/getV1Workouts.ts","../src/generated/client/api/getV1WorkoutsCount.ts","../src/generated/client/api/getV1WorkoutsEvents.ts","../src/generated/client/api/getV1WorkoutsWorkoutid.ts","../src/generated/client/api/postV1ExerciseTemplates.ts","../src/generated/client/api/postV1RoutineFolders.ts","../src/generated/client/api/postV1Routines.ts","../src/generated/client/api/postV1Workouts.ts","../src/generated/client/api/putV1RoutinesRoutineid.ts","../src/generated/client/api/putV1WorkoutsWorkoutid.ts","../src/utils/hevyClientKubb.ts","../src/utils/hevyClient.ts","../src/index.ts"],"sourcesContent":["/**\n * Centralized error handling utility for MCP tools\n */\n\n// Import the McpToolResponse type from response-formatter to ensure consistency\nimport { isAxiosError } from \"axios\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\n/**\n * Standard error response interface\n */\nexport interface ErrorResponse {\n\tmessage: string;\n\tcode?: string;\n\tdetails?: unknown;\n}\n\n/**\n * Specific error types for better categorization\n */\nexport enum ErrorType {\n\tAPI_ERROR = \"API_ERROR\",\n\tVALIDATION_ERROR = \"VALIDATION_ERROR\",\n\tNOT_FOUND = \"NOT_FOUND\",\n\tNETWORK_ERROR = \"NETWORK_ERROR\",\n\tUNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\n/**\n * Enhanced error response with type categorization\n */\nexport interface EnhancedErrorResponse extends ErrorResponse {\n\ttype: ErrorType;\n}\n\n/**\n * Create a standardized error response for MCP tools\n *\n * @param error - The error object or message\n * @param context - Optional context information about where the error occurred\n * @returns A formatted MCP tool response with error information\n */\nexport function createErrorResponse(\n\terror: unknown,\n\tcontext?: string,\n): McpToolResponse {\n\t// Extract axios response data if available\n\tlet errorMessage = error instanceof Error ? error.message : String(error);\n\n\t// Check for axios error with response data\n\tif (isAxiosError(error) && error.response?.data) {\n\t\tconst { data } = error.response;\n\t\tif (typeof data === \"string\") {\n\t\t\terrorMessage = data;\n\t\t} else if (data && typeof data === \"object\") {\n\t\t\ttry {\n\t\t\t\terrorMessage = JSON.stringify(data);\n\t\t\t} catch (_e) {\n\t\t\t\terrorMessage = String(data);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract error code if available (for logging purposes)\n\tconst errorCode =\n\t\terror instanceof Error && \"code\" in error\n\t\t\t? (error as { code?: string }).code\n\t\t\t: undefined;\n\n\t// Determine error type based on error characteristics\n\tconst errorType = determineErrorType(error, errorMessage);\n\n\t// Include error code in logs if available\n\tif (errorCode) {\n\t\tconsole.debug(`Error code: ${errorCode}`);\n\t}\n\n\tconst contextPrefix = context ? `[${context}] ` : \"\";\n\tconst formattedMessage = `${contextPrefix}Error: ${errorMessage}`;\n\n\t// Log the error for server-side debugging with type information\n\tconsole.error(`${formattedMessage} (Type: ${errorType})`, error);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: formattedMessage,\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t};\n}\n\n/**\n * Determine the type of error based on error characteristics\n */\nfunction determineErrorType(error: unknown, message: string): ErrorType {\n\tconst messageLower = message.toLowerCase();\n\tconst nameLower = error instanceof Error ? error.name.toLowerCase() : \"\";\n\n\tif (\n\t\tnameLower.includes(\"network\") ||\n\t\tmessageLower.includes(\"network\") ||\n\t\tnameLower.includes(\"fetch\") ||\n\t\tmessageLower.includes(\"fetch\") ||\n\t\tnameLower.includes(\"timeout\") ||\n\t\tmessageLower.includes(\"timeout\")\n\t) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"invalid\") ||\n\t\tmessageLower.includes(\"required\")\n\t) {\n\t\treturn ErrorType.VALIDATION_ERROR;\n\t}\n\n\tif (\n\t\tmessageLower.includes(\"not found\") ||\n\t\tmessageLower.includes(\"404\") ||\n\t\tmessageLower.includes(\"does not exist\")\n\t) {\n\t\treturn ErrorType.NOT_FOUND;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"server error\") ||\n\t\tmessageLower.includes(\"500\")\n\t) {\n\t\treturn ErrorType.API_ERROR;\n\t}\n\n\treturn ErrorType.UNKNOWN_ERROR;\n}\n\n/**\n * Wrap an async function with standardized error handling\n *\n * This function preserves the parameter types of the wrapped function while\n * providing error handling. The returned function accepts Record<string, unknown>\n * (as required by MCP SDK) but internally casts to the original parameter type.\n *\n * @param fn - The async function to wrap\n * @param context - Context information for error messages\n * @returns A function that catches errors and returns standardized error responses\n */\nexport function withErrorHandling<TParams extends Record<string, unknown>>(\n\tfn: (args: TParams) => Promise<McpToolResponse>,\n\tcontext: string,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\treturn async (args: Record<string, unknown>) => {\n\t\ttry {\n\t\t\treturn await fn(args as TParams);\n\t\t} catch (error) {\n\t\t\treturn createErrorResponse(error, context);\n\t\t}\n\t};\n}\n","import type {\n\tExerciseHistoryEntry,\n\tExerciseTemplate,\n\tRoutine,\n\tRoutineFolder,\n\tWorkout,\n} from \"../generated/client/types/index.js\";\n\n/**\n * Formatted workout set interface\n */\nexport interface FormattedWorkoutSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n}\n\n/**\n * Formatted workout exercise interface\n */\nexport interface FormattedWorkoutExercise {\n\tindex: number | undefined;\n\tname: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetsId: number | undefined | null;\n\tsets: FormattedWorkoutSet[] | undefined;\n}\n\n/**\n * Formatted workout interface\n */\nexport interface FormattedWorkout {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tdescription: string | undefined | null;\n\tstartTime: string | number | undefined;\n\tendTime: string | number | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\tduration: string;\n\texercises: FormattedWorkoutExercise[] | undefined;\n}\n\n/**\n * Formatted routine set interface\n */\nexport interface FormattedRoutineSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\trepRange?: { start?: number | null; end?: number | null } | undefined | null;\n\trpe?: number | undefined | null;\n}\n\n/**\n * Formatted routine exercise interface\n */\nexport interface FormattedRoutineExercise {\n\tname: string | undefined;\n\tindex: number | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetId: number | undefined | null;\n\trestSeconds: string | undefined;\n\tsets: FormattedRoutineSet[] | undefined;\n}\n\n/**\n * Formatted routine interface\n */\nexport interface FormattedRoutine {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tfolderId: number | undefined | null;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\texercises: FormattedRoutineExercise[] | undefined;\n}\n\n/**\n * Formatted routine folder interface\n */\nexport interface FormattedRoutineFolder {\n\tid: number | undefined;\n\ttitle: string | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n}\n\n/**\n * Formatted exercise template interface\n */\nexport interface FormattedExerciseTemplate {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\ttype: string | undefined;\n\tprimaryMuscleGroup: string | undefined;\n\tsecondaryMuscleGroups: string[] | undefined;\n\tisCustom: boolean | undefined;\n}\n\nexport interface FormattedExerciseHistoryEntry {\n\tworkoutId: string | undefined;\n\tworkoutTitle: string | undefined;\n\tworkoutStartTime: string | undefined;\n\tworkoutEndTime: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\tsetType: string | undefined;\n}\n\n/**\n * Format a workout object for consistent presentation\n *\n * @param workout - The workout object from the API\n * @returns A formatted workout object with standardized properties\n */\nexport function formatWorkout(workout: Workout): FormattedWorkout {\n\treturn {\n\t\tid: workout.id,\n\t\ttitle: workout.title,\n\t\tdescription: workout.description,\n\t\tstartTime: workout.start_time,\n\t\tendTime: workout.end_time,\n\t\tcreatedAt: workout.created_at,\n\t\tupdatedAt: workout.updated_at,\n\t\tduration: calculateDuration(workout.start_time, workout.end_time),\n\t\texercises: workout.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tindex: exercise.index,\n\t\t\t\tname: exercise.title,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetsId: exercise.supersets_id,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\trpe: set.rpe,\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine object for consistent presentation\n *\n * @param routine - The routine object from the API\n * @returns A formatted routine object with standardized properties\n */\nexport function formatRoutine(routine: Routine): FormattedRoutine {\n\treturn {\n\t\tid: routine.id,\n\t\ttitle: routine.title,\n\t\tfolderId: routine.folder_id,\n\t\tcreatedAt: routine.created_at,\n\t\tupdatedAt: routine.updated_at,\n\t\texercises: routine.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tname: exercise.title,\n\t\t\t\tindex: exercise.index,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetId: exercise.supersets_id,\n\t\t\t\trestSeconds: exercise.rest_seconds,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\t...(set.rep_range !== undefined && { repRange: set.rep_range }),\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\t...(set.rpe !== undefined && { rpe: set.rpe }),\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine folder object for consistent presentation\n *\n * @param folder - The routine folder object from the API\n * @returns A formatted routine folder object with standardized properties\n */\nexport function formatRoutineFolder(\n\tfolder: RoutineFolder,\n): FormattedRoutineFolder {\n\treturn {\n\t\tid: folder.id,\n\t\ttitle: folder.title,\n\t\tcreatedAt: folder.created_at,\n\t\tupdatedAt: folder.updated_at,\n\t};\n}\n\n/**\n * Calculate duration between two ISO timestamp strings\n *\n * @param startTime - The start time as ISO string or timestamp\n * @param endTime - The end time as ISO string or timestamp\n * @returns A formatted duration string (e.g. \"1h 30m 45s\") or \"Unknown duration\" if inputs are invalid\n */\nexport function calculateDuration(\n\tstartTime: string | number | null | undefined,\n\tendTime: string | number | null | undefined,\n): string {\n\tif (!startTime || !endTime) return \"Unknown duration\";\n\n\ttry {\n\t\tconst start = new Date(startTime);\n\t\tconst end = new Date(endTime);\n\n\t\t// Validate dates\n\t\tif (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) {\n\t\t\treturn \"Unknown duration\";\n\t\t}\n\n\t\tconst durationMs = end.getTime() - start.getTime();\n\n\t\t// Handle negative durations\n\t\tif (durationMs < 0) {\n\t\t\treturn \"Invalid duration (end time before start time)\";\n\t\t}\n\n\t\tconst hours = Math.floor(durationMs / (1000 * 60 * 60));\n\t\tconst minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60));\n\t\tconst seconds = Math.floor((durationMs % (1000 * 60)) / 1000);\n\n\t\treturn `${hours}h ${minutes}m ${seconds}s`;\n\t} catch (error) {\n\t\tconsole.error(\"Error calculating duration:\", error);\n\t\treturn \"Unknown duration\";\n\t}\n}\n\n/**\n * Format an exercise template object for consistent presentation\n *\n * @param template - The exercise template object from the API\n * @returns A formatted exercise template object with standardized properties\n */\nexport function formatExerciseTemplate(\n\ttemplate: ExerciseTemplate,\n): FormattedExerciseTemplate {\n\treturn {\n\t\tid: template.id,\n\t\ttitle: template.title,\n\t\ttype: template.type,\n\t\tprimaryMuscleGroup: template.primary_muscle_group,\n\t\tsecondaryMuscleGroups: template.secondary_muscle_groups,\n\t\tisCustom: template.is_custom,\n\t};\n}\n\nexport function formatExerciseHistoryEntry(\n\tentry: ExerciseHistoryEntry,\n): FormattedExerciseHistoryEntry {\n\treturn {\n\t\tworkoutId: entry.workout_id,\n\t\tworkoutTitle: entry.workout_title,\n\t\tworkoutStartTime: entry.workout_start_time,\n\t\tworkoutEndTime: entry.workout_end_time,\n\t\texerciseTemplateId: entry.exercise_template_id,\n\t\tweight: entry.weight_kg,\n\t\treps: entry.reps,\n\t\tdistance: entry.distance_meters,\n\t\tduration: entry.duration_seconds,\n\t\trpe: entry.rpe,\n\t\tcustomMetric: entry.custom_metric,\n\t\tsetType: entry.set_type,\n\t};\n}\n","/**\n * MCP Tool Response type\n */\nexport interface McpToolResponse {\n\t[x: string]: unknown;\n\tcontent: Array<{\n\t\ttype: \"text\";\n\t\ttext: string;\n\t}>;\n}\n\n/**\n * Format options for JSON responses\n */\nexport interface JsonFormatOptions {\n\t/** Whether to pretty-print the JSON with indentation */\n\tpretty?: boolean;\n\t/** Indentation spaces for pretty-printing (default: 2) */\n\tindent?: number;\n}\n\n/**\n * Create a standardized success response with JSON data\n *\n * @param data - The data to include in the response\n * @param options - Formatting options\n * @returns A formatted MCP tool response with the data as JSON\n */\nexport function createJsonResponse(\n\tdata: unknown,\n\toptions: JsonFormatOptions = { pretty: true, indent: 2 },\n): McpToolResponse {\n\tconst jsonString = options.pretty\n\t\t? JSON.stringify(data, null, options.indent)\n\t\t: JSON.stringify(data);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: jsonString,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response with text data\n *\n * @param message - The text message to include in the response\n * @returns A formatted MCP tool response with the text message\n */\nexport function createTextResponse(message: string): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response for empty or null results\n *\n * @param message - Optional message to include (default: \"No data found\")\n * @returns A formatted MCP tool response for empty results\n */\nexport function createEmptyResponse(\n\tmessage = \"No data found\",\n): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1RoutineFolders200,\n\tGetV1RoutineFoldersFolderid200,\n\tPostV1RoutineFolders201,\n\tRoutineFolder,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutineFolder } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the folder operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n/**\n * Register all routine folder-related tools with the MCP server\n */\nexport function registerFolderTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routine folders\n\tconst getRoutineFoldersSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutineFoldersParams = InferToolParams<\n\t\ttypeof getRoutineFoldersSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-routine-folders\",\n\t\t\"Get a paginated list of your routine folders, including both default and custom folders. Useful for organizing and browsing your workout routines.\",\n\t\tgetRoutineFoldersSchema,\n\t\twithErrorHandling(async (args: GetRoutineFoldersParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1RoutineFolders200 = await hevyClient.getRoutineFolders({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routine folders to extract relevant information\n\t\t\tconst folders =\n\t\t\t\tdata?.routine_folders?.map((folder: RoutineFolder) =>\n\t\t\t\t\tformatRoutineFolder(folder),\n\t\t\t\t) || [];\n\n\t\t\tif (folders.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routine folders found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(folders);\n\t\t}, \"get-routine-folders\"),\n\t);\n\n\t// Get single routine folder by ID\n\tconst getRoutineFolderSchema = {\n\t\tfolderId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineFolderParams = InferToolParams<typeof getRoutineFolderSchema>;\n\n\tserver.tool(\n\t\t\"get-routine-folder\",\n\t\t\"Get complete details of a specific routine folder by its ID, including name, creation date, and associated routines.\",\n\t\tgetRoutineFolderSchema,\n\t\twithErrorHandling(async (args: GetRoutineFolderParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { folderId } = args;\n\t\t\tconst data: GetV1RoutineFoldersFolderid200 =\n\t\t\t\tawait hevyClient.getRoutineFolder(folderId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Routine folder with ID ${folderId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder);\n\t\t}, \"get-routine-folder\"),\n\t);\n\n\t// Create new routine folder\n\tconst createRoutineFolderSchema = {\n\t\tname: z.string().min(1),\n\t} as const;\n\ttype CreateRoutineFolderParams = InferToolParams<\n\t\ttypeof createRoutineFolderSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-routine-folder\",\n\t\t\"Create a new routine folder in your Hevy account. Requires a name for the folder. Returns the full folder details including the new folder ID.\",\n\t\tcreateRoutineFolderSchema,\n\t\twithErrorHandling(async (args: CreateRoutineFolderParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { name } = args;\n\t\t\tconst data: PostV1RoutineFolders201 =\n\t\t\t\tawait hevyClient.createRoutineFolder({\n\t\t\t\t\troutine_folder: {\n\t\t\t\t\t\ttitle: name,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine folder: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-routine-folder\"),\n\t);\n}\n","/**\n * Preprocessor to handle MCP clients that send JSON-stringified arrays\n * instead of native arrays for complex parameters.\n *\n * This is used with Zod's z.preprocess to handle cases where MCP clients\n * serialize complex nested structures as JSON strings.\n *\n * @param val - The value to potentially parse\n * @returns The parsed array if val is a valid JSON string, otherwise returns val unchanged\n */\nexport function parseJsonArray(val: unknown): unknown {\n\t// Handle case where MCP client sends JSON string instead of array\n\tif (typeof val === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(val);\n\t\t} catch {\n\t\t\t// Let Zod validation handle the error\n\t\t\treturn val;\n\t\t}\n\t}\n\treturn val;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1Routines200,\n\tGetV1RoutinesRoutineid200,\n\tPostRoutinesRequestExercise,\n\tPostRoutinesRequestSet,\n\tPostRoutinesRequestSetTypeEnumKey,\n\tPostV1Routines201,\n\tPutRoutinesRequestExercise,\n\tPutRoutinesRequestSet,\n\tPutRoutinesRequestSetTypeEnumKey,\n\tPutV1RoutinesRoutineid200,\n\tRoutine,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutine } from \"../utils/formatters.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the routine operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nfunction coerceNullishNumberInput(value: unknown): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\n\tif (typeof value !== \"string\") {\n\t\treturn value;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed === \"\") {\n\t\treturn undefined;\n\t}\n\n\tconst lowered = trimmed.toLowerCase();\n\tif (lowered === \"null\") {\n\t\treturn null;\n\t}\n\tif (lowered === \"undefined\") {\n\t\treturn undefined;\n\t}\n\n\tconst asNumber = Number(trimmed);\n\tif (Number.isNaN(asNumber)) {\n\t\treturn value;\n\t}\n\n\treturn asNumber;\n}\n\nconst zNullableInt = z.preprocess(\n\tcoerceNullishNumberInput,\n\tz.number().int().nullable().optional(),\n);\n\nconst zOptionalRepRange = z.preprocess(\n\t(value) => (value === null ? undefined : value),\n\tz\n\t\t.object({\n\t\t\tstart: zNullableInt,\n\t\t\tend: zNullableInt,\n\t\t})\n\t\t.optional(),\n);\n\nfunction buildRepRange(repRange?: {\n\tstart?: number | null;\n\tend?: number | null;\n}): { start: number | null; end: number | null } | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? null;\n\tconst end = repRange.end ?? null;\n\tif (start === null && end === null) {\n\t\treturn null;\n\t}\n\n\treturn { start, end };\n}\n\n/**\n * Returns a fixed rep count when `repRange` is a fixed range (start and end are\n * both non-null and equal). Otherwise returns null.\n */\nfunction getFixedRepsFromRepRange(\n\trepRange:\n\t\t| {\n\t\t\t\tstart?: number | null;\n\t\t\t\tend?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): number | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? null;\n\tconst end = repRange.end ?? null;\n\tif (start === null || end === null) {\n\t\treturn null;\n\t}\n\tif (start !== end) {\n\t\treturn null;\n\t}\n\n\treturn start;\n}\n\nconst repRangeDisplayWarningText =\n\t\"Note: Hevy's public API stores rep ranges (rep_range), but the Hevy apps may \" +\n\t\"not display them because they rely on an internal-only exercise field \" +\n\t\"(input_modifier). See https://github.com/chrisdoc/hevy-mcp/issues/261 for \" +\n\t\"details/workarounds.\";\n\n/**\n * Register all routine-related tools with the MCP server\n */\nexport function registerRoutineTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routines\n\tconst getRoutinesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutinesParams = InferToolParams<typeof getRoutinesSchema>;\n\n\tserver.tool(\n\t\t\"get-routines\",\n\t\t\"Get a paginated list of your workout routines, including custom and default routines. Useful for browsing or searching your available routines.\",\n\t\tgetRoutinesSchema,\n\t\twithErrorHandling(async (args: GetRoutinesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Routines200 = await hevyClient.getRoutines({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routines to extract relevant information\n\t\t\tconst routines =\n\t\t\t\tdata?.routines?.map((routine: Routine) => formatRoutine(routine)) || [];\n\n\t\t\tif (routines.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routines found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(routines);\n\t\t}, \"get-routines\"),\n\t);\n\n\t// Get single routine by ID (new, direct endpoint)\n\tconst getRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineParams = InferToolParams<typeof getRoutineSchema>;\n\n\tserver.tool(\n\t\t\"get-routine\",\n\t\t\"Get a routine by its ID using the direct endpoint. Returns all details for the specified routine.\",\n\t\tgetRoutineSchema,\n\t\twithErrorHandling(async (args: GetRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { routineId } = args;\n\t\t\tconst data: GetV1RoutinesRoutineid200 = await hevyClient.getRoutineById(\n\t\t\t\tString(routineId),\n\t\t\t);\n\t\t\tif (!data || !data.routine) {\n\t\t\t\treturn createEmptyResponse(`Routine with ID ${routineId} not found`);\n\t\t\t}\n\t\t\tconst routine = formatRoutine(data.routine);\n\t\t\treturn createJsonResponse(routine);\n\t\t}, \"get-routine\"),\n\t);\n\n\t// Create new routine\n\tconst createRoutineSchema = {\n\t\ttitle: z.string().min(1),\n\t\tfolderId: z.coerce.number().nullable().optional(),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateRoutineParams = InferToolParams<typeof createRoutineSchema>;\n\n\tserver.tool(\n\t\t\"create-routine\",\n\t\t\"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.\",\n\t\tcreateRoutineSchema,\n\t\twithErrorHandling(async (args: CreateRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { title, folderId, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PostV1Routines201 = await hevyClient.createRoutine({\n\t\t\t\troutine: {\n\t\t\t\t\ttitle,\n\t\t\t\t\tfolder_id: folderId ?? null,\n\t\t\t\t\tnotes: notes ?? \"\",\n\t\t\t\t\texercises: exercises.map((exercise): PostRoutinesRequestExercise => {\n\t\t\t\t\t\tconst sets = exercise.sets.map((set): PostRoutinesRequestSet => {\n\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\tconst reps = typeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttype: set.type as PostRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"create-routine\"),\n\t);\n\n\t// Update existing routine\n\tconst updateRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateRoutineParams = InferToolParams<typeof updateRoutineSchema>;\n\n\tserver.tool(\n\t\t\"update-routine\",\n\t\t\"Update an existing routine by ID. You can modify the title, notes, and exercise configurations. Returns the updated routine with all changes applied.\",\n\t\tupdateRoutineSchema,\n\t\twithErrorHandling(async (args: UpdateRoutineParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { routineId, title, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PutV1RoutinesRoutineid200 = await hevyClient.updateRoutine(\n\t\t\t\troutineId,\n\t\t\t\t{\n\t\t\t\t\troutine: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\tnotes: notes ?? null,\n\t\t\t\t\t\texercises: exercises.map((exercise): PutRoutinesRequestExercise => {\n\t\t\t\t\t\t\tconst sets = exercise.sets.map((set): PutRoutinesRequestSet => {\n\t\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\t\tconst reps =\n\t\t\t\t\t\t\t\t\ttypeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\ttype: set.type as PutRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update routine with ID ${routineId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"update-routine\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tExerciseTemplate,\n\tGetV1ExerciseHistoryExercisetemplateid200,\n\tGetV1ExerciseTemplates200,\n\tGetV1ExerciseTemplatesExercisetemplateid200,\n\tPostV1ExerciseTemplates200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tformatExerciseHistoryEntry,\n\tformatExerciseTemplate,\n} from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the template operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n// Shared muscle group values used by both create and search tools\nconst MUSCLE_GROUPS = [\n\t\"abdominals\",\n\t\"shoulders\",\n\t\"biceps\",\n\t\"triceps\",\n\t\"forearms\",\n\t\"quadriceps\",\n\t\"hamstrings\",\n\t\"calves\",\n\t\"glutes\",\n\t\"abductors\",\n\t\"adductors\",\n\t\"lats\",\n\t\"upper_back\",\n\t\"traps\",\n\t\"lower_back\",\n\t\"chest\",\n\t\"cardio\",\n\t\"neck\",\n\t\"full_body\",\n\t\"other\",\n] as const;\n\n// Module-level cache for all exercise templates\nlet exerciseTemplateCache: ExerciseTemplate[] | null = null;\n// In-flight promise to prevent concurrent duplicate fetches\nlet exerciseTemplateFetch: Promise<ExerciseTemplate[]> | null = null;\n\n/** Reset the exercise template cache (exposed for testing). */\nexport function resetExerciseTemplateCache(): void {\n\texerciseTemplateCache = null;\n\texerciseTemplateFetch = null;\n}\n\n/**\n * Register all exercise template-related tools with the MCP server\n */\nexport function registerTemplateTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get exercise templates\n\tconst getExerciseTemplatesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(100).default(5),\n\t} as const;\n\ttype GetExerciseTemplatesParams = InferToolParams<\n\t\ttypeof getExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-templates\",\n\t\t\"Get a paginated list of exercise templates (default and custom) with details like name, category, equipment, and muscle groups. Useful for browsing or searching available exercises.\",\n\t\tgetExerciseTemplatesSchema,\n\t\twithErrorHandling(async (args: GetExerciseTemplatesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\t\tpage,\n\t\t\t\t\tpageSize,\n\t\t\t\t});\n\n\t\t\t// Process exercise templates to extract relevant information\n\t\t\tconst templates =\n\t\t\t\tdata?.exercise_templates?.map((template: ExerciseTemplate) =>\n\t\t\t\t\tformatExerciseTemplate(template),\n\t\t\t\t) || [];\n\n\t\t\tif (templates.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No exercise templates found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(templates);\n\t\t}, \"get-exercise-templates\"),\n\t);\n\n\t// Get single exercise template by ID\n\tconst getExerciseTemplateSchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t} as const;\n\ttype GetExerciseTemplateParams = InferToolParams<\n\t\ttypeof getExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-template\",\n\t\t\"Get complete details of a specific exercise template by its ID, including name, category, equipment, muscle groups, and notes.\",\n\t\tgetExerciseTemplateSchema,\n\t\twithErrorHandling(async (args: GetExerciseTemplateParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { exerciseTemplateId } = args;\n\t\t\tconst data: GetV1ExerciseTemplatesExercisetemplateid200 =\n\t\t\t\tawait hevyClient.getExerciseTemplate(exerciseTemplateId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Exercise template with ID ${exerciseTemplateId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst template = formatExerciseTemplate(data);\n\t\t\treturn createJsonResponse(template);\n\t\t}, \"get-exercise-template\"),\n\t);\n\n\t// Get exercise history for a template\n\tconst getExerciseHistorySchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t\tstartDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 start date for filtering history\")\n\t\t\t.optional(),\n\t\tendDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 end date for filtering history\")\n\t\t\t.optional(),\n\t} as const;\n\ttype GetExerciseHistoryParams = InferToolParams<\n\t\ttypeof getExerciseHistorySchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-history\",\n\t\t\"Get past sets for a specific exercise template, optionally filtered by start and end dates.\",\n\t\tgetExerciseHistorySchema,\n\t\twithErrorHandling(async (args: GetExerciseHistoryParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { exerciseTemplateId, startDate, endDate } = args;\n\t\t\tconst data: GetV1ExerciseHistoryExercisetemplateid200 =\n\t\t\t\tawait hevyClient.getExerciseHistory(exerciseTemplateId, {\n\t\t\t\t\t...(startDate ? { start_date: startDate } : {}),\n\t\t\t\t\t...(endDate ? { end_date: endDate } : {}),\n\t\t\t\t});\n\n\t\t\tconst history =\n\t\t\t\tdata?.exercise_history?.map((entry) =>\n\t\t\t\t\tformatExerciseHistoryEntry(entry),\n\t\t\t\t) || [];\n\n\t\t\tif (history.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise history found for template ${exerciseTemplateId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(history);\n\t\t}, \"get-exercise-history\"),\n\t);\n\n\t// Create a custom exercise template\n\tconst createExerciseTemplateSchema = {\n\t\ttitle: z.string().min(1),\n\t\texerciseType: z.enum([\n\t\t\t\"weight_reps\",\n\t\t\t\"reps_only\",\n\t\t\t\"bodyweight_reps\",\n\t\t\t\"bodyweight_assisted_reps\",\n\t\t\t\"duration\",\n\t\t\t\"weight_duration\",\n\t\t\t\"distance_duration\",\n\t\t\t\"short_distance_weight\",\n\t\t]),\n\t\tequipmentCategory: z.enum([\n\t\t\t\"none\",\n\t\t\t\"barbell\",\n\t\t\t\"dumbbell\",\n\t\t\t\"kettlebell\",\n\t\t\t\"machine\",\n\t\t\t\"plate\",\n\t\t\t\"resistance_band\",\n\t\t\t\"suspension\",\n\t\t\t\"other\",\n\t\t]),\n\t\tmuscleGroup: z.enum(MUSCLE_GROUPS),\n\t\totherMuscles: z.array(z.enum(MUSCLE_GROUPS)).default([]),\n\t} as const;\n\ttype CreateExerciseTemplateParams = InferToolParams<\n\t\ttypeof createExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-exercise-template\",\n\t\t\"Create a custom exercise template with title, type, equipment, and muscle groups.\",\n\t\tcreateExerciseTemplateSchema,\n\t\twithErrorHandling(async (args: CreateExerciseTemplateParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst {\n\t\t\t\ttitle,\n\t\t\t\texerciseType,\n\t\t\t\tequipmentCategory,\n\t\t\t\tmuscleGroup,\n\t\t\t\totherMuscles,\n\t\t\t} = args;\n\n\t\t\tconst response: PostV1ExerciseTemplates200 =\n\t\t\t\tawait hevyClient.createExerciseTemplate({\n\t\t\t\t\texercise: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\texercise_type: exerciseType,\n\t\t\t\t\t\tequipment_category: equipmentCategory,\n\t\t\t\t\t\tmuscle_group: muscleGroup,\n\t\t\t\t\t\tother_muscles: otherMuscles,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\treturn createJsonResponse({\n\t\t\t\tid: response?.id,\n\t\t\t\tmessage: \"Exercise template created successfully\",\n\t\t\t});\n\t\t}, \"create-exercise-template\"),\n\t);\n\n\t// Search exercise templates (cached)\n\tconst searchExerciseTemplatesSchema = {\n\t\tquery: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.describe(\n\t\t\t\t\"Case-insensitive substring to match against exercise template titles\",\n\t\t\t),\n\t\tprimaryMuscleGroup: z\n\t\t\t.enum(MUSCLE_GROUPS)\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional filter to restrict results to a specific primary muscle group\",\n\t\t\t),\n\t\trefresh: z\n\t\t\t.boolean()\n\t\t\t.optional()\n\t\t\t.default(false)\n\t\t\t.describe(\n\t\t\t\t\"Set to true to bust the in-memory cache and re-fetch all templates from the API\",\n\t\t\t),\n\t} as const;\n\ttype SearchExerciseTemplatesParams = InferToolParams<\n\t\ttypeof searchExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"search-exercise-templates\",\n\t\t\"Search exercise templates by name with optional muscle group filter. Fetches all templates from the Hevy API on first call and caches them in memory for subsequent searches. Use refresh:true to force a re-fetch.\",\n\t\tsearchExerciseTemplatesSchema,\n\t\twithErrorHandling(async (args: SearchExerciseTemplatesParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { query, primaryMuscleGroup, refresh } = args;\n\n\t\t\t// Populate cache if empty or refresh requested.\n\t\t\t// Use an in-flight promise to prevent concurrent duplicate fetches.\n\t\t\tif (exerciseTemplateCache === null || refresh) {\n\t\t\t\tif (refresh) exerciseTemplateFetch = null;\n\n\t\t\t\tif (exerciseTemplateFetch === null) {\n\t\t\t\t\texerciseTemplateFetch = (async () => {\n\t\t\t\t\t\tconst allTemplates: ExerciseTemplate[] = [];\n\t\t\t\t\t\tlet page = 1;\n\t\t\t\t\t\tlet pageCount = 1;\n\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\t\t\t\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\t\t\t\t\t\tpage,\n\t\t\t\t\t\t\t\t\tpageSize: 100,\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst templates = data?.exercise_templates ?? [];\n\t\t\t\t\t\t\tallTemplates.push(...templates);\n\t\t\t\t\t\t\tpageCount = data?.page_count ?? 1;\n\t\t\t\t\t\t\tpage++;\n\t\t\t\t\t\t} while (page <= pageCount);\n\n\t\t\t\t\t\texerciseTemplateCache = allTemplates;\n\t\t\t\t\t\texerciseTemplateFetch = null;\n\t\t\t\t\t\treturn allTemplates;\n\t\t\t\t\t})();\n\t\t\t\t}\n\n\t\t\t\tawait exerciseTemplateFetch;\n\t\t\t}\n\n\t\t\t// Filter by query (case-insensitive title substring match)\n\t\t\tconst queryLower = query.toLowerCase();\n\t\t\tif (exerciseTemplateCache === null) {\n\t\t\t\tthrow new Error(\"Failed to populate exercise template cache.\");\n\t\t\t}\n\t\t\tlet results = exerciseTemplateCache.filter((t) =>\n\t\t\t\t(t.title ?? \"\").toLowerCase().includes(queryLower),\n\t\t\t);\n\n\t\t\t// Optional primary muscle group filter\n\t\t\tif (primaryMuscleGroup !== undefined) {\n\t\t\t\tresults = results.filter(\n\t\t\t\t\t(t) => t.primary_muscle_group === primaryMuscleGroup,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise templates found matching \"${query}\"${primaryMuscleGroup ? ` with primary muscle group \"${primaryMuscleGroup}\"` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(results.map(formatExerciseTemplate));\n\t\t}, \"search-exercise-templates\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n> & {\n\tgetWebhookSubscription?: () => Promise<unknown>;\n\tcreateWebhookSubscription?: (data: {\n\t\twebhook: {\n\t\t\turl: string;\n\t\t\tauthToken: string | null;\n\t\t};\n\t}) => Promise<unknown>;\n\tdeleteWebhookSubscription?: () => Promise<unknown>;\n};\n\n// Enhanced webhook URL validation\nconst webhookUrlSchema = z\n\t.string()\n\t.url()\n\t.refine(\n\t\t(url) => {\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(url);\n\t\t\t\treturn parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tmessage: \"Webhook URL must be a valid HTTP or HTTPS URL\",\n\t\t},\n\t)\n\t.refine(\n\t\t(url) => {\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(url);\n\t\t\t\treturn (\n\t\t\t\t\tparsed.hostname !== \"localhost\" && !parsed.hostname.startsWith(\"127.\")\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tmessage: \"Webhook URL cannot be localhost or loopback address\",\n\t\t},\n\t);\n\nexport function registerWebhookTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get webhook subscription\n\tconst getWebhookSubscriptionSchema = {} as const;\n\ttype GetWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof getWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-webhook-subscription\",\n\t\t\"Get the current webhook subscription for this account. Returns the webhook URL and auth token if a subscription exists.\",\n\t\tgetWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (_args: GetWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!hevyClient.getWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.getWebhookSubscription();\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No webhook subscription found for this account\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"get-webhook-subscription\"),\n\t);\n\n\t// Create webhook subscription\n\tconst createWebhookSubscriptionSchema = {\n\t\turl: webhookUrlSchema.describe(\n\t\t\t\"The webhook URL that will receive POST requests when workouts are created\",\n\t\t),\n\t\tauthToken: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional auth token that will be sent as Authorization header in webhook requests\",\n\t\t\t),\n\t} as const;\n\ttype CreateWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof createWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-webhook-subscription\",\n\t\t\"Create a new webhook subscription for this account. The webhook will receive POST requests when workouts are created. Your endpoint must respond with 200 OK within 5 seconds.\",\n\t\tcreateWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (args: CreateWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { url, authToken } = args;\n\t\t\tif (!hevyClient.createWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.createWebhookSubscription({\n\t\t\t\twebhook: {\n\t\t\t\t\turl,\n\t\t\t\t\tauthToken: authToken || null,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create webhook subscription - please check your URL and try again\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"create-webhook-subscription\"),\n\t);\n\n\t// Delete webhook subscription\n\tconst deleteWebhookSubscriptionSchema = {} as const;\n\ttype DeleteWebhookSubscriptionParams = InferToolParams<\n\t\ttypeof deleteWebhookSubscriptionSchema\n\t>;\n\n\tserver.tool(\n\t\t\"delete-webhook-subscription\",\n\t\t\"Delete the current webhook subscription for this account. This will stop all webhook notifications.\",\n\t\tdeleteWebhookSubscriptionSchema,\n\t\twithErrorHandling(async (_args: DeleteWebhookSubscriptionParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!hevyClient.deleteWebhookSubscription) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await hevyClient.deleteWebhookSubscription();\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to delete webhook subscription - no subscription may exist or there was a server error\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data);\n\t\t}, \"delete-webhook-subscription\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tGetV1Workouts200,\n\tGetV1WorkoutsCount200,\n\tGetV1WorkoutsEvents200,\n\tGetV1WorkoutsWorkoutid200,\n\tPostV1Workouts201,\n\tPostWorkoutsRequestBody,\n\tPostWorkoutsRequestExercise,\n\tPostWorkoutsRequestSetRpeEnumKey,\n\tPostWorkoutsRequestSetTypeEnumKey,\n\tPutV1WorkoutsWorkoutid200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatWorkout } from \"../utils/formatters.js\";\nimport type { HevyClient } from \"../utils/hevyClient.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport type { InferToolParams } from \"../utils/tool-helpers.js\";\n\n/**\n * Register all workout-related tools with the MCP server\n */\nexport function registerWorkoutTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get workouts\n\tconst getWorkoutsSchema = {\n\t\tpage: z.coerce.number().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetWorkoutsParams = InferToolParams<typeof getWorkoutsSchema>;\n\n\tserver.tool(\n\t\t\"get-workouts\",\n\t\t\"Get a paginated list of workouts. Returns workout details including title, description, start/end times, and exercises performed. Results are ordered from newest to oldest.\",\n\t\tgetWorkoutsSchema,\n\t\twithErrorHandling(async (args: GetWorkoutsParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Workouts200 = await hevyClient.getWorkouts({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst workouts =\n\t\t\t\tdata?.workouts?.map((workout) => formatWorkout(workout)) || [];\n\n\t\t\tif (workouts.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No workouts found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(workouts);\n\t\t}, \"get-workouts\"),\n\t);\n\n\t// Get single workout by ID\n\tconst getWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t} as const;\n\ttype GetWorkoutParams = InferToolParams<typeof getWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"get-workout\",\n\t\t\"Get complete details of a specific workout by ID. Returns all workout information including title, description, start/end times, and detailed exercise data.\",\n\t\tgetWorkoutSchema,\n\t\twithErrorHandling(async (args: GetWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { workoutId } = args;\n\t\t\tconst data: GetV1WorkoutsWorkoutid200 =\n\t\t\t\tawait hevyClient.getWorkout(workoutId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(`Workout with ID ${workoutId} not found`);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout);\n\t\t}, \"get-workout\"),\n\t);\n\n\t// Get workout count\n\tserver.tool(\n\t\t\"get-workout-count\",\n\t\t\"Get the total number of workouts on the account. Useful for pagination or statistics.\",\n\t\t{},\n\t\twithErrorHandling(async () => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data: GetV1WorkoutsCount200 = await hevyClient.getWorkoutCount();\n\t\t\tconst count = data?.workout_count ?? 0;\n\t\t\treturn createJsonResponse({ count });\n\t\t}, \"get-workout-count\"),\n\t);\n\n\t// Get workout events (updates/deletes)\n\tconst getWorkoutEventsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t\tsince: z.string().default(\"1970-01-01T00:00:00Z\"),\n\t} as const;\n\ttype GetWorkoutEventsParams = InferToolParams<typeof getWorkoutEventsSchema>;\n\n\tserver.tool(\n\t\t\"get-workout-events\",\n\t\t\"Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\",\n\t\tgetWorkoutEventsSchema,\n\t\twithErrorHandling(async (args: GetWorkoutEventsParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { page, pageSize, since } = args;\n\t\t\tconst data: GetV1WorkoutsEvents200 = await hevyClient.getWorkoutEvents({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t\tsince,\n\t\t\t});\n\n\t\t\tconst events = data?.events || [];\n\n\t\t\tif (events.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No workout events found for the specified parameters since ${since}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(events);\n\t\t}, \"get-workout-events\"),\n\t);\n\n\t// Create workout\n\tconst createWorkoutSchema = {\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateWorkoutParams = InferToolParams<typeof createWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"create-workout\",\n\t\t\"Create a new workout in your Hevy account. Requires title, start/end times, and at least one exercise with sets. Returns the complete workout details upon successful creation including the newly assigned workout ID.\",\n\t\tcreateWorkoutSchema,\n\t\twithErrorHandling(async (args: CreateWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { title, description, startTime, endTime, isPrivate, exercises } =\n\t\t\t\targs;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PostV1Workouts201 =\n\t\t\t\tawait hevyClient.createWorkout(requestBody);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create workout: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-workout\"),\n\t);\n\n\t// Update workout\n\tconst updateWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: z\n\t\t\t\t\t\t\t\t.enum([\"warmup\", \"normal\", \"failure\", \"dropset\"])\n\t\t\t\t\t\t\t\t.default(\"normal\"),\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateWorkoutParams = InferToolParams<typeof updateWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"update-workout\",\n\t\t\"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.\",\n\t\tupdateWorkoutSchema,\n\t\twithErrorHandling(async (args: UpdateWorkoutParams) => {\n\t\t\tif (!hevyClient) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"API client not initialized. Please provide HEVY_API_KEY.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tworkoutId,\n\t\t\t\ttitle,\n\t\t\t\tdescription,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisPrivate,\n\t\t\t\texercises,\n\t\t\t} = args;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PutV1WorkoutsWorkoutid200 = await hevyClient.updateWorkout(\n\t\t\t\tworkoutId,\n\t\t\t\trequestBody,\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update workout with ID ${workoutId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"update-workout-operation\"),\n\t);\n}\n","export interface HevyConfig {\n\tapiKey?: string;\n}\n\n/**\n * Parse CLI arguments and environment to derive configuration.\n * Priority order for API key: CLI flag forms > environment variable.\n * Supported CLI arg forms:\n * --hevy-api-key=KEY\n * --hevyApiKey=KEY\n * hevy-api-key=KEY (bare, e.g. when passed after npm start -- )\n */\nexport function parseConfig(\n\targv: string[],\n\tenv: NodeJS.ProcessEnv,\n): HevyConfig {\n\tlet apiKey = \"\";\n\tconst apiKeyArgPatterns = [\n\t\t/^--hevy-api-key=(.+)$/i,\n\t\t/^--hevyApiKey=(.+)$/i,\n\t\t/^hevy-api-key=(.+)$/i,\n\t];\n\tfor (const raw of argv) {\n\t\tfor (const pattern of apiKeyArgPatterns) {\n\t\t\tconst m = raw.match(pattern);\n\t\t\tif (m) {\n\t\t\t\tapiKey = m[1];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (apiKey) break;\n\t}\n\tif (!apiKey) {\n\t\tapiKey = env.HEVY_API_KEY || \"\";\n\t}\n\n\treturn {\n\t\tapiKey,\n\t};\n}\n\nexport function assertApiKey(\n\tapiKey: string | undefined,\n): asserts apiKey is string {\n\tif (!apiKey) {\n\t\tconsole.error(\n\t\t\t\"Hevy API key is required. Provide it via the HEVY_API_KEY environment variable or the --hevy-api-key=YOUR_KEY command argument.\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n GetV1ExerciseHistoryExercisetemplateidPathParams,\n GetV1ExerciseHistoryExercisetemplateidQueryParams,\n GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n GetV1ExerciseHistoryExercisetemplateid400,\n} from \"../types/GetV1ExerciseHistoryExercisetemplateid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_history/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get exercise history for a specific exercise template\n * {@link /v1/exercise_history/:exerciseTemplateId}\n */\nexport async function getV1ExerciseHistoryExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n params?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseHistoryExercisetemplateid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1ExerciseTemplatesQueryResponse,\n GetV1ExerciseTemplatesQueryParams,\n GetV1ExerciseTemplatesHeaderParams,\n GetV1ExerciseTemplates400,\n} from \"../types/GetV1ExerciseTemplates.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseTemplatesUrl() {\n const res = { method: \"GET\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of exercise templates available on the account.\n * {@link /v1/exercise_templates}\n */\nexport async function getV1ExerciseTemplates(\n headers: GetV1ExerciseTemplatesHeaderParams,\n params?: GetV1ExerciseTemplatesQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplates400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n GetV1ExerciseTemplatesExercisetemplateidPathParams,\n GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n GetV1ExerciseTemplatesExercisetemplateid404,\n} from \"../types/GetV1ExerciseTemplatesExercisetemplateid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_templates/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single exercise template by id.\n * {@link /v1/exercise_templates/:exerciseTemplateId}\n */\nexport async function getV1ExerciseTemplatesExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplatesExercisetemplateid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1RoutineFoldersQueryResponse,\n GetV1RoutineFoldersQueryParams,\n GetV1RoutineFoldersHeaderParams,\n GetV1RoutineFolders400,\n} from \"../types/GetV1RoutineFolders.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutineFoldersUrl() {\n const res = { method: \"GET\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routine folders available on the account.\n * {@link /v1/routine_folders}\n */\nexport async function getV1RoutineFolders(\n headers: GetV1RoutineFoldersHeaderParams,\n params?: GetV1RoutineFoldersQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersQueryResponse,\n ResponseErrorConfig<GetV1RoutineFolders400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1RoutineFoldersFolderidQueryResponse,\n GetV1RoutineFoldersFolderidPathParams,\n GetV1RoutineFoldersFolderidHeaderParams,\n GetV1RoutineFoldersFolderid404,\n} from \"../types/GetV1RoutineFoldersFolderid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutineFoldersFolderidUrl(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/routine_folders/${folderId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single routine folder by id.\n * {@link /v1/routine_folders/:folderId}\n */\nexport async function getV1RoutineFoldersFolderid(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n headers: GetV1RoutineFoldersFolderidHeaderParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersFolderidQueryResponse,\n ResponseErrorConfig<GetV1RoutineFoldersFolderid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersFolderidUrl(folderId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1RoutinesQueryResponse,\n GetV1RoutinesQueryParams,\n GetV1RoutinesHeaderParams,\n GetV1Routines400,\n} from \"../types/GetV1Routines.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutinesUrl() {\n const res = { method: \"GET\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routines\n * {@link /v1/routines}\n */\nexport async function getV1Routines(\n headers: GetV1RoutinesHeaderParams,\n params?: GetV1RoutinesQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesQueryResponse,\n ResponseErrorConfig<GetV1Routines400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1RoutinesRoutineidQueryResponse,\n GetV1RoutinesRoutineidPathParams,\n GetV1RoutinesRoutineidHeaderParams,\n GetV1RoutinesRoutineid400,\n} from \"../types/GetV1RoutinesRoutineid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1RoutinesRoutineidUrl(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"GET\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Get a routine by its Id\n * {@link /v1/routines/:routineId}\n */\nexport async function getV1RoutinesRoutineid(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n headers: GetV1RoutinesRoutineidHeaderParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesRoutineidQueryResponse,\n ResponseErrorConfig<GetV1RoutinesRoutineid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesRoutineidUrl(routineId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1WorkoutsQueryResponse,\n GetV1WorkoutsQueryParams,\n GetV1WorkoutsHeaderParams,\n GetV1Workouts400,\n} from \"../types/GetV1Workouts.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of workouts\n * {@link /v1/workouts}\n */\nexport async function getV1Workouts(\n headers: GetV1WorkoutsHeaderParams,\n params?: GetV1WorkoutsQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsQueryResponse,\n ResponseErrorConfig<GetV1Workouts400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1WorkoutsCountQueryResponse,\n GetV1WorkoutsCountHeaderParams,\n} from \"../types/GetV1WorkoutsCount.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsCountUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/count` as const };\n return res;\n}\n\n/**\n * @summary Get the total number of workouts on the account\n * {@link /v1/workouts/count}\n */\nexport async function getV1WorkoutsCount(\n headers: GetV1WorkoutsCountHeaderParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsCountQueryResponse,\n ResponseErrorConfig<Error>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsCountUrl().url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1WorkoutsEventsQueryResponse,\n GetV1WorkoutsEventsQueryParams,\n GetV1WorkoutsEventsHeaderParams,\n GetV1WorkoutsEvents500,\n} from \"../types/GetV1WorkoutsEvents.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsEventsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/events` as const };\n return res;\n}\n\n/**\n * @description Returns a paginated array of workout events, indicating updates or deletions.\n * @summary Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\n * {@link /v1/workouts/events}\n */\nexport async function getV1WorkoutsEvents(\n headers: GetV1WorkoutsEventsHeaderParams,\n params?: GetV1WorkoutsEventsQueryParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsEventsQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsEvents500>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsEventsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n GetV1WorkoutsWorkoutidQueryResponse,\n GetV1WorkoutsWorkoutidPathParams,\n GetV1WorkoutsWorkoutidHeaderParams,\n GetV1WorkoutsWorkoutid404,\n} from \"../types/GetV1WorkoutsWorkoutid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getGetV1WorkoutsWorkoutidUrl(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"GET\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Get a single workout’s complete details by the workoutId\n * {@link /v1/workouts/:workoutId}\n */\nexport async function getV1WorkoutsWorkoutid(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n headers: GetV1WorkoutsWorkoutidHeaderParams,\n config: Partial<RequestConfig> & { client?: typeof fetch } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsWorkoutidQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsWorkoutid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PostV1ExerciseTemplatesMutationRequest,\n PostV1ExerciseTemplatesMutationResponse,\n PostV1ExerciseTemplatesHeaderParams,\n PostV1ExerciseTemplates400,\n PostV1ExerciseTemplates403,\n} from \"../types/PostV1ExerciseTemplates.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1ExerciseTemplatesUrl() {\n const res = { method: \"POST\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Create a new custom exercise template.\n * {@link /v1/exercise_templates}\n */\nexport async function postV1ExerciseTemplates(\n data: PostV1ExerciseTemplatesMutationRequest,\n headers: PostV1ExerciseTemplatesHeaderParams,\n config: Partial<RequestConfig<PostV1ExerciseTemplatesMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1ExerciseTemplatesMutationResponse,\n ResponseErrorConfig<\n PostV1ExerciseTemplates400 | PostV1ExerciseTemplates403\n >,\n PostV1ExerciseTemplatesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1ExerciseTemplatesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PostV1RoutineFoldersMutationRequest,\n PostV1RoutineFoldersMutationResponse,\n PostV1RoutineFoldersHeaderParams,\n PostV1RoutineFolders400,\n} from \"../types/PostV1RoutineFolders.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1RoutineFoldersUrl() {\n const res = { method: \"POST\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine folder. The folder will be created at index 0, and all other folders will have their indexes incremented.\n * {@link /v1/routine_folders}\n */\nexport async function postV1RoutineFolders(\n headers: PostV1RoutineFoldersHeaderParams,\n data?: PostV1RoutineFoldersMutationRequest,\n config: Partial<RequestConfig<PostV1RoutineFoldersMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutineFoldersMutationResponse,\n ResponseErrorConfig<PostV1RoutineFolders400>,\n PostV1RoutineFoldersMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutineFoldersUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PostV1RoutinesMutationRequest,\n PostV1RoutinesMutationResponse,\n PostV1RoutinesHeaderParams,\n PostV1Routines400,\n PostV1Routines403,\n} from \"../types/PostV1Routines.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1RoutinesUrl() {\n const res = { method: \"POST\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine\n * {@link /v1/routines}\n */\nexport async function postV1Routines(\n headers: PostV1RoutinesHeaderParams,\n data?: PostV1RoutinesMutationRequest,\n config: Partial<RequestConfig<PostV1RoutinesMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutinesMutationResponse,\n ResponseErrorConfig<PostV1Routines400 | PostV1Routines403>,\n PostV1RoutinesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutinesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PostV1WorkoutsMutationRequest,\n PostV1WorkoutsMutationResponse,\n PostV1WorkoutsHeaderParams,\n PostV1Workouts400,\n} from \"../types/PostV1Workouts.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPostV1WorkoutsUrl() {\n const res = { method: \"POST\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Create a new workout\n * {@link /v1/workouts}\n */\nexport async function postV1Workouts(\n headers: PostV1WorkoutsHeaderParams,\n data?: PostV1WorkoutsMutationRequest,\n config: Partial<RequestConfig<PostV1WorkoutsMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1WorkoutsMutationResponse,\n ResponseErrorConfig<PostV1Workouts400>,\n PostV1WorkoutsMutationRequest\n >({\n method: \"POST\",\n url: getPostV1WorkoutsUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PutV1RoutinesRoutineidMutationRequest,\n PutV1RoutinesRoutineidMutationResponse,\n PutV1RoutinesRoutineidPathParams,\n PutV1RoutinesRoutineidHeaderParams,\n PutV1RoutinesRoutineid400,\n PutV1RoutinesRoutineid404,\n} from \"../types/PutV1RoutinesRoutineid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPutV1RoutinesRoutineidUrl(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing routine\n * {@link /v1/routines/:routineId}\n */\nexport async function putV1RoutinesRoutineid(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n headers: PutV1RoutinesRoutineidHeaderParams,\n data?: PutV1RoutinesRoutineidMutationRequest,\n config: Partial<RequestConfig<PutV1RoutinesRoutineidMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1RoutinesRoutineidMutationResponse,\n ResponseErrorConfig<PutV1RoutinesRoutineid400 | PutV1RoutinesRoutineid404>,\n PutV1RoutinesRoutineidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1RoutinesRoutineidUrl(routineId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport fetch from \"@kubb/plugin-client/clients/axios\";\nimport type {\n PutV1WorkoutsWorkoutidMutationRequest,\n PutV1WorkoutsWorkoutidMutationResponse,\n PutV1WorkoutsWorkoutidPathParams,\n PutV1WorkoutsWorkoutidHeaderParams,\n PutV1WorkoutsWorkoutid400,\n} from \"../types/PutV1WorkoutsWorkoutid.ts\";\nimport type {\n RequestConfig,\n ResponseErrorConfig,\n} from \"@kubb/plugin-client/clients/axios\";\n\nfunction getPutV1WorkoutsWorkoutidUrl(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing workout\n * {@link /v1/workouts/:workoutId}\n */\nexport async function putV1WorkoutsWorkoutid(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n headers: PutV1WorkoutsWorkoutidHeaderParams,\n data?: PutV1WorkoutsWorkoutidMutationRequest,\n config: Partial<RequestConfig<PutV1WorkoutsWorkoutidMutationRequest>> & {\n client?: typeof fetch;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1WorkoutsWorkoutidMutationResponse,\n ResponseErrorConfig<PutV1WorkoutsWorkoutid400>,\n PutV1WorkoutsWorkoutidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","import type {\n\tRequestConfig,\n\tResponseConfig,\n} from \"@kubb/plugin-client/clients/axios\";\nimport axios from \"axios\";\nimport * as api from \"../generated/client/api\";\nimport type {\n\tGetV1ExerciseHistoryExercisetemplateidQueryParams,\n\tGetV1ExerciseTemplatesQueryParams,\n\tGetV1RoutineFoldersQueryParams,\n\tGetV1RoutinesQueryParams,\n\tGetV1WorkoutsEventsQueryParams,\n\tGetV1WorkoutsQueryParams,\n\tPostV1ExerciseTemplatesMutationRequest,\n\tPostV1RoutineFoldersMutationRequest,\n\tPostV1RoutinesMutationRequest,\n\tPostV1WorkoutsMutationRequest,\n\tPutV1RoutinesRoutineidMutationRequest,\n\tPutV1WorkoutsWorkoutidMutationRequest,\n} from \"../generated/client/types\";\n\n// Define a proper client type that matches the Kubb client interface\ntype KubbClient = {\n\t<TData, _TError = unknown, TVariables = unknown>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>>;\n\tgetConfig: () => Partial<RequestConfig<unknown>>;\n\tsetConfig: (config: RequestConfig) => Partial<RequestConfig<unknown>>;\n};\n\n/**\n * Type-safe wrapper helper that enforces parameter types match the generated API.\n * This prevents arg-order regressions by using Parameters<> to extract expected types.\n *\n * Usage: wrapApi(api.postV1ExerciseTemplates)(data, headers, { client })\n * TypeScript will error if arguments don't match the generated signature.\n */\nfunction wrapApi<T extends (...args: Parameters<T>) => ReturnType<T>>(\n\tfn: T,\n): (...args: Parameters<T>) => ReturnType<T> {\n\treturn fn;\n}\n\ntype CreateWebhookSubscriptionRequest = {\n\twebhook: {\n\t\turl: string;\n\t\tauthToken: string | null;\n\t};\n};\n\nexport function createClient(\n\tapiKey: string,\n\tbaseUrl = \"https://api.hevyapp.com\",\n) {\n\t// Create an axios instance with the API key\n\tconst axiosInstance = axios.create({\n\t\tbaseURL: baseUrl,\n\t\theaders: {\n\t\t\t\"api-key\": apiKey,\n\t\t},\n\t});\n\n\t// Create headers object with API key\n\tconst headers = {\n\t\t\"api-key\": apiKey,\n\t};\n\n\t// Cast axios instance to the expected client type\n\tconst client = axiosInstance as unknown as KubbClient;\n\n\t// Return an object with all the API methods using ReturnType for automatic type inference\n\t// All API calls use wrapApi to ensure TypeScript validates arg order matches generated API\n\treturn {\n\t\t// Workouts\n\t\tgetWorkouts: (\n\t\t\tparams?: GetV1WorkoutsQueryParams,\n\t\t): ReturnType<typeof api.getV1Workouts> =>\n\t\t\twrapApi(api.getV1Workouts)(headers, params, { client }),\n\t\tgetWorkout: (\n\t\t\tworkoutId: string,\n\t\t): ReturnType<typeof api.getV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.getV1WorkoutsWorkoutid)(workoutId, headers, { client }),\n\t\tcreateWorkout: (\n\t\t\tdata: PostV1WorkoutsMutationRequest,\n\t\t): ReturnType<typeof api.postV1Workouts> =>\n\t\t\twrapApi(api.postV1Workouts)(headers, data, { client }),\n\t\tupdateWorkout: (\n\t\t\tworkoutId: string,\n\t\t\tdata: PutV1WorkoutsWorkoutidMutationRequest,\n\t\t): ReturnType<typeof api.putV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.putV1WorkoutsWorkoutid)(workoutId, headers, data, {\n\t\t\t\tclient,\n\t\t\t}),\n\t\tgetWorkoutCount: (): ReturnType<typeof api.getV1WorkoutsCount> =>\n\t\t\twrapApi(api.getV1WorkoutsCount)(headers, { client }),\n\t\tgetWorkoutEvents: (\n\t\t\tparams?: GetV1WorkoutsEventsQueryParams,\n\t\t): ReturnType<typeof api.getV1WorkoutsEvents> =>\n\t\t\twrapApi(api.getV1WorkoutsEvents)(headers, params, { client }),\n\n\t\t// Routines\n\t\tgetRoutines: (\n\t\t\tparams?: GetV1RoutinesQueryParams,\n\t\t): ReturnType<typeof api.getV1Routines> =>\n\t\t\twrapApi(api.getV1Routines)(headers, params, { client }),\n\t\tgetRoutineById: (\n\t\t\troutineId: string,\n\t\t): ReturnType<typeof api.getV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.getV1RoutinesRoutineid)(routineId, headers, { client }),\n\t\tcreateRoutine: (\n\t\t\tdata: PostV1RoutinesMutationRequest,\n\t\t): ReturnType<typeof api.postV1Routines> =>\n\t\t\twrapApi(api.postV1Routines)(headers, data, { client }),\n\t\tupdateRoutine: (\n\t\t\troutineId: string,\n\t\t\tdata: PutV1RoutinesRoutineidMutationRequest,\n\t\t): ReturnType<typeof api.putV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.putV1RoutinesRoutineid)(routineId, headers, data, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Exercise Templates\n\t\tgetExerciseTemplates: (\n\t\t\tparams?: GetV1ExerciseTemplatesQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplates> =>\n\t\t\twrapApi(api.getV1ExerciseTemplates)(headers, params, { client }),\n\t\tgetExerciseTemplate: (\n\t\t\ttemplateId: string,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplatesExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseTemplatesExercisetemplateid)(\n\t\t\t\ttemplateId,\n\t\t\t\theaders,\n\t\t\t\t{\n\t\t\t\t\tclient,\n\t\t\t\t},\n\t\t\t),\n\t\tgetExerciseHistory: (\n\t\t\texerciseTemplateId: string,\n\t\t\tparams?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseHistoryExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseHistoryExercisetemplateid)(\n\t\t\t\texerciseTemplateId,\n\t\t\t\theaders,\n\t\t\t\tparams,\n\t\t\t\t{ client },\n\t\t\t),\n\t\tcreateExerciseTemplate: (\n\t\t\tdata: PostV1ExerciseTemplatesMutationRequest,\n\t\t): ReturnType<typeof api.postV1ExerciseTemplates> =>\n\t\t\twrapApi(api.postV1ExerciseTemplates)(data, headers, { client }),\n\n\t\t// Routine Folders\n\t\tgetRoutineFolders: (\n\t\t\tparams?: GetV1RoutineFoldersQueryParams,\n\t\t): ReturnType<typeof api.getV1RoutineFolders> =>\n\t\t\twrapApi(api.getV1RoutineFolders)(headers, params, { client }),\n\t\tcreateRoutineFolder: (\n\t\t\tdata: PostV1RoutineFoldersMutationRequest,\n\t\t): ReturnType<typeof api.postV1RoutineFolders> =>\n\t\t\twrapApi(api.postV1RoutineFolders)(headers, data, { client }),\n\t\tgetRoutineFolder: (\n\t\t\tfolderId: string,\n\t\t): ReturnType<typeof api.getV1RoutineFoldersFolderid> =>\n\t\t\twrapApi(api.getV1RoutineFoldersFolderid)(folderId, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\tgetWebhookSubscription: async (): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t\tcreateWebhookSubscription: async (\n\t\t\t_data: CreateWebhookSubscriptionRequest,\n\t\t): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t\tdeleteWebhookSubscription: async (): Promise<unknown> => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Webhook subscription API not available. Please regenerate the client from the updated OpenAPI spec.\",\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Type representing the Hevy API client returned by createClient.\n * Useful for typing variables that hold the client instance.\n */\nexport type HevyApiClient = ReturnType<typeof createClient>;\n","// Import the Kubb-based client\nimport { createClient as createKubbClient } from \"./hevyClientKubb.js\";\n\nexport function createClient(apiKey: string, baseUrl: string) {\n\treturn createKubbClient(apiKey, baseUrl);\n}\n\n// Export the HevyClient type for use in other modules\nexport type HevyClient = ReturnType<typeof createClient>;\n","import * as Sentry from \"@sentry/node\";\n\ndeclare const __HEVY_MCP_NAME__: string | undefined;\ndeclare const __HEVY_MCP_VERSION__: string | undefined;\ndeclare const __HEVY_MCP_BUILD__: boolean | undefined;\n\nconst isBuiltArtifact =\n\ttypeof __HEVY_MCP_BUILD__ === \"boolean\" ? __HEVY_MCP_BUILD__ : false;\nif (\n\tisBuiltArtifact &&\n\t(typeof __HEVY_MCP_NAME__ !== \"string\" ||\n\t\ttypeof __HEVY_MCP_VERSION__ !== \"string\")\n) {\n\tthrow new Error(\n\t\t\"Build-time variables __HEVY_MCP_NAME__ and __HEVY_MCP_VERSION__ must be defined.\",\n\t);\n}\n\nconst name =\n\ttypeof __HEVY_MCP_NAME__ === \"string\" ? __HEVY_MCP_NAME__ : \"hevy-mcp\";\nconst version =\n\ttypeof __HEVY_MCP_VERSION__ === \"string\" ? __HEVY_MCP_VERSION__ : \"dev\";\n\n// Environment variables are loaded via Node.js native --env-file flag (Node.js 20.6+)\n// or set directly in the environment. No dotenv dependency needed.\n// This avoids stdout pollution that corrupts MCP JSON-RPC communication in stdio mode.\n\n// Sentry monitoring is baked into the built MCP server so usage and errors\n// from users of the published package are captured for observability.\nconst sentryRelease = process.env.SENTRY_RELEASE ?? `${name}@${version}`;\nconst sentryConfig = {\n\tdsn: \"https://ce696d8333b507acbf5203eb877bce0f@o4508975499575296.ingest.de.sentry.io/4509049671647312\",\n\trelease: sentryRelease,\n\t// Tracing must be enabled for MCP monitoring to work\n\ttracesSampleRate: 1.0,\n\tsendDefaultPii: false,\n} as const;\n\nSentry.init(sentryConfig);\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { registerFolderTools } from \"./tools/folders.js\";\nimport { registerRoutineTools } from \"./tools/routines.js\";\nimport { registerTemplateTools } from \"./tools/templates.js\";\nimport { registerWebhookTools } from \"./tools/webhooks.js\";\nimport { registerWorkoutTools } from \"./tools/workouts.js\";\nimport { assertApiKey, parseConfig } from \"./utils/config.js\";\nimport { createClient } from \"./utils/hevyClient.js\";\n\nconst HEVY_API_BASEURL = \"https://api.hevyapp.com\";\n\nconst serverConfigSchema = z.object({\n\tapiKey: z\n\t\t.string()\n\t\t.min(1, \"Hevy API key is required\")\n\t\t.describe(\"Your Hevy API key (available in the Hevy app settings).\"),\n});\n\nexport const configSchema = serverConfigSchema;\ntype ServerConfig = z.infer<typeof serverConfigSchema>;\n\nfunction buildServer(apiKey: string) {\n\tconst baseServer = new McpServer({\n\t\tname,\n\t\tversion,\n\t});\n\tconst server = Sentry.wrapMcpServerWithSentry(baseServer);\n\n\tconst hevyClient = createClient(apiKey, HEVY_API_BASEURL);\n\tconsole.error(\"Hevy client initialized with API key\");\n\n\tregisterWorkoutTools(server, hevyClient);\n\tregisterRoutineTools(server, hevyClient);\n\tregisterTemplateTools(server, hevyClient);\n\tregisterFolderTools(server, hevyClient);\n\tregisterWebhookTools(server, hevyClient);\n\n\treturn server;\n}\n\nexport default function createServer({ config }: { config: ServerConfig }) {\n\tconst { apiKey } = serverConfigSchema.parse(config);\n\tconst server = buildServer(apiKey);\n\treturn server;\n}\n\nexport async function runServer() {\n\tconst args = process.argv.slice(2);\n\tconst cfg = parseConfig(args, process.env);\n\tconst apiKey = cfg.apiKey;\n\tassertApiKey(apiKey);\n\n\tconst server = buildServer(apiKey);\n\tconsole.error(\"Starting MCP server in stdio mode\");\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"],"mappings":"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"}
|