Skip to main content
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.
Mirobody architecture overview

The five pieces

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 agentres/agents/base.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.
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.

Providers

The agent registers up to four 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.
  • mirothinker-1.7 — MiroThinker (MiroMind), MiroThinkerClient.
  • 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 differs by provider: OpenAI and Gemini receive the tools as function-call descriptors and the engine runs each call locally, in-process as the authenticated user; MiroThinker runs tools provider-side — MiroMind reaches back to your /mcp endpoint over the public internet at MCP_PUBLIC_URL. Realtime audio chat is available over WebSocket via OpenAI Realtime and Gemini Live. See Tools & Agent Overview for configuration.

MCP tools

Tools are C++ files in 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.
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 and Adding Custom 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: 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 Observations. Add a source by implementing a vendor::Vendor; see 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. (verify against the current build for the exact state.)

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/.
  • 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.
  • Configconfig.yml (from config.example.yml); precedence is env vars > config.yml > remote config > config.example.yml. Values whose names contain _KEY / _PASSWORD / _SECRET / _TOKEN (and similar) are auto-encrypted (Fernet) with CONFIG_ENCRYPTION_KEY. See 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.shbuild/mirobody, serving HTTP + WebSocket on HTTP_HOST:HTTP_PORT (default 0.0.0.0:8080) and reading ./config.yml.
  2. Androidlibmirobody.so loaded via JNI inside the host app (Gradle + NDK).
  3. iOSlibmirobody.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

End-to-end request flow

Here’s what happens when a signed-in user sends “How did I sleep recently?” in the web UI:
For the session-sharing read path, see Session Sharing.

Where to go next

Providers

How devices and EHRs hook in

Data Flow

From raw vendor payloads to normalized FHIR

File Processing

Multi-format file ingestion and parsing

Tools & Agent

Build and expose tools across the MCP ecosystem