Getting Started
Self-Host Mirobody
Run the Mirobody engine on your own infrastructure: what you get, the three stages, how the data flows, and how to extend it.
Run Mirobody on your own machine, server, or cloud instance. The engine is open source under Apache 2.0 — a Python package (3.12+) usable as a library, plus an HTTP server, a background worker, PostgreSQL with pgvector, and Redis when you want the full capability. The source is at thetahealth/mirobody.
For what Mirobody is and the problem it solves, start at Introduction to Mirobody. This page is about running it yourself.
The three stages in the engine
Section titled “The three stages in the engine”The code layout, the contribution areas and this documentation all follow the same three stages — C · S · A, where the A is both Answers and the agent that produces them.
| Stage | What it means | Where in the package | |
|---|---|---|---|
| ① | Collect | Take data in from device providers, uploaded documents and on-device batches | mirobody/pulse/ |
| ② | Standardize | Resolve readings to canonical codes (LOINC · SNOMED CT · RxNorm), normalize units, store as FHIR R4 | mirobody/indicator/ |
| ③ | Answers | An agent reads the original documents through a virtual filesystem and answers with charts and citations. The same standardized series also drives the derived uses: scheduled insights, a drafted report, or the alerts you build on top | mirobody/agent/ |
Providers, file parsing and on-device batch imports, with every source landing in one indicator table.
A concept graph and multilingual aliases put every spelling of a test on the same code.
Two agents share one MCP tool surface; the tool loop can run locally or in an external model. Answering is one use of the standardized data, not the only one.
The standardization mechanism
Section titled “The standardization mechanism”The same measurement is written differently by every source that produces it, with its own units and reference ranges — differences that are enough to stop one person’s own history from being compared against itself. That is the layer Mirobody occupies: an indicator name is resolved before the reading is stored, rather than kept as the string it arrived as. 血红蛋白, ヘモグロビン and hemoglobin all resolve to LOINC 718-7; LDL-C and 低密度脂蛋白胆固醇 both resolve to LOINC 13457-7. Units are normalized to UCUM in the same pass, so 毫摩尔每升 and mmol/L are recorded as one unit. The result is that reports from different devices, laboratories and languages can be placed on a single time series.
Resolution runs locally against vocabularies shipped inside the package — no key, no configuration, and no network connection:
pip install mirobodymirobody resolve "LDL cholesterol" "血红蛋白" "ヘモグロビン"from mirobody.engine import resolve
resolve("血红蛋白").loinc # -> '718-7'Standardization is installable on its own, so this stage can be adopted without running the rest of the services. The resolution rules and the shipped vocabularies are described in Health Indicators; the library API is in The Engine as a Library.
Data flow
Section titled “Data flow”Providers and on-device batches converge on StandardPulseData before anything is written; file extraction writes straight to the store, keeping the report’s own indicator names for semantic search to reconcile. Both routes land in the same indicator table, which is why the agent queries indicators rather than one shape per vendor. The write path, the two tables behind it and the aggregation that follows are described in Data Flow.
Where the tool loop runs
Section titled “Where the tool loop runs”There is an agent for each, and the difference is who runs the tool loop.
| DeepAgent — you run the engine | BaseAgent — an external model calls in | |
|---|---|---|
| Tool loop runs | here, in your deployment | in the LLM provider, against /mcp over HTTP |
| For | running the whole engine yourself | Claude Desktop · Cursor · ChatGPT Apps · any MCP client |
| Extras | virtual filesystem, QuickJS, Agent Skills, charts | whatever the MCP tool surface exposes |
The engine mints a per-user MCP URL on request — POST /personal/mcp — so one person’s MCP client reaches only their own data. The bundled web client offers it under Settings; your own client can call the endpoint directly. See Agent Types and MCP Integration.
Extension directories
Section titled “Extension directories”Five configuration keys each point at a set of directories, which the engine scans at startup. Extending it requires no compile step and no entry in any registry.
| Key | Default | What goes there |
|---|---|---|
MCP_TOOL_DIRS | mirobody/agent/tools | Tool modules: a function or a *Service class becomes an MCP tool |
MCP_RESOURCE_DIRS | mirobody/agent/resources | MCP UI resources |
AGENT_DIRS | mirobody/agent | Agent implementations |
PROVIDER_DIRS | mirobody/pulse/providers | Data providers, one mirobody_<slug>/ package per source |
SKILL_DIRS | mirobody/agent/skills | Agent Skills: a directory holding one SKILL.md |
Add your own directory in config.{env}.yaml and place it first in the list to take precedence over the packaged one. See Adding Custom Tools, Agent Skills and Building a Provider.
Deployments and surfaces
Section titled “Deployments and surfaces”Self-hosting is one of two ways to run Mirobody, and each comes with finished surfaces, not only an API:
| Surface | Address | What it is |
|---|---|---|
| Your own deployment | localhost:18080 | git clone → ./deploy.sh → sign in. Your data stays on your machine, and the bundled web client is a full app: /data for documents and readings, /ask for the agent, plus Care Circle sharing: a member can let family — or a clinician — ask the AI using their records. |
| Your MCP endpoint | localhost:18080/mcp | For Claude Desktop / Cursor. Set MCP_PUBLIC_URL for HTTPS and remote clients. |
| Hosted chat | chat.mirobody.ai | The client we operate. |
| Mirobody Cloud | platform.mirobody.ai | Keys, usage, and the health-data API for building on top; see the Cloud tab. |
| WeChat miniprogram | search mirobody in WeChat | China only, Chinese interface. Same backend, same records and indicators as the hosted chat client. |
Next steps
Section titled “Next steps”Run it
Follow the Quickstart: clone, ./deploy.sh, sign in.
Configure it
Add an LLM key and an embedding key in config.{env}.yaml; see Configuration. They are two different keys, and the second one is why indicators stay at 0 when it is missing.
Understand it
Read The Engine as a Library for the install layers, then the Architecture Overview.
Extend it
Add a tool with Adding Custom Tools, or a data source with Building a Provider.
Contributing and support
Section titled “Contributing and support”Contributions are organized around the same three stages. The lowest-barrier kind is making an unresolved indicator name resolve: check it with mirobody resolve "<term>", add a mapping to resolver_overrides.tsv, and add a case to test_engine_coverage.py.
Source code, issues, and pull requests
The three areas, and how to submit changes
A lab report that parses incorrectly makes a valuable issue; please attach the de-identified sample
Direct technical contact