首页 / 系统架构

# 系统架构设计

任意设备控制任意设备 · 全部通过客户端 MCP Server · 多通道统一记忆

## 核心模型：任意设备 → 任意设备

#### 自建客户端：两个功能模块

功能 1 — 与 Gateway 沟通（发送命令）：客户端通过 WebSocket 连接 OpenClaw Gateway，提供聊天界面、设备管理、远程桌面。用户在客户端里的操作（聊天、点按钮）走的是 Gateway 的 API。
功能 2 — 暴露本机能力（MCP Server）：客户端启动后自动注册到 Gateway 作为 MCP Server。AI 或其他设备要操作这台机器时，Gateway 调用它暴露的 MCP Tools（file_list、exec、screenshot 等）。
所有被控设备都装客户端。不装客户端的设备不纳入控制范围。

┌─────────────────────────────────────────────────────────────────────────────┐ │ 发起方 — 任意设备 / 任意通道 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 手机客户端│ │ 电脑客户端│ │ 飞书 │ │ 微信 │ │ Telegram │ │ │ │(MCP+UI) │ │(MCP+UI) │ │ │ │ │ │ │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ └────────┼─────────────┼─────────────┼─────────────┼─────────────┼────────────┘ ▼ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ OpenClaw Gateway（MCP Host） │ │ │ │ AI Agent · 通道路由 · 记忆系统 · MCP Host │ │ │ │ ── 设备注册表（全部通过客户端 MCP Server）── │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ "home-pc" → MCP SSE 在线 [file,exec,screen,input] │ │ │ │ "cloud-svr" → MCP SSE 在线 [file,exec,sysinfo] │ │ │ │ "my-phone" → MCP SSE 在线 [file,exec,screenshot] │ │ │ │ "work-pc" → MCP SSE 离线 [—] │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └───────────┬───────────────────────────────────────────────────────────────┘ │ ▼ ┌────────┴────────┐ ┌──────────────────┐ ▼ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ home-pc │ │ cloud-svr│ │ my-phone │ │ work-pc │ │客户端 │ │客户端 │ │客户端 │ │离线 │ └──────────┘ └──────────┘ └──────────┘ └──────────┘

## 典型场景

#### 📱 手机找电脑文件

手机 App → Gateway → home-pc
"找桌面上的 PDF" → `file_list("home-pc", "C:\\Desktop", "*.pdf")`

#### 💻 电脑查服务器日志

电脑 App → Gateway → cloud-svr
"看 nginx 最近 50 行日志" → `exec("cloud-svr", "tail -50 /var/log/nginx.log")`

#### 💬 微信开关游戏服务器

微信 → Gateway AI → game-svr（客户端）
"把游戏服务器关了" → `exec("game-svr", "systemctl stop minecraft")`

#### 📱 电脑看手机屏幕

电脑客户端 → Gateway → my-phone（客户端）
`screenshot("my-phone")` → 返回手机当前屏幕截图

#### 🔄 跨设备文件传输

手机 App → Gateway → 从 NAS 传到电脑
`file_transfer("nas", "/backup/data.zip", "home-pc", "D:\\backup\\")`

#### 🤖 AI 自动巡检

定时任务 → Gateway AI → 遍历所有设备
"检查所有服务器磁盘使用率" → AI 逐个调用 `sysinfo`

## 目标设备接入方式

设备 | 客户端类型 | 说明
--- | --- | ---
Windows / macOS / Linux 桌面 | 桌面客户端 | Tauri 桌面客户端，MCP Server + 完整 UI（聊天/文件/远程桌面）
Android 手机 | 移动端客户端 | React Native 客户端，MCP Server + 完整 UI
NAS（群晖/威联通等） | CLI 客户端 | Node.js CLI，MCP Server 无 UI，Docker/systemd 后台运行
Linux 服务器 | CLI 客户端 | 同 NAS CLI 版，npx 或 Docker 部署
树莓派 / 开发板 | CLI 客户端 | 同 CLI 版，支持 GPIO/传感器扩展

### 能力说明

