Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
query_healthA

Query Garmin health data (e.g. heart rate, sleep, stress, body battery, steps) for one field over a date range. Use query_context instead for weather, pollen and air quality; call list_available_fields first if the exact field name is unknown.

field: a health field name, e.g. "resting_heart_rate", "hrv_last_night", "body_battery_max", "steps_series". A "_series" suffix means intraday timeseries data; a plain name means one value per day. Pass the field that matches what you want — "sleep_score" returns three related fields together (sleep_score, sleep_score_feedback, sleep_score_qualifier). date_from/date_to: ISO "YYYY-MM-DD", inclusive. resolution is accepted but ignored — the field name alone decides the shape.

Unknown or ambiguous field names return an "error", often with a "did_you_mean" list of candidates (e.g. "steps" or "stress" without suffix: choose the daily or the _series variant). A clear typo or alias is resolved automatically; _meta.field_resolved_from / field_used then show what was substituted. A field with no data in the range returns empty values, not an error. Every field carries a "unit".

query_contextA

Query external context data (weather, pollen, air quality) for one field over a date range. Use query_health for Garmin body data (heart rate, sleep, stress, ...) instead; call list_available_fields first if the exact field name is unknown.

field: a context field name (e.g. "temperature_max", "pollen_grass_series"), or a category name — "weather", "pollen" or "air" — to get the main fields of that category at once. A "_series" suffix means intraday timeseries data; a plain name means one value per day. date_from/date_to: ISO "YYYY-MM-DD", inclusive. resolution is accepted but ignored — the field name alone decides the shape.

Unknown or ambiguous field names return an "error", often with a "did_you_mean" list of candidates. A clear typo or alias is resolved automatically; _meta.field_resolved_from / field_used then show what was substituted. A field with no data in the range returns empty values, not an error.

baselinesA

Query the rolling 90-day baseline and statistical reference range (mean +/- 3 standard deviations) for one health field over a date range. Use this to see what "normal" has looked like for a field recently, or alongside query_health() to compare today's value against the person's own history rather than a fixed threshold.

anomaliesA

Find days where one health field broke from its own recent pattern. Returns two kinds of findings: "outliers" (single days far outside the normal range) and "streaks" (five or more consecutive days consistently above or below the baseline average, even if none of them individually qualifies as an outlier -- useful for catching a slow drift, e.g. a gradually rising resting heart rate).

gapsB

List days with no usable data over a date range. domain is "health", "context", or "fit" ("fit" always degrades to "domain not yet available" -- no FIT pipeline exists yet). A gap is a day that was never synced at all, or was synced but came back empty/failed.

correlateA

Measure how closely two fields (health or context, any combination) move together over a date range -- e.g. does stress correlate with pollen count, or resting heart rate with sleep duration. lag_days (-7 to +7) shifts field_b relative to field_a: a positive lag compares field_a on a given day against field_b lag_days days LATER (useful for "does X today predict Y a few days from now" questions); 0 (the default) compares same-day values. Returns both Pearson (linear relationship) and Spearman (monotonic relationship, more robust to outliers) correlation coefficients, each in [-1, 1], plus how many overlapping data points they were computed from.

query_fit_activitiesA

Query FIT activity data for a field over a date range. Not yet available (FIT pipeline is v1.8) — returns a clean "not available" result until then, never an error.

query_rawA

Query archived Garmin data as stored in raw/, without value extraction, for fields the processed tools cannot reduce to a daily value (lists, event logs). Interpreting the content is up to the caller, and no units are provided. Use query_health instead whenever the data you need exists there: three of these fields have a processed counterpart there for everyday questions (floors: floors_climbed, daily_weigh_ins: body_weight, intensity_minutes_data: intensity_min_moderate and intensity_min_vigorous).

field: one of the raw field names (health domain only; these are NOT listed by list_available_fields): daily_weigh_ins, menstrual_calendar_data, pregnancy_summary, lifestyle_logging_data, nutrition_daily_food_log, nutrition_daily_meals, nutrition_daily_settings, floors, intensity_minutes_data, body_battery_events, lactate_threshold, running_tolerance. date_from/date_to: ISO "YYYY-MM-DD", inclusive. domain: only "health" holds raw data.

