Skip to content

Commit 540c5eb

Browse files
fix: keep MCP stdio clean on routine update errors (#330)
Co-authored-by: CharlieHelps <charlie@charlielabs.ai>
1 parent 8dbd99c commit 540c5eb

4 files changed

Lines changed: 74 additions & 9 deletions

File tree

src/tools/routines.test.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,69 @@ describe("registerRoutineTools", () => {
579579
expect(response.content).toHaveLength(1);
580580
});
581581

582+
it("update-routine omits rep_range when repRange does not contain values", async () => {
583+
const { server, tool } = createMockServer();
584+
const routine: Routine = {
585+
id: "updated-routine",
586+
title: "Updated Routine",
587+
folder_id: null,
588+
created_at: "2025-03-26T19:00:00Z",
589+
updated_at: "2025-03-26T19:30:00Z",
590+
exercises: [],
591+
};
592+
const updateRoutineMock = vi.fn().mockResolvedValue(routine);
593+
const hevyClient: HevyClient = {
594+
updateRoutine: updateRoutineMock,
595+
} as unknown as HevyClient;
596+
597+
registerRoutineTools(server, hevyClient);
598+
const { handler } = getToolRegistration(tool, "update-routine");
599+
600+
await handler({
601+
routineId: "routine-123",
602+
title: "Updated Routine",
603+
exercises: [
604+
{
605+
exerciseTemplateId: "template-id",
606+
supersetId: null,
607+
restSeconds: 90,
608+
sets: [
609+
{
610+
type: "normal" as const,
611+
weightKg: 100,
612+
reps: 10,
613+
repRange: { start: null, end: null },
614+
},
615+
],
616+
},
617+
],
618+
} as Record<string, unknown>);
619+
620+
expect(updateRoutineMock).toHaveBeenCalledWith(
621+
"routine-123",
622+
expect.objectContaining({
623+
routine: expect.objectContaining({
624+
exercises: [
625+
expect.objectContaining({
626+
sets: [expect.objectContaining({ reps: 10 })],
627+
}),
628+
],
629+
}),
630+
}),
631+
);
632+
633+
const updatePayload = updateRoutineMock.mock.calls[0]?.[1] as {
634+
routine: {
635+
exercises: Array<{
636+
sets: Array<Record<string, unknown>>;
637+
}>;
638+
};
639+
};
640+
expect(updatePayload.routine.exercises[0]?.sets[0]).not.toHaveProperty(
641+
"rep_range",
642+
);
643+
});
644+
582645
it("update-routine includes a rep range display warning when repRange is provided", async () => {
583646
const { server, tool } = createMockServer();
584647
const routine: Routine = {
@@ -685,7 +748,6 @@ describe("registerRoutineTools", () => {
685748
distance_meters: null,
686749
duration_seconds: null,
687750
custom_metric: null,
688-
rep_range: null,
689751
},
690752
],
691753
},

src/tools/routines.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ export function registerRoutineTools(
375375
distance_meters: set.distance ?? set.distanceMeters ?? null,
376376
duration_seconds: set.duration ?? set.durationSeconds ?? null,
377377
custom_metric: set.customMetric ?? null,
378-
rep_range: repRange,
378+
...(repRange ? { rep_range: repRange } : {}),
379379
};
380380
});
381381

src/utils/error-handler.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ describe("Error Handler", () => {
6666
const response = createErrorResponse(errorWithCode);
6767

6868
expect(response.content[0].text).toBe("Error: Error with code");
69-
expect(console.debug).toHaveBeenCalledWith("Error code: ERR_TEST_CODE");
69+
expect(console.debug).not.toHaveBeenCalled();
70+
expect(console.error).toHaveBeenCalledWith(
71+
expect.stringContaining("Code: ERR_TEST_CODE"),
72+
errorWithCode,
73+
);
7074
});
7175

7276
it("classifies network-related errors as NETWORK_ERROR", () => {

src/utils/error-handler.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,15 @@ export function createErrorResponse(
7070
// Determine error type based on error characteristics
7171
const errorType = determineErrorType(error, errorMessage);
7272

73-
// Include error code in logs if available
74-
if (errorCode) {
75-
console.debug(`Error code: ${errorCode}`);
76-
}
77-
7873
const contextPrefix = context ? `[${context}] ` : "";
7974
const formattedMessage = `${contextPrefix}Error: ${errorMessage}`;
75+
const errorCodeSuffix = errorCode ? `, Code: ${errorCode}` : "";
8076

8177
// Log the error for server-side debugging with type information
82-
console.error(`${formattedMessage} (Type: ${errorType})`, error);
78+
console.error(
79+
`${formattedMessage} (Type: ${errorType}${errorCodeSuffix})`,
80+
error,
81+
);
8382

8483
return {
8584
content: [

0 commit comments

Comments
 (0)