af-gym
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@af-gymHow busy is the gym right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
af-unofficial-mcp-server
An unofficial MCP server for Anytime Fitness. Ask your assistant how busy the gym is, when it will be quieter, which nearby clubs are less crowded, or how often you have visited.
It uses the same private API as version 4.5.0 of the Anytime Fitness app. The API may change without warning. This project is not affiliated with Anytime Fitness.
Tools
Tool | What it returns |
| Live headcount, how it compares with the usual crowd, and a go-now verdict |
| Typical hourly attendance for a chosen day |
| Nearby clubs, distance, opening status, and live headcount |
| Visit history and common visit times |
| Login status without exposing tokens |
Attendance comparisons use the club's 100-day hourly averages. The server finds the home club and its timezone from your account.
Related MCP server: hevy-mcp
Setup
You need Python 3.11 or later, uv, and an MCP-compatible client.
git clone https://github.com/Sajush00/af-unofficial-mcp-server.git
cd af-unofficial-mcp-server
uv sync
uv run af-gym login --phone +61400000000The login command sends an SMS code to the phone number registered with your Anytime Fitness account and prompts you to enter it.
Claude Desktop
Add this to claude_desktop_config.json:
{
"mcpServers": {
"af-gym": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/af-unofficial-mcp-server", "af-mcp"]
}
}
}Claude Code
claude mcp add af-gym -- uv run --directory /absolute/path/to/af-unofficial-mcp-server af-mcpHermes Agent
Add this to ~/.hermes/config.yaml:
mcp_servers:
af-gym:
command: uv
args: ["run", "--directory", "/absolute/path/to/af-unofficial-mcp-server", "af-mcp"]Then ask your assistant: "How busy is the gym right now?"
Authentication and privacy
uv run af-gym status
uv run af-gym logoutTokens are stored in ~/.af_token.json. Pending login details use
~/.af_session.json. Both files are private to your user account, and the CLI
and MCP tools never print their contents.
Set AF_CLUB_TZ to an IANA timezone such as Australia/Sydney if you need to
override automatic timezone detection.
Development
make checkThis runs Ruff, mypy, project-specific static checks, and the offline test suite. Implementation notes are in docs/adr.
License
MIT © 2026 Sajush Arukat
Available Tools
5 toolsauth_statusAuth StatusA
Report whether a saved Anytime Fitness session exists and still refreshes.
Returns only metadata; token values are never returned. When this or any
other call reports no usable session, ask the user to run
af-gym login --phone <number> in their terminal.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden and does so well: it states that only metadata is returned, token values are never exposed, and it defines the agent's expected action when no usable session exists. This covers safety, output scope, and failure handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core purpose, and the following sentences add only high-value behavioral and remediation details. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status-check tool with an output schema available, the description fully covers what the agent needs: purpose, return scope, token safety, and user-facing recovery instructions. No critical context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so parameter documentation is unnecessary. Baseline 4 applies because there is nothing for the description to add beyond the already-complete empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and resource: 'Report whether a saved Anytime Fitness session exists and still refreshes.' This clearly differentiates it from data-query siblings like occupancy, forecast, nearby_clubs, and visits, which return domain data rather than session state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear operational context: when this tool or any other call reports no usable session, the agent should direct the user to run `af-gym login --phone <number>`. It does not explicitly list when-not-to-use alternatives, but the zero-parameter auth-check role is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forecastForecastA
Typical hourly busy pattern for a day (100-day rolling averages, club-local time).
| Name | Required | Description | Default |
|---|---|---|---|
| day | No | "today", "tomorrow", or a weekday name like "saturday". Defaults to "tomorrow". | tomorrow |
| club | No | AF club number like "AU-0000". Defaults to the home gym. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds meaningful context by stating the data is a 100-day rolling average and expressed in club-local time, which clarifies computation method and timezone handling. It does not mention output structure, but an output schema exists, so that gap is covered elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that communicates the core purpose and the two most important behavioral nuances: rolling averages and club-local time. There is no wasted text or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with two optional parameters and an output schema, the description provides enough context to understand what the tool returns and how the parameters affect the result. The main missing piece is explicit guidance on when to choose this tool over the sibling occupancy tool, but that is a usage-guideline gap rather than a completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by clarifying that the busy pattern is in club-local time, which affects how the 'day' and 'club' parameters should be interpreted. This is a useful semantic addition, though most parameter details are already fully documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool provides a typical hourly busy pattern for a day, based on 100-day rolling averages and club-local time. This is distinct from the sibling tools, especially occupancy, because it describes a historical/typical pattern rather than a current state, though it does not explicitly name the sibling it differs from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for planning or understanding expected busyness rather than real-time occupancy, but it does not explicitly state when to use this tool versus alternatives like occupancy. There is no exclusion or alternative routing, leaving the agent to infer context from the word 'typical' and the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nearby_clubsNearby ClubsA
Clubs near the home gym, nearest first, each with distance and a live headcount.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of clubs to return. | |
| radius_km | No | Search radius in kilometres around the home gym. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses ordering ('nearest first'), scope ('near the home gym'), and a notable live-data trait ('live headcount'). It does not mention authentication, data freshness limits, or behavior when no clubs are found, but for a simple read-style tool this is reasonably transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler. It front-loads the core scope ('Clubs near the home gym') and then packs in ordering, distance, and live headcount efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity, fully documented parameters, and presence of an output schema, the description covers the essential context: what is returned, from where, and in what order. It could add a note on authentication or data freshness, but nothing critical is missing for a basic nearby-clubs lookup.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already fully documents limit and radius_km. The description adds no parameter-level meaning beyond what the schema provides, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource (clubs near the home gym), the ordering (nearest first), and the returned fields (distance, live headcount). It lacks an explicit verb like 'list' or 'get', and it does not directly contrast with sibling tools, but its meaning is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: an agent would use this when it needs nearby clubs with distance and headcount. However, there is no explicit guidance about when to choose this over siblings like occupancy or visits, and no exclusions or prerequisites are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
occupancyOccupancyB
Live headcount right now, a go-now verdict, and typical counts for the rest of today.
The verdict compares the live count to the typical count for this hour: go-now, good-time, normal, wait or skip (see verdictMessage). restOfDay lists the typical count for each remaining hour of today.
| Name | Required | Description | Default |
|---|---|---|---|
| club | No | AF club number like "AU-0000". Defaults to the home gym. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden. It explains the verdict logic and the restOfDay output, which adds meaningful behavioral context. However, it does not explicitly label the operation as read-only or disclose any latency, privacy, or edge-case behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence captures the core purpose, and the second adds necessary detail about verdict values and restOfDay. Every sentence contributes value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the parameter schema is complete, the description sufficiently explains the tool's primary outputs and verdict logic. It could be slightly more complete by clarifying when to use it relative to forecast, but the core information an agent needs to invoke it is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single optional parameter 'club' is 100% documented in the schema, including its format and default behavior, so the description does not need to add much. It adds no extra parameter insight, but the schema already covers it fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what the tool returns: live headcount, a go-now verdict, and typical counts for the rest of today. It distinguishes itself from sibling tools like forecast by focusing on current occupancy and today's remaining hours, though it does not explicitly name any sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when current occupancy or a go-now recommendation is needed, but it gives no explicit guidance on when to prefer this tool over forecast or other siblings. There are no usage conditions, prerequisites, or exclusions stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
visitsVisitsA
Gym check-ins in a date range, newest first, with totals and habits.
Defaults to the last 90 days. Prefer a range over pulling all history: "visits in August" is start "2026-08-01", end "2026-08-31" (count 1 when only the total matters). When the range reaches today it also reports days since the last visit and, when the window is wide enough, 7/30-day counts; it always reports the most common day and hour in the range. Dates are club-local and inclusive.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | Range end, inclusive; a bare date covers the whole day. Default: now. | |
| count | No | Max visits to list, newest first (default 20, max 200). | |
| start | No | Range start, inclusive. Default: 90 days before end. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and discharges it exceptionally well: discloses sort order (newest first), default range, conditional metrics (7/30-day counts only when the range reaches today and is wide enough), always-on aggregates (most common day/hour), and date semantics (club-local, inclusive). This goes well beyond what the schema or structured fields reveal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every sentence earns its place — purpose is front-loaded, followed by defaults, usage guidance, conditional behavior, and date semantics in logical order. It is slightly dense as one block and the "count 1" hint is compressed, but there is virtually no waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists to explain return values and all three parameters have full schema descriptions, the description is complete for correct invocation: it covers defaults, conditional output behavior, date semantics, and query-framing strategy. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, but the description adds real meaning: it clarifies that dates are inclusive and club-local, provides a concrete mapping from a natural query to start/end values, and explains that count=1 retrieves the total efficiently. This is meaningful value beyond the schema's own field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource statement — "Gym check-ins in a date range, newest first, with totals and habits" — that immediately distinguishes it from siblings (occupancy, forecast, nearby_clubs, auth_status are all clearly different domains). An agent can identify what this tool returns without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: defaults to 90 days, advises preferring a bounded range over pulling all history, and gives a concrete natural-language-to-parameters example ("visits in August" → start/end). It stops short of explicit when-not-to-use guidance or alternative routing to siblings, though those tools are distinct enough that confusion is unlikely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.2.0- First observed
auth_status - First observed
forecast - First observed
nearby_clubs - First observed
occupancy - First observed
visits
TDQS
Scored across 5 tools
Occupancy and forecast both deal with busyness and could be confused, but their live-vs-typical distinction is clear from the descriptions. The remaining tools are each tied to a distinct concern: nearby alternatives, visit history, and auth status.
All tool names are lowercase noun-style names, forming a consistent and predictable query-oriented pattern. Single-word names like occupancy and multi-word names like nearby_clubs both follow snake_case, so there is no convention mixing.
Five tools is well-scoped for a gym assistant: live busyness, typical trends, nearby options, visit history, and session status. Each tool earns its place and none feels redundant or missing enough to enlarge the set.
The core member workflows are covered: deciding when to go, checking nearby alternatives, and reviewing past visits. Minor gaps exist around club details like hours or address and membership info, but the surface seems intentionally focused and auth is explicitly handled via CLI.
Maintenance
Related MCP Connectors
Manage fitness coaching clients, workouts, programs, chats and funnels from your assistant.
Log workouts and meals by telling your AI. 873 exercises, muscle diagrams, food lookup.
Look up Momence members, class schedules, bookings and memberships, and handle front-desk actions.
Ask your AI about your fitness: activities and data from Garmin, COROS, Strava, GPX and more
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables interaction with Intervals.icu data, including activities, wellness, and calendar events, via natural language.1024 npm1MIT
- FlicenseNot gradedqualityDmaintenanceAccess your Hevy workout data through natural language. Query workout history, exercise details, routines, and track progress.-
- AlicenseBqualityDmaintenanceIntegrates with the Boostcamp fitness platform to provide workout history, programs, exercises, and analytics via natural language.12MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying your Garmin Connect data including recent activities, detailed metrics, and daily stats through natural language.-