五个部分
| 部分 | 路径 | 说明 |
|---|---|---|
| LLM 客户端 | src/llm/ | 每个 provider 一个流式 llm::Client:OpenAIChatClient、GeminiClient、MiroThinkerClient,外加 EmbeddingClient 以及实时的 OpenAIRealtimeClient / GeminiLiveClient(WebSocket 上的音频)。 |
| MCP 工具 | src/mcp/ + res/mcp_tools/ | 通过 /mcp 端点(JSON-RPC 2.0)暴露的服务端工具。九个内置工具是在编译时自注册的 C++ 文件。 |
| Agent | src/chat/ + res/agents/base.cpp | 一个 Agent(“Base”):按 provider 选择一个 LLM 客户端,构建 system prompt,把这一轮流式返回,其间调用 MCP 工具。 |
| 健康 vendor | src/health/vendor/ | 每个数据源一个 vendor::Vendor,置于 authorize / fetch / webhook 契约之后,通过注册表按 id 解析。 |
| FHIR R4 | src/fhir/ | 内嵌的 RESTful FHIR R4 端点 + 术语(单位归一化为 UCUM)。 |
.cpp 丢进相应的 res/ 目录并重新构建 —— CMakeLists.txt 会用 CONFIGURE_DEPENDS glob res/mcp_tools/*.cpp(以及 res/agents/)。
Agent
Mirobody 运行一个简单的 Agent ——res/agents/base.cpp。它没有 Agent 循环,没有 planner,也没有中间件。每一轮它按 provider 名称选择一个 LLM 客户端,构建一段固定的内联 system prompt(当前时间、回复语言,以及使用文件 / 健康工具的引导),并把 provider 的事件直接流式返回,让模型调用内置的 MCP 工具。
该 Agent 刻意保持轻量:它选择一个 provider,构建提示词,流式返回一轮,并按需调用 MCP 工具。你选择的是一个 模型(
provider),而不是 Agent 类型。支持的提供商
该 Agent 注册最多四个 provider 客户端,以/api/providers 选择器展示的模型名为键:
gemini-2.5-flash—— Google Gemini 2.5 Flash(默认 provider),GeminiClient。gpt-5-nano—— OpenAI GPT-5 nano,OpenAIChatClient。mirothinker-1.7—— MiroThinker(MiroMind),MiroThinkerClient。gemma-4-e2b—— 端侧 Gemma 4 E2B,通过本地 OpenAI 兼容端点提供服务(仅在设置了 base URL 时才注册)。
MCP_PUBLIC_URL 反向访问你的 /mcp 端点。实时音频聊天可通过 WebSocket 经 OpenAI Realtime 和 Gemini Live 使用。
配置见 工具与 Agent 概览。
MCP 工具
工具是res/mcp_tools/ 中的 C++ 文件。每个声明一个 Tool —— 名称、描述、一个 auth 标志、一张 Param 表以及一个 handler —— 并通过 MIROBODY_REGISTER_TOOL(...) 自注册。C++11 没有运行时反射,因此参数显式声明,注册表会把它们展开成 MCP 的 inputSchema 以及 OpenAI / Gemini 的 function 描述符。
list_files、read_file、family_health、whoami、recall_memory、remember、render_chart、summarize_conversation 和 echo。一个 auth 工具以 UserInfo 接收调用者身份;它需要的其它后端(缓存、对象存储、数据库、记忆)通过 ToolContext 送达。参见 内置工具 与 添加自定义工具。
健康 vendor
每个数据源是src/health/vendor/ 中的一个 vendor::Vendor,置于同一份 authorize / fetch / webhook 契约之后,并通过注册表按 id 解析。分桶如下:
| 分桶 | 路径 | 数据源 |
|---|---|---|
| Platforms | platform/ | 15 个 B2B 聚合器 —— Terra、Validic、Human API、Junction、Metriport…… |
| Phone | phone/ | Huawei |
| Device | device/ | Fitbit、Garmin、Withings、Oura、Polar |
| EHR | ehr/ | SMART on FHIR —— 面向 ONC 认证 EHR(Epic、Oracle Health / Cerner、athenahealth)的一个通用客户端,通过 ONC Lantern 发现 |
Observation。要添加一个数据源,实现一个 vendor::Vendor;参见 Provider 集成。
FHIR R4 与术语
src/fhir/ 内嵌了一个 RESTful FHIR R4 端点(/fhir/*)。单位归一化为 UCUM。上传的文档会被解析成指标和数值。把指标映射到 SNOMED CT / LOINC / RxNorm,以及完整的文档→指标术语流水线,部分仍在进行中 —— UCUM 已交付;更广的术语映射仍在落地。(verify:以当前构建为准确认确切状态。)
存储与基础设施
- 数据库 —— 在构建期通过 CMake
-DMIROBODY_DATABASE_BACKEND=选定:SQLITE(移动端默认)、POSTGRESQL(桌面端默认)、MYSQL、DUCKDB或CLICKHOUSE。SQL schema 位于res/sql/。 - 文件存储 —— S3 / S3 兼容(MinIO、R2)、阿里云 OSS、Azure Blob 或本地文件系统(默认),在运行时选定。
- 缓存 —— 默认是一个进程内的内存 KV 存储,或在设置了
REDIS_HOST时使用 Redis。 - 配置 ——
config.yml(源自config.example.yml);优先级为 环境变量 >config.yml> 远程配置 >config.example.yml。键名包含_KEY/_PASSWORD/_SECRET/_TOKEN(及类似)的值会用CONFIG_ENCRYPTION_KEY自动加密(Fernet)。参见 配置。 - 认证 —— 多用户 JWT;一个带 OIDC discovery + PKCE 的 OAuth 2.0 授权服务器(以便 MCP 客户端为
/mcp获取 token);通过邮箱一次性验证码,以及 Google / Apple / WeChat / GitHub(Firebase)外加 Tanka QR 登录。 - Web 客户端 ——
htdoc/中的一个静态 SPA,构建进res/htdoc(HTTP_ROOT)并在 HTTP 根路径提供服务。
部署:一个核心,三种形态
同一个核心以三种方式交付:- 独立二进制 ——
./build.sh→build/mirobody,在HTTP_HOST:HTTP_PORT(默认0.0.0.0:8080)上提供 HTTP + WebSocket 服务,并读取./config.yml。 - Android ——
libmirobody.so通过 JNI 加载进宿主应用(Gradle + NDK)。 - iOS ——
libmirobody.a/mirobody.xcframework通过src/mirobody.h中的 C API 链接。
extern "C" C API 还让 Java、Go、C#、Rust、Swift 或 Python 得以直接嵌入该核心。
HTTP 路由
| 路由 | 用途 |
|---|---|
/api/health | 健康检查 |
/api/chat | 聊天 —— POST 流式返回 Server-Sent Events;GET 升级为 WebSocket(实时) |
/api/providers | 列出可用 provider |
/api/history | 对话历史 |
/api/files | 文件上传 / 列表 |
/fhir/* | 内嵌的 FHIR R4 端点 |
/mcp, /mcp/{secret} | MCP 端点(JSON-RPC 2.0) |
/oauth/* | OAuth 2.0 授权服务器 |
端到端请求流程
已登录用户在 Web UI 里发出*“我最近睡得怎么样?“*时,会发生什么:下一步去哪
Providers
设备和 EHR 如何接入
数据流
从厂商原始 payload 到归一化的 FHIR
文件处理
多格式文件的接入与解析
工具与 Agent
跨 MCP 生态构建并暴露工具