所有被控设备必须安装客户端。客户端作为 MCP Server 注册到 Gateway，能力完整（文件/命令/屏幕/输入/系统信息）。不装客户端的设备不纳入控制范围。

## 自建客户端：两个功能

自建客户端部署在用户的手机和电脑上，连接到主机的 Gateway。

#### 功能 1：与 Gateway 沟通

通过 WebSocket 连接 Gateway，提供聊天界面、设备管理、远程桌面。用户操作走 Gateway API。

#### 功能 2：暴露本机能力（MCP Server）

启动后自动注册到 Gateway 作为 MCP Server。AI 或其他设备要操作这台机器时，Gateway 调用它的 MCP Tools。

#### 远程桌面

获取目标设备屏幕推流，直接操控鼠标键盘。通过 WS 数据端口传输。

#### 跨设备操作

手机上找电脑文件、电脑上查服务器日志。客户端不需要知道目标设备用什么协议，Gateway 统一路由。

#### 独立代理

客户端内置独立代理配置（SOCKS5/HTTP），不影响系统代理。只代理客户端自身的 WebSocket 连接。适合需要代理才能访问 Tailscale/外网的场景。

#### 启动自动连接

保存 Gateway 地址 + 认证 token。打开客户端自动连接 Gateway、注册 MCP Server、拉取设备列表。断线自动重连（指数退避 1s→2s→4s→...→60s）。

### 客户端配置

客户端设置

    // 本地存储，首次启动时配置，之后自动连接
    {
      "gateway": {
        "url": "ws://100.x.x.x:18789",     // Gateway 地址（Tailscale IP / DDNS 域名 / 内网 IP）
        "token": "your-auth-token",        // 认证 token
        "autoConnect": true,                // 启动自动连接
        "reconnect": true                   // 断线自动重连
      },
      "proxy": {
        "enabled": false,                   // 是否启用独立代理
        "type": "socks5",                   // socks5 / http
        "host": "127.0.0.1",
        "port": 7890
      },
      "device": {
        "name": "我的手机",                  // 本设备名称
        "exposeAsMcp": true                 // 是否暴露本机能力给 Gateway
      },
      // OTA 更新由 expo-updates 自动处理，无需手动配置
      // 更新 URL 在 app.json 的 updates.url 中配置
    }

## 客户端完整连接流程

### 启动流程

┌──────────────────┐ │ 客户端启动 │ └────────┬─────────┘ ▼ ┌──────────────────┐ 通了 ┌──────────────┐ │ ① 测试 Gateway │───────────▶│ 连接 Gateway │ │ 是否通联 │ │ 注册 MCP Server│ │ (config 中的 URL │ │ 拉取设备列表 │ │ timeout: 3s) │ │ 启动心跳 │ └────────┬─────────┘ └──────────────┘ │ 不通 ▼ ┌──────────────────┐ │ ② 检查 Tailscale │ │ 状态 │ └────────┬─────────┘ │ ┌────┼──────────────┐ ▼ ▼ ▼ 没运行 运行未连接 运行已连接 │ │ │ ▼ ▼ ▼ 启动TS ③重连TS ┌─────────────┐ started │ │ Gateway 不通 │ _by_us=T │ │ 提示用户检查 │ │ ┌─┴──┐ └─────────────┘ │ ▼ ▼ │ up 成功 up失败(需认证) │ │ │ │ │ ▼ │ │ tailscale login │ │ │ │ │ ┌─┴──┐ │ │ ▼ ▼ │ │ 成功 失败→提示用户 │ │ │ ▼ ▼ ▼ ┌──────────────┐ │ 回到 ① 重试 │ └──────────────┘

### 运行中心跳保活

┌──────────────────┐ │ 正常运行中 │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 每 30s 发 WS ping│◀─────────────────────┐ └────────┬─────────┘ │ │ │ ┌────┴────┐ │ ▼ ▼ │ 收到pong 连续3次无响应 │ │ │ │ 继续运行 ▼ │ ┌──────────┐ │ │ 判定断开 │ │ └────┬─────┘ │ ▼ │ ┌──────────┐ 成功 │ │ 重连流程 │──────────────────────┘ │ ①②③ │ └────┬─────┘ │ 全部失败 ▼ ┌──────────┐ │ 通知用户 │ │ 连接丢失 │ └──────────┘

### 退出流程

┌──────────────────┐ │ 客户端退出 │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 断开 Gateway WS │ └────────┬─────────┘ ▼ ┌──────────────────┐ 是 ┌──────────────┐ │ started_by_us? │───────────▶│ tailscale down│ └────────┬─────────┘ │ 恢复进入前状态 │ │ 否 └──────────────┘ ▼ ┌──────────────────┐ │ 不动 Tailscale │ └──────────────────┘

### 完整状态机

客户端状态： IDLE ──启动──▶ TESTING ──通──▶ CONNECTED ──断开──▶ RECONNECTING ──成功──▶ CONNECTED │ │ │ │ 不通 │ 退出 │ 全部失败 ▼ ▼ ▼ CHECK_TS SHUTDOWN DISCONNECTED │ ┌─────┼─────┐ ▼ ▼ ▼ 没运行 未连接 已连接 │ │ │ ▼ ▼ ▼ 启动TS 重连TS 报错 │ │ ▼ ▼ TESTING（重试）

## 设备在外面怎么连？

当设备不在同一局域网时（手机在外面、出差用笔记本、云服务器），需要穿透 NAT 连到主机 Gateway。

方案 | 原理 | 优点 | 缺点 | 国内可用
--- | --- | --- | --- | ---
FRP | 主机跑 frpc，连到有公网 IP 的 frps 服务器。客户端通过 frps 的公网地址连 Gateway。 | 国内最流行、开源免费、配置灵活、延迟低 | 需要一台有公网 IP 的服务器（轻量云 30 元/年） | 最佳
ZeroTier | 类似 Tailscale，设备装 ZeroTier 自动组网。有官方中继服务器。 | 开源、国内可用、零配置 | 官方服务器偶尔抽风，可自建 Planet | 推荐
Cloudflare Tunnel | 主机跑 cloudflared，Gateway 通过 Cloudflare 网络暴露。 | 免费、不需要公网 IP、自带 DDoS 防护 | 国内访问可能慢/被墙 | 看网络
Tailscale | 设备装 Tailscale 自动组网。OpenClaw 官方推荐。 | 零配置、加密 | 国内可能需要 DERP 中继、延迟高 | 看网络
WireGuard | 自建 VPN，所有设备连入。 | 高性能、自控 | 需要公网 IP 服务器、手机配置麻烦 | 可选
公网直连 | 主机有公网 IP，Gateway 直接暴露。 | 最简单、延迟最低 | 安全风险高 | 谨慎

### 当前方案

#### Tailscale

所有设备装 Tailscale，自动组网。客户端通过 Tailscale IP 连 Gateway。OpenClaw 官方推荐。

#### DDNS-GO

主机跑 DDNS-GO，自动更新动态公网 IP 到域名。客户端通过域名连 Gateway。

初期通过聊天通道（微信/飞书/Telegram）控制设备不需要穿透 NAT。客户端直连（远程桌面等）用 Tailscale 或 DDNS-GO。

## 多通道记忆统一

机制 | 配置 | 作用
--- | --- | ---
身份统一 | `session.identityLinks` | 手机 App / 飞书 / 微信 / Telegram 映射为同一用户
会话共享 | `dmScope: "per-peer"` | 跨通道共享对话上下文
长期记忆 | `MEMORY.md` | 设备信息、用户偏好、操作历史
每日笔记 | `memory/YYYY-MM-DD.md` | 按天记录操作日志，支持语义检索

## OpenClaw Gateway 配置

以下是主机上 OpenClaw 需要的完整配置。

