> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirobody.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Host Mirobody

> Run the open-source engine on your own machine or server: the three ways in, where each stage lives, and what a running deployment serves.

export const OssVersion = ({lang = "en"}) => <p className="text-sm text-gray-500 dark:text-gray-400">
    {lang === "zh" ? "对应 mirobody " : "Written for mirobody "}
    <a href="https://github.com/thetahealth/mirobody/tree/c1aae297b4f3fad5cb87c5fc5bffc5163f7758c9">
      <code>1.5.3</code>
    </a>
  </p>;

export const OssLink = ({path = "", children}) => {
  const base = "https://github.com/thetahealth/mirobody";
  const commit = "c1aae297b4f3fad5cb87c5fc5bffc5163f7758c9";
  const href = !path ? base + "/tree/" + commit : base + (path.endsWith("/") ? "/tree/" : "/blob/") + commit + "/" + path.replace(/\/$/, "");
  return <a href={href}>{children ?? <code>{path}</code>}</a>;
};

export const Fact = ({k, code = false, sep = ", "}) => {
  const facts = {
    "version": "1.5.3",
    "commit": "c1aae297b4f3fad5cb87c5fc5bffc5163f7758c9",
    "commitShort": "c1aae29",
    "repo": "https://github.com/thetahealth/mirobody",
    "python": "3.12",
    "port": 18060,
    "url": "http://localhost:18060",
    "pgPort": 18062,
    "redisPort": null,
    "account": "you@mirobody.ai",
    "accounts": ["you@mirobody.ai", "mom@mirobody.ai"],
    "code": "111111",
    "mcpUrlTtlDays": 10,
    "llmKeys": ["OPENROUTER_API_KEY", "DASHSCOPE_API_KEY", "GOOGLE_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "DEEPSEEK_API_KEY"],
    "cli": ["serve", "dev", "worker", "doctor", "fetch", "parse", "import", "resolve", "device-bundle", "mcp", "migrate-observations", "migrate-genotypes", "recode"],
    "tools": {
      "mcp": ["query_genetic_data", "query_health_indicators", "query_medications", "query_pharmacogenomics", "resolve_indicator", "convert_unit", "normalize_unit"],
      "gated": ["query_genetic_data", "query_pharmacogenomics", "query_health_indicators", "query_medications"]
    },
    "readme": {
      "en": {
        "tagline": "Self-hosted AI health data engine: every source, one standard, answers that cite their source.",
        "stages": [{
          "mark": "①",
          "name": "Collect",
          "what": "Lab reports, wearables, phone photos, genetic files, all pulled in. The source file is kept as it was, so every indicator points back to the page it was read from."
        }, {
          "mark": "②",
          "name": "Translate",
          "what": "One name to one code, one unit to UCUM, offline and deterministic. `A1c`, `HbA1c` and `Glycated Hemoglobin` become the same test here, and `头疼` and `headache` the same complaint (ICPC-3)."
        }, {
          "mark": "③",
          "name": "Agent",
          "what": "Ask over the coded record. Trend a value by minute, hour, day, week or month; get count, min, max, avg or change over any window in one call; compare across labs and devices, because they share one code. It charts the result in its reply, reads medications and genetic variants too, and names the file every number came from."
        }]
      },
      "zh": {
        "tagline": "自托管的 AI 原生健康数据引擎：任何来源，一套标准，每个答案都有出处。",
        "stages": [{
          "mark": "①",
          "name": "收集 Collect",
          "what": "化验单、穿戴设备、手机照片、基因文件，都收进来。源文件原样留下，每一项指标都能指回它被读出来的那一页。"
        }, {
          "mark": "②",
          "name": "转译 Translate",
          "what": "一个名字解析成一个码，一个单位统一到 UCUM，全程离线、结果确定。`A1c`、`HbA1c`、`糖化血红蛋白` 在这一层变成同一项检查，`头疼` 和 `headache` 也成了同一条主诉（ICPC-3）。"
        }, {
          "mark": "③",
          "name": "智能体 Agent",
          "what": "在编码后的记录上提问。按分钟、小时、天、周、月给出趋势，一次调用就能算出计数、最小值、最大值、均值和变化量；同一个码，跨化验所、跨设备直接比较。图表画在回复里，用药记录和基因型数据也读得了，每个数字都说明出自哪份文件。"
        }]
      }
    },
    "source": {
      "cli": "mirobody/cli.py",
      "tools": "mirobody/agent/tools"
    }
  };
  const value = k.split(".").reduce((o, p) => o == null ? undefined : o[p], facts);
  if (value === undefined) return <span>{"[unknown fact " + k + "]"}</span>;
  const items = Array.isArray(value) ? value : [value];
  return <>
      {items.map((item, i) => <span key={i}>
          {i > 0 ? sep : null}
          {code ? <code>{String(item)}</code> : String(item)}
        </span>)}
    </>;
};

<OssVersion lang="en" />

Mirobody runs anywhere Python <Fact k="python" /> or Docker runs: a laptop, an on-premises server or a cloud VM. The engine is open source under Apache 2.0 at [thetahealth/mirobody](https://github.com/thetahealth/mirobody), and the data it holds stays in a Postgres you operate. What Mirobody is, and how self-hosting compares with Mirobody Cloud, is on the [overview](/en).

## Ways to run it

Pick the row that matches what you want; the three are alternatives, not steps.

| You want | Path | Needs | Model key |
| - | - | - | - |
| Names and units resolved in your own code | [The library](/en/quickstart#a--the-library) | Python <Fact k="python" /> | none |
| The whole product running, with demo data in it | [The Docker stack](/en/quickstart#b--the-stack) | Git, Docker with Compose | one for model features |
| To change the code and see the result | [A source checkout](/en/quickstart#c--a-checkout) | Python and a Postgres with pgvector | one for model features |

The Docker stack is three containers: Postgres with pgvector, the server and the background worker. It serves the bundled web client at <Fact k="url" code />.

<h2 id="first-local-result">
  First local result
</h2>

With Git and Docker Compose installed, run the local demo and check its seeded readings. Model features require a supported key in `.env`; the sample readings are available without one.

<Steps>
  <Step title="Start the demo">
    Clone the engine and start the stack. The script pulls the application image and creates demo accounts and example readings, then follows the service logs.

    ```bash theme={null}
    git clone --depth 1 https://github.com/thetahealth/mirobody.git && cd mirobody
    ./deploy.sh
    ```
  </Step>

  <Step title="Check the services">
    When the script reports `Up`, keep that terminal open. In another terminal, run these commands from the engine checkout:

    ```bash theme={null}
    docker compose ps
    curl -fsS http://localhost:18060/api/health
    docker compose exec mirobody mirobody doctor
    ```

    The `mirobody` service should become `healthy`, and the health response includes `version` and `agent`. The last command checks model features **inside the container**. If you add a model key to `.env` after startup, run `docker compose up -d`; `docker compose restart` does not re-read `.env`.
  </Step>

  <Step title="Inspect the readings">
    Open <Fact k="url" code />, sign in as `you@mirobody.ai` with code `111111`, then open **Data**. The seeded readings should appear there. The [Quickstart](/en/quickstart#b--the-stack) also covers demo upload files and the other run modes.
  </Step>
</Steps>

For real records, apply the settings in [Deploy on a Server](/en/deployment/production) **before the first start**. After running the demo, follow the [existing-demo path](/en/deployment/production#after-a-local-demo) to start with clean data volumes.

Self-hosting keeps the stored record in the Postgres and file storage you operate. Extraction and agent answers send data to whichever model provider you configure; review that provider's handling of health data before enabling those features.

## Where the three stages live

The package is organized around the same three stages as this documentation.

<Frame caption="A reading moves through collection, standardization, and agent access.">
  <img alt="Collect, Translate, Agent: three stages from left to right" src="https://mintcdn.com/thetahealth/ypMLkjCdwPelODUf/images/oss/docs/images/collect-translate-agent.svg?fit=max&auto=format&n=ypMLkjCdwPelODUf&q=85&s=169192172d6be26338963b62bca91c6b" className="block dark:hidden" width="1120" height="380" data-path="images/oss/docs/images/collect-translate-agent.svg" />

  <img alt="Collect, Translate, Agent: three stages from left to right" src="https://mintcdn.com/thetahealth/ypMLkjCdwPelODUf/images/oss/docs/images/collect-translate-agent-dark.svg?fit=max&auto=format&n=ypMLkjCdwPelODUf&q=85&s=4c4554d69b4ad77af959c2c23cc62bae" className="hidden dark:block" width="1120" height="380" data-path="images/oss/docs/images/collect-translate-agent-dark.svg" />
</Frame>

| Stage | Package | Pages |
| - | - | - |
| ① Collect | `mirobody/collect/` | [Device Providers](/en/providers/using-providers), [Apple Health](/en/providers/apple-health), [File Processing](/en/concepts/file-processing) |
| ② Translate | `mirobody/engine/`, `mirobody/translate/` | [Standardization](/en/concepts/indicators), [Device Crosswalk](/en/concepts/device-crosswalk) |
| ③ Agent | `mirobody/agent/` | [The Agent](/en/tools/agents), [Health-Data Tools](/en/tools/overview), [MCP Integration](/en/tools/mcp-integration) |

How a single reading passes through all three is described in [The Pipeline](/en/concepts/architecture); the directory map is [Repository Layout](/en/concepts/repository-layout).

## What a deployment serves

| Surface | Address | Used by |
| - | - | - |
| Web client | `/` | People: documents and readings at `/data`, the agent at `/ask`, and care-circle sharing |
| HTTP API | `/api/*` | Your own application; begin with the [local HTTP API guide](/en/http-api) |
| MCP endpoint | `/mcp` | Claude Desktop, Cursor, or an agent loop of your own; see [MCP Integration](/en/tools/mcp-integration) |

A self-hosted engine does not serve the Cloud `/v1` API. The Cloud tab documents that surface; the routes above are the engine's own.

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/en/quickstart">
    Install the library, bring up the stack, or run a checkout.
  </Card>

  <Card title="Configuration" icon="sliders" href="/en/configuration">
    The model key, the configuration files, and the settings a deployment changes.
  </Card>

  <Card title="HTTP API" icon="code" href="/en/http-api">
    Get a local token, write a reading, and read it back.
  </Card>

  <Card title="Walkthrough" icon="play" href="/en/walkthrough">
    The running stack in four scenes, with the demo record.
  </Card>

  <Card title="Deploy on a Server" icon="server" href="/en/deployment/production">
    Production posture, secrets, HTTPS and a deployment check.
  </Card>

  <Card title="Upgrade a Deployment" icon="arrow-up" href="/en/deployment/upgrade">
    Back up, review a release, upgrade and verify the running stack.
  </Card>

  <Card title="Verify and Restore a Backup" icon="database" href="/en/deployment/restore">
    Rehearse a restore and recover Postgres and local uploads.
  </Card>
</CardGroup>

When a deployment does not come up, [Troubleshooting](/en/troubleshooting) lists the common causes and their fixes.

<h2 id="contributing">
  Contributing
</h2>

The highest-leverage contribution is a term the resolver gets wrong. Run `mirobody resolve "<term>"`; if the answer is wrong or empty, report it, or add a row to <OssLink path="mirobody/res/loinc/resolver_overrides.tsv" /> together with a case in <OssLink path="mirobody/tests/test_engine_coverage.py" />. The coverage score is the review.

A development checkout installs the test extra and runs the suite and the import contracts:

```bash theme={null}
pip install -e '.[test]' && pytest -q && lint-imports
```

The full contributor workflow is in <OssLink path="CONTRIBUTING.md" />, and the test layout in <OssLink path="docs/testing.md" />.

Public benchmarks under `benchmarks/` run from a clone with no private data: `python -m unittest benchmarks.health_records.test_cases` (13 synthetic readings and 26 complaint phrases in five languages, checked against their LOINC/UCUM and ICPC-3 codes) and `python -m unittest discover -s benchmarks/genomics -p 'test_*.py'` (13 public 1000 Genomes calls in ten file shapes). See <OssLink path="benchmarks/health_records/README.md" /> and <OssLink path="benchmarks/genomics/README.md" />.

<CardGroup cols={2}>
  <Card title="GitHub repository" icon="github" href="https://github.com/thetahealth/mirobody">
    Source code, issues and pull requests.
  </Card>

  <Card title="Report a problem" icon="bug" href="https://github.com/thetahealth/mirobody/issues">
    A report that parses incorrectly makes a valuable issue; attach a de-identified sample.
  </Card>
</CardGroup>

Security reports go through a private advisory, not a public issue; see <OssLink path="SECURITY.md" />.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.