Skip to content

fix(mcp): the read tools answer the question that was asked - #355

Merged
DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/mcp-read-tools
Oct 7, 2026
Merged

DuarteSantos8 merged 1 commit into
DuarteSantos8:mainfrom
kurktchiev:gh/mcp-read-tools

Conversation

@kurktchiev

Copy link
Copy Markdown
Contributor

Seven places where an MCP answer was wrong and gave no sign of it. All in mcp/src/tools.js.

"What are my PRs?" prTable scanned the rows itself with the rule from before #212. A one-arm
set is one row carrying both sides, so its r is L+R. A dumbbell curl logged 8+8 read as 16 reps,
over the 12-rep cap, and got no estimate. A row with one side still unchecked was not done, though
the finished side is completed work. So the exercise had a 1RM in the per-exercise answer and no
line in the table. The table also listed assistance machines, which the app keeps out of every
estimate (#232). prTable now calls bestSetOf per entry, the same reading the per-exercise answer
and the app use.

"How many workouts in March?" list_workouts returns total_count, which is all-time and
counted before the from/to filter, and a list cut at 25 with nothing saying so. 25 rows and a total
of 340 say nothing about the 40 in March. New fields: matching_count (in the range asked for) and
truncated. total_count keeps its meaning.

A made-up exercise id read as "never trained". exOr's miss is a placeholder, not null, so a
typo'd exercise_id got "No completed sets logged for this exercise". It now says no exercise with
that id exists and sets exercise.unknown. A deleted custom exercise with logged sets keeps the real
answer. An empty exercise_id fell through to the whole PR table; it is now rejected as invalid
params.

2026-02-30 was answered as March 2. The date regex let it through and new Date() rolled it
over, so preview_session answered for March 2 while echoing "2026-02-30" back. Every date argument
(list_workouts, get_workout, get_bodyweight, preview_session) now has to round-trip through
the calendar, so an impossible date is a -32602 before any handler runs. 2024-02-29 passes,
2025-02-29 does not.

to had no default. list_workouts and get_bodyweight document it as "Defaults to today". A
row dated in the future (another device with a wrong clock) was listed first as the newest session
and became latest in the body-weight summary. It now falls back to the local today; asking for a
future range explicitly still returns the row.

"Last 7 days" covered 8 dates. muscle_balance cut off at an instant 7×24 h back. A workout
with no clock (an import, a hand-added session) counts at local noon, so noon seven days ago was
still inside the window: 8 dates for a week, 31 for a month. The window is now whole local days
counting today, 7 and 30.

Its cutoff_iso was a UTC date. toISOString().slice(0, 10) gave a date a day off from the one
the filter used, in the evening west of Greenwich and in the morning east of it. It is local now,
like every other date the API reports.

11 new tests in mcp/test/tools.test.js, which now has 74, all passing. 10 of the 11 fail against the
old tools.js; the eleventh checks that real dates, including a leap day, still get through. The
date and empty-id tests drive the real McpServer over an in-memory transport, because what they
test is what zod does before a handler runs. The cutoff test runs in Asia/Tokyo, where the UTC and
local dates differ. check:node-loadable is clean.

Overlaps:

🤖 Generated with Claude Code

Seven places where an MCP answer was confidently wrong.

- "What are my PRs?": estimate_1rm's PR table scanned the rows itself
  with the rule from before DuarteSantos8#212. A one-arm set is one row carrying both
  sides, so its `r` is L+R; 8+8 reps read as 16, over the 12-rep cap, and
  a dumbbell curl had a 1RM and no line in the table. An assistance
  machine, which the app keeps out of every estimate (DuarteSantos8#232), was listed.
  prTable now asks bestSetOf per entry, as the per-exercise answer does.
- "How many workouts in March?": list_workouts' total_count is all-time
  and the list stops at 25 without saying so. New matching_count (in the
  from/to range) and truncated. total_count keeps its meaning.
- A made-up exercise_id read "No completed sets logged for this
  exercise", because exOr's miss is a placeholder, not null. It now says
  no exercise with that id exists and sets exercise.unknown. A deleted
  custom with logged sets keeps the real answer. An empty exercise_id,
  which fell through to the whole PR table, is now invalid params.
- 2026-02-30 passed the date regex and new Date() rolled it to March 2,
  so preview_session answered for March 2 while echoing February 30.
  Every date argument now has to round-trip through the calendar, so an
  impossible date is a -32602 before any handler runs.
- `to` is documented as "Defaults to today" in list_workouts and
  get_bodyweight and had no default. A row dated in the future (another
  device with a wrong clock) was listed first and became `latest`.
- muscle_balance's "last 7 days" was an instant 7x24h back. A workout
  with no clock (an import, a hand-added session) counts at local noon,
  so the week covered 8 dates and the month 31. The window is now whole
  local days counting today: 7 dates, and 30.
- Its cutoff_iso was toISOString(), a UTC date: a day off from the date
  the filter used in the evening west of Greenwich and in the morning
  east of it. It is a local date now, like every other date in the API.

11 new tests in mcp/test/tools.test.js (now 74). 10 fail against the old
tools.js; the eleventh checks a real leap day still gets through.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@DuarteSantos8
DuarteSantos8 merged commit ad9634b into DuarteSantos8:main Oct 7, 2026
4 checks passed
@DuarteSantos8

Copy link
Copy Markdown
Owner

Merged and released in v1.3.10, thanks @kurktchiev!

https://github.com/DuarteSantos8/openGym/releases/tag/v1.3.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants