mcpField
H
health-os

health-os

Local
github.comHealth3Updated today

About health-os

health-os is a local-first personal health record backed by Postgres, for people who want MCP clients to access and update their health data. Its safety checks are deterministic code, while new lab panels remain pending until explicitly approved.

Key features

  1. 01Store labs, diagnoses, medications and food logs
  2. 02Import Apple Health exports and Garmin data
  3. 03Track trends, baselines and screening schedules
  4. 04Run deterministic safety checks and alerts
  5. 05Review extracted lab panels before approval
  6. 06Generate nutrition reports and visit briefs

Use cases

  1. 01Keep personal health records in a local database
  2. 02Review lab results extracted from reports
  3. 03Track nutrition and health trends over time
  4. 04Prepare a brief for a doctor visit

MCP support

Exposes 36 read and write tools and server instructions to MCP clients. The server communicates over stdio; data is stored in the user's Postgres database.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"andronaft-health-os": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"DATABASE_URL",
"-e",
"READONLY_DATABASE_URL",
"ghcr.io/andronaft/health-os:0.3.0"
],
"env": {
"DATABASE_URL": "<DATABASE_URL>",
"READONLY_DATABASE_URL": "<READONLY_DATABASE_URL>"
}
}
}
}
Run commanddocker run -i --rm -e DATABASE_URL -e READONLY_DATABASE_URL ghcr.io/andronaft/health-os:0.3.0
Environment variables to set
DATABASE_URLSecretPostgreSQL 16 + pgvector connection string, e.g. postgresql+psycopg://health:[email protected]:5432/health_os. Run migrations and seed first (see README).
READONLY_DATABASE_URLSecretRecommended: connection as the restricted health_readonly login (scripts/setup_readonly.py). Gives DB-level read isolation; sql_query runs only with it.

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
ocighcr.io/andronaft/health-os:0.3.0

Tools

No tool list yet

Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.

Details

From the project README

health-os

tests Listed on mcpservers.org

Local-first personal health record, exposed over MCP. Your labs, diagnoses, medications, wearable data and food log live in your own Postgres; any MCP client — one running a local model or a cloud assistant — can read and update them through guarded tools. Critical values, drug-safety rules and screening schedules are deterministic code, not LLM judgement.

An MCP session with the demo patient: LDL trend and the pending-review queue

Medical disclaimer. This is not a medical device and does not give medical advice. Critical-value alerts and screening reminders are only a signal to contact a doctor — never a diagnosis and never a reason to delay care. Use at your own risk.

What it does

  • Lab results — drop a PDF or photo into your MCP client; the model extracts the values, health-os normalizes names (uk/ru/en/Latin synonyms) and units, and stages the panel as pending. Nothing counts as fact until you approve it.
  • Safety net in code — critical values alert immediately (log, macOS notification, optional Telegram); critical findings in narrative reports are flagged; drug-interaction questions are refused and redirected to a doctor/pharmacist (only deterministic checks run: total daily paracetamol across products, biotin before lab tests); a crisis tool returns a fixed response with hotlines, independent of the model.
  • Trends and analytics — Mann-Kendall trends, personal baselines and anomalies, age-gated risk calculators, a screening calendar, a weekly report, a doctor-visit brief.
  • Food log — meals with a 41-nutrient profile, %RDA, deficiency/excess flags, meal templates.
  • Devices — Apple Health export and Garmin import.
  • 36 MCP tools + server instructions — the safety rules are sent to every client on connect; see mcp_server/README.md.

Try it in one command

Only Docker needed. Starts a throwaway database with a fictional patient — two years of labs (LDL creeping up), blood pressure, medications, a food log and a lab panel awaiting approval:

git clone https://github.com/andronaft/health-os && cd health-os
make demo                             # or: cd demo && docker compose up -d --build

Point your MCP client at it:

