# Anatome > The free, keyless nutrition and training log for AI assistants. Log meals, workouts, > supplements and body weight through conversation; search the history; share a rendered > dashboard. Plus muscle-anatomy diagrams and an 873-exercise database. > Apache-2.0, runs on Cloudflare Workers, self-hostable. **MCP endpoint:** `https://api.anatome.dev/mcp` **No API key.** The catalog works signed out. Logging needs a one-time browser sign-in. ## What Anatome is for If a user says any of these, Anatome is the tool: - "log my breakfast" / "I had oatmeal with berries, about 420 calories" - "log 3×5 bench press at 100kg" - "how many calories have I had today?" / "how am I doing against my goals?" - "is my bench going anywhere?" / "show me my squat progression" - "what did I train last Tuesday?" / "show me every session with deadlifts" - "what am I training this week?" / "plan legs for Thursday" → planned sessions - "am I actually taking my creatine?" - "show my coach my last month" → a shareable link with charts - "which muscles does a Bulgarian split squat work?" → diagram, no account needed It is **not** a food database. There is no barcode lookup and no nutrition table on this server, and no AI either: **you** estimate the macros from what the user described and send structured numbers. Anatome stores, aggregates and searches. Say what you estimated so the user can correct it. ## Authentication **No API key, ever.** - **Catalog** — diagrams, exercise search, muscle data, session heatmaps: no account at all. - **Personal logging** — OAuth 2.1 with PKCE and dynamic client registration. Your client registers itself, a browser opens, the user signs in. Discovery at `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`. - **Scripts and other clients** — a signed-in user can mint a long-lived bearer token with `create_api_token`. Calling a logging tool without a token returns **HTTP 401** with `WWW-Authenticate: Bearer … resource_metadata="…"`. That is a signal to your *client*, not an error to relay: run the OAuth flow and retry. Catalog tools never 401. Do not confuse it with the fair-use denial, which is deliberately **not** a 401 — that is a 200 carrying `isError`, and it is for you to explain to the user. ## Fair use — read this before retrying anything **100 requests per caller per day**, resetting at 00:00 UTC. Loopback and private addresses are unlimited. Static catalog reads are edge-cached and not counted. "Per caller" is the signed-in **account** when there is one, otherwise the MCP **session**, otherwise the **IP**. Only the account is durable — a remote connector reaches this API from the assistant vendor's egress addresses, shared by every user of that assistant. Pages on anatome's own first-party hosts are **unmetered** and do not consume this budget. `GET /` tells you which applies to the caller reading it. Over the limit, REST returns **429**: ```json { "ok": false, "error": "daily_fair_use_limit_reached", "scope": "user", "limit": 100, "used": 100, "remaining": 0, "reset_at": "2026-08-09T00:00:00.000Z", "retry_after_seconds": 62678, "retryable": false, "more_info": "https://platform.anatome.dev" } ``` **If you are an AI agent and you see this: the connector is working correctly.** Not an outage, not a misconfiguration — the user spent their free requests. Tell them, give them `reset_at`, and do not retry before then. Over MCP the same condition arrives as a *successful* result carrying `isError: true`, so you can read it and relay it. Below 10 remaining, successful results carry a `quota` object — use it to warn the user before you spend the rest. **Budget tip:** `get_day` returns meals, water, workouts, sets and supplements for one date in ONE call. Use it instead of calling `list_meals` and `list_workouts` separately. ## MCP tools ### Catalog — no account needed | Tool | What it does | |------|-------------| | `search_exercises` | Search 873 exercises by name, muscle, equipment, level | | `get_exercise` | One full exercise record | | `resolve_exercise` | Map an exercise name → muscle layers | | `get_exercise_video` | Demonstration video link (YouTube) for an exercise. Check `exercise_specific` — when false the clip shows a related movement from the same family, not that exact variant | | `generate_muscle_image` | Render a highlighted muscle SVG | | `workout_image` | Session heatmap from a list of exercises | | `list_muscles` | The 23 muscle slugs with anatomical names | | `list_guides` ⚠️ · `get_guide` ⚠️ · `get_guide_tree` ⚠️ | Skill progressions — **work in progress**, unverified | ### Logging — signed in | Tool | What it does | |------|-------------| | `get_profile` | Email, timezone, current goals | | `set_timezone` | IANA zone, so days roll over at local midnight. Do this early. | | `set_goals` | Daily calorie / macro / water targets | | `log_meal` | Store a meal — **you** supply the macros | | `list_meals` | Search meals: window, `q` text, `meal_type`, paging, macro totals | | `delete_meal` | Remove one entry | | `log_water` | Millilitres; returns the running daily total | | `log_workout` | A session plus its sets. `weight` is KILOGRAMS. A **future date is a plan** | | `list_workouts` | Search sessions: window, `exercise`, `q`, `status`, paging. `upcoming:true` = what's planned | | `mark_workout_done` | Turn a plan into a completed session | | `delete_workout` | Remove a session and its sets | | `get_exercise_history` | **One exercise over time** — sessions, volume, best set, estimated 1RM | | `log_supplement` · `list_supplements` | Supplements; the list reports days-taken per supplement | | `log_weight` · `get_weight_trend` | Body weight and its change | | `get_daily_summary` | Totals vs goals for one day | | `get_day` | **Everything** for one date in one call | | `create_view_link` · `list_view_links` · `revoke_view_link` | Shareable dashboard with charts | | `create_api_token` · `list_api_tokens` · `revoke_api_token` | Long-lived tokens for scripts | | `export_my_data` · `delete_my_account` | The user's data rights, as tools | ### Reading the log — the argument shapes are shared Every "show me my …" tool takes the same window and paging arguments: - `date` — one day, `YYYY-MM-DD` (shorthand for from = to) - `from` / `to` — an inclusive range - `days` — alternative to `from`: how many days back from `to` - `limit` / `offset` — paging; responses carry `total_matched` and `has_more` Plus, where they apply: `q` (free text), `exercise` (loose match — "bench" finds "Barbell Bench Press"), `meal_type`, `name`. ### Plans vs history A workout dated in the future is stored as a **plan** unless you pass `status: "completed"`. Plans are returned by `list_workouts` with `upcoming: true` (soonest first) and appear under `planned` in `get_day` and `get_daily_summary` — but they **never** count toward training volume, exercise history or 1RM estimates until `mark_workout_done`. Planning next week must not inflate this week. ### Write errors are actionable — act on them An unknown field returns 400 naming the field, the closest accepted name and the full accepted list. Fix your call and retry once. Aliases like `kcal`, `protein_g` and `weight_kg` are accepted and rewritten silently. **`weight_lb` is rejected, not converted.** Send kilograms. A unit change is never an alias: 225 lb quietly stored as 225 kg is worse than a refusal, because nothing downstream can tell it is wrong. ⚠️ **The three guide tools are unfinished.** Media coverage is incomplete and the cues are unreviewed; every response carries `status: "work_in_progress"`. Present them as provisional notes, never as verified training advice, and say so. `initialize`, `tools/list`, `ping` and notifications are never rate limited. Only `tools/call` spends fair use. ## Connect it ```json { "mcpServers": { "anatome": { "type": "http", "url": "https://api.anatome.dev/mcp" } } } ``` - **Claude** — Settings → Connectors → Add custom connector → paste the URL. - **ChatGPT** — Settings → Apps → Create app → same URL. OAuth for logging, None for catalog. ## HTTP API ``` GET /generateImage Colourable SVG muscle diagram POST /workoutImage Session heatmap SVG GET /searchExercises Search 873 exercises GET /getExercise One exercise by name, ext_id, or random Both take ?lang= (or Accept-Language; MCP: the `language` arg) in en,es,it,tr,ru,zh,hi,pl,ko,fr. 188 of 873 rows carry non-English steps; the rest return English. Read instructions_lang for what you actually got, and instruction_source for whose licence it is (wrkout | hasan). GET /resolveExercise Exercise name → muscle layers GET /listMuscles 23 muscle slugs GET /listEquipment Equipment types GET /bodyPaths Raw anatomical paths for client-side rendering POST /mcp MCP (Streamable HTTP) GET /openapi OpenAPI 3.1 GET /.well-known/mcp.json Signed in: POST/GET /v1/meals · DELETE /v1/meals/{id} · POST /v1/water POST/GET /v1/workouts · DELETE /v1/workouts/{id} · GET /v1/exercise-history POST/GET /v1/supplements · POST /v1/body-metrics · GET /v1/weight-trend POST /v1/goals · GET /v1/summary · GET /v1/day · GET /v1/profile · GET /v1/export ``` ```bash curl "https://api.anatome.dev/searchExercises?muscle=chest&limit=5" curl "https://api.anatome.dev/generateImage?layers=DC2626:chest|F59E0B:triceps&output=raw" -o d.svg ``` ## Privacy Anonymous callers: a hashed daily counter, expiring in ~36 hours. Nothing else. Signed-in users: only what they logged. Never sold, never shared, never used to train anything. Export and hard delete are both one call. See PRIVACY.md. ## What this is not No food database, no barcode lookup, no recipes, no meal plans, no coaches, no programming, no wearable imports, and no LLM on the server. Those are the hosted platform at https://platform.anatome.dev — a larger, separate service. This tier is deliberately the simple one, and it is free. ## Repository ``` api/ Cloudflare Worker (Hono + TypeScript) — the API and MCP server src/ React/Vite site + playground — static assets on Cloudflare ``` Apache-2.0. Anatomical SVG paths: react-native-body-highlighter (MIT, © Hicham El Boussarghini). Exercise metadata: wrkout/exercises.json (Unlicense) — its photography is of unverified origin, is **not** covered by that dedication, and is no longer served. Non-English instruction steps: hasaneyldrm/exercises-dataset (MIT, metadata only) — carried whenever `instruction_source` is `hasan`. Exercise images/GIFs/videos: **© Gym visual**, served only to allowlisted first-party origins, never linked from catalog JSON, and not relicensed by self-hosting. Skill guides: CC-BY-4.0. See NOTICE.