apple-health-mcp: SQL over your Apple Health export, inside your own MCP client
Local-first Apple Health MCP server. Lets AI assistants answer questions about your sleep, workouts, activity and heart data from a local export.
At a glance
- What is it?
- A local MCP server that loads CSV exports from Simple Health Export CSV into DuckDB and exposes three tools to an AI assistant. It solves the plumbing problem of getting health records into a client without uploading them, and it accepts a narrow input format to do so.
- Who is it for?
- Adopt it if you already run Simple Health Export CSV, you have Node.js 22 or newer, and your MCP client is one you would hand your full health history to. Do not adopt it if your export is the native export.xml, or if you want incremental persistence across restarts, because the DuckDB database is in memory and rebuilt for each server process.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The plumbing problem this removes, and who still has it
Apple Health data sits on an iPhone in a format designed for the Health app, not for analysis. Getting it into an AI assistant normally means exporting, converting, and pasting or uploading, and the upload step is the one most people stop at. This project takes a different route: the MCP server runs on the same machine as the export, reads the CSV files in place, and answers questions through SQL. The README states plainly that it does not upload the export or make network requests, with one caveat it also states: query results returned to your MCP client may be sent to that client's configured model provider. So the boundary is the client, not the server.
The intended user is someone who already exports health data and wants to ask questions of it in natural language without building a pipeline. It is not for someone who wants a dashboard, and it is not for someone whose export is still in Apple's native export.xml, which the README says is not currently supported. That single constraint decides most adoption questions before anything else does.
Three tools, one SQL surface, and a schema you have to discover first
The server exposes three tools. health_schema returns table names, columns, units, and sample rows. health_query runs a read-only SELECT with JSON, CSV, or summary output. health_report generates a weekly, monthly, or custom health summary. The README's own instruction is to start with health_schema, and the reason is structural: table names depend on which files are in your export, so there is no fixed schema to code against. A query written against one person's export may not run against another's if the file set differs.
Underneath, DuckDB does the work. CSV files are loaded into an in-memory DuckDB database, and SQL runs against that. The data flow is one direction: CSV on disk, table in memory, result returned to the MCP client. There is no write path back to the export and no query tool that is not read-only. The docs directory contains a querying page describing the data model and working examples, which is where the actual column semantics live; the README only sketches the tool list.
Configuration is three environment variables and one JSON block
Installation is an npx invocation rather than a global install. For Claude Desktop, the README gives this block for ~/Library/Application Support/Claude/claude_desktop_config.json, with the server registered under the name apple-health, command npx, and args ["-y", "@neiltron/apple-health-mcp"]. The environment carries HEALTH_DATA_DIR, which is required and has no default, pointing at the unzipped export directory. Restart the client after editing the file. Other MCP clients use the same command, arguments, environment, and stdio transport, so the configuration is portable even though only one client is documented concretely.
Two optional variables matter more than they look. MAX_MEMORY_MB defaults to 2048 and caps DuckDB's memory. CACHE_SIZE defaults to 100 and caps how many query results are cached. If you raise MAX_MEMORY_MB, you are trading host RAM for export size, and the README's guidance is that roughly 1 GiB covers a two-year multi-table export, so the 2048MB default leaves headroom. From source, the development path is git clone, bun install, then npm test, npm run typecheck, and npm run build. Node.js 22 or newer is a hard requirement.
Memory is the failure mode, and it fails loudly by design
The first request that needs a table loads that table's full CSV history. There is no date window. A query can reach as far back as the export goes, which is the feature and also the constraint: you cannot ask the server to load only the last ninety days to save memory. Loaded tables stay in memory for the life of the process, bounded by MAX_MEMORY_MB.
The README is explicit that the server never spills health rows to a temporary directory on disk, so an export that does not fit in the limit fails with an explicit error instead. That is a defensible choice. Spilling would keep the query alive but would also write health records to disk outside the directory you chose, which contradicts the local-first premise. The cost is that a large multi-year export on a small machine simply will not run until you raise the limit. A second failure mode is quieter: device overlap can produce duplicate-looking measurements, and the README says queries should account for sourceName where appropriate. If you have ever worn an Apple Watch and carried an iPhone at the same time, step counts and similar metrics can appear twice, and a naive SUM will be wrong. That is a query-authoring problem the server does not solve for you.
DuckDB in memory versus a persistent health database
The obvious alternative is a tool that imports Apple Health into a durable database once and queries it thereafter, typically from a web app or a notebook. The difference is where state lives. Here, the DuckDB database is in memory and is rebuilt for each server process, so every launch reloads from the CSV files. The README lists persistent incremental import as planned future work, not current behavior, and that distinction matters: if you restart your MCP client often, you pay the load cost each time.
A persistent import also gives you a place to store derived tables, deduplicate across devices once, and add indexes. This project gives you none of that, and in exchange it gives you something a hosted service cannot: no account, no upload, no server-side copy of your records, and a schema that adapts to whatever files you exported. A general SQL tool over a converted database can express everything health_query can, but you would have to write the conversion and the client integration yourself. Choosing between them is mostly a question of whether repeated reload is acceptable and whether you want the MCP client to be the only interface.
Maintenance, versioning, and what MIT does and does not cover
The project is TypeScript, MIT licensed, not archived, and the release history shows v1.3.0, v1.4.0, and v1.4.1 within August 2026, with the last push to main shortly after v1.4.1. That cadence suggests active work, but it is a version number, not a stability guarantee, and the README's own limitations section lists unfinished areas including persistent incremental import. The npm package is published as @neiltron/apple-health-mcp, and the npx invocation pins nothing, so a fresh launch can pull a newer version than the one you tested. If that matters, pin the version in your client config instead of relying on -y.
On licensing, MIT is permissive and imposes no copyleft obligation on your own code, but it also carries no warranty. Note what the licence does not touch: the Apple Health data itself, and the Simple Health Export CSV app, which is a separate product with its own terms. Nothing here is legal advice, and health data handling can attract obligations that a source licence says nothing about. The README also states that health reports summarize recorded data and are not medical advice, which is worth repeating to anyone who might read a generated weekly summary as a clinical signal.
Who should adopt it, who should not, and what to check first
Adopt it if you already use Simple Health Export CSV, run Node.js 22 or newer, and want an assistant to answer questions about sleep, workouts, activity, and heart data without a hosted intermediary. The local-only read path and the absence of a disk spill are the two design decisions that make it credible for that use. Do not adopt it if your export is export.xml, if you need incremental persistence, or if you are not comfortable with the MCP client's model provider receiving query results; the README warns about exactly that and recommends starting the server only from a client you trust with the data.
Before relying on any figure, run health_schema and read the units and sample rows for the tables you plan to query, because table names come from your files rather than a fixed schema. Then check whether your export fits under MAX_MEMORY_MB, remembering that roughly 1 GiB covers a two-year multi-table export and that exceeding the limit produces an explicit error rather than a partial answer. Finally, inspect sourceName on any metric you might have recorded on two devices at once. The server is a query layer, not a validator, and it will return a confidently wrong total if the SQL asks for one.
Editorial conclusion
Adopt it if you already run Simple Health Export CSV, you have Node.js 22 or newer, and your MCP client is one you would hand your full health history to. Do not adopt it if your export is the native export.xml, or if you want incremental persistence across restarts, because the DuckDB database is in memory and rebuilt for each server process. Before trusting a number, verify three things: that the CSV layout matches Simple Health Export CSV, that your export fits under MAX_MEMORY_MB (roughly 1 GiB covers a two-year multi-table export, and the server fails with an explicit error rather than spilling to disk), and that queries joining multiple devices account for sourceName.
Community notes