Skip to content

Add tool annotations and fix body measurement payload handling#342

Merged
chrisdoc merged 5 commits into
mainfrom
claude/hevy-mcp-improvements-ma7dhn
Jun 13, 2026
Merged

Add tool annotations and fix body measurement payload handling#342
chrisdoc merged 5 commits into
mainfrom
claude/hevy-mcp-improvements-ma7dhn

Conversation

@chrisdoc

@chrisdoc chrisdoc commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds MCP tool annotations to all registered tools and fixes the body measurement update endpoint to only send non-null fields to the API, resolving an issue where omitted fields were being set to null.

Key Changes

  • Tool Annotations: Added tool-annotations.ts utility with factory functions (readOnlyAnnotations, createAnnotations, updateAnnotations, destructiveAnnotations) and applied them to all tools across workouts, routines, templates, folders, webhooks, body measurements, and user info tools. Each annotation includes a title and appropriate hints for read-only, destructive, and idempotent operations.

  • Body Measurement Payload Handling: Refactored buildMeasurementPayload() to only include fields with actual values (non-null) in the API request, fixing issue body measurement tools reject valid partial inputs #341 where the Hevy API was rejecting null values for omitted fields. The function now iterates through provided fields and only adds them to the payload if they have a value.

  • Numeric Coercion: Updated body measurement field schema to use z.coerce.number() to handle numeric strings from MCP clients that serialize numbers as strings, while preserving null values.

  • User Tools: Added new user.ts tool module with get-user-info endpoint to retrieve authenticated user account information (ID, display name, profile URL).

  • Test Coverage: Added comprehensive test suite in annotations.test.ts verifying all tools have proper annotations with correct hints. Added user.test.ts for user info tool. Enhanced body measurement tests to verify payload construction, field mapping, numeric coercion, and null handling.

  • Test Refactoring: Updated test helper functions across all tool test files to use more flexible extraction patterns (match.at(-1)) to accommodate the new annotations parameter in tool registration.

  • Documentation: Updated README.md to include body measurements and user info in the available tools table.

  • Dependencies: Moved Kubb CLI and plugin packages from dependencies to devDependencies since they're only needed for code generation, not runtime.

Notable Implementation Details

  • The MEASUREMENT_FIELD_TO_API_KEY mapping ensures consistent field name translation from camelCase (tool input) to snake_case (API format).
  • Tool annotations follow a consistent pattern: all tools have openWorldHint: false since they operate on a closed, authenticated domain.
  • The payload builder uses a type-safe approach with satisfies to ensure the mapping covers all measurement fields.

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8

Summary by CodeRabbit

  • New Features

    • Added get-user-info tool to fetch user account info from the backend.
    • Body-measurement tools now accept numeric strings, preserve explicit nulls, and omit empty/unspecified fields from requests.
  • Documentation

    • Updated README’s "Available MCP Tools" table with clarified and expanded tool listings.
  • Tests

    • Added/updated unit tests covering tool registration, annotations, and body-measurement parsing/validation.

✨ PR Description

Purpose: Add MCP tool annotations and fix body measurement payload handling to exclude null fields from API requests.

