> ## 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.

# Architecture Overview

> How the Mirobody C++ engine is laid out: LLM clients, MCP tools, the agent, health vendors, and embedded FHIR R4.

Mirobody is a **C++11 engine**. It runs standalone on desktop/server or **on-device** inside the Android / iOS apps, so health data never has to leave the phone. It builds with CMake (plus vcpkg on Windows) and is composed of five pieces you can extend independently.

<Frame caption="Mirobody: one C++ core (LLM clients · MCP tools · agent · health vendors · FHIR R4) shipping as a standalone binary, an Android JNI library, or an iOS C API.">
  <img src="https://mintcdn.com/thetahealth/5myzHHPHug2m7fAL/images/architecture.svg?fit=max&auto=format&n=5myzHHPHug2m7fAL&q=85&s=e5ed06101bb760f371332d0d87dcb9f1" alt="Mirobody architecture overview" width="1060" height="660" data-path="images/architecture.svg" />
</Frame>

## The five pieces

| Piece              | Path                                    | Description                                                                                                                                                                               |
| ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **LLM clients**    | `src/llm/`                              | One streaming `llm::Client` per provider: `OpenAIChatClient`, `GeminiClient`, plus `EmbeddingClient` and the realtime `OpenAIRealtimeClient` / `GeminiLiveClient` (audio over WebSocket). |
| **MCP tools**      | `src/mcp/` + `res/mcp_tools/`           | Server-side tools exposed over the `/mcp` endpoint (JSON-RPC 2.0). The nine built-ins are C++ files that self-register at compile time.                                                   |
| **Agent**          | `src/chat/` + `res/agents/baseline.cpp` | One agent ("Baseline"): picks an LLM client by provider, builds a system prompt, streams the turn back, calling MCP tools.                                                                |
| **Health vendors** | `src/health/vendor/`                    | One `vendor::Vendor` per source behind an authorize / fetch / webhook contract, resolved by id via a registry.                                                                            |
| **FHIR R4**        | `src/fhir/`                             | Embedded RESTful FHIR R4 endpoint + terminology (units normalized to UCUM).                                                                                                               |

Agents and tools **self-register at compile time**: drop a `.cpp` in the matching `res/` directory and rebuild — `CMakeLists.txt` globs `res/mcp_tools/*.cpp` (and `res/agents/`) with `CONFIGURE_DEPENDS`.

## The agent