{
  "mcpServers": {
    "health-os-demo": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--network", "health-os-demo",
               "-e", "DATABASE_URL=postgresql+psycopg://health:demo@db:5432/health_os",
               "-e", "READONLY_DATABASE_URL=postgresql+psycopg://health_readonly:demo_ro@db:5432/health_os",
               "health-os:local"]
    }
  }
}

Ask "show my health summary", "is my LDL trending up?", "what's pending review?", "what am I short on nutritionally?". Remove it all with make demo-down.

Install for your own data

Requires Docker and Python 3.12+.

git clone https://github.com/andronaft/health-os && cd health-os
cp .env.example .env                  # set the passwords
docker compose up -d db               # Postgres 16 + pgvector
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/alembic upgrade head        # schema
.venv/bin/python -m seed.load         # marker catalog, synonyms, units, nutrients
.venv/bin/python -m seed.demo         # optional: a fictional demo patient to play with

Then connect an MCP client — config for LM Studio, Open WebUI, Ollama CLI and Claude is in mcp_server/README.md. Try: "show my health summary", "LDL trend", "what am I short on nutritionally this week?".

Local models: the server speaks standard MCP over stdio, so any MCP client that runs a local model can use it. Verified so far: the server itself with the official MCP Python client (CI + the Docker demo). Not yet verified end-to-end with a local model — see #9; reports welcome.

How it works

Architecture: MCP client over stdio to mcp_server; read tools query approved views, write tools go through core/services into pending; safety, analytics, PostgreSQL with pgvector, ingestion

A lab result, from report to fact

Every row of a staged panel ends up pending — nothing becomes a fact without an explicit approve. A row the catalog can't place is kept, not dropped:

How a lab result row moves from stage_lab_panel through pending states to approved

Unmapped and pending rows show up in list_pending_reviews and in the health summary's "awaiting review" block; a learned name maps automatically on the next panel.

DirectoryWhat's inside
core/config, DB, normalization, services, dedup, health summary
mcp_server/MCP server, read and write tools
safety/deterministic safety rules and alert delivery
analytics/trends, baselines, calculators, screening, nutrition, reports
ingestion/extraction schema, confidence scoring, device importers, embeddings
migrations/Alembic schema
seed/reference catalog + the demo patient
evals/red-team scenarios (injections, hidden critical values, unit tricks)
scripts/backup/restore (restic; install_launchd.sh schedules them on macOS), read-only role setup, importers

Privacy / local-first

  • Your data stays in your own database. Postgres runs locally in Docker; data/ and .env are outside git. Nothing is sent anywhere by health-os itself.
  • What leaves the machine depends on the MCP client you connect. With a local model (LM Studio, Open WebUI + Ollama, …) nothing does. With a cloud assistant, whatever the tools return is sent to that provider — use one whose terms fit medical data (no training on your data, zero/short retention).
  • The goal is fully local: local models for chat and extraction, local embeddings for search (already supported via fastembed). Cloud clients remain optional.
  • Optional alert channel (Telegram) sends only a generic "check your health system" text, never values.
  • Encrypt the disk (FileVault / LUKS / BitLocker) — the database files are plaintext at rest.
  • Never put real medical data in issues, PRs or tests — synthetic data only.

Tests

make test              # everything (needs Postgres for the integration part)
make test-unit         # pure unit tests — no database needed
make test-integration  # only tests marked `integration`

Integration tests never touch the working database: tests/conftest.py drops and recreates <POSTGRES_DB>_test on the same server (migrations + seed) on every run. Override with TEST_DATABASE_URL (the name must end in _test). Without Postgres, integration tests are skipped locally; CI sets REQUIRE_DB=1 so they fail instead.

Development history: PROGRESS.md.

License

AGPL-3.0-or-later. You may use, modify and fork health-os; if you distribute it or run a modified version as a network service, you must publish your source under the same license.

Want to use it in a closed-source or commercial product without those obligations? A separate commercial license is available from the author — reach out via GitHub (@andronaft).

Contributions are welcome — see CONTRIBUTING.md (includes a short CLA).

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.