import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
// Import types from generated client
import type { ExerciseTemplate } from "../generated/client/types/index.js";
import { withErrorHandling } from "../utils/error-handler.js";
import { formatExerciseTemplate } from "../utils/formatters.js";
import {
createEmptyResponse,
createJsonResponse,
} from "../utils/response-formatter.js";
import type { InferToolParams } from "../utils/tool-helpers.js";
// Type definitions for the template operations
type HevyClient = ReturnType<
typeof import("../utils/hevyClientKubb.js").createClient
>;
/**
* Register all exercise template-related tools with the MCP server
*/
export function registerTemplateTools(
server: McpServer,
hevyClient: HevyClient | null,
) {
// Get exercise templates
const getExerciseTemplatesSchema = {
page: z.coerce.number().int().gte(1).default(1),
pageSize: z.coerce.number().int().gte(1).lte(100).default(5),
} as const;
type GetExerciseTemplatesParams = InferToolParams<
typeof getExerciseTemplatesSchema
>;
server.tool(
"get-exercise-templates",
"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.",
getExerciseTemplatesSchema,
withErrorHandling(async (args: GetExerciseTemplatesParams) => {
if (!hevyClient) {
throw new Error(
"API client not initialized. Please provide HEVY_API_KEY.",
);
}
const { page, pageSize } = args;
const data = await hevyClient.getExerciseTemplates({
page,
pageSize,
});
// Process exercise templates to extract relevant information
const templates =
data?.exercise_templates?.map((template: ExerciseTemplate) =>
formatExerciseTemplate(template),
) || [];
if (templates.length === 0) {
return createEmptyResponse(
"No exercise templates found for the specified parameters",
);
}
return createJsonResponse(templates);
}, "get-exercise-templates"),
);
// Get single exercise template by ID
const getExerciseTemplateSchema = {
exerciseTemplateId: z.string().min(1),
} as const;
type GetExerciseTemplateParams = InferToolParams<
typeof getExerciseTemplateSchema
>;
server.tool(
"get-exercise-template",
"Get complete details of a specific exercise template by its ID, including name, category, equipment, muscle groups, and notes.",
getExerciseTemplateSchema,
withErrorHandling(async (args: GetExerciseTemplateParams) => {
if (!hevyClient) {
throw new Error(
"API client not initialized. Please provide HEVY_API_KEY.",
);
}
const { exerciseTemplateId } = args;
const data = await hevyClient.getExerciseTemplate(exerciseTemplateId);
if (!data) {
return createEmptyResponse(
`Exercise template with ID ${exerciseTemplateId} not found`,
);
}
const template = formatExerciseTemplate(data);
return createJsonResponse(template);
}, "get-exercise-template"),
);
}