Skip to main content
Glama
Thecimal

Quantified Self MCP Server

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
HEALTH_DB_PATHNoOptional path to the SQLite health database. If not set, the server uses its default database path.

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": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}

Tools

Functions exposed to the LLM to take actions

NameDescription
read_health_dataA

Read daily health metrics from the local database: steps, sleep hours, resting heart rate, weight (kg), workout minutes, mood, and water intake (ml).

Use this tool when:

  • the request is broad/general, across multiple metrics at once (e.g. "what health data do I have?", "overview of this week").

Do not use this tool when:

  • the user wants one specific metric's history/trend over time -> use get_metric_history instead.

  • the user wants raw/individual measurement rows (timestamp, source) -> use read_measurements instead.

  • the user wants workout sessions specifically -> use read_workout_sessions instead.

  • the user is asking why something changed, or wants a trend, anomaly, comparison, or correlation -> use explain_metric_change (one metric, one date) or get_recent_changes (scan across all metrics) instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

export_health_data_csvA

Write daily health metrics for a date range to a CSV file on disk, next to the database, instead of returning every row through this tool's own result.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

Unlike read_health_data, this is not capped at MAX_ROWS_RETURNED and the row values themselves are not included in this tool's response — only the resulting file's path and a row count are. That means a long-range export doesn't have to pass through a cloud LLM's context just to produce a file you can open yourself (in a spreadsheet, a notebook, another tool, etc.). Any metric listed in HEALTH_PRIVATE_FIELDS is still written as an empty cell in the file, since those fields shouldn't leave the database at all, not just stay out of the model's context.

log_daily_metricA

Record one or more health metrics for a single day, creating that day's row if it doesn't already have one.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

Only the metrics you pass are written — anything left as null is not touched, so logging just today's mood doesn't erase today's steps if they were set earlier. To undo a value logged by mistake, use clear_metric rather than trying to overwrite it with a placeholder.

Use this tool when:

  • the user is recording a simple day-level value for one of the nine fixed metrics below (e.g. "log my weight as 82 kg", "I walked 8,000 steps today").

Do not use this tool when:

  • the observation needs its own timestamp/source, or the day may have more than one reading of the same metric -> use log_measurement instead.

  • it's a workout/exercise session -> use log_workout_session instead (workout_minutes here is just the daily total, not the session itself).

clear_metricA

Blank out (set to null) a single metric for a single day, without touching that day's other metrics. The counterpart to log_daily_metric for undoing a bad value — e.g. a mood logged for the wrong day, or a weight entered with the wrong units. Clears everything recorded for that metric/day — including individual log_measurement readings or imported rows, not just a value log_daily_metric wrote directly — so the metric genuinely goes back to "nothing recorded" rather than falling back to a blended value from whatever else is left.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

log_measurementA

Record a single raw observation — one metric, one value, one point in time — rather than a whole day's summary. Use this instead of log_daily_metric when the source, exact time, or the fact that there were multiple readings that day matters (e.g. three separate workouts, or a wearable's periodic heart-rate samples).

Use this tool when:

  • recording one timestamped observation where the exact time, source, or possibility of multiple same-day readings matters (e.g. "record my blood pressure reading from my cuff at 7am").

Do not use this tool when:

  • it's just a single end-of-day value for a fixed metric -> use log_daily_metric instead.

  • it's a workout/exercise session -> use log_workout_session instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

read_measurementsA

Read individual measurement rows (not the daily_metrics aggregate), most recent first. Use this to see exactly when and where each reading came from, rather than just a day's summarized value.

Use this tool when:

  • the user wants raw/individual observations (e.g. "what measurements have I recorded?"), including their timestamp or source.

Do not use this tool when:

  • the user wants a broad, multi-metric overview -> use read_health_data instead.

  • the user wants one metric's day-by-day history -> use get_metric_history instead.

  • the user wants workout sessions -> use read_workout_sessions instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

aggregate_measurementsA

Preview what one day's raw measurements would roll up to if a conflicting metric were resolved using source_priority, alongside that day's actual current daily_metrics values.