Mirobody runs **one simple agent** — [`res/agents/baseline.cpp`](https://github.com/thetahealth/mirobody/blob/main-v2/res/agents/baseline.cpp). It has no agent loop, no planner, and no middleware. For each turn it picks an LLM client by **provider name**, builds a fixed inline **system prompt** (current time, response language, and guidance to use the file / health tools), and **streams the provider's events straight back**, letting the model call the built-in MCP tools.

<Note>
  The agent is deliberately lightweight: it selects a **provider**, builds a prompt, and streams a turn, invoking MCP tools as needed. You select a **model** (`provider`), not an agent type.
</Note>

### Providers

The agent registers up to three provider clients, keyed by the model name the `/api/providers` selector shows:

* **`gemini-2.5-flash`** — Google Gemini 2.5 Flash (the **default** provider), `GeminiClient`.
* **`gpt-5-nano`** — OpenAI GPT-5 nano, `OpenAIChatClient`.
* **`gemma-4-e2b`** — on-device Gemma 4 E2B served over a local OpenAI-compatible endpoint (registered only when a base URL is set).

The native apps also run **Gemma 4 E2B on-device** (LiteRT-LM on Android/iOS, llama.cpp on Electron) — fully offline, no API key. **Tool execution:** OpenAI and Gemini receive the tools as function-call descriptors and the engine runs each call **locally, in-process** as the authenticated user. Realtime audio chat is available over WebSocket via OpenAI Realtime and Gemini Live.

See [Tools & Agent Overview](/en/tools/overview) for configuration.

## MCP tools

Tools are C++ files in [`res/mcp_tools/`](https://github.com/thetahealth/mirobody/tree/main-v2/res/mcp_tools). Each declares a `Tool` — name, description, an `auth` flag, a `Param` table, and a handler — and self-registers via `MIROBODY_REGISTER_TOOL(...)`. C++11 has no runtime reflection, so parameters are declared explicitly and the registry expands them into the MCP `inputSchema` and the OpenAI / Gemini function descriptors.

```cpp theme={null}
// res/mcp_tools/echo.cpp — the smallest complete tool
const Tool kEcho = {
    "echo",
    "Echo back the provided text.",
    false,                                                    // auth
    { Param("text", Type::String, Required, "Text to echo back") },
    &echo,
};
MIROBODY_REGISTER_TOOL(kEcho);
```

Nine tools ship: `list_files`, `read_file`, `family_health`, `whoami`, `recall_memory`, `remember`, `render_chart`, `summarize_conversation`, and `echo`. An `auth` tool receives the caller's identity as `UserInfo`; other backends it needs (cache, object store, database, memory) arrive through `ToolContext`. See [Built-in Tools](/en/tools/built-in) and [Adding Custom Tools](/en/tools/adding-tools).

## Health vendors

Each data source is a `vendor::Vendor` in `src/health/vendor/`, behind one authorize / fetch / webhook contract and resolved by id via a registry. The buckets:

| Bucket        | Path        | Sources                                                                                                                           |
| ------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Platforms** | `platform/` | 15 B2B aggregators — Terra, Validic, Human API, Junction, Metriport, …                                                            |
| **Phone**     | `phone/`    | Huawei                                                                                                                            |
| **Device**    | `device/`   | Fitbit, Garmin, Withings, Dexcom, Oura, Whoop, Polar                                                                              |
| **EHR**       | `ehr/`      | SMART on FHIR — one generic client for ONC-certified EHRs (Epic, Oracle Health / Cerner, athenahealth), discovery via ONC Lantern |

On-device-only stores (Apple Health, Samsung Health, Google Health Connect, Xiaomi) have **no server client** — the host apps read them on-device and POST FHIR `Observation`s. Add a source by implementing a `vendor::Vendor`; see [Provider Integration](/en/development/provider-integration).

## FHIR R4 & terminology

`src/fhir/` embeds a RESTful FHIR R4 endpoint (`/fhir/*`). Units are normalized to **UCUM**. Uploaded documents are parsed into indicators and values. Mapping indicators to **SNOMED CT / LOINC / RxNorm**, and the full document→indicator terminology pipeline, are **partly in progress** — UCUM has shipped; the broader terminology mapping is still landing.

## Storage & infrastructure

* **Database** — chosen at **build time** via CMake `-DMIROBODY_DATABASE_BACKEND=`: `SQLITE` (mobile default), `POSTGRESQL` (desktop default), `MYSQL`, `DUCKDB`, or `CLICKHOUSE`. SQL schemas live in [`res/sql/`](https://github.com/thetahealth/mirobody/tree/main-v2/res/sql).
* **File storage** — S3 / S3-compatible (MinIO, R2), Alibaba OSS, Azure Blob, or the local filesystem (default), selected at runtime.
* **Cache** — an in-process in-memory KV store by default, or Redis when `REDIS_HOST` is set.
* **Config** — `config.yml` (from `config.example.yml`); precedence is env vars > `config.yml` > remote config > `config.example.yml`. Secrets stored as Fernet ciphertext (`gAAAA…`) are decrypted on load with `CONFIG_ENCRYPTION_KEY` (pre-encrypt them with the `fernet` CLI). See [Configuration](/en/configuration).
* **Auth** — multi-user JWT; an OAuth 2.0 authorization server with OIDC discovery + PKCE (so MCP clients can get tokens for `/mcp`); login via email one-time-code and Google / Apple / WeChat / GitHub (Firebase) plus Tanka QR.
* **Web client** — a static SPA in `htdoc/`, built into `res/htdoc` (`HTTP_ROOT`) and served at the HTTP root.

## Deployment: one core, three forms

The same core ships three ways:

1. **Standalone binary** — `./build.sh` → `build/mirobody`, serving HTTP + WebSocket on `HTTP_HOST:HTTP_PORT` (default `0.0.0.0:8080`) and reading `./config.yml`.
2. **Android** — `libmirobody.so` loaded via **JNI** inside the host app (Gradle + NDK).
3. **iOS** — `libmirobody.a` / `mirobody.xcframework` linked via the **C API** in `src/mirobody.h`.

That `extern "C"` C API also lets Java, Go, C#, Rust, Swift, or Python embed the core directly.

### HTTP routes

| Route                   | Purpose                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------ |
| `/api/health`           | Health check                                                                         |
| `/api/chat`             | Chat — **POST** streams Server-Sent Events; **GET** upgrades to WebSocket (realtime) |
| `/api/providers`        | List available providers                                                             |
| `/api/history`          | Conversation history                                                                 |
| `/api/files`            | File upload / listing                                                                |
| `/fhir/*`               | Embedded FHIR R4 endpoint                                                            |
| `/mcp`, `/mcp/{secret}` | MCP endpoint (JSON-RPC 2.0)                                                          |
| `/oauth/*`              | OAuth 2.0 authorization server                                                       |

## End-to-end request flow

Here's what happens when a signed-in user sends *"How did I sleep recently?"* in the web UI:

```
1. Browser POSTs to /api/chat (Server-Sent Events).
2. JWT middleware resolves the caller → user_id.
3. The chat service seeds/uses a conversation and persists the user message.
4. The Baseline agent is created: it detects the response language, builds the
   system prompt, and resolves the LLM client for the requested provider
   (default gemini-2.5-flash).
5. The client streams the turn. When the model calls a tool, the engine
   runs it locally in-process as the user (e.g. family_health → recent
   FHIR Observations; render_chart → a chart event the frontend draws
   with ECharts).
6. Reply chunks stream back over SSE; the response is persisted.
7. summarize_conversation may set a short title for the chat-history list.
```

## Where to go next

<CardGroup cols={2}>
  <Card title="Providers" icon="plug" href="/en/concepts/providers">
    How devices and EHRs hook in
  </Card>

  <Card title="Data Flow" icon="arrow-progress" href="/en/concepts/data-flow">
    From raw vendor payloads to normalized FHIR
  </Card>

  <Card title="File Processing" icon="file" href="/en/concepts/file-processing">
    Multi-format file ingestion and parsing
  </Card>

  <Card title="Tools & Agent" icon="wrench" href="/en/tools/overview">
    Build and expose tools across the MCP ecosystem
  </Card>
</CardGroup>
