HealthLedger MCP
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., "@HealthLedger MCP log my blood pressure today: 120/80"
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.
🩺 HealthLedger MCP
Your health record, on your machine. Let any AI read and reason over it — on your terms.
A local-first, model-agnostic Model Context Protocol server that stores your personal health data in a local SQLite file and hands back analysis-ready views, so any MCP client — and any LLM behind it — can log, retrieve, and reason over that record on demand.
Not a medical device. HealthLedger stores and summarizes what you record. Its analysis tools return descriptive statistics, trends, and associations — not diagnosis. For any clinical decision, consult a licensed professional.
✨ What it does
HealthLedger is a personal health ledger you run yourself. Install it wherever you want, point your AI client at it, and start adding your data. By default it runs as a local stdio server — nothing binds to the network and the record never leaves your machine.
🏠 Local-first | Runs as a stdio subprocess of your MCP client. No server to host, no account, no network — your data lives in a local SQLite file. |
🤖 Model-agnostic | It's a plain MCP server. Works with any MCP-capable client (Claude Desktop, Cline, Cursor, Zed, Continue, LibreChat, custom agents…) and any model behind it. |
🧱 Structured clinical schema | 20+ dedicated tables (conditions, meds, labs, biomarkers, oncology, imaging, wearables, …) rather than a bag of notes. |
📈 Analysis-ready | Trend tools compute count / min / max / mean / median plus a slope with uncertainty over dated numeric values. |
🔗 Cross-signal reasoning | Correlate two signals, estimate before/after change around an event, align many signals onto one time grid, and reconcile units & reference ranges. |
📐 Trend intelligence | Slopes with a confidence interval and p-value (real trend vs noise), robust outlier flags, latest-vs-baseline framing, non-linear/cyclical warnings, and change-point detection. |
🔎 Retrieval & grounding | Ranked full-text search over all free text (local FTS5, no embeddings), an explicit "what's present / absent / stale" coverage view, and |
🧑🤝🧑 Multi-person | Every tool takes an optional |
🌐 Optional remote mode | If you want a shared instance, it can run as an OAuth-protected HTTP server behind a tunnel. Entirely opt-in — see Remote mode. |
Related MCP server: personal-health-mcp
🚀 Quick start
You need Python 3.11+. The fastest path uses uv (uvx runs it with zero install):
# Try it directly from the repo — no clone, no install:
uvx --from git+https://github.com/Cole-Will-I-Am/HealthLedger-MCP healthledger-mcpPrefer a persistent install?
pipx install git+https://github.com/Cole-Will-I-Am/HealthLedger-MCP
# or, from a clone:
git clone https://github.com/Cole-Will-I-Am/HealthLedger-MCP && cd HealthLedger-MCP
pip install .
healthledger-mcp # starts a local stdio serverThat's it — no OAuth, no tunnel, no account. Your data is written to
~/.healthledger/health.db (override with HEALTH_MCP_DB).
🔌 Use it with any client / any model
HealthLedger speaks stdio MCP, so it drops into the standard mcpServers config that
virtually every MCP client uses. Point your client at it and you're done — the model on
the other side can be Claude, a local Llama, GPT-something, whatever your client runs.
Zero-install (uvx):
{
"mcpServers": {
"healthledger": {
"command": "uvx",
"args": ["--from", "git+https://github.com/Cole-Will-I-Am/HealthLedger-MCP", "healthledger-mcp"]
}
}
}After pipx/pip install:
{
"mcpServers": {
"healthledger": { "command": "healthledger-mcp" }
}
}Claude Desktop →
claude_desktop_config.jsonCursor →
.cursor/mcp.json· Zed →context_servers· Cline / Continue / LibreChat → their MCP settingsAny other MCP client → the same
command/argsshape
Want it to hold more than one person? Pass a
userlabel on any tool call (defaults tome, fromHEALTH_MCP_DEFAULT_USER).
🗄️ Storage
SQLite at
~/.healthledger/health.db— mode0600, WAL journaling. Override withHEALTH_MCP_DB.Schema v4 covers quantitative metrics, events, notes, profile facts, conditions, allergies, medications & dose logs, lab reports/results, biomarkers, tumor/cancer records, encounters/physicals, procedures, imaging, immunizations, care tasks, documents, enriched family history, genomic/PGx records, reproductive-health records, substance-use logs, wearable/app sources, wearable samples, and a generic
health_recordscatch-all.~/.healthledger/audit.logrecords every tool call (override withHEALTH_MCP_AUDIT_LOG).It's just a SQLite file — back it up, sync it, or delete it like any other file.
Profile keys (stable facts only)
Recommended keys for clients: birth_date, sex, gender, height_cm, blood_type,
emergency_contact, primary_care_provider, preferred_pharmacy, insurance,
advance_directive_on_file, plus stable preferences/goals.
⏳ Time-varying data belongs in the dedicated tables, not in profile keys.
🧰 Tool catalog
79 tools, grouped by purpose. Every tool accepts an optional user label (default
me, from HEALTH_MCP_DEFAULT_USER).
log_metric · get_metrics · list_metrics · analyze_metric · log_event ·
get_events · log_note · get_notes · set_profile · get_profile · delete_profile
add_condition · list_conditions · add_allergy · list_allergies ·
add_medication · list_medications · log_medication_taken ·
list_medication_schedule · list_medication_logs · add_encounter ·
list_encounters · add_procedure · list_procedures · add_imaging_report ·
list_imaging_reports · add_immunization · list_immunizations
add_lab_report · list_lab_reports · add_lab_result · list_lab_results ·
analyze_lab_trend · add_biomarker · list_biomarkers · analyze_biomarker_trend ·
add_tumor_record · list_tumor_records · add_document · list_documents ·
add_family_history · list_family_history · add_health_record · list_health_records
add_reproductive_record · list_reproductive_records · analyze_reproductive_trend ·
add_substance_use_log · list_substance_use_logs · analyze_substance_trend ·
add_wearable_source · list_wearable_sources · add_wearable_sample ·
import_wearable_samples · list_wearable_samples · analyze_wearable_trend
add_genomic_record · list_genomic_records
correlate_metrics · analyze_event_impact · align_series · normalize_series ·
analyze_trend
semantic_search · get_record · data_coverage
get_reasoning_guide returns the packaged reasoning guide; clients with MCP
resource support can also read healthledger://skill/reasoning. Analysis tools
guarantee top-level value, reference_range, recency, and source_ids
keys; source_ids are table/id citations suitable for get_record. Analysis,
summary, care-gap, and clinician-packet tools advertise statementType: descriptive.
add_care_task · complete_care_task · list_care_tasks · list_due_tasks ·
health_agenda · care_gap_report · summarize_health · build_clinician_packet · search_records ·
delete_record · export_data · health_status
How the "smart" tools behave
Tool | What it returns |
| count · min · max · mean · median · least-squares slope over dated numeric values — the slope now carries a standard error, 95% CI, p-value, and R² so a trend can be told from noise |
| full trend intelligence for one signal: slope with uncertainty (SE, 95% CI, p-value, "distinguishable from flat / treat as noise") · robust median/MAD outlier flags · baseline framing (latest vs your own median & Q1–Q3) · rate-of-change (recent vs earlier slope) · shape check warning when a straight line is the wrong model for a bounded/cyclical signal · single change-point detection |
| Pearson & Spearman between two signals aligned on a common time grid, with paired sample size, a two-sided p-value, and significance caveats |
| before/after descriptive stats around a discrete event (med start, procedure) plus the difference in means and a Welch t-test |
| 2+ signals resampled onto one shared day/week/month grid — one row per bucket, one column per signal (inner or outer join) |
| one signal's readings converted to a common unit (incl. mg/dL↔mmol/L via analyte molar mass) with reference ranges reconciled and a unitless in-range position |
| relevance-ranked (BM25) full-text over all free text — notes, event details, encounter reasons/plans, lab flags, imaging findings, document text, … — stemmed, best-first; each hit carries |
| what's present / absent / stale, as data: per-domain counts with latest date & staleness, an explicit list of empty domains, and a per-signal inventory — so the model checks before asserting instead of confabulating |
| fetch one exact row by |
| analysis tools now return |
| compact cross-domain digest of the record |
| source-cited visit-prep packet with current snapshot, changed signals, stored follow-ups, genomic/PGx records, reason-for-visit matches, Markdown output, and no clinical recommendations |
| stored upcoming tasks, refills, follow-ups, immunizations, reproductive due dates |
| missing/stale stored data and unresolved follow-ups — without clinical screening claims |
| paginated & capped; use |
Wearables, on purpose
Wearable imports are kept separate from ordinary metrics:
wearable_sourcesidentify the device / app / feed.wearable_samplesstore high-volume typed samples — steps, HRV, resting HR, workouts, sleep, SpO₂, calories, temperature, and similar.Use
import_wearable_samplesfor bulk. Per call: up toHEALTH_MCP_MAX_WEARABLE_IMPORT_ROWS=500samples andHEALTH_MCP_MAX_BULK_JSON_CHARS=200000bytes of JSON.
⚙️ Configuration
Everything is environment variables. Defaults shown; the local-mode defaults need no setup.
Variable | Default | Purpose |
|
|
|
|
| SQLite database path |
|
| audit log path |
|
| default |
|
| max rows returned by a list query |
|
| max rows per export page |
|
| max chars per free-text field |
|
| max wearable samples per import call |
|
| max JSON payload size for bulk import |
|
| calls allowed per window |
|
| rate-limit window length |
Remote-mode-only (HEALTH_MCP_TRANSPORT=http): HEALTH_MCP_GITHUB_CLIENT_ID,
HEALTH_MCP_GITHUB_CLIENT_SECRET, HEALTH_MCP_ALLOWED_LOGINS, HEALTH_MCP_PUBLIC_URL,
HEALTH_MCP_HOST (127.0.0.1), HEALTH_MCP_PORT (8800), HEALTH_MCP_PATH (/mcp).
✅ Offline tests
From a clone (these touch neither your real database nor real GitHub credentials — they use a temp DB and dummy config):
python test_tools.py # exercises the tools end-to-end
python test_wiring.py # exercises the optional remote (OAuth) wiring🌐 Remote mode (optional)
You don't need any of this to use HealthLedger — it's for people who want to reach one
instance from a networked client (e.g. a web-based assistant) instead of running it
locally. Set HEALTH_MCP_TRANSPORT=http and it becomes an OAuth-protected HTTP server:
client ──HTTPS──► reverse proxy / tunnel ──► 127.0.0.1:8800 (HealthLedger, http mode)
│ │
GitHub OAuth SQLite 0600 / WAL
(allow-list only) + audit.logBinds
127.0.0.1only; expose it via your own reverse proxy or a Cloudflare Tunnel.Auth: OAuth 2.1 via FastMCP's GitHub OAuth proxy. Only the GitHub logins in
HEALTH_MCP_ALLOWED_LOGINSmay connect — everyone else gets401.Fail-closed: in http mode the process refuses to start without client id/secret and at least one allow-listed login. There is no open networked mode.
Health check: an unauthenticated request returns
401(up and guarded).
Live demo: a single-tenant instance runs at https://health-mcp.manticthink.com/mcp
(allow-listed to the maintainer). It's there to show the remote path working — to actually
use HealthLedger, run your own local copy per Quick start.
Available Tools
79 toolsadd_allergyAdd an allergyC
Store a structured allergy or intolerance record.
Inputs: allergen (required), user, notes, status, +3 more. Returns: object
add_biomarkerAdd a biomarkerC
Store a biomarker observation, including oncology/genetic/inflammatory markers.
Inputs: value (required), biomarker (required), flag, unit, +9 more. Returns: object
add_care_taskAdd care taskB
Store an actionable health task: appointment, refill, lab, screening, follow-up, upload, call, etc.
Inputs: title (required), user, notes, status, +6 more. Returns: object
add_conditionAdd a conditionC
Store a structured problem-list condition. Descriptive record only.
Inputs: name (required), user, notes, status, +4 more. Returns: object
add_documentAdd documentB
Store document/report metadata and extracted text. Binary files are not stored here.
Inputs: title (required), document_type (required), tags, user, +7 more. Returns: object
add_encounterAdd encounterC
Store a visit/encounter such as annual physical, specialist visit, ER visit, therapy, dental, or vision.
Inputs: encounter_type (required), plan, user, notes, +7 more. Returns: object
add_family_historyAdd family historyC
Store family history facts by relation.
Inputs: relation (required), condition_name (required), user, notes, +5 more. Returns: object
add_genomic_recordAdd genomic/PGx recordC
Store one structured genomic/PGx record as lab-reported data.
Inputs: record_type (required), gene, rsid, user, +22 more. Returns: object
add_health_recordAdd generic health recordB
Store any health datum that does not fit a dedicated table yet.
Inputs: title (required), record_type (required), body, tags, +4 more. Returns: object
add_imaging_reportAdd imaging reportC
Store imaging/radiology report metadata and text findings.
Inputs: modality (required), user, notes, facility, +7 more. Returns: object
add_immunizationAdd immunizationC
Store an immunization/vaccine record and optional next due date.
Inputs: vaccine (required), lot, dose, user, +5 more. Returns: object
add_lab_reportAdd a lab reportB
Store metadata for a lab/bloodwork report. Add individual results separately.
Inputs: title (required), user, notes, source, +6 more. Returns: object
add_lab_resultAdd a lab resultC
Store one lab/bloodwork result. Numeric values can later be trended.
Inputs: value (required), analyte (required), flag, unit, +9 more. Returns: object
add_medicationAdd a medicationC
Store a structured medication with schedule/refill metadata.
Inputs: name (required), dose, user, notes, +11 more. Returns: object
add_procedureAdd procedureB
Store a procedure/surgery/test record and any follow-up date.
Inputs: name (required), user, notes, outcome, +5 more. Returns: object
add_reproductive_recordAdd reproductive health recordC
Store menstrual cycle, pregnancy, contraception, fertility sign, or related reproductive record.
Inputs: record_type (required), user, notes, method, +14 more. Returns: object
add_substance_use_logAdd substance use logC
Store time-varying substance exposure such as alcohol, nicotine, caffeine, cannabis, or other.
Inputs: substance (required), unit, user, notes, +5 more. Returns: object
add_tumor_recordAdd a tumor recordC
Store tumor/cancer-related structured information as user-provided data.
Inputs: tumor_name (required), user, grade, notes, +10 more. Returns: object
add_wearable_sampleAdd wearable sampleA
Store one wearable sample. Use import_wearable_samples for batches.
Inputs: value (required), sample_type (required), unit, user, +8 more. Returns: object
add_wearable_sourceAdd wearable sourceC
Store a wearable/app/data-source identity such as Apple Health, Garmin, Oura, Fitbit, CGM, or scale.
Inputs: name (required), user, model, notes, +5 more. Returns: object
align_seriesAlign multiple signalsARead-onlyIdempotent
Resample 2+ signals onto one shared time grid for side-by-side comparison.
Takes a JSON array of signal specs and returns a single aligned table — one row per time bucket, one column per signal — so signals can be compared without hand-matching timestamps.
Inputs: series_json (required), agg, join, user, +4 more. Returns: object
analyze_biomarker_trendAnalyze biomarker trendBRead-onlyIdempotent
Return descriptive trend stats for numeric biomarker observations.
Inputs: biomarker (required), user, since, until. Returns: object
analyze_event_impactAnalyze event impactARead-onlyIdempotent
Estimate a signal's before/after change around a discrete event.
Splits one signal at an anchor date (e.g. a medication start, procedure, or regimen change) into 'before' and 'after' groups, reports descriptive stats for each, and adds the difference in means plus a Welch t-test.
Inputs: name (required), event_date (required), user, source, +3 more. Returns: object
analyze_lab_trendAnalyze lab trendBRead-onlyIdempotent
Return descriptive trend stats for numeric lab results for one analyte.
Inputs: analyte (required), user, since, until. Returns: object
analyze_metricAnalyze a metricARead-onlyIdempotent
Compute analysis-ready statistics and a trend for one metric over a window.
Returns count, first/last/latest, min/max, mean, median, standard deviation, and a least-squares linear trend (slope per day, projected next value, direction). These are descriptive statistics for interpretation — not a diagnosis.
Inputs: metric (required), user, since, until. Returns: object
analyze_reproductive_trendAnalyze reproductive trendARead-onlyIdempotent
Return descriptive cycle length/duration stats from stored cycle records only.
Inputs: user, limit. Returns: object
analyze_substance_trendAnalyze substance trendBRead-onlyIdempotent
Return descriptive daily-total stats for one substance when numeric amounts exist.
Inputs: substance (required), user, since, until. Returns: object
analyze_trendAnalyze trend (advanced)ARead-onlyIdempotent
Trend intelligence for one signal — beyond a single straight line.
Pulls a signal's dated numeric readings and returns, in one call:
trend — least-squares slope with a standard error, 95% CI, p-value, and an honest 'distinguishable from flat / treat as noise' verdict;
baseline — the latest reading framed against your own recent median and typical range (Q1-Q3), the way a clinician reads a value;
rate_of_change — recent vs earlier slope, exposing acceleration;
outliers — points flagged by a robust median/MAD z-score, not silently averaged into the mean;
shape — whether a straight line is the right model at all (weak fit, residual runs, or a better-fitting quadratic) and whether linear extrapolation is advisable for bounded or cyclical signals;
change_point — the single most likely regime shift, if any.
Inputs: name (required), user, since, until, +3 more. Returns: object
analyze_wearable_trendAnalyze wearable trendCRead-onlyIdempotent
Return descriptive stats/trend for one wearable sample type.
Inputs: sample_type (required), user, since, until, +1 more. Returns: object
build_clinician_packetBuild clinician packetARead-onlyIdempotent
Build a source-cited, descriptive visit-prep packet for a clinician or specialist.
The packet is deterministic and local: current medications/conditions/allergies, recent changed numeric signals with uncertainty, relevant stored records, follow-up/completeness items, lab-reported genomic/PGx records, and a Markdown rendering. It does not diagnose, rank clinical urgency, or suggest treatment.
Inputs: user, limit, since, until, +2 more. Returns: object
care_gap_reportCare gap reportARead-onlyIdempotent
Report missing/stale data and unresolved stored follow-ups. This is organizational, not clinical guidance.
Inputs: user. Returns: object
complete_care_taskComplete care taskCIdempotent
Mark a care task completed.
Inputs: task_id (required), user, notes. Returns: object
correlate_metricsCorrelate two signalsARead-onlyIdempotent
Correlate two health signals aligned onto a common time grid.
Resamples each signal to one value per resample bucket (day/week/month)
with agg, inner-joins the buckets they share, then computes Pearson and/or
Spearman correlation with a two-sided p-value and the paired sample size.
Either signal may come from any source: metric, wearable, lab, biomarker,
substance.
Inputs: name_a (required), name_b (required), source_a (required), source_b (required), +7 more. Returns: object
data_coverageData coverage / what's missingARead-onlyIdempotent
Expose what data actually exists — and what's absent or stale — as data.
Purpose: let the model check the record before asserting, instead of confabulating around missing values. Two modes:
source + name given → coverage for that one signal: present?, count, first/last date, and days since the last reading.
otherwise → a whole-record inventory: per-domain counts with latest date and staleness, an explicit list of EMPTY domains, and a per-signal inventory (which metrics / analytes / biomarkers / wearable types / substances are tracked, each with count + last date + staleness).
Inputs: name, user, source. Returns: object
delete_profileDelete a profile fieldADestructiveIdempotent
Delete one durable profile fact by key. Use for corrections/removals.
Inputs: key (required), user. Returns: object
delete_recordDelete a recordBDestructiveIdempotent
Delete one record by id (for corrections). DESTRUCTIVE.
Inputs: table (required), record_id (required), user. Returns: object
export_dataExport data pageARead-onlyIdempotent
Export a bounded page of a user's record as structured JSON.
Inputs: user, limit, table, offset, +1 more. Returns: object
get_eventsGet event historyARead-onlyIdempotent
Return recorded events (symptoms/medications/meals/activities), newest first.
Inputs: user, limit, since, until, +1 more. Returns: object
get_metricsGet metric historyARead-onlyIdempotent
Return raw metric readings, newest first, optionally filtered by metric/date.
Inputs: user, limit, since, until, +1 more. Returns: object
get_notesGet notesARead-onlyIdempotent
Return journal notes, newest first, optionally filtered by date or tag substring.
Inputs: tag, user, limit, since, +1 more. Returns: object
get_profileGet profileARead-onlyIdempotent
Return all durable profile facts for a user as a key/value map.
Inputs: user. Returns: object
get_reasoning_guideGet reasoning guideARead-onlyIdempotent
Return HealthLedger's packaged guidance on interpreting this schema: order of operations, when to defer to a clinician, and how to phrase uncertainty. Call this once per session before doing cross-signal reasoning.
Inputs: no named parameters. Returns: object
get_recordGet a record by idARead-onlyIdempotent
Fetch one exact stored row by table + id — the citation primitive.
Search and analysis tools return source_table / source_ids; this resolves one of those to the full row, so a statement can be grounded in the actual data.
Inputs: table (required), record_id (required), user. Returns: object
health_agendaHealth agendaARead-onlyIdempotent
Return a deterministic agenda: due tasks, refills, follow-ups, immunizations, and medication schedule.
Inputs: days, user. Returns: object
health_statusHealth MCP statusARead-onlyIdempotent
Return non-secret operational status and per-user record counts.
Inputs: user. Returns: object
import_wearable_samplesImport wearable samplesB
Bulk import wearable samples from a JSON array of objects. Capped per call.
Inputs: samples_json (required), user. Returns: object
list_allergiesList allergiesARead-onlyIdempotent
List stored allergies/intolerances, optionally filtered by status.
Inputs: user, limit, status. Returns: object
list_biomarkersList biomarkersBRead-onlyIdempotent
List biomarker observations, optionally filtered by marker/category/date.
Inputs: user, limit, since, until, +2 more. Returns: object
list_care_tasksList care tasksBRead-onlyIdempotent
List care tasks, optionally filtered by status or task type.
Inputs: user, limit, status, task_type. Returns: object
list_conditionsList conditionsBRead-onlyIdempotent
List stored conditions, optionally filtered by status.
Inputs: user, limit, status. Returns: object
list_documentsList documentsBRead-onlyIdempotent
List stored health documents/reports and extracted text metadata.
Inputs: user, limit, since, until, +1 more. Returns: object
list_due_tasksList due tasksARead-onlyIdempotent
List open care tasks due within N days, optionally including overdue tasks.
Inputs: days, user, limit, include_overdue. Returns: object
list_encountersList encountersCRead-onlyIdempotent
List visits/encounters, optionally filtered by type.
Inputs: user, limit, encounter_type. Returns: object
list_family_historyList family historyBRead-onlyIdempotent
List family history records, optionally filtered by relation.
Inputs: user, limit, relation. Returns: object
list_genomic_recordsList genomic/PGx recordsARead-onlyIdempotent
List genomic/PGx records, optionally filtered by type or gene.
Inputs: gene, user, limit, record_type. Returns: object
list_health_recordsList generic health recordsARead-onlyIdempotent
List generic/catch-all health records, optionally filtered by type/date.
Inputs: user, limit, since, until, +1 more. Returns: object
list_imaging_reportsList imaging reportsARead-onlyIdempotent
List imaging/radiology reports, optionally filtered by modality/date.
Inputs: user, limit, since, until, +1 more. Returns: object
list_immunizationsList immunizationsARead-onlyIdempotent
List immunizations, optionally limited to vaccines due within N days.
Inputs: user, limit, due_within_days. Returns: object
list_lab_reportsList lab reportsBRead-onlyIdempotent
List lab/bloodwork report containers, newest first.
Inputs: user, limit, since, until. Returns: object
list_lab_resultsList lab resultsBRead-onlyIdempotent
List lab results, optionally filtered by analyte and date range.
Inputs: user, limit, since, until, +1 more. Returns: object
list_medication_logsList medication logsARead-onlyIdempotent
List medication adherence/dose logs, optionally filtered by medication/date.
Inputs: user, limit, since, until, +1 more. Returns: object
list_medicationsList medicationsBRead-onlyIdempotent
List medications, defaulting to active/current medications.
Inputs: user, limit, status. Returns: object
list_medication_scheduleList medication scheduleBRead-onlyIdempotent
Return active medication schedules and refill dates.
Inputs: user. Returns: object
list_metricsList tracked metricsBRead-onlyIdempotent
List which metrics have data for a user, with counts and the latest value of each.
Inputs: user. Returns: object
list_proceduresList proceduresCRead-onlyIdempotent
List procedures, surgeries, and tests with outcomes/follow-up dates.
Inputs: user, limit, since, until. Returns: object
list_reproductive_recordsList reproductive health recordsCRead-onlyIdempotent
List reproductive health records, optionally filtered by type/date.
Inputs: user, limit, since, until, +1 more. Returns: object
list_substance_use_logsList substance use logsBRead-onlyIdempotent
List substance-use logs, optionally filtered by substance/date.
Inputs: user, limit, since, until, +1 more. Returns: object
list_tumor_recordsList tumor recordsBRead-onlyIdempotent
List tumor/cancer-related records. Descriptive storage only.
Inputs: user, limit, status. Returns: object
list_wearable_samplesList wearable samplesBRead-onlyIdempotent
List wearable samples, optionally filtered by type/source/date.
Inputs: user, limit, since, until, +2 more. Returns: object
list_wearable_sourcesList wearable sourcesCRead-onlyIdempotent
List wearable/app data sources.
Inputs: user, limit. Returns: object
log_eventLog a health eventA
Record a discrete event: a symptom, a medication dose, a meal, or an activity.
Inputs: name (required), category (required), user, detail, +2 more. Returns: object
log_medication_takenLog medication takenC
Log an adherence event: taken, missed, skipped, delayed, or other status.
Inputs: medication_name (required), note, user, status, +4 more. Returns: object
log_metricLog a health metricA
Record one quantitative reading (a point in a time series).
Inputs: value (required), metric (required), note, unit, +2 more. Returns: object
log_noteLog a free-form noteC
Record a free-form health journal entry.
Inputs: body (required), tags, user, title, +1 more. Returns: object
normalize_seriesNormalize units & rangesARead-onlyIdempotent
Reconcile mixed units and reference ranges within one signal.
Pulls a signal's readings, converts every value (and its reference range, for labs/biomarkers) to a single common unit, and adds a unitless 'reference position' so readings taken with different units or reference ranges become directly comparable.
Inputs: name (required), user, limit, since, +4 more. Returns: object
search_recordsSearch recordsARead-onlyIdempotent
Full-text-ish search across stored health domains (case-insensitive substring).
Inputs: query (required), user, limit. Returns: object
semantic_searchSemantic searchARead-onlyIdempotent
Relevance-ranked full-text search across all free-text health history.
Unlike search_records (exact case-insensitive substring), this builds a transient SQLite FTS5 index over every free-text field — notes, event details, encounter reasons/assessments/plans, lab flags, imaging findings, document text, care-task notes, and more — stems terms, and ranks hits by BM25. So the model can query history by meaning/keywords instead of an exact key and gets the best matches first. This is lexical ranking (local, no embeddings or network), not vector semantics.
Every hit carries source_table + record_id (feed them to get_record to pull the exact row) and a highlighted snippet, so findings can be grounded in a row.
Inputs: query (required), user, limit, tables. Returns: object
set_profileSet a profile fieldBIdempotent
Set (upsert) a durable profile fact for a user.
Inputs: key (required), value (required), user. Returns: object
summarize_healthSummarize health recordARead-onlyIdempotent
Produce a compact, analysis-ready digest of a user's whole record over a window: profile, per-metric statistics + trend, recent events grouped by category, and recent notes. This is the primary tool for an LLM to reason over someone's health; it returns computed descriptive data only, never a diagnosis.
Inputs: user, since, until. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 79 tools
Most tools are scoped to distinct domains, but there is meaningful overlap among the many trend-analysis tools (analyze_trend, analyze_metric, analyze_lab_trend, analyze_wearable_trend, etc.) and between generic catch-all records and domain-specific records. The detailed descriptions help, but with 79 tools the risk of misselection is elevated.
The overwhelming majority of tools follow a clear verb_noun pattern like list_medications, add_condition, and delete_record. Minor deviations exist with noun-phrase names such as health_agenda, data_coverage, and semantic_search, and the mix of get_ vs list_ for retrieval actions creates slight inconsistency without breaking the overall pattern.
79 tools is far beyond the practical range for an MCP server and will heavily burden tool selection and context windows. The count is driven by repetitive add/list pairs across many domains plus multiple overlapping analysis tools, making the surface feel bloated rather than curated.
The server covers an impressively broad health-record surface: profiles, metrics, events, notes, medications, labs, imaging, genomics, procedures, care tasks, documents, family history, and more. The main gap is the lack of a generic update/edit path beyond delete-plus-re-add, though delete_record and set_profile partially mitigate this for corrections.
Maintenance
Related MCP Connectors
Hosted MCP server for the Healthie EHR & telehealth API: patients, appointments, charting, tasks.
Hosted MCP server exposing US hospital procedure cost data to AI assistants
Hosted MCP server for Cliniko — patients, appointments, availability, and invoices for AI agents.
Governed personal world model and memory for your AI agent. Pair once, connect over MCP.
Related MCP Servers
- AlicenseBqualityAmaintenanceA local-first MCP server that enables AI agents to read user-authorized Google Health API v4 data from Fitbit, Pixel Watch, and partners via OAuth, with tokens never leaving the machine.26850 npm81MIT
- AlicenseNot gradedqualityDmaintenanceSelf-hosted MCP server that aggregates personal health data from Google Health, Oura, and Withings into a single, provider-attributed interface with configurable source of truth preferences.MIT
- AlicenseNot gradedqualityBmaintenanceA local-first MCP server for querying multi-omic personal health data (genome, labs, wearables) with an honesty contract and progressive disclosure skills.1AGPL 3.0
- AlicenseAqualityDmaintenanceAn MCP server that locally authenticates with Google Health API v4 and provides read-only access to Fitbit, Pixel Watch, and other health data for AI agents.29119 npm19MIT