~/.openclaw/openclaw.json

    {
      // ① MCP Server 注册 — 客户端设备
      "mcpServers": {
        "home-pc": {
          "url": "http://192.168.1.100:3001/sse"
        },
        "cloud-svr": {
          "url": "http://100.64.0.3:3001/sse"
        }
      },

      // ② 全部设备通过客户端 MCP Server 接入

      // ③ 跨通道记忆统一
      "session": {
        "dmScope": "per-peer",
        "identityLinks": {
          "user:me": {
            "channels": {
              "feishu": "ou_xxx",
              "wechat": "wxid_xxx",
              "telegram": "12345678"
            }
          }
        }
      },

      // ④ Gateway 绑定（根据网络环境选一种）
      "gateway": {
        "bind": "tailnet",              // Tailscale 虚拟网络
        "auth": {
          "mode": "token",
          "token": "your-secret-token"
        }
      },

      // ⑤ 模型配置
      "agent": {
        "model": "openai/gpt-4o"
      },

      // ⑥ 通道配置（按需启用）
      "channels": {
        "telegram": {
          "token": "your-telegram-bot-token",
          "dmPolicy": "pairing"
        },
        "feishu": {
          "appId": "your-feishu-app-id",
          "appSecret": "your-feishu-app-secret"
        }
      }
    }

### 配置说明

配置项 | 作用 | 必填
--- | --- | ---
`mcpServers` | 注册客户端设备，Gateway 自动发现其 MCP Tools | 是
`session.dmScope` | 跨通道会话共享（per-peer = 同一用户共享） | 推荐
`session.identityLinks` | 飞书/微信/Telegram 用户映射为同一人 | 推荐
`gateway.bind` | Gateway 绑定地址（tailnet/0.0.0.0/127.0.0.1） | 是
`gateway.auth` | 认证方式（token/password） | 是
`agent.model` | AI 模型（建议用旗舰模型） | 是
`channels` | 聊天通道配置（Telegram/飞书/微信等） | 按需

## 最终技术方案

组件 | 技术 | 说明
--- | --- | ---
Gateway（主机） | OpenClaw | MCP Host，AI 大脑，通道路由
MCP Server 核心 | TypeScript + `@modelcontextprotocol/sdk` | 全平台通用，36 个 MCP Tools
Desktop 客户端 | Tauri v2 (Rust + React) | Windows/Linux/macOS，~5MB，内置 OTA updater
Android 客户端 | React Native + Expo | 移动端，Expo Updates OTA 热更新
CLI 客户端 | TypeScript (Node.js) | NAS/服务器/树莓派，Docker/systemd 部署
共享类型 | TypeScript | 协议定义、MCP Tool 类型、配置类型
屏幕推流 | WS 数据端口直连 | screenshot-desktop + Sharp + MJPEG
鼠标键盘 | nut.js | 跨平台输入模拟
OTA 更新 | Expo Updates (JS bundle) + Tauri updater (APK) | 小更新 JS bundle OTA 静默推送（新增页面/改 UI/修 Bug）；大更新 APK 重装（原生模块变更）
CI/CD | GitHub Actions / Gitee | push tag → 自动构建所有平台
编辑器 | IntelliJ IDEA | TypeScript + Rust 开发

## OTA 更新策略

#### 双轨更新：小更新 OTA 静默推送，大更新 APK 重装

小更新（JS bundle）：新增页面、改 UI、修 Bug、改业务逻辑 → expo-updates 静默推送 JS bundle（~1-2MB），用户无感，下次打开自动生效。
大更新（APK）：新增原生模块、改图标、升级 React Native 版本 → 需要重新打包 APK，用户手动安装。

更新类型 | 方式 | 用户感知 | 场景
--- | --- | --- | ---
小更新 | JS bundle OTA (expo-updates) | 无感，自动生效 | 新增页面、改 UI、修 Bug、改逻辑、新增 JS 依赖
大更新 | APK 重装 | 需手动安装 | 新增原生模块、改图标/启动图、改包名、升级 RN

### OTA 发布流程

