nc://athletedata

v0.1.0Pinned
ThomSharktools/nodecode-athletedata: The agent asks the athletedata server about your own Garmin, Oura, WHOOP and Hevy training and health data - a rewrite of athletedata-health/mcp (MIT), credited to athletedata-health65be4ed· 9 Nov1 commit
test1 filecell.lisp7.3 KBwire.lisp10.4 KB

nodecode-athletedata

Athletedata: the athlete's own training and health data from 39 apps, through the athletedata MCP server. A Nodecode rewrite of athletedata-health/mcp by athletedata-health.

athletedata is a hosted MCP server for athletes. Connect your training and health apps once at athletedata.health -- Garmin, Oura, WHOOP, Hevy, Apple Health, Intervals.icu, Cronometer, Withings, Zwift and more -- then ask the agent about your own data instead of pasting numbers: activities, training load (CTL, ATL, TSB), HRV and resting heart rate, readiness, sleep trends, power and pace curves, race predictions, nutrition and body composition.

The cell speaks the server's own protocol, MCP over Streamable HTTP, with the core's HTTP seam. It registers two tools:

Tool What it does
athletedata_tools The server's tools, one line each, a * marking one that writes.
athletedata_call Calls one of them: tool is its name, arguments its own JSON object.

The server serves its tool set at run time, so the two verbs outlive any version of it; the list is asked once and kept for the process.

Get it

Tell the agent "add the athletedata cell", or run:

nodecode add nc://athletedata

Set it up

You need an athletedata account (there is a 7-day free trial) and the key on its MCP page, sk_soma_.... Put it in the environment variable the section names, ATHLETEDATA_API_KEY by default:

export ATHLETEDATA_API_KEY=sk_soma_...

or set athletedata.api_key_env to another variable's name. The section:

"athletedata": {
  "api_key_env": "ATHLETEDATA_API_KEY",     // the variable holding the key
  "url": "https://mcp.athletedata.health/mcp",
  "timeout_seconds": 60,
  "allow_writes": false                       // true: a writing tool runs without confirm
}

A key that is set but refused, or a section with no key at all, is said in the answer and in the cell's own line; /athletedata shows which variable it is looking at and whether one is set. Every call, with its arguments, goes to mcp.athletedata.health: that is the whole point of the cell, and nothing else is sent anywhere.

Use it

Ask about your training, sleep or recovery; the agent lists the server's tools and picks one. From eval:

(help :athletedata)                         ; the primer the model reads
(nle::find-tool "athletedata_tools")        ; what the model calls

or type /athletedata for its state and /athletedata tools for the list.

Writing tools -- push a workout to the watch, log a meal, create a Hevy routine -- change the athlete's own accounts. The server marks the tools that only read; any other one refuses to run until the call carries confirm: true (or allow_writes is on), so the agent asks first.

What is in it

File What it is
wire.lisp MCP over Streamable HTTP: one POST per message, the event stream read when the answer comes as one, the session id echoed.
cell.lisp The section, the manual topic, the two tools and /athletedata.
test/ The lifecycle, the missing key, the list, the confirm gate and the session, all offline.

License

MIT. The original package is Copyright (c) 2026 HealthspanOS AG: see LICENSE and NOTICE.

Add nc://athletedata

  1. 1

    Install Nodecode

    Once per machine.

    $ curl -fsSL https://nodecode.ai/install.sh | sh
  2. 2

    Add the cell

    Pinned at 65be4ed.

    $ nodecode add nc://athletedata

    Or tell the agent add the athletedata cell.