@thenextrace/tnr
v0.10.0
Published
CLI and MCP server for thenextrace.app — plan races and training from your terminal and from AI agents.
Maintainers
Readme
tnr — thenextrace CLI & MCP server
Plan races and training from your terminal — and from AI agents (Claude Code, Cursor, Claude Desktop).
npm install -g @thenextrace/tnr
tnr loginHow it works
tnr mcp runs as a stdio MCP server — Claude Desktop / Cursor / Claude Code spawn the tnr binary as a child process and talk to it over stdin/stdout. There's no hosted service and no URL to point at; the MCP runs locally on your machine, and from there makes authenticated HTTPS calls to https://www.thenextrace.app/api/v1.
agent ── stdio ──► tnr (your machine) ── HTTPS + Bearer ──► thenextrace.appThis is the same model GitHub MCP, filesystem MCP, and most other MCP servers use. Your token never leaves your machine; the agent never sees it.
Use with AI agents
The MCP server exposes these tools. Each includes detailed instructions for the agent (preconditions, enums, friendly aliases like ironman → tri):
- Discovery —
whoami,list_races,list_plans,list_library_workouts,list_plan_workouts,list_activities,get_race,get_plan,get_library_workout,get_activity,get_profile - Races —
create_race,update_race,delete_race - Plans —
create_training_plan,update_plan,delete_plan - Library workouts —
create_library_workout,update_library_workout,delete_library_workout - Scheduling (planned workouts inside a plan) —
schedule_workout,update_scheduled_workout,remove_scheduled_workout(and linking actual activities to planned workouts viaupdate_scheduled_workout'slinked_activity_id) - Profile —
update_profile
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"tnr": { "command": "tnr", "args": ["mcp"] }
}
}Restart Claude Desktop. Try: "What races do I have planned in thenextrace?"
Claude Code
claude mcp add tnr -- tnr mcpCursor
Edit ~/.cursor/mcp.json (or the project-local .cursor/mcp.json):
{
"mcpServers": {
"tnr": { "command": "tnr", "args": ["mcp"] }
}
}Sign in
- Generate a token at thenextrace.app — sign in, open the Settings dialog → API Tokens → Generate token. Copy the
tnr_…string immediately; it's shown only once. - Run
tnr loginand paste it (ortnr login --token tnr_…in scripts).
Tokens are stored in your OS config dir (~/Library/Application Support/tnr on macOS, ~/.config/tnr on Linux, %APPDATA%\tnr on Windows). Revoke any token at any time from the same Settings page.
CLI
Every command supports --json for machine-readable output to stdout. Status messages go to stderr. Exit codes follow standard conventions.
tnr login [--token <token>] Save your API token
tnr logout Clear stored credentials
tnr whoami Show the current user
tnr race list [--upcoming] List races
tnr race show <id> Show a single race
tnr race create --title <t> --date <YYYY-MM-DD> --plan <id>
[--type <type>] [--location <l>] [--description <d>]
tnr race update <id> [--title <t>] [--date <d>] [--plan <id>] [--type <t>]
[--location <l>] [--description <d>]
[--completed | --not-completed]
tnr race delete <id> [-y] Delete a race
tnr plan list List training plans
tnr plan show <id> Show a single training plan
tnr plan create --title <t> Create an empty plan
tnr plan update <id> [--title <t>] [--public | --no-public] [--access view|comment|edit]
[--allow-duplication | --no-allow-duplication]
tnr plan delete <id> [-y] Delete a plan (cascades to its races)
tnr workout list [--sport <s>] List library workouts
tnr workout show <id> Show a single library workout
tnr workout create --title <t> --sport <s>
[--type <type>] [--description <d>]
tnr workout update <id> [--title <t>] [--sport <s>] [--type <t>]
[--description <d>] [--distance <d>] [--duration <d>] [--pace <p>]
tnr workout delete <id> [-y] Delete a library workout (unless locked)
tnr schedule list <planId> [--from <d>] [--to <d>] List planned workouts in a plan
tnr schedule show <planId> <scheduledId> Show a planned workout
tnr schedule add <planId> --title <t> --sport <s>
[--date <YYYY-MM-DD>] [--week <n>] [--day <0-6>]
[--type <t>] [--description <d>]
tnr schedule update <planId> <scheduledId> [--title <t>] [--date <d>]
[--sport <s>] [--type <t>]
[--description <d>]
[--completed | --not-completed]
tnr schedule remove <planId> <scheduledId> [-y] Remove a planned workout
tnr schedule link <planId> <scheduledId> --activity <activityId>
tnr schedule unlink <planId> <scheduledId>
tnr activity list [--from <d>] [--to <d>] [--sport <s>] [--source <src>]
[--unlinked] [--limit <n>]
tnr activity show <id> Show a single activity with full detail
tnr profile show Show profile and physiology
tnr profile set [--ftp <w>] [--threshold-pace <mm:ss>] [--max-hr <bpm>]
[--resting-hr <bpm>] [--weight <kg>] [--css <mm:ss>]
[--vo2max <v>]
tnr mcp Run as an MCP server over stdioPlanned workouts vs activities. Planned workouts (tnr schedule …) live inside a training plan — they're sessions the athlete is supposed to do. Activities (tnr activity …) are what the athlete actually did — uploaded manually or imported from Strava. Link an activity to a planned workout with tnr schedule link.
Race types are: run, tri, swim, bike, custom. Friendly aliases (marathon, ironman, 70.3, 5k, half_marathon, ultra, olympic, sprint, duathlon, aquathlon, gravel, mtb, pool, open_water, virtual) are accepted and normalized.
Configuration
| Variable | Default | Purpose |
|---|---|---|
| THENEXTRACE_API_URL | https://www.thenextrace.app/api/v1 | Override the API host (e.g. for staging) |
Examples
# What races do I have coming up?
tnr race list --upcoming
# Pipe to jq for scripting
tnr --json race list --upcoming | jq '.[] | .title'
# Quick race entry
tnr race create \
--title "Berlin Marathon" \
--date 2026-09-27 \
--plan 123 \
--type marathon \
--location Berlin
# Update your zones
tnr profile set --ftp 285 --threshold-pace 4:05 --max-hr 188Releasing
npm version patch # or minor / major
git push --follow-tags # GitHub Actions publishes to npmCI runs on every v* tag (.github/workflows/release.yml).
License
MIT
