Intervals.icu MCP Server
The server lets an MCP client inspect your Intervals.icu training account and make selected updates.
Read athlete identity/profile and public profile.
List/search activities and fetch activity details, intervals, streams, power curve, best efforts, and weather.
Read power curves and wellness/fitness records.
List calendar events and get a specific event.
Create calendar events such as planned workouts, races, notes, or holidays.
Update wellness records (HRV, sleep, weight, mood, stress, notes, etc.).
List workouts and get a workout by ID.
List gear and routes, and get a route by ID.
Use field selection and stream downsampling to keep responses compact.
Per the README, the full server also includes additional write tools for activities, events, workouts, folders, gear, plans, and gated deletes.
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., "@Intervals.icu MCP ServerShow me my last 5 rides with average power and heart rate"
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.
Intervals.icu MCP Server
An MCP server that exposes your Intervals.icu training data — activities, power curves, wellness, calendar, workouts, gear and routes — to an MCP client such as Claude.
Runs locally over stdio, or as a hosted multi-user server on Cloudflare Workers
(see Hosting it for others). 45 tools — 27 read-only and 18 that write — plus one
resource, the Intervals.icu workout syntax reference. Built on v2 of the MCP
TypeScript SDK (@modelcontextprotocol/server).
Requirements
Node.js 20 or newer (required by the MCP SDK; the server also uses the global
fetchandAbortSignal.timeout)An Intervals.icu API key: Settings → Developer Settings on intervals.icu
Related MCP server: intervals-mcp
Configuration
The server reads two required environment variables and exits with a clear message if either is missing, plus three optional ones:
Variable | Description |
| Your Intervals.icu API key |
| Your athlete ID, e.g. |
| Optional. API root, for pointing the client at a local fake server. Defaults to |
| Optional. |
| Optional. IANA zone, e.g. |
Note: there is no
dotenvdependency, so a.envfile is not loaded automatically..env.exampleis a reference for the values you need — supply them through your MCP client'senvblock (below), or export them in your shell beforenpm start.
Keeping your key safe
Your API key grants full read and write access to your Intervals.icu account — treat it like a password.
Never commit it.
.envis gitignored;.env.exampleholds placeholders only. Your MCP client's config file lives outside this repository, which is the right place for the real value.Rotate it at Settings → Developer Settings if it is ever exposed.
The server sends the key only to
intervals.icu, over HTTPS, as an HTTP BasicAuthorizationheader. It is never logged, never written to disk, and never included in an error message.Credential-shaped fields in API responses are stripped before anything is returned to the model — see Credentials are withheld below.
Install and build
git clone https://github.com/OneMoeLine/intervals-mcp-server.gitThen, from the clone:
npm install && npm run buildnpm install builds automatically via prepare, so installing straight from
the repository also works:
npm install -g github:OneMoeLine/intervals-mcp-serverThat puts an intervals-mcp-server command on your PATH, which you can use in
place of node /path/to/dist/index.js below.
Running
npm startMore usefully, register it with your MCP client. For Claude Desktop, add this to
claude_desktop_config.json:
{
"mcpServers": {
"intervals-icu": {
"command": "node",
"args": ["/absolute/path/to/Intervals MCP Server/dist/index.js"],
"env": {
"INTERVALS_API_KEY": "your_api_key_here",
"INTERVALS_ATHLETE_ID": "i12345"
}
}
}
}For development without a build step:
npm run devHosting it for others
The same tools can run as one hosted server that you and your friends each add to Claude as a custom connector, from the web, desktop or phone apps. Each person signs in once with their own Intervals.icu API key, so each person sees only their own account. It runs on Cloudflare Workers, and the free plan is enough for a handful of people.
How it works
worker/index.tsmakes the Worker its own OAuth 2.1 server with@cloudflare/workers-oauth-provider, which handles client registration, PKCE and tokens, the way claude.ai connectors expect.When someone connects, Claude opens
/authorize(worker/authorize.ts). They enter an invite code, their API key, and optionally their athlete ID, timezone and delete mode. The key is checked against Intervals.icu once, before any grant exists.The key is stored only in the grant's
props, which the library encrypts with a key derived from that user's token. Tokens are stored only as hashes. Someone reading the KV namespace cannot recover anyone's API key.Each request to
/mcpbuilds a server bound to the caller's own credentials (worker/mcp.ts). Nothing is shared between users.
Deploying
You need a free Cloudflare account. From the clone:
npm install
npx wrangler login
npx wrangler kv namespace create OAUTH_KV # paste the printed id into wrangler.toml
openssl rand -hex 16 # the invite code you'll share
npx wrangler secret put INVITE_CODE # paste it
npm run deploynpm run deploy prints the Worker's URL, e.g.
https://intervals-mcp.<your-subdomain>.workers.dev.
Automatic deploys
.github/workflows/test.yml runs the typecheck and tests on every pull request,
so a failure shows on the PR before it is merged.
.github/workflows/deploy.yml runs the typecheck and tests on every push to
main (so on every merged pull request) and, if they pass, runs
wrangler deploy. It deploys wrangler.toml as-is, so the OAUTH_KV
namespace and everyone's sign-ins are untouched, and secrets such as
INVITE_CODE stay as you set them. You can also run it by hand from the
Actions tab (Deploy Worker → Run workflow).
It needs two repository secrets, added once under Settings → Secrets and variables → Actions → New repository secret:
CLOUDFLARE_API_TOKEN: in the Cloudflare dashboard, My Profile → API Tokens → Create Token, use the Edit Cloudflare Workers template, limit it to your account, and create it.CLOUDFLARE_ACCOUNT_ID: shown on the dashboard's Workers & Pages overview, or bynpx wrangler whoami.
Connecting (you and each friend)
In Claude: Settings → Connectors → Add custom connector. Name it
Intervals.icu and use the URL with /mcp on the end:
https://intervals-mcp.<your-subdomain>.workers.dev/mcpClaude opens the sign-in page. Enter the invite code and your API key (intervals.icu → Settings → Developer Settings). The athlete ID is read from the key when the field is left blank. The timezone is filled in from the browser. A connection stays signed in while it is used, and lapses after 60 days unused.
Running it locally
cp .dev.vars.example .dev.vars # set INVITE_CODE
npm run dev:worker # http://localhost:8787/mcpThings to know
Trust. Friends hand their write-capable API key to your Worker. It is stored encrypted and never logged, but code you deploy handles it in memory. Anyone can cut off access by regenerating their key in Intervals.icu.
One shared code. Everyone, you included, signs in with the same
INVITE_CODE, so there is no list to keep track of. To change it, runnpx wrangler secret put INVITE_CODEagain and give people the new one. That affects only new sign-ins: anyone already connected stays connected until their sign-in lapses or they regenerate their Intervals.icu key. It also means you can't shut out one person without changing it for all.Free-plan CPU limit. Workers Free allows 10 ms of CPU per request. Waiting on Intervals.icu doesn't count toward it. Most tools use about a millisecond, but
get_activity_streamson a long activity has to parse roughly 1.4 MB of JSON (about 15 ms measured for a 4-hour ride with every channel). It can fail with Cloudflare error 1102. Asking for only the channels you need (types) avoids that. The paid plan ($5/month) raises the limit to 30 s.INTERVALS_BASE_URLcan be set as a Worker var only to point the server at a fake API, as the tests do.
Tests
npm test188 vitest tests, about 4 seconds. No credentials and
no network access are needed — nothing in the suite contacts Intervals.icu.
npm test builds first (via pretest), because the protocol tests spawn the
compiled dist/index.js. npm run test:watch reruns on change, and
npm run typecheck checks src, test and worker.
Four layers:
test/transform.test.ts— the pure helpers, no I/O:decimate(including themax_points: 1case that once divided by zero),downsampleStreams,project/projectNestedand the date schemas.test/api.test.ts—IntervalsClientagainst a throwawaynode:httpserver on an ephemeral loopback port: auth header, query building, JSON vs text parsing, which statuses retry and which do not, theRetry-Afterschedule and its cap, per-attempt timeouts and error-body truncation. The backoff is injected as zero, so the retry tests do not sleep.test/mcp.test.ts— the real server binary over stdio:initialize, thentools/listasserting all 45 tools and their input schemas, plustools/callfor the handler rules (the either/or onget_activity_best_efforts, date rejection before any HTTP call) and a handful of end-to-end calls against the fake API.test/worker.test.ts— the hosted Worker underwrangler dev(local workerd and KV, nothing deployed), driven through the whole OAuth flow the way claude.ai drives it: registration, the sign-in page (wrong invite, wrong key, Cancel), the token exchange, thentools/listand atools/callthat must reach the fake API with that user's own key and athlete ID.test/server.test.tscovers the delete-mode and timezone helpers.
Tools
Athlete — get_athlete, get_athlete_profile, update_sport_settings
(writes)
Activities — list_activities, get_activity, search_activities,
get_activity_intervals, search_intervals, get_activity_streams, get_activity_power_curve,
get_activity_best_efforts, get_activity_weather, get_activity_histogram,
get_activity_messages, add_activity_message (writes), update_activity
(writes)
Power, HR and pace — get_power_curves, get_hr_curves,
get_pace_curves
Wellness and fitness — list_wellness, get_wellness,
update_wellness (writes), get_fitness_chart
Calendar — list_events, get_event, create_event (writes),
create_events (writes), update_event (writes), duplicate_events (writes), apply_plan
(writes), delete_event (writes, gated)
Workouts — list_workouts, get_workout, create_workout (writes),
update_workout (writes), delete_workout (writes, gated),
list_folders, create_folder (writes)
Gear — list_gear, create_gear (writes), update_gear (writes),
add_gear_reminder (writes), update_gear_reminder (writes)
Routes — list_routes, get_route
Resources
intervals-icu://workout-syntax — the structured-workout text format, which
is what description carries on a workout event or a library workout. Read it
before writing a workout: the syntax fails silently, and the resource lists the
cases where it does.
Behaviour worth knowing
Streams are downsampled. get_activity_streams would otherwise return tens
of thousands of samples across every channel — easily megabytes, enough to
exhaust a model's context in one call. Each channel is reduced to 500 evenly
spaced points by default, always keeping the first and last. When a channel is
reduced, the response includes a downsampled field reporting the original and
returned point counts. Pass types to fetch only the channels you need
(e.g. ["watts","heartrate"]) and max_points to change the resolution.
Records are trimmed. The API returns fixed, very wide records — 184 fields
per activity, 84 per interval lap, 162 on the athlete, 62 per calendar event,
47 per wellness day — with much of it null or irrelevant for any given sport.
Nine tools therefore return a compact summary by default and accept a fields
parameter. Measured against real data:
Call | Default | Full | Saving |
| 0.4 KB | 14.9 KB | 97% |
| 14.9 KB | 91.9 KB | 84% |
| 10.9 KB | 63.8 KB | 83% |
| 0.9 KB | 4.8 KB | 82% |
| 7.4 KB | 29.0 KB | 74% |
| 5.4 KB | 17.9 KB | 70% |
| 3.3 KB | 10.8 KB | 69% |
| 2.6 KB | 10.6 KB | 75% |
| 5.4 KB | 12.9 KB | 58% |
Pass fields to choose exactly what you want — fields: ["id","name", "icu_training_load"] returns those three and nothing else — or
fields: ["*"] for the complete record. Because the API's key set is fixed
(inapplicable metrics come back null rather than absent), a field name that
matches no record is treated as a typo: the call fails and lists the valid
field names so the mistake can be corrected in one step.
Three cases are worth knowing. On get_activity_intervals the bulk is the
nested per-lap list, so fields applies to the laps inside icu_intervals and
icu_groups rather than to the wrapper. On get_athlete, sportSettings
holds per-sport FTP, thresholds and zones and is 10.2 KB on its own — ask for
it explicitly with fields: ["sportSettings"]. On the three curve tools the
activities lookup map is roughly as large as the curves themselves and is
omitted unless you pass ["*"]; secs and values on each power or HR
curve are the curve, and distance against values on a pace curve.
Credentials are withheld. The athlete record carries a slot for the
account's own API key (icu_api_key) and a shareable icu_friend_invite_token.
Both are replaced with a visible marker, at any depth, on every tool result -
not just athlete responses, and including when you ask for fields: ["*"] - so
neither can reach a model's context, a transcript or a log. email and icu_date_of_birth are personal but not
credentials, so they are merely absent from the default field set and can still
be requested by name.
IDs are validated locally. Activity IDs must look like i12345678 (or a
bare number); event, workout and route IDs must be numeric. An ID is spliced into
an API path, so a slash, dot, %, ? or # is refused before any request is
made, and the client also refuses any path the URL parser would rewrite. Without
this, delete_workout with ../events/5 would reach an event.
Dates are validated locally. Date inputs must be YYYY-MM-DD
(create_event and update_event also accept YYYY-MM-DDTHH:MM:SS). Malformed values fail
immediately with an actionable message rather than producing a confusing 422
from the API.
Requests time out and retry. Each HTTP attempt is aborted after 30 seconds.
Responses of 429 or 5xx, timeouts and dropped connections are retried up to 3
times with exponential backoff, honouring a Retry-After header when the server
sends one. A POST is retried only on a 429: after a 5xx or a timeout it may
already have created what it asked for, so the error says to check first. Intervals.icu rate
limits both per day and per rolling 15-minute window, so this matters in
practice.
Responses are compact. Tool results are minified JSON; the indentation in pretty-printed output roughly doubles token cost for no benefit.
Structured workouts are plain text. Workout steps are not JSON: they are
written in Intervals.icu's own workout syntax and passed in description on
create_event, update_event, create_workout or update_workout.
Intervals.icu parses that text server-side into a structured workout with
training load, zone targets and device sync. A description it cannot parse is
kept verbatim as free text with no load and nothing to push to a head unit —
and nothing in the API response says so. Because that failure is silent, the
syntax is published as the intervals-icu://workout-syntax resource, including
the traps: a bare m is minutes (400m is 400 minutes, not 400 metres —
that is 400mtr), and an absolute pace target needs the trailing word
pace.
Deleting is gated. INTERVALS_DELETE_MODE decides how much deleting the
server will do, and the gate is in the server rather than in a tool argument
because a model can set an argument itself:
Mode | Effect |
| The delete tools are registered, but |
| Any event can be deleted, past included, with no pre-flight read. |
| The delete tools are not registered at all, so no client can see or call them. |
delete_workout is allowed in both safe and full: a library workout is a
template and carries no training history of its own. Deleting one leaves
calendar events already created from it untouched.
Reads and writes are labelled. 27 of the 45 tools only read, and are
annotated readOnlyHint: true so a client can auto-approve them. The eighteen
writers come in three shapes. The updates — update_activity,
update_wellness, update_event, update_workout, update_sport_settings,
update_gear, update_gear_reminder — overwrite fields on an existing record (destructiveHint: true, idempotentHint: true: repeating
the call leaves the record in the same state). The creates — create_event,
create_events, duplicate_events, apply_plan, create_workout,
create_folder, create_gear, add_gear_reminder, add_activity_message —
only ever add (destructiveHint: false,
but idempotentHint: false, since a second call adds a second entry). The
deletes — delete_event, delete_workout — are destructiveHint: true and
idempotentHint: true, since once a record is gone a second delete changes
nothing further. Every tool is openWorldHint: true: they all reach the
Intervals.icu API, whose contents this server does not control. A test asserts
the split, so a new tool cannot be added without a hint.
Known gaps
The athlete ID is fixed at startup, so coach/multi-athlete use is not possible without restarting with a different ID.
Athlete zones are read through
get_athletewithfields: ["sportSettings"].update_sport_settingschanges them for activities from then on, but nothing here re-applies them to activities already recorded (sport-settings/{id}/apply): that rewrites history and is not exposed.update_activity,update_event,delete_event,create_workout,update_workout,delete_workout,list_folders,get_fitness_chartand the workout-syntax resource were exercised against a live Intervals.icu account on 2026-10-16 and behave as documented. Still unverified there:create_folder(the account had a folder already, so none was created), andINTERVALS_DELETE_MODE=full, which is covered only by the fake-server test — running it against a real account risks real history for no new information.Changing
categoryon an existing event is one-way for some kinds: once an event isTARGETorPLAN, the API answers 422 "Cannot change category" and the only route is delete-and-recreate.SET_EFTPadditionally requirestype, since eFTP is per sport. All fourteen categories in the enum were accepted by the live API.get_fitness_chartreports future days asprojectedby comparing dates against "today" inINTERVALS_TIMEZONE(or the timezone chosen at hosted sign-in), falling back to the host's zone. A hosted server with neither set would count days in UTC.No tool declares an
outputSchema, so a client cannot validate a result against a promised shape before handing it to a model.The test suite never contacts Intervals.icu, so it pins down this server's behaviour rather than the upstream API's. A change in what Intervals.icu actually returns would not be caught by it.
Of the 45 tools, twenty-eight are driven end to end against the fake API (
list_activities,search_intervals,get_activity_streams,get_activity_histogram,get_activity_messages,add_activity_message,update_activity,update_sport_settings,get_power_curves,get_hr_curves,get_pace_curves,update_wellness,get_fitness_chart,list_events,get_event,create_event,create_events,update_event,duplicate_events,apply_plan,delete_event,create_workout,delete_workout,list_folders,create_gear,update_gear,add_gear_reminder,update_gear_reminder) and two more are exercised on their error paths. The remaining fifteen are covered only at the schema level, bytools/list.list_gearandlist_routesreturn zero records for the configured athlete, so they have never been exercised against real data and are unverified. (list_workoutshas since been exercised live, against a workout created and then deleted by the verification run.)The
intervals-icu://workout-syntaxresource was rewritten from what the live parser does, not from the forum documentation, after round-tripping each rule through a real event. Six of its claims were wrong: the dashed- 3xrepeat form (never parses), a blank line after theNxmarker (kills the repeat), clock step lengths5:00and1:30:00(dropped),lap pressas a manual step (becomes prompt text), and absolute bpm targets in every spelling (dropped). An unparseable line is dropped on its own, silently, so a wrong rule shortens the workout rather than failing it.The curve tools take exactly one sport
type; the API rejects a comma-separated list, so there is no all-sports view.
Contributing
Issues and pull requests are welcome. Please run npm run typecheck and
npm test before opening a PR; the suite needs no credentials and no network.
License
MIT © Travis Moe
Available Tools
22 toolscreate_eventCreate calendar eventB
Create an event on the athlete's training calendar (planned workout, race, note, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Event name/title | |
| type | No | Sport type e.g. Ride, Run, Swim, WeightTraining | |
| category | Yes | Event category | |
| distance | No | Planned distance in meters | |
| description | No | Event notes or description | |
| moving_time | No | Planned duration in seconds | |
| start_date_local | Yes | Start date/time in ISO 8601 format e.g. 2024-06-01T08:00:00 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-idempotent, non-destructive, open-world write, so the safety profile is covered externally. The description adds only that the target is the athlete's training calendar; it does not say whether duplicate events are allowed, what permissions are required, or what happens on a date collision.
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?
A single front-loaded sentence with the verb and resource first and the clarifying examples after. Nothing is padded and nothing needs to be re-read.
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 7-parameter mutation with no output schema, the description is thin: it says nothing about the created object's return shape, error behavior, or whether category choices alter required fields. Annotations cover the safety side, but the description leaves a real gap around mutation outcomes.
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 every parameter (category enum, ISO date pattern, distance/duration units) is already documented in the schema. The description contributes no additional parameter meaning, which is the expected baseline when the schema does the heavy lifting.
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?
States a specific verb ('Create') and resource ('event on the athlete's training calendar'), with parenthetical examples (planned workout, race, note) that make the intent unambiguous. It implicitly separates itself from read-side siblings like get_event/list_events, though it never names them explicitly.
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?
There is no when-to-use guidance, no mention of prerequisites, and no routing between this and siblings such as update/delete or bulk list operations. The parenthetical gives event kinds but not the conditions under which an agent should call this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activityGet activityBRead-only
Get detailed information about a specific activity by its ID. Returns a compact summary by default; pass fields for other metrics.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 30-field summary; the full record has ~184 fields, many of them null. Pass ["*"] for everything. | |
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds useful behavioral context — that the default result is a compact summary and that `fields` unlocks other metrics — which goes beyond the annotations, though it stops short of explaining the cost/size tradeoff.
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?
Two tightly written sentences, front-loaded with purpose and the return-shape caveat. Minimal waste, though the first clause partly echoes the name/title.
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 read tool with full schema coverage and annotations, the essentials are present. The notable gap is routing: with so many get_activity_* siblings, the definition does not equip an agent to confidently select this tool over the specialized ones.
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 activity_id and fields are already fully documented in the schema (including the 30-vs-184 field detail). The description restates the fields behavior at a high level without adding syntax or examples beyond the schema, so the baseline of 3 applies.
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?
States a specific verb (get) and resource (activity) plus the lookup key (by its ID) and return scope (detailed information). However, it does not differentiate itself from the many get_activity_* siblings (streams, intervals, power_curve, weather), so an agent cannot tell from the description alone which of these to choose.
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 gives no when-to-use context and never names an alternative, despite numerous sibling tools that fetch activity-related data. Nothing tells the agent when this core-record tool is preferred over get_activity_streams or the other specialized variants.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_best_effortsGet activity best effortsARead-only
Find best efforts within an activity - e.g. peak 5-min power, fastest 1km. Requires a stream to measure and exactly one of duration or distance.
| Name | Required | Description | Default |
|---|---|---|---|
| stream | Yes | Stream to measure, which must exist on the activity - see its `stream_types`. e.g. watts, heartrate, velocity_smooth, distance. Note "pace" is NOT valid; use velocity_smooth. | |
| distance | No | Effort length in meters, e.g. 1000 for fastest 1km | |
| duration | No | Effort length in seconds, e.g. 300 for peak 5-minute | |
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds the genuinely useful constraint that the stream must exist on the activity and that exactly one of duration/distance is required, but says nothing about the shape or ordering of returned efforts. With annotations carrying the safety burden, a 3 is appropriate.
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?
Two sentences, zero filler, with the core purpose and its examples front-loaded and the calling constraint second. Every clause 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 read-only computation with no output schema, the description covers what the tool computes and the constraints needed to invoke it. It could optionally sketch the returned entity (e.g. per-effort duration/distance/value) to complete the picture, but nothing essential to a correct call 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%, giving a baseline of 3, and the schema already documents each field richly (units, examples, the 'pace is NOT valid' caveat). The description goes beyond the schema by stating the mutually-exclusive constraint 'exactly one of duration or distance', which the schema's required list does not encode. That is real added semantic value.
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?
Names a specific verb ('Find') and resource ('best efforts within an activity') and grounds it with two concrete examples (peak 5-min power, fastest 1km), so the agent knows exactly what is computed. It does not explicitly distinguish itself from near-siblings such as get_activity_power_curve or get_activity_intervals, which describe overlapping peak-effort concepts.
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 supplies a real precondition ('Requires a stream to measure and exactly one of duration or distance'), which tells the agent how to call it correctly. It gives no guidance on when to prefer this tool over get_activity_power_curve or get_activity_intervals, so usage against alternatives is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_intervalsGet activity intervalsARead-only
Get the lap/interval breakdown for an activity. Each lap carries 84 fields, so a compact subset is returned by default; fields applies to the individual laps inside icu_intervals and icu_groups.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 24-field summary; the full record has ~84 fields, many of them null. Pass ["*"] for everything. | |
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds genuinely useful behavioral context beyond that: laps have 84 fields, a compact subset is returned by default, and the response is organized into icu_intervals and icu_groups. It stops short of noting pagination or other limits, but that gap is minor against the annotation coverage.
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?
Two sentences, zero padding. The purpose is front-loaded in the first sentence and the non-obvious nested-field scoping caveat follows immediately.
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?
With no output schema, the description carries the burden of describing returns; it names the top-level result keys (icu_intervals, icu_groups) and the default compact shape, which is enough for an agent to call it correctly. A note on what the default 24 fields actually contain would close the remaining 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 baseline is 3. The description goes further by clarifying the scope of `fields`: it applies to the individual laps nested inside icu_intervals and icu_groups, not to top-level records. That is real meaning the schema's generic 'Fields to return' text does not convey.
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?
States a specific verb and resource: 'Get the lap/interval breakdown for an activity.' This is clearly distinct from the plain get_activity sibling, though it never names that sibling or any other alternative explicitly. An agent can infer the distinction from the resource scope.
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 only implied: you call this when you need lap/interval detail rather than an aggregate activity record. No when-to-use condition, no exclusions, and no pointer to get_activity or get_activity_streams for related data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_power_curveGet activity power curveBRead-only
Get the mean maximal power curve for a specific activity.
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered and the bar is lower. The description adds the specific meaning of the returned data ('mean maximal power curve'), but says nothing about return format, units, or whether the curve is time-windowed. With no output schema, a bit more behavioral detail would help.
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?
A single front-loaded sentence with no filler. It is efficiently sized, though notably under-specified rather than deliberately minimal.
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 single-parameter read tool with annotations covering the safety profile, the essentials are present. The main gaps are the lack of distinction from get_power_curves and no indication of what the returned curve contains at a high level, which matters since there is no output schema.
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% for the single activity_id parameter, so the schema fully documents it. The description adds no syntax, format, or sourcing guidance for the ID, leaving the baseline 3 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?
States a specific verb ('Get') and resource ('mean maximal power curve') scoped to 'a specific activity', which is clearer than a bare title restatement. However, it offers no differentiation from the sibling get_power_curves, so an agent cannot tell from the description alone which of the two power-curve tools to pick.
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 no when-to-use context, no prerequisites, and does not name or distinguish itself from the obvious alternative (get_power_curves). Usage must be inferred entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_streamsGet activity streamsARead-only
Get time-series data streams for an activity (power, HR, cadence, speed, altitude, GPS, etc.). Streams are large, so each channel is downsampled to 500 evenly spaced points by default. Pass types to fetch only the channels you need, and raise max_points only when you genuinely need finer resolution.
| Name | Required | Description | Default |
|---|---|---|---|
| types | No | Channels to return, e.g. ["watts","heartrate","cadence"]. Omit for all channels (much larger). | |
| max_points | No | Downsample each channel to at most this many points (default 500) | |
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, openWorldHint), and the description usefully adds what they cannot: the payload is large, channels are silently downsampled to 500 points by default, and finer resolution is opt-in. It stops short of describing the return shape or ordering.
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?
Three tight sentences, front-loaded with purpose then behavior then guidance, with no filler. Slight redundancy with the schema's own types/max_points descriptions keeps it off a 5.
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 read-only, three-parameter tool with no output schema, the description covers size, downsampling semantics, and filtering well enough to call it correctly. The one gap is that the shape of the returned stream data (per-channel series, timestamps vs values) is left entirely unstated.
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 both optional parameters already document their defaults, bounds, and the 'omit for all channels (much larger)' behavior. The description largely restates that and adds only rationale (size/resolution tradeoff), which lands at the baseline for fully-covered schemas.
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?
States a precise verb+resource ('Get time-series data streams for an activity') and enumerates the channel types returned, which cleanly separates it from summary tools like get_activity. It never names a sibling, however, so an agent must still infer the boundary against get_activity_intervals or get_activity_power_curve on its own.
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?
Offers real efficiency guidance — pass types to limit channels, and raise max_points 'only when you genuinely need finer resolution' — but this is parameter-level advice, not tool-selection advice. Nothing tells the agent when to prefer this over get_activity_intervals or get_activity_power_curve, which return overlapping time-series data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_weatherGet activity weatherCRead-only
Get the weather summary for an activity.
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes | The activity ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, conveying the safe-read and external-data profile. The description adds nothing beyond that — no indication of whether weather data may be unavailable, what units/fields the summary contains, or any latency/caching behavior for an external lookup.
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?
A single front-loaded sentence with no wasted words. It is efficient, though arguably too terse to be maximally helpful.
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 one-parameter read whose annotations cover the safety profile, the description is minimally adequate. With no output schema, it could reasonably say what the 'weather summary' includes, which is the main remaining 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?
Only one parameter (activity_id) with 100% schema description coverage, so the schema does the work. The description adds no meaning beyond the schema, which is the baseline expectation at this coverage level.
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?
States a specific verb ('Get') and resource ('weather summary for an activity'), so an agent knows exactly what this returns. It is naturally distinct from siblings like get_activity_streams or get_activity_power_curve, though it does not explicitly differentiate itself.
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?
There is no guidance on when to use this tool versus the many other get_activity_* siblings, nor any prerequisite or exclusion noted. Usage is only implied by the name and description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_athleteGet athleteARead-only
Get the athlete profile: identity, physiology and account info. Returns a compact subset by default - pass fields ["sportSettings"] for per-sport FTP, thresholds and zones (~10 KB), or ["*"] for everything including per-vendor sync configuration. Credential fields are always withheld, and email and date of birth are available only on explicit request.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 21-field summary; the full record has ~162 fields, many of them null. Pass ["*"] for everything. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, it discloses concrete behavioral traits: the default is a compact 21-field-ish subset, the sportSettings payload is ~10 KB, credentials are always withheld, and email/DOB are gated behind explicit request. These are exactly the privacy and payload-size facts an agent needs and cannot get from the annotations.
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?
Three tight sentences, front-loaded with what the tool returns, followed by the default/payload-size behavior and then the privacy caveats. No filler and no restatement of the title.
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?
There is no output schema, so the description carries the full burden of describing returns, and it does: it explains the default vs. expanded shape, approximate sizes, and which fields are withheld. For a single-optional-parameter read tool, nothing material 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 already 100% for the single `fields` parameter, so the baseline is 3. The description nonetheless adds value beyond the schema: it names a concrete useful field ('sportSettings') with its contents and rough size, and flags that certain fields (credentials, email, DOB) behave specially when requested.
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 names a specific verb and resource ('Get the athlete profile: identity, physiology and account info'), which is far more informative than the tautological title. It does not, however, differentiate itself from the sibling get_athlete_profile, leaving the agent to guess which of the two retrieves what.
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?
It implies when to use which field selection ('pass fields ["sportSettings"] for per-sport FTP... or ["*"] for everything'), but gives no explicit guidance on when to prefer get_athlete over get_athlete_profile, nor any exclusion conditions. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_athlete_profileGet athlete public profileBRead-only
Get public profile info for the athlete (name, bio, location, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety and boundary behavior are covered by structured fields. The description adds only that the profile is 'public', which is modest extra context but does not disclose return shape, pagination, or field availability.
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?
A single tight sentence that front-loads the verb and resource with no filler. The '(name, bio, location, etc.)' parenthetical is useful illustration, though the 'etc.' is slightly loose.
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-param read tool with annotations carrying the safety profile and no output schema, the description is minimally adequate. It never explains the difference from the similarly named sibling get_athlete, which is the main completeness gap an agent would care about.
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 takes zero parameters, which is the baseline-4 case. The schema has no parameters to document, and the description correctly implies no inputs are needed, so nothing material is missing.
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?
Clear verb (get) and resource (athlete public profile), plus an enumeration of what fields come back (name, bio, location). It does not differentiate from the sibling get_athlete, which appears to be a closely related tool, so it falls short of a 5.
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?
No when-to-use guidance and no exclusions. In a family that contains a sibling named get_athlete, the description never tells an agent which of the two to call or under what circumstances, leaving selection to guesswork.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventGet calendar eventARead-only
Get a specific calendar event by ID. Returns a compact summary by default - pass fields ["*"] (or name workout_doc) to get the structured workout.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 14-field summary; the full record has ~62 fields, many of them null. Pass ["*"] for everything. | |
| event_id | Yes | The event ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. Beyond that, the description discloses return-shape behavior the annotations do not: a compact summary is returned by default, and the full structured workout requires passing fields ['*'] or naming workout_doc. This is useful behavioral context, though permission/auth and error behavior remain unstated.
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?
Two tight sentences with zero filler; the primary retrieval purpose is front-loaded and the non-obvious return-shape caveat follows immediately.
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?
With no output schema, the description correctly carries the burden of explaining what comes back, and it does so by contrasting the default compact summary against the full record. It could go further on what the compact summary contains or how IDs are obtained, but it covers what an agent needs to call it correctly.
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 baseline is 3, but the description adds a field name not present anywhere in the schema ('workout_doc') as a way to pull the structured workout, giving an agent domain-specific guidance beyond the schema's generic '["*"] for everything'.
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?
States a specific verb and resource ('Get a specific calendar event by ID'), which separates it from list_events and from get_activity/get_workout. It never names a sibling tool explicitly, so an agent must infer the boundary rather than being told, keeping it just short of a 5.
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 by 'by ID' (you call this when you already hold an event ID), but the description offers no explicit when-to-use versus list_events or search-adjacent retrieval tools, and states no prerequisites for obtaining the ID.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_power_curvesGet power curvesARead-only
Get the athlete's best mean maximal power curves across activities of one sport. secs and values on each curve are the curve itself. The bulk activities lookup map is omitted unless you pass fields ["*"].
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Sport type - REQUIRED, and exactly one (the API rejects a comma-separated list). e.g. Ride, VirtualRide, GravelRide, Run, VirtualRun, Swim | |
| curves | No | Which curves to return, e.g. "42d" or "all". Invalid values are rejected by the API with the list of valid ones. | |
| fields | No | Fields to return. Defaults to a compact 13-field summary; the full record has ~20 fields, many of them null. Pass ["*"] for everything. | |
| newest | No | End date YYYY-MM-DD | |
| oldest | No | Start date YYYY-MM-DD |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this is a read-only, open-world call, so the bar is lower. The description adds genuinely useful behavioral detail beyond them: the shape of each returned curve (`secs`/`values`) and the non-obvious default that the bulk `activities` lookup map is stripped unless fields ["*"] is passed.
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?
Three sentences, front-loaded with the core purpose, and each sentence carries distinct information (scope, response shape, default field filtering). No padding, though the abrupt parameter references ('`secs` and `values`') assume the reader has already seen a response.
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?
With no output schema, the description takes on the return-value burden and does explain the curve structure and the omitted activities map. It leaves minor gaps, such as what curve windows ('42d', 'all') mean or how dates bound the aggregation, but the essentials for calling the tool correctly are 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?
Schema description coverage is 100%, so the schema already documents all five parameters, including field selection and defaults; baseline 3 applies. The description's note about the omitted `activities` map adds a small amount of meaning to `fields`, but it largely restates what the schema's ["*"] wording already conveys.
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?
States a specific verb and resource ('Get the athlete's best mean maximal power curves') and adds the scope 'across activities of one sport', which implicitly separates it from the single-activity sibling get_activity_power_curve. It never names that sibling explicitly, so the agent must infer the distinction from the 'across activities' phrasing.
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?
There is no when-to-use guidance and no alternatives named. The only conditional text ('unless you pass fields ["*"]') describes a parameter behavior, not a situation for choosing this tool over get_activity_power_curve or get_activity_best_efforts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_routeGet routeCRead-only
Get a specific route by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| route_id | Yes | The route ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds nothing beyond that: it does not say what happens on a missing/invalid ID, whether the result includes nested route data, or any rate-limit/access behavior.
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?
A single short sentence with the key qualifier ('by ID') front-loaded and zero filler. It is efficient, though the brevity comes partly from under-specification rather than tight editing.
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 one-parameter read tool with full schema coverage and read-only annotations, the core information is present. However, with no output schema, the description never hints at what a route object contains, leaving the return shape entirely unexplained.
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?
Only one parameter and schema description coverage is 100%, so the schema already documents route_id fully. The description's 'by ID' merely restates the parameter; baseline 3 applies since the schema does the work.
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?
States a specific verb (get) and resource (route) with the retrieval key (ID), so an agent knows it fetches a single route rather than a collection. It does not explicitly name list_routes or search_activities as the alternatives, so it is clear but not sibling-differentiating.
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?
No when-to-use guidance, no prerequisites, and no mention of when to prefer list_routes or another sibling. The agent must infer that this is for single-route lookup by identifier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_wellnessGet wellness recordBRead-only
Get the wellness record for a specific date.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Date in YYYY-MM-DD format |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description adds nothing beyond them: no indication of what a wellness record contains, whether a missing date returns empty or errors, or any auth/quota context. It does not contradict the annotations, it simply adds no behavioral value.
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?
One short, front-loaded sentence with zero filler. It is efficient rather than padded, though the brevity leaves no room for the routing or return-shape context an agent would benefit from.
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 single-parameter read tool with full schema coverage this is close to adequate, but with no output schema the description does not tell the agent what a wellness record actually holds. Minimal but defensible.
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%, and the single date parameter is fully documented with a regex pattern and YYYY-MM-DD guidance. The description cannot add meaning beyond the schema here, so the baseline 3 applies.
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?
Clear verb+resource ("Get the wellness record") narrowed by scope ("for a specific date"), which distinguishes it from the range-oriented list_wellness and the mutating update_wellness. It stops short of naming those siblings explicitly, so the differentiation is inferable rather than stated.
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 by "for a specific date" — a single-record fetch — but the description never says when to prefer it over list_wellness or what to do for a range. No prerequisites, no exclusions, no named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workoutGet workoutBRead-only
Get a specific workout from the library by ID.
| Name | Required | Description | Default |
|---|---|---|---|
| workout_id | Yes | The workout ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds nothing beyond that: no note on behavior for an unknown ID, no indication of what a workout record contains, and no scope constraints on 'library'.
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?
One short sentence with no filler, and the resource and lookup key are front-loaded. It is efficient, though the extreme brevity leaves room for a useful clause about the identifier's origin or failure behavior.
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 single-parameter read tool with annotations covering the safety profile, the essentials are present. With no output schema and no description of the returned workout structure or error behavior for a bad ID, an agent still lacks some operational context.
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?
There is a single required parameter and schema description coverage is 100%, so the schema fully documents workout_id. The description only restates that the lookup is by ID, adding no format or sourcing detail beyond the schema; baseline 3 applies.
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?
States a specific verb and resource ('Get a specific workout from the library by ID'), which is unambiguous about what the tool returns. It doesn't explicitly name the sibling list_workouts to contrast retrieval of one item vs enumeration, so sibling differentiation is implied rather than stated.
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 phrase 'by ID' implies the caller must already have an identifier, which is the natural precondition for use. However, there is no explicit when-to-use guidance or routing to alternatives such as list_workouts or search_activities.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_activitiesList activitiesARead-only
List activities for a date range. Returns a compact summary of each activity by default; use fields to choose exactly what you need.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of activities to return | |
| fields | No | Fields to return. Defaults to a compact 30-field summary; the full record has ~184 fields, many of them null. Pass ["*"] for everything. | |
| newest | Yes | End date in YYYY-MM-DD format (inclusive) | |
| oldest | Yes | Start date in YYYY-MM-DD format (inclusive) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds that results are a compact summary by default, but that same fact is already spelled out in the `fields` schema entry, so the added behavioral value is thin. Nothing about pagination or the `limit` ceiling of 500 is surfaced.
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?
Two tight sentences with the list/date-range scope front-loaded and no filler. The second sentence largely restates the `fields` schema description, which slightly dilutes its value.
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 read-only list tool with a fully documented schema and no output schema, an agent has what it needs: scope, defaults, and how to expand the payload. Only pagination behavior and the relationship to search_activities are unaddressed.
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% and each parameter carries its own description, so the baseline is 3. The description points at `fields` but adds no syntax or default detail beyond what the schema already provides.
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?
States a specific verb+resource (list activities) with scope (for a date range), which cleanly separates it from get_activity, get_activity_streams, and other single-activity siblings. It does not explicitly name search_activities as the alternative, so differentiation is implied rather than stated.
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 date-range framing implies when this tool applies, and the hint about `fields` steers parameter choice, but there is no explicit when-to-use versus search_activities or the get_* siblings, and no prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList calendar eventsARead-only
List events on the athlete's training calendar for a date range. Returns a compact summary of each event by default, omitting the structured-workout document; pass fields to change that.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 14-field summary; the full record has ~62 fields, many of them null. Pass ["*"] for everything. | |
| newest | Yes | End date YYYY-MM-DD | |
| oldest | Yes | Start date YYYY-MM-DD |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, openWorldHint), yet the description adds genuinely useful behavior: the default response is a compact summary that omits the structured-workout document, and fields can change that. This non-obvious default would otherwise surprise an agent. It stops short of 5 because it says nothing about result ordering, result caps, or pagination for large ranges.
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?
Two sentences, zero waste, and the core purpose plus the most surprising behavior (default compact projection) are both front-loaded. Nothing could be trimmed without losing information.
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 list tool with no output schema, the description covers purpose, scope, and the return-shape default, and annotations cover read-only safety. It is missing only operational detail such as pagination or whether very wide date ranges are truncated, which keeps it from a 5.
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%, with fields, oldest, and newest all documented in the schema (including the compact 14-field default and the ["*"] escape hatch), so the schema carries the load. The description restates the fields behavior but adds no syntax or format detail beyond it, making the baseline 3 correct.
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?
States a specific verb (List) and resource (events on the athlete's training calendar) scoped to a date range, which an agent can readily distinguish from the singular get_event sibling. It does not explicitly name a sibling or carve out what it is not, so it falls just short of a 5.
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 only implied: the date-range framing suggests bulk retrieval versus get_event for a single event, but no when-to-use or when-not-to-use guidance is given. No mention of alternatives, prerequisites, or limits on range size.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_gearList gearARead-only
List all gear (bikes, shoes, etc.) for the athlete.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds nothing beyond that: no indication of pagination, result size, whether retired/inactive gear is included, or that it is scoped to the authenticated athlete (leaving that to inference).
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?
A single short sentence with the resource front-loaded and the scope trailing. Nothing is padded or redundant.
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 read-only list tool with annotations covering safety and no output schema, the description is sufficient to call it correctly and even sketches the return contents ('bikes, shoes, etc.'). It stops just short of noting athlete scoping/auth and whether all gear or only active gear is returned.
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 takes zero parameters, so per the rubric the baseline is 4. There is no parameter surface for the description to explain or omit.
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?
Clear verb + resource ('List all gear') with concrete examples (bikes, shoes) and an explicit scope ('for the athlete'). No sibling tool covers gear, so there is nothing to confuse it with, though it does not explicitly differentiate itself from the get_/list_ activity and event family.
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 rather than stated: 'for the athlete' signals it returns the authenticated athlete's equipment, and there are no alternative gear tools to route between. No when-not conditions or prerequisites (e.g., auth/scope requirements) are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_routesList routesBRead-only
List saved routes for the athlete.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is known. The description adds only the vague 'saved' qualifier and athlete scoping; it says nothing about result volume, ordering, or pagination behavior for what is presumably an unbounded list.
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?
A single short, front-loaded sentence with no waste. It is efficient, though arguably under-specified rather than crisply concise.
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?
The tool is simple (no params, no nested objects), but with no output schema the description should at least hint at what a 'route' list contains and whether it is paginated. It is minimally adequate rather than complete.
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 takes zero parameters, so the baseline is 4. There are no parameter semantics for the description to clarify.
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?
States a specific verb and resource ('List saved routes') with athlete scoping, so the agent knows this is a retrieval of persisted routes. It does not explicitly distinguish itself from the sibling get_route (singular) or list_activities, leaving the list-vs-single distinction implicit.
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?
No guidance on when to use this versus get_route or the activity-listing tools, and no mention of filtering, pagination, or prerequisites. Usage must be inferred entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_wellnessList wellness recordsARead-only
List wellness records for a date range: fitness model (CTL/ATL), HRV, resting HR, sleep, weight, mood and the other subjective scores.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. Defaults to a compact 23-field summary; the full record has ~47 fields, many of them null. Pass ["*"] for everything. | |
| newest | Yes | End date YYYY-MM-DD | |
| oldest | Yes | Start date YYYY-MM-DD |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds a useful inventory of what the records contain (fitness model, HRV, sleep, subjective scores), which helps an agent judge relevance. It says nothing about volume, pagination, cost, or how sparse/missing data behaves, so it adds only modest behavioral context beyond the annotations.
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?
A single sentence that front-loads the verb and resource, then qualifies with the date-range scope and the returned data. Every clause carries information and there is no filler or 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?
With no output schema, the description usefully compensates by enumerating the categories of data returned, letting an agent confirm the tool covers the metrics it needs. What is missing — cardinality of results, whether missing days are returned as nulls, ordering — is minor for a read-only list call with two required date params.
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 oldest/newest formats (YYYY-MM-DD) and the fields selector (compact 23-field default, ["*"] for all ~47) are already fully documented in the schema. The description only restates that a date range is required and does not add syntax or defaults beyond that, so the baseline 3 applies.
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?
Names a specific verb (List) and resource (wellness records) and scopes it to a date range, then enumerates the metric families returned (CTL/ATL, HRV, resting HR, sleep, weight, mood). It does not explicitly distinguish itself from the get_wellness sibling, which is the closest alternative, so it falls short of a 5.
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 by the phrase 'for a date range' — an agent can infer this is the multi-day retrieval tool as opposed to the single-record get_wellness. However, there is no explicit when-to-use statement, no guidance on choosing between list_wellness and get_wellness, and no mention of prerequisites or limits.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workoutsList workoutsBRead-only
List all workouts in the athlete's workout library.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, and the description adds essentially nothing beyond them apart from the word 'all'. It says nothing about result volume, pagination, or whether the full library is always returned, so it does not enrich the safety profile the annotations provide.
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?
A single front-loaded sentence with no filler or repetition. It is efficient, though arguably so terse that it forgoes any of the extra context a list tool could usefully carry.
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 list tool with annotations covering read-only semantics, this is close to sufficient. With no output schema to describe returns, however, the description omits any hint of result shape or pagination, leaving minor gaps.
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 takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. No param-level meaning is missing.
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 states a specific verb (List) and resource (workouts) and scopes it to the athlete's workout library, so the agent knows what it retrieves. It does not, however, distinguish itself from the sibling get_workout, which also targets workouts.
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?
There is no when-to-use guidance, no statement of when to prefer get_workout, and no mention of prerequisites or the absence of filtering. The listing intent is only implied by the verb in the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_activitiesSearch activitiesCRead-only
Search for activities by name or tag.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results (the API returns 30 by default) | |
| query | Yes | Search query (name or tag) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered, but the description adds no behavioral context of its own — no result volume, no default limit note, no pagination or match semantics. It essentially restates the schema's parameter description.
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?
A single short sentence with no filler and the core action up front. It is efficient, though so terse that it borders on under-specification rather than true conciseness.
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 two-parameter read tool with no output schema, the description is minimally sufficient. The notable gap is disambiguation from list_activities and get_activity, which an agent needs to route correctly among the many activity siblings.
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 both parameters (query, limit) are already documented in the schema. The description repeats 'name or tag' without adding syntax, matching rules, or guidance on the limit parameter, so the baseline 3 applies.
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?
States a specific verb (search) and resource (activities) and scopes it to name or tag matching. However, it does not differentiate itself from the sibling list_activities, so an agent cannot tell from the description alone which one to pick when browsing vs querying.
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?
No explicit when-to-use guidance and no mention of alternatives such as list_activities or get_activity. Usage is only weakly implied by the phrase 'by name or tag'; nothing tells the agent what to do when it lacks a query term.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_wellnessUpdate wellness recordADestructiveIdempotent
Update the wellness record for a specific date. Only supply the fields you want to change.
| Name | Required | Description | Default |
|---|---|---|---|
| hrv | No | HRV score | |
| date | Yes | Date in YYYY-MM-DD format | |
| mood | No | Mood score (1-10) | |
| notes | No | Free text notes | |
| injury | No | Injury score (1-10) | |
| stress | No | Stress score (1-10) | |
| weight | No | Body weight in kg | |
| fatigue | No | Fatigue score (1-10) | |
| hrvSDNN | No | HRV SDNN (ms) | |
| sleepTq | No | Sleep time in bed quality | |
| soreness | No | Soreness score (1-10) | |
| restingHR | No | Resting heart rate (bpm) | |
| sleepSecs | No | Sleep duration in seconds | |
| sleepScore | No | Sleep quality score | |
| kcalConsumed | No | Calories consumed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false. The description usefully adds patch semantics (only changed fields), which helps the agent avoid blanking fields, but it does not explain what happens to omitted fields, the destruction risk, or the return.
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?
Two short sentences, front-loaded with the action and scope, with the partial-update rule second. No filler or 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?
For a 15-parameter destructive update with no output schema, the description is minimal but adequate: it establishes purpose and patch behavior. It leaves the return value and the fate of omitted fields unstated, which is a real gap for a destructive mutation.
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 all 15 parameters are already self-documenting. The description adds no parameter-level meaning beyond the schema, which is the expected baseline.
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?
States a specific verb+resource ('Update the wellness record') and scopes it to a specific date. It is distinguishable from the read siblings list_wellness/get_wellness, though it does not explicitly name them.
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?
'Only supply the fields you want to change' gives clear how-to-use (partial update) guidance. However, there is no when-to-use context, no exclusions, and no routing to alternatives such as the get_/list_wellness siblings.
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.
22 tool updates
v1.0.0- First observed
create_event - First observed
get_activity - First observed
get_activity_best_efforts - First observed
get_activity_intervals - First observed
get_activity_power_curve - First observed
get_activity_streams - First observed
get_activity_weather - First observed
get_athlete - First observed
get_athlete_profile - First observed
get_event - First observed
get_power_curves - First observed
get_route - First observed
get_wellness - First observed
get_workout - First observed
list_activities - First observed
list_events - First observed
list_gear - First observed
list_routes - First observed
list_wellness - First observed
list_workouts - First observed
search_activities - First observed
update_wellness
TDQS
Scored across 22 tools
Most tools target distinct resource/action pairs, especially the many activity-specific getters. The main overlap is between get_athlete and get_athlete_profile, which could be confused despite descriptions clarifying public versus full athlete data.
Tool names consistently use snake_case verb_noun patterns such as get_event, list_activities, create_event, and update_wellness. The use of search_activities instead of list_activities is semantically appropriate rather than a naming inconsistency.
With 22 tools, the surface is slightly heavy but reasonable for a sports-training API covering activities, streams, intervals, wellness, events, workouts, gear, and routes. Most tools correspond to distinct operations, though some activity-detail tools could feel numerous.
The server covers reading and analyzing activities, wellness, events, workouts, gear, and routes, plus a few write operations. However, notable gaps exist: no update/delete for events, and no create/update/delete for workouts, gear, or routes, limiting lifecycle management.
Maintenance
Related MCP Connectors
tri-train is a training platform for triathletes that syncs activities from Strava and Garmin and exposes them to Claude through a remote MCP server. Ask Claude how your last block went, why your run pace dropped, or whether you are fresh enough for Sunday's race, and it answers from your real data: activities with laps and grade-adjusted pace, weekly load and the performance management chart (CTL/ATL/TSB), sleep, HRV and resting heart rate, and your race calendar with predictions. Claude can also act: create and adjust planned workouts with structured intervals, push them to your Garmin watch, add races and write notes. Every change is journaled and can be undone. Read and write access are separate OAuth scopes, and the server enforces them on every call. Built and hosted in Switzerland by a triathlete; data stays on our own servers (Swiss revDSG / GDPR).
Your own cycling data for your AI assistant: rides, power, climbs and routes. Read-only.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
Your swim, bike and run training: readiness, HRV, sleep, workouts and race predictions. Read-only.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides Claude with read-only access to Garmin Connect data including daily health metrics, training status, activity details, and trends through 32 tools.-
- AlicenseAqualityBmaintenanceProvides AI assistants with read-only access to an athlete's Intervals.icu training data, including activities, wellness metrics, zones, and planned events, for use with MCP clients like ChatGPT and Claude.15MIT
- AlicenseBqualityBmaintenanceEnables Claude and other MCP clients to query Garmin Connect health, training, activity, and body data, analyze FIT files, and create structured workouts that sync to a Garmin watch.39MIT
- AlicenseAqualityAmaintenanceEnables AI assistants like Claude to read a single user's own Strava account through its API: profile and totals, activities with laps, splits, zones and per-second streams, plus segments, routes, gear and clubs. It is strictly read-only, using the user's own Strava API application and OAuth tokens stored locally, and returns model-friendly, context-sized data.14MIT