Main changes:

  • Created tool-annotations utility with readOnlyAnnotations, createAnnotations, updateAnnotations, and destructiveAnnotations factories for consistent MCP metadata
  • Refactored body measurement payload builder to omit null fields instead of including them, preventing API rejection (issue body measurement tools reject valid partial inputs #341)
  • Added zNullableNumber preprocessor to coerce numeric strings and treat empty strings as undefined, plus new get-user-info tool and comprehensive annotation test suite

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how

claude added 4 commits June 12, 2026 06:58
Six @kubb/* packages were declared as runtime dependencies but are only
used by `npm run build:client` (kubb generate). Keeping them in
dependencies made `npx hevy-mcp` installs resolve their caret ranges
directly, which broke whenever an unpublished @kubb version was
referenced (#322). Only @kubb/plugin-client is imported at runtime by
the generated client, so it stays in dependencies.

Also syncs package-lock.json, which was missing yaml@2.9.0.

Fixes #322

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8
Two bugs prevented valid body measurement writes (#341):

- Measurement fields used strict z.number(), rejecting numeric strings
  like "81.5" that some MCP clients send. They now use
  z.coerce.number() like the other tools, while null/undefined still
  short-circuit before coercion.
- buildMeasurementPayload() forwarded every omitted field as null,
  which the Hevy API rejects. Nullish fields are now omitted from the
  payload entirely, for both create and update.

Fixes #341

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8
Exposes the Hevy API's GET /v1/user/info endpoint, which existed in the
generated client but had no MCP tool. Returns the authenticated user's
ID, display name, and public profile URL — useful for verifying which
account an API key belongs to.

Also refreshes the README tools table, which was stale
(get-routine-by-id, missing body measurement and exercise template
tools).

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8
Every tool now declares title, readOnlyHint, destructiveHint,
idempotentHint, and openWorldHint so MCP clients can render tools
properly and decide when calls are safe to auto-approve:

- get-*/search-* tools are marked read-only
- create-* tools are non-destructive, non-idempotent writes
- update-* tools are destructive (PUT-style overwrites) and idempotent
- delete-webhook-subscription is destructive and idempotent
- openWorldHint is false everywhere since the Hevy API is a closed
  domain limited to the authenticated user's data

Shared annotation factories live in src/utils/tool-annotations.ts and a
new annotations.test.ts asserts the policy for all 26 tools. Test
helpers now extract handlers position-independently so the added
registration argument doesn't break them.

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8
Copilot AI review requested due to automatic review settings June 12, 2026 07:04
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds shared MCP tool annotation factories, registers a new get-user-info tool and Hevy client getter, refactors body-measurement schema/payload to coerce numeric strings and omit null/undefined fields, applies annotations across tools, standardizes test helpers, and adds validation tests and README/package.json updates.

Changes

Tool Annotations & User Info Integration

Layer / File(s) Summary
Tool Annotations Infrastructure
src/utils/tool-annotations.ts
Adds readOnlyAnnotations, createAnnotations, updateAnnotations, and destructiveAnnotations factories that return configured ToolAnnotations objects (all set openWorldHint: false).
User Tools Feature
src/tools/user.ts, src/tools/user.test.ts, src/utils/hevyClientKubb.ts
Adds registerUserTools registering get-user-info on the MCP server, adds getUserInfo() to the Hevy client wrapper, and tests null-client, success, and empty-data behaviors.
Body Measurements Refactoring
src/tools/body-measurements.ts, src/tools/body-measurements.test.ts
Switches measurement parsing to preprocess/coerce numeric strings (preserve null, treat empty string as omitted), centralizes MEASUREMENT_FIELD_TO_API_KEY, builds payloads that omit null/undefined fields, prevents empty update payloads, and expands tests for coercion, omission, mapping, and empty-update rejection.
Apply Annotations to Existing Tools & Test Helpers
src/tools/routines.ts, src/tools/workouts.ts, src/tools/templates.ts, src/tools/folders.ts, src/tools/webhooks.ts, and multiple *.test.ts
Applies annotation helpers to existing tool registrations by operation type and standardizes test helpers to extract tool schema/handler from mock calls using indexed/last-element access.
Annotation Validation Test Suite
src/tools/annotations.test.ts
Adds a suite that registers all tools against a mock MCP server and asserts registration, non-empty titles, openWorldHint=false, and correct readOnlyHint/destructiveHint/idempotentHint flags via table-driven tests.
Server Integration & Documentation
src/index.ts, README.md, package.json
Wires registerUserTools into server build, updates README "Available MCP Tools" table, and moves several @kubb/* packages from dependencies to devDependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested labels

20 min review

🐰 I hopped through code to make tools play,
Annotations tagged the proper way,
User info fetched, numbers coerce true,
Nulls omitted — payloads trimmed anew,
Tests dance lightly, README sings hooray! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Add tool annotations and fix body measurement payload handling' accurately summarizes the two main objectives: adding tool annotations across the codebase and fixing body measurement payload construction to omit null values.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/hevy-mcp-improvements-ma7dhn

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.29630% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 70.63%. Comparing base (bfe5f82) to head (c71a88f).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/utils/hevyClientKubb.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #342      +/-   ##
==========================================
+ Coverage   70.28%   70.63%   +0.34%     
==========================================
  Files          15       17       +2     
  Lines         589      596       +7     
  Branches      200      188      -12     
==========================================
+ Hits          414      421       +7     
- Misses        100      101       +1     
+ Partials       75       74       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gitstream-cm gitstream-cm Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨ PR Review

LGTM

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Review using Guidelines Learn how

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request registers a new get-user-info tool, implements shared MCP tool annotations across all tools, refactors body measurement payload construction to omit null/undefined fields, and moves several @kubb dependencies to devDependencies. The review feedback identifies two key issues in src/tools/body-measurements.ts: an inconsistency where explicit null values intended to clear fields are silently omitted from the payload, and a potential bug where z.coerce.number() coorces empty strings to 0 instead of treating them as omitted.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +101 to +104
const value = args[camelKey];
if (value != null) {
payload[apiKey] = value;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is an inconsistency between the Zod schema and the payload construction.

The schema zNullableNumber uses .nullable().optional(), which allows clients to explicitly pass null (presumably to clear a measurement value). However, buildMeasurementPayload uses value != null to filter out both undefined and null values. This means any explicit null passed by the client to clear a field will be silently omitted from the API payload, resulting in no change to that field on the server.

Depending on whether the Hevy API supports clearing fields by setting them to null:

  1. If the API supports null to clear fields:
    Change the check to value !== undefined so that explicit nulls are preserved and sent to the API, while omitted (undefined) fields are excluded.
  2. If the API does not support null at all:
    Remove .nullable() from zNullableNumber so the schema accurately reflects that null is not a valid input.
Suggested change
const value = args[camelKey];
if (value != null) {
payload[apiKey] = value;
}
const value = args[camelKey];
if (value !== undefined) {
payload[apiKey] = value;
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with a third option in c71a88f: the Hevy API rejects null field values outright (that's the root cause of #341), so option 1 isn't possible — there is no way to clear a field via the API. Removing .nullable() (option 2) would break the lenient MCP clients that send null for unspecified fields, which is the exact scenario #341 was filed about. So null stays accepted and treated as omitted, and both tool descriptions now state this explicitly instead of leaving it silent. update-body-measurement additionally errors if no non-null field remains, so a null-only call surfaces a diagnostic rather than a misleading success.


Generated by Claude Code

Comment thread src/tools/body-measurements.ts Outdated
// Coerce numeric strings ("81.5") since some MCP clients serialize numbers
// as strings; nullable()/optional() short-circuit before coercion, so null
// stays null instead of becoming 0.
const zNullableNumber = z.coerce.number().nullable().optional();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using z.coerce.number() will coerce empty strings ("") to 0 because Number("") evaluates to 0 in JavaScript. If an MCP client serializes an empty or cleared input field as an empty string, it will be saved as 0 (e.g., 0 kg or 0 cm), which is likely invalid for body measurements.

To prevent this, you can preprocess the input to map empty strings to undefined before coercion, allowing them to be treated as omitted/optional.

const zNullableNumber = z.preprocess(
	(val) => (val === "" ? undefined : val),
	z.coerce.number().nullable().optional(),
);

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug (#341) where the body measurement update endpoint was sending null for every omitted field — which the Hevy API rejects — by refactoring buildMeasurementPayload to only include fields with actual values. It also adds MCP tool annotations across all tools, a new get-user-info tool, numeric coercion for measurement fields, and moves Kubb code-generation packages to devDependencies.

  • Payload fix: buildMeasurementPayload now iterates a MEASUREMENT_FIELD_TO_API_KEY mapping and skips any field whose value is null or undefined, resolving the API rejection. z.coerce.number() is added so MCP clients that serialize numbers as strings still work correctly.
  • Annotations: A new tool-annotations.ts utility provides four consistent factory functions (readOnlyAnnotations, createAnnotations, updateAnnotations, destructiveAnnotations) applied uniformly across all seven tool modules, with a full annotation test suite to enforce coverage.
  • User tool & dependency cleanup: New get-user-info tool follows established patterns; @kubb/cli, @kubb/core, and the build-only plugins are correctly moved to devDependencies while @kubb/plugin-client — a runtime import — stays in dependencies.

Confidence Score: 4/5

Safe to merge — the payload fix addresses a confirmed API rejection, the new user tool follows established patterns, and the dependency reshuffle is consistent with runtime import evidence.

The buildMeasurementPayload change correctly solves the API rejection by omitting null fields, and the test suite explicitly verifies null-dropping, full-field mapping, and coercion. The one notable gap is that callers who explicitly pass null hoping to clear a measurement field will receive a success response with no indication that the field was not cleared — the silent drop could lead to subtle data confusion. The pre-existing "update-workout-operation" error context tag also went unfixed during the annotation cleanup pass. Neither blocks a merge, but both are worth addressing soon.

src/tools/body-measurements.ts (null-drop behavior) and src/tools/workouts.ts (mismatched error context tag)

Important Files Changed

Filename Overview
src/tools/body-measurements.ts Core payload fix: buildMeasurementPayload now filters out null/undefined using a type-safe field map; numeric coercion added via z.coerce.number(). Minor: explicit nulls are silently dropped instead of surfacing a diagnostic.
src/utils/tool-annotations.ts New utility with four annotation factories (read-only, create, update, destructive); consistent openWorldHint: false across all. Clean and correct.
src/tools/user.ts New get-user-info tool following the established pattern; null-guard on data.data, proper annotation, unit tests provided.
package.json Build-only Kubb packages moved to devDependencies; @kubb/plugin-client correctly stays in production deps since it is imported at runtime in hevyClientKubb.ts and the generated API files.
src/tools/annotations.test.ts New annotation test suite verifies every registered tool has a title, openWorldHint: false, and the correct read/write/destructive hint combination.
src/tools/body-measurements.test.ts Expanded test suite covers null-omission, all-fields mapping, numeric string coercion, and schema validation; uses match.at(-1) to accommodate the new annotations parameter.
src/utils/hevyClientKubb.ts Adds getUserInfo client method wired to the generated getV1UserInfo API call, following the same pattern as all other methods.
src/tools/workouts.ts Annotations added to all workout tools; pre-existing "update-workout-operation" error-context tag was not corrected (minor inconsistency with every other tool).

Sequence Diagram

sequenceDiagram
    participant MCP as MCP Client
    participant Tool as update-body-measurement
    participant Builder as buildMeasurementPayload
    participant API as Hevy API

    MCP->>Tool: "date, weightKg: 80, chestCm: null"
    Note over Tool: Zod validates input
    Tool->>Builder: "weightKg: 80, chestCm: null"
    Note over Builder: Iterates MEASUREMENT_FIELD_TO_API_KEY skipping null values
    Builder-->>Tool: "weight_kg: 80"
    Tool->>API: "PUT /body-measurements/date {weight_kg: 80}"
    API-->>Tool: 200 OK
    Tool-->>MCP: "Body measurement updated successfully"
Loading

Comments Outside Diff (1)

  1. src/tools/workouts.ts, line 347-350 (link)

    P2 Error context tag is "update-workout-operation" instead of "update-workout"

    The error-handling wrapper for update-workout is tagged "update-workout-operation", while every other tool uses its exact registered name (e.g., "get-workout", "create-workout"). This inconsistency would surface in error logs or Sentry traces under a different label than the MCP tool name, making them harder to correlate. This pre-exists the PR but was not corrected along with the surrounding annotation work.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "feat: add MCP tool annotations to all to..." | Re-trigger Greptile

Comment on lines +92 to 107
// The Hevy API rejects null for omitted fields, so only fields with actual
// values are included in the payload (#341).
function buildMeasurementPayload(
args: MeasurementFieldArgs,
): Omit<BodyMeasurement, "date"> {
const payload: Omit<BodyMeasurement, "date"> = {};
for (const [camelKey, apiKey] of Object.entries(
MEASUREMENT_FIELD_TO_API_KEY,
) as [keyof MeasurementFieldArgs, keyof Omit<BodyMeasurement, "date">][]) {
const value = args[camelKey];
if (value != null) {
payload[apiKey] = value;
}
}
return payload;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Explicit null inputs are silently dropped rather than surfacing an error

buildMeasurementPayload uses value != null which filters out both undefined (omitted) and null (explicitly provided). A caller who passes {weightKg: null} intending to clear a measurement will receive a 200 success response, but the update payload sent to the API will be empty — the field is not actually cleared and no diagnostic is shown. Since the API rejects null and there is currently no way to delete individual fields, the tool description and/or a guard could make this explicit rather than silently ignoring the value.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR standardizes MCP tool metadata by adding annotations to every registered tool, and fixes body measurement write behavior so only non-null measurement fields are sent to the Hevy API (addressing partial-update failures). It also adds a new read-only user info tool, updates tests to accommodate the new tool signature, and refreshes docs/dependency placement to match the generation/runtime split.

Changes:

  • Added tool-annotations.ts factories and applied annotations consistently across all tool registrations.
  • Refactored body measurement input handling (numeric coercion + omit nullish fields) and expanded regression tests around payload construction/mapping.
  • Introduced a new get-user-info tool with unit tests; updated README and dependency classifications.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/utils/tool-annotations.ts Adds shared factories for MCP ToolAnnotations (read/create/update/delete).
src/utils/hevyClientKubb.ts Adds getUserInfo() wrapper to the generated client facade.
src/tools/workouts.ts Applies annotations to workout tools.
src/tools/workouts.test.ts Updates test helper to handle the added annotations argument.
src/tools/webhooks.ts Applies annotations to webhook tools.
src/tools/webhooks.test.ts Updates test helper to handle schema + annotations + handler call shape.
src/tools/user.ts Adds new get-user-info read-only tool.
src/tools/user.test.ts Adds unit tests for the new user tool (success/empty/not-initialized).
src/tools/templates.ts Applies annotations to template tools.
src/tools/templates.test.ts Updates test helper to handle the added annotations argument.
src/tools/routines.ts Applies annotations to routine tools.
src/tools/routines.test.ts Updates test helper to handle schema + annotations + handler call shape.
src/tools/folders.ts Applies annotations to folder tools.
src/tools/folders.test.ts Updates test helper to handle the added annotations argument.
src/tools/body-measurements.ts Coerces numeric strings, introduces field-to-API mapping, and omits nullish fields from payloads; applies annotations.
src/tools/body-measurements.test.ts Updates expectations for omitted fields, adds regression coverage for mapping/coercion/null handling.
src/tools/annotations.test.ts Adds a suite asserting every tool is registered with proper annotations/hints.
src/index.ts Registers the new user tool module.
README.md Updates the available tools table to include body measurements and user info.
package.json Moves Kubb generation-only packages to devDependencies.
package-lock.json Updates lockfile to reflect dependency classification changes.

Comment thread src/tools/body-measurements.ts Outdated
Comment on lines 244 to 248
"Update an existing body measurement entry for a given date. Only the fields you provide are sent; omitted fields are not included in the request. Returns 404 if no entry exists for the date.",
updateBodyMeasurementSchema,
updateAnnotations("Update Body Measurement"),
withErrorHandling(async (args: UpdateBodyMeasurementParams) => {
if (!hevyClient) {
Comment on lines +277 to +290
it("accepts date-only input and explicit nulls in the schema", () => {
const { server, tool } = createMockServer();
registerBodyMeasurementTools(server, {} as unknown as HevyClient);
const { schema } = getToolRegistration(tool, "update-body-measurement");

const dateOnly = z.object(schema).parse({ date: "2025-04-01" });
expect(dateOnly).toEqual({ date: "2025-04-01" });

const withNull = z.object(schema).parse({
date: "2025-04-01",
weightKg: null,
});
expect(withNull.weightKg).toBeNull();
});
Addresses PR #342 review feedback:

- Empty strings are treated as omitted instead of being coerced to 0
  by z.coerce.number().
- update-body-measurement now rejects calls without at least one
  non-null measurement field instead of sending an empty PUT body.
- Tool descriptions document that null values are treated as omitted,
  since the Hevy API rejects nulls and has no way to clear individual
  fields.

https://claude.ai/code/session_01CuJWqXKY94msBi4cUgn1D8
@chrisdoc chrisdoc merged commit 8df9a52 into main Jun 13, 2026
20 checks passed
@chrisdoc chrisdoc deleted the claude/hevy-mcp-improvements-ma7dhn branch June 13, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants