feat(training-history): date filtering, pagination, and detail tiers#2
Open
dcaslin wants to merge 1 commit into
Open
feat(training-history): date filtering, pagination, and detail tiers#2dcaslin wants to merge 1 commit into
dcaslin wants to merge 1 commit into
Conversation
4113924 to
d5ba09a
Compare
get_training_history returned the user's entire history in one blob (~3.4 MB on a real account, 98.9% of it per-set records data), which MCP clients reject with "result too large". The upstream /programs/history endpoint only accepts timezone_offset, so all shaping is done client-side. Adds optional, backward-compatible params: - start_date / end_date: inclusive YYYY-MM-DD date-range filter - detail: "summary" (default) or "full" - page / page_size: walk large histories in chunks (has_more flag) Summary mode returns per-workout date/program/exercises/total_volume (~500B each); full mode adds records with each set slimmed to the meaningful fields (weight, reps, target, rpe, skipped, weight_unit). page_size is capped per tier (summary <= 100, full <= 25) as a truncation guardrail, and every response carries pagination, filters, and a hint for fetching more. Superset records (which carry no name/sets of their own, only a `supersets` child list) are flattened so each child exercise is listed individually and its sets count toward total_volume — previously these surfaced as a null exercise and their volume was silently dropped. In full detail the children keep a `superset` id so the grouping stays visible. Volume_unit is read from any set declaring a weight_unit so bodyweight/skipped-only days report a unit instead of null. Transforms live in a new pure module src/boostcamp_mcp/history.py and are covered by 27 unit tests (no network). A bare call now returns the summary of the 50 most recent workouts (~2.5 KB) instead of the full dump. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d5ba09a to
39f388c
Compare
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
get_training_historyreturns the user's entire workout history in one JSONblob. On a representative account that's 231 workouts / ~3.4 MB, of which
98.9% is the per-set
recordsdata (sets average ~14.6 KB/workout, dominatedby redundant fields like
previous_*,archived_*,valueEmpty). MCP clients(e.g. Claude Desktop) reject it with "result too large", so the tool is
effectively unusable on any account with real history.
The upstream
/programs/historyendpoint accepts onlytimezone_offsetandreturns everything grouped by date — there are no server-side filtering or
pagination knobs. So all shaping is done client-side in the MCP server.
What changed
get_training_historygains optional parameters (all backward-compatible — abare call still works, now bounded and useful):
start_date/end_dateYYYY-MM-DDdate-range filterdetailsummary(default) orfullpage/page_sizehas_moreflag)summary(default): per workout — date, title, program, week/day,exercise_count, exercise names, and computedtotal_volume. ~500 bytes each.full: addsrecordswith each set slimmed to the meaningful fields(
weight,reps,target,rpe,skipped,weight_unit), dropping theredundant bloat. Roughly halves full-mode size with no analytical loss.
page_sizeis capped per tier (summary ≤ 100, full ≤ 25) so nosingle response can blow past the client limit regardless of arguments.
pagination(incl.has_more),filters, and ahinttelling the model how to fetch more.A bare
get_training_history()now returns the summary of the 50 most recentworkouts instead of the full 3.4 MB dump.
Architecture
All transforms live in a new pure module
src/boostcamp_mcp/history.py(flatten → date-filter → newest-first sort → detail-shape → paginate →
envelope).
server.pyvalidates params, calls the API once, delegates tohistory.shape_history, and returns JSON. The pure module is fully unit-testedwith no network.
Test plan
uv run pytest— 22 unit tests covering set slimming, volume math(skipped/empty sets), summary/full shaping, date-filter boundaries,
newest-first ordering, pagination edges, page_size caps, and validation.
has_more: truedetail="full"(3 workouts): ~12 KB with slimmed setsstart_date="2026-04-07": 20 workouts, correct filteringError: start_date must be YYYY-MM-DDmessageDesign and implementation notes:
docs/superpowers/specs/2026-06-12-training-history-pagination-design.md.🤖 Generated with Claude Code