daily_metrics is a database-maintained projection (see db/schema.sql): every log_measurement/import automatically keeps it in sync the moment it's written, using each metric's fixed aggregation method (sum/mean/last — see aggregation_rules, or get_baseline's "method" field). When a metric has measurements from more than one source on a day, the projection uses only one source's observations — never a blend of devices. It takes the highest-ranked present source in the stored source priority list (manual log_daily_metric entries rank first by default); if none is ranked, the source that observed the most hours of that day, then the one with the latest observation, then by name. This tool writes nothing: "aggregated" previews what the source_priority you pass would produce; "row" is the real, currently-stored value, which differs from "aggregated" whenever the stored priority differs from the one you pass.

If a metric has measurements from more than one source that day (e.g. an Apple Watch and a Garmin both logging resting_heart_rate), use get_metric_provenance first to see whether they actually disagree.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_metric_provenanceA

Show one metric's raw measurements for one day, broken down by which source reported them — answers "which one is correct?" when e.g. an Apple Watch and a Garmin disagree on resting heart rate, instead of silently averaging two different devices into one number.

Do not use this tool when:

  • the user just wants a plain day-by-day history for the metric, with no need to see the per-source breakdown -> use get_metric_history instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

log_workout_sessionA

Record one workout as a structured event — activity, timing, intensity, and heart-rate response — rather than folding it into the day's workout_minutes total. Use this alongside (not instead of) log_daily_metric/log_measurement for workout_minutes: this is what lets explain_metric_change say what the workout was, not just how long it ran. A day can have more than one session; each call adds a new row.

Use this tool when:

  • the user describes an actual workout/exercise session (e.g. "I went running for 40 minutes", "log today's strength workout").

Do not use this tool when:

  • the user only wants to record the day's total exercise minutes as a single number, with no activity type/timing/intensity -> use log_daily_metric (workout_minutes) or log_measurement instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

read_workout_sessionsA

Read individual workout sessions (not the daily_metrics workout_minutes total), most recent day first. Use this to see what each workout actually was — activity, timing, intensity, heart rate — rather than just a day's summed minutes.

Use this tool when:

  • the user asks about workouts/exercise sessions specifically (e.g. "what workouts did I do this week?", "show my recent gym sessions").

Do not use this tool when:

  • the user just wants the daily workout_minutes total, not individual sessions -> use read_health_data or get_metric_history instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_data_statusA

Report how current and complete the database is: latest data date, coverage window, gaps, last successful import, and an overall status of CURRENT, STALE, INCOMPLETE, NO_DATA or IMPORT_FAILED. Check this before drawing conclusions from any analysis, and say so when the status is anything other than CURRENT.

Use this tool when:

  • the user asks how up to date their data is, or whether an import is needed.

  • you are about to interpret recent data and want to know whether it is fresh enough to trust.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_import_statusA

List the most recent import runs, newest first: which importer, the source file's name and SHA-256, whether the run succeeded, failed or was interrupted, and how many rows were loaded, skipped and written.

Use this tool when:

  • the user asks what was imported and when, or why an import did not go through.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_metric_historyA

Read one metric's day-by-day values, without the other six metrics read_health_data always includes. Use this when you only care about a single metric (e.g. before calling get_baseline or calculate_metric_trend yourself) and don't need the full multi-metric payload.

Use this tool when:

  • the user wants one specific metric's history/trend over time (e.g. "show my weight over the last 30 days", "how has resting heart rate changed this month").

Do not use this tool when:

  • the request is broad/general, across multiple metrics at once -> use read_health_data instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_baselineA

Compute "what's normal" for one metric over a window: mean, median, and standard deviation. This is the number every other analytics tool below measures against, so a wider window (60-90+ days) gives a more stable baseline than the 30-day default read_health_data uses.

Use this tool when:

  • the user asks what's normal/typical/usual for one metric (e.g. "what's normal for my resting heart rate?"), with no particular day or direction of change in mind.

Do not use this tool when:

  • the user asks whether a metric is going up/down over time -> use calculate_metric_trend instead.

  • the user asks whether specific days looked unusual -> use detect_metric_anomalies instead.

  • the user wants two ranges compared against each other -> use compare_metric_periods instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

detect_metric_anomaliesA

Flag days where one metric deviated sharply from its own baseline over the window, using a median/MAD-based modified z-score rather than a mean/stdev z-score — more robust for short, noisy personal-health series, where the mean/stdev version is easily dragged around by the very outliers it's supposed to catch.

Use this tool when:

  • the user asks whether anything looked unusual/off/weird on particular days for one metric (e.g. "was there anything unusual about my sleep last month?").

Do not use this tool when:

  • the user wants a general sense of what's typical, with no interest in flagging specific days -> use get_baseline instead.

  • the user asks about a steady increase/decrease over time rather than isolated spikes/dips -> use calculate_metric_trend instead.

  • the user already has one specific date in mind and wants the full "why" behind it (baseline, anomaly, trend, and correlations together) -> use explain_metric_change instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

calculate_metric_trendA

Fit a simple straight-line trend to one metric over a window and report its direction, slope (change per day), and r_squared (how well a straight line actually fits — low r_squared means "noisy," not "flat").

Use this tool when:

  • the user asks whether one metric is trending up/down/flat over a continuous window (e.g. "is my weight trending down?", "how has my HRV changed?").

Do not use this tool when:

  • the user wants two specific, separately-defined ranges compared (e.g. "this month vs last month") rather than a single continuous slope -> use compare_metric_periods instead.

  • the user asks what's typical/normal rather than which direction it's moving -> use get_baseline instead.

  • the user asks about isolated unusual days rather than an overall direction -> use detect_metric_anomalies instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

compare_metric_periodsA

Compare one metric's average between two date ranges — e.g. "this month vs. last month" or "since starting a new medication vs. before." The two ranges may be any length and need not be adjacent or equal in size; each is summarized with its own baseline first.

Use this tool when:

  • the user names or implies two distinct date ranges to weigh against each other (e.g. "compare my average steps this month to last month", "since starting a new medication vs. before").

Do not use this tool when:

  • there's only one continuous window and the question is about direction over time, not two discrete ranges -> use calculate_metric_trend instead.

  • the user wants "what's normal" for a single window, not a before/after comparison -> use get_baseline instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

find_metric_correlationA

Compute the Pearson correlation between two metrics over the same window, joined by date. Correlation, not causation: a strong r just means the two moved together, not that one caused the other.

Use this tool when:

  • the user names or implies two different metrics and asks whether they move together (e.g. "does my sleep affect my mood?", "did my HRV change after I increased my workouts?").

Do not use this tool when:

  • only one metric is in question -> use get_baseline, calculate_metric_trend, or detect_metric_anomalies instead, depending on what's being asked about that one metric.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

get_recent_changesA

Scan every (non-private) metric for what's changed lately: a recent period vs. the four-times-as-long period before it (period-over-period shift), any anomalies inside the recent period, and a trend over it. The single best tool to start a "how have I been doing?" conversation with — it does the scanning across all metrics that would otherwise take one get_baseline/detect_metric_anomalies/calculate_metric_trend call per metric.

Do not use this tool when:

  • the user already named a specific metric and wants the full why-bundle for it (value, baseline, anomaly flag, trend, correlated metrics) -> use explain_metric_change instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

explain_metric_changeA

Build an evidence bundle for "why did my look like that on ?": that day's value against a 90-day baseline, whether it qualifies as an anomaly, the trend leading into it, and any other metric that correlates with it strongly enough to be worth mentioning. Returns facts, not an explanation — turning "sleep was 2.6 stdev below baseline and resting heart rate correlates at r=0.71" into an actual answer for the person is what the calling model should do with these facts, not something this tool guesses at itself.

Do not use this tool when:

  • scanning across many metrics for what changed lately, without a specific metric/date in mind -> use get_recent_changes instead.

  • you only need one piece of this bundle (just the baseline, just the trend, just anomalies, or just a correlation) rather than the full why-explanation -> use get_baseline, calculate_metric_trend, detect_metric_anomalies, or find_metric_correlation directly instead.

Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
Metric schemaThe full set of metrics this server tracks, with each one's valid range (see logic.METRIC_BOUNDS) and whether it's currently configured as private (see HEALTH_PRIVATE_FIELDS). Read this to see accepted ranges up front, instead of discovering them one at a time from log_daily_metric's invalid_metric_value errors.

TDQS

A4.4/5.0

Scored across 20 tools

Disambiguation5/5

Every tool carries explicit 'use this when' and 'do not use this when' guidance that routes overlapping analytics tools to one another, so the boundaries between get_baseline, detect_metric_anomalies, calculate_metric_trend, compare_metric_periods, get_recent_changes, and explain_metric_change are unambiguous. Read paths (read_health_data vs get_metric_history vs read_measurements) and write paths (log_measurement vs log_daily_metric vs log_workout_session) are similarly well-separated.

Naming Consistency5/5

All 20 tools use lower_snake_case with a clear verb_noun shape (get_*, read_*, log_*, calculate_*, detect_*, compare_*, find_*, export_*, clear_*), plus one consistent naming of the aggregate. There are no camelCase/naming aberrations or vague single-word verbs, so the pattern is highly predictable.

Tool Count4/5

At 20 tools this is on the heavier end, but the domain genuinely spans raw observations, daily aggregates, workouts, imports, exports, and a layered analytics stack, and each tool earns its place. It sits just below the 'heavy' 16-25 range boundary, so it is slightly over but reasonable.

Completeness4/5

The surface covers ingestion (raw and daily), clearing/undo, multi-source provenance, freshness and import monitoring, CSV export, and a full analytics suite, which is near-complete for a quantified-self domain. Minor gaps exist, such as no explicit update/edit for an already-logged workout session (only day-level clear_metric), which an agent can work around.

Maintenance

ActivityActive
ResponsivenessResponsive