list_routine_folders
Retrieve your Hevy routine folders to organize and view workout categories such as Push/Pull/Legs or Hypertrophy Block.
Instructions
List the user's routine folders (e.g. 'Push/Pull/Legs', 'Hypertrophy Block').
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| page_size | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/hevy_mcp/tools/folders.py:15-18 (handler)The async handler function that executes the list_routine_folders tool logic. It calls client.get('/routine_folders') with pagination params.
async def list_routine_folders(page: int = 1, page_size: int = 10) -> dict[str, Any]: """List the user's routine folders (e.g. 'Push/Pull/Legs', 'Hypertrophy Block').""" return {"data": await client.get("/routine_folders", params={"page": page, "pageSize": page_size})} - src/hevy_mcp/tools/__init__.py:6-12 (registration)The register_all function calls folders.register(mcp, ctx), which registers list_routine_folders as an MCP tool.
def register_all(mcp, ctx) -> None: workouts.register(mcp, ctx) routines.register(mcp, ctx) folders.register(mcp, ctx) templates.register(mcp, ctx) webhooks.register(mcp, ctx) analytics.register(mcp, ctx) - src/hevy_mcp/tools/folders.py:10-18 (registration)The register() function that decorates list_routine_folders with @mcp.tool() to register it as an MCP tool.
def register(mcp, ctx) -> None: client = ctx.client @mcp.tool() @tool_guard async def list_routine_folders(page: int = 1, page_size: int = 10) -> dict[str, Any]: """List the user's routine folders (e.g. 'Push/Pull/Legs', 'Hypertrophy Block').""" return {"data": await client.get("/routine_folders", params={"page": page, "pageSize": page_size})} - src/hevy_mcp/errors.py:47-80 (helper)The @tool_guard decorator used on the handler to catch errors and return structured {error, hint} responses.
def tool_guard(func: Callable[..., Awaitable[Any]]) -> Callable[..., Awaitable[Any]]: """Decorator: convert exceptions into `{error, hint}` and emit structured logs.""" @functools.wraps(func) async def wrapper(*args: Any, **kwargs: Any) -> Any: start = time.monotonic() name = func.__name__ try: result = await func(*args, **kwargs) log.info("tool=%s status=ok duration_ms=%.1f", name, (time.monotonic() - start) * 1000) return result except HevyApiError as e: log.warning( "tool=%s status=hevy_error http=%d duration_ms=%.1f msg=%s", name, e.status, (time.monotonic() - start) * 1000, e.message, ) return {"error": e.message, "hint": e.hint, "http_status": e.status} except httpx.TimeoutException: log.warning("tool=%s status=timeout duration_ms=%.1f", name, (time.monotonic() - start) * 1000) return { "error": "Hevy API request timed out.", "hint": "Retry the call. If it keeps timing out, reduce page_size or scope.", } except ValueError as e: log.warning("tool=%s status=bad_input duration_ms=%.1f msg=%s", name, (time.monotonic() - start) * 1000, e) return {"error": str(e), "hint": "Re-read the tool's input schema and adjust the arguments."} except Exception as e: # noqa: BLE001 — last-resort guard so Claude never sees a stack trace log.exception("tool=%s status=internal_error duration_ms=%.1f", name, (time.monotonic() - start) * 1000) return { "error": f"Unexpected internal error: {type(e).__name__}: {e}", "hint": "This is a bug in hevy-mcp. Retry once; if it persists, file an issue with the tool name and inputs.", } return wrapper