Only the requested field is returned. A field name that is almost right is corrected automatically (_meta.field_resolved_from / field_used show the substitution); an unknown name returns an error, with did_you_mean when similar names exist. A domain other than "health" returns an error.

Result: {"health": {field: {"values": [{"date": ..., "raw": ...}], "source_resolution": "raw"}}}. A day that is not in the archive has no entry; an archived day with nothing stored for the field has "raw": null. Read-only; does not change the archive.

get_archive_metadataA

Read archive-state metadata: how complete and healthy the archive is, plus sync and quality logs. kind selects the artefact:

  • "stats": small coverage/quality overview (total, high/standard/failed counts, date range, coverage_pct, last sync, integrity warnings). Use this for "how big/complete/healthy is my archive" questions.

  • "device_table": devices seen in the archive, with date range and number of days each.

  • "quality_log": per-day quality register.

  • "source_api_log": one record per data fetch (time, source, validator status, endpoints fetched).

  • "token_log": token events (created/invalidated/blocked/valid), never token contents.

  • "capability_config": which optional Garmin endpoints are enabled (may be empty).

  • "daily_logs", "fail_logs", "recent_logs": sanitized sync log lines, one entry per log file.

date_from/date_to (ISO "YYYY-MM-DD", inclusive) are needed for "quality_log", "source_api_log", "daily_logs", "fail_logs" and "recent_logs": without both dates these return an empty result (no error, no default range). They are ignored for the other kinds. The log kinds are large (a single week of daily_logs is several hundred KB), so request only the days you need and prefer "stats" for overview questions.

Result: {"data": ..., "error": None}. An unknown kind raises an error.

list_available_fieldsA

List the queryable fields, grouped by domain and source. Call this first when the exact field name for query_health or query_context is unknown (the fields of query_raw are not listed here; they are named in that tool's description). Omit domain for the full overview, or pass "health" or "context" to narrow it — the narrowed result is much smaller. "fit" returns an empty list (not available yet); an unknown domain returns no fields rather than an error.

Result: "domains" (the domain names), "metadata_kinds" (the archive- state kinds get_archive_metadata works with), "fields" ({domain: {source: [field, ...]}}; an empty list for "fit") and "units" ({field: unit} covering every field returned; values such as "index" or "text" mark fields without a physical unit). A field name ending in "_series" holds an intraday timeseries; any other name holds one value per day.

refresh_cacheA

Manually trigger a SQLite cache sync against the archive — use this if recent archive changes (a sync just run, a backfill/recheck just completed) might not yet be reflected in query results. Runs the same sync the server already performs automatically at startup. May take a while on a large pending delta (long idle period since the last sync) — this call blocks until the sync finishes.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.1/5.0

Scored across 11 tools

Disambiguation5/5

Each tool has a clearly distinct role: query_health vs query_context split cleanly by body vs external data, baselines vs anomalies vs gaps vs correlate each target a different analytical question, and query_raw is explicitly scoped against query_health with guidance on when to prefer each. The descriptions actively cross-reference and steer the agent away from the most likely confusions.

Naming Consistency4/5

All names are lowercase snake_case, but the pattern mixes verb_noun forms (query_health, refresh_cache, get_archive_metadata, list_available_fields) with bare-noun analytical tools (baselines, anomalies, gaps, correlate). Readable and predictable enough, but not a single consistent convention.

Tool Count5/5

Eleven tools is well within the ideal range and each one earns its place: discovery, health/context querying, raw access, three analytics tools, gap listing, cache refresh, and archive metadata. No redundant or filler tools.

Completeness4/5

For a read-only local archive the query/analytics surface is thorough (field discovery, daily and series queries, raw access, baselines, anomalies, gaps, correlation, metadata, cache refresh). The main gap is that FIT support is entirely non-functional — query_fit_activities is a stub and gaps 'fit' always degrades — which leaves a whole promised domain uncovered.

Maintenance

ActivityActive
ResponsivenessResponsive