发布 JS bundle 更新

    # 1. 修改代码（JS/TS）
    # 2. 增加版本号（app.json version + versionCode）

    # 3. 导出 JS bundle
    npx expo export --platform android

    # 4. 上传 dist/ 到 Gitee 静态仓库
    git add dist/ && git commit -m "ota: v0.1.1" && git push

    # 5. App 自动检测更新（启动时 + 每 24 小时）
    # 用户下次打开 App 自动生效

### OTA 配置（app.json）

app.json

    {
      "expo": {
        "updates": {
          "url": "https://gitee.com/your-org/gca-ota/manifest.json"
        },
        "plugins": [
          ["expo-updates", { "username": "gca" }]
        ]
      }
    }

## 项目结构

    gca/
    ├── packages/
    │   ├── client/                  # 桌面/移动端客户端（MCP Server + UI）
    │   │   ├── src/
    │   │   │   ├── server/          # MCP Server（暴露本机能力给 Gateway）
    │   │   │   │   ├── tools/       # MCP Tools（file/exec/screen/input/sysinfo）
    │   │   │   │   └── data-channel/# WS 数据端口（推流/文件/键鼠）
    │   │   │   ├── ui/              # UI（聊天/文件浏览/远程桌面，连 Gateway WS API）
    │   │   │   └── platform/        # 平台适配（win/linux/mac/android）
    │   │   └── package.json
    │   ├── client-cli/              # CLI 版客户端（NAS/树莓派/无显示器设备）
    │   │   ├── src/
    │   │   │   ├── index.ts         # CLI 入口（gca-cli start/stop/status）
    │   │   │   ├── daemon.ts        # 后台守护进程
    │   │   │   └── server/          # 复用 client/server 的 MCP Tools
    │   │   └── package.json
    │   └── shared/                  # 共享类型
    ├── pnpm-workspace.yaml
    └── README.md

## 实现细节

### 客户端实现

模块 | 实现 | 说明
--- | --- | ---
MCP Server | `@modelcontextprotocol/sdk` | 启动时创建 MCP Server 实例，注册 Tools，通过 SSE/WS 暴露给 Gateway
Gateway 连接 | WebSocket Client | 连接 Gateway 的 WS API，支持独立代理（SOCKS5/HTTP）、自动重连
文件服务 | Node.js `fs` / Rust `std::fs` | 实现 file_list/read/write/move/delete，支持 glob 过滤
命令执行 | `child_process` / Rust `std::process::Command` | 实现 exec，支持超时、工作目录、环境变量
屏幕捕获 | `screenshot-desktop` (Node) / `screenshots` crate (Rust) | 截取屏幕，JPEG 压缩后返回 base64
系统信息 | `systeminformation` (Node) / `sysinfo` crate (Rust) | CPU/内存/磁盘/网络/运行时间
独立代理 | Tauri: `tokio-tungstenite` + HTTP CONNECT / RN: OkHttp proxy | 只代理客户端自身的 WS 连接，不影响系统代理
UI | Tauri: React / RN: React Native | 聊天界面、设备列表、文件浏览器、远程桌面、设置页面

### 通信流程

场景：用户在手机上找电脑文件 手机客户端 Gateway 电脑客户端 │ │ │ │ ① 用户操作/发消息 │ │ │ ──WS──▶ │ │ │ ② AI 调用 MCP Tool │ │ │ file_list("pc-1") │ │ │ │ ③ 转发到电脑客户端 │ │ │ ──MCP──▶ │ │ │ ④ 电脑执行 file_list│ │ │ 本地文件系统操作 │ │ │ ◀──结果── │ │ ◀──结果── │ │ │ ⑤ 返回给手机 │ │ │ ◀──结果── │ │ │ │ │ 场景：用户在电脑上看手机屏幕 电脑客户端 Gateway 手机客户端 │ │ │ │ ① 调用 screenshot("phone") │ │ │ ──WS──▶ │ │ │ ② 转发到手机客户端 │ │ │ │ ──MCP──▶ │ │ │ ③ 手机截屏 │ │ │ ◀──base64─ │ │ ◀──图片── │ │ │ ④ 显示手机屏幕 │ │ │ ◀──图片── │ │