Skip to main content
Glama
README.md
<div align="center">

<img src="assets/host-console-256.png" width="96" alt="主机台 HostConsole" />

# 主机台 HostConsole

**把 SSH 交给 AI 操作,但把密钥留在自己手里。**

[English](README.en.md) · 简体中文

[![License: MIT](https://img.shields.io/badge/License-MIT-35c987.svg)](LICENSE)
[![Platform](https://img.shields.io/badge/平台-Windows-blue)](#)
[![MCP](https://img.shields.io/badge/MCP-Model_Context_Protocol-orange)](https://modelcontextprotocol.io)
[![Electron](https://img.shields.io/badge/Electron-43-9feaf9?logo=electron&logoColor=white)](#)
[![Tests](https://img.shields.io/badge/测试-29%2F29%20通过-brightgreen)](#)

[特性](#核心特性) · [截图](#截图) · [快速开始](#快速开始) · [接入你的-ai](#接入你的-ai) · [安全模型](#安全模型) · [工作原理](#工作原理) · [FAQ](#faq)

</div>

---

## 为什么需要主机台

你大概也遇到过这种纠结:想让 AI 帮你照看 NAS、服务器或路由器,但把 SSH 密钥、密码直接交给一个 AI 客户端,总觉得不踏实——

- **密钥一旦粘贴进 AI 配置,就等于交出了整台机器**,而你无法确定它会被记录到哪里;
- 给 AI 生成临时公钥再装进 `authorized_keys`,用完还要记得清理,麻烦且容易遗忘;
- AI 执行 `sudo` 时你根本看不到它要跑什么命令,更谈不上审批;
- 换一个 AI 客户端(Codex、OpenCode、ZCode……),整套授权流程又要重来一遍。

**主机台的答案:密钥永不离开你的电脑。**

你在主机台里手动连接 SSH(密码 / 私钥,系统级加密保存),再把"已授权的会话"通过本机 MCP 桥接器交给 AI。AI 全程只看到会话别名(比如「家里 NAS」),能操作终端、能被你随时暂停和断开——但**永远拿不到地址、端口、用户名和私钥**。

```
┌─────────────┐   SSH 凭据只到这里,加密保存    ┌──────────────┐
│   你本人     │ ────────────────────────────▶ │  你的 NAS /  │
│  (主机台 UI) │ ◀──────────────────────────── │   服务器      │
└──────┬──────┘        已建立的 SSH 会话        └──────────────┘
       │ 授权(相对安全 / 完全开放)
       ▼
┌──────────────┐  本机命名管道(不出网、不开端口) ┌─────────────┐
│  主机台 MCP   │ ◀──────────────────────────▶ │  AI Agent   │
│   桥接器      │      只传命令与输出、别名        │ Codex 等     │
└──────────────┘                                └─────────────┘
```

## 适用场景

- 🏠 **家用 NAS / 家庭服务器**:让 AI 帮你查 SMART 状态、清理 Docker、修 RAID 告警,但不想把 root 权限交给它
- 🖥️ **个人 VPS / 开发机**:部署、看日志、改 nginx 配置,AI 干活你审批
- 🌐 **路由器 / 网络设备**:偶尔需要 AI 帮忙诊断,但设备凭据绝不能外流
- 🔁 **多 AI 客户端用户**:Codex、OpenCode、ZCode、WorkBuddy 共享同一组已授权 SSH 会话,换工具不用重新授权
- 🛡️ **重视审计的人**:每条 sudo 命令都要经过你眼前弹出的审批框,命令原文清清楚楚

## 截图

| 主界面(Agent 接入中心 + 权限模式) | Agent 接入向导 |
|:---:|:---:|
| <img src="docs/images/overview.png" alt="主机台主界面:左侧 SSH 会话列表,右侧终端预览、Agent 接入中心与 AI 访问权限模式" width="480"> | <img src="docs/images/agent-wizard.png" alt="Agent 接入向导:选择配置类型与 MCP 配置文件,预览后写入" width="480"> |

| Agent 接入中心(展开) | 窄屏响应式 |
|:---:|:---:|
| <img src="docs/images/agent-center.png" alt="Agent 接入中心展开:每个 Agent 独立状态灯与连接开关" width="480"> | <img src="docs/images/mobile.png" alt="窄屏单列布局" width="200"> |

## 核心特性

- 🔐 **凭据隔离**:SSH 地址、端口、用户名只存在本地配置;密码与私钥经 Electron `safeStorage`(Windows 系统凭据保护)加密存入独立保险箱。AI 通过 MCP 只能拿到会话**别名**和授权状态,其余一概不可见——这一点有专门的测试断言保证。
- 🚦 **双权限模式**:**相对安全**(AI 只能执行身份 / 系统 / 存储 / 进程 / 容器 / 服务 / 日志七类固定只读检查)和**完全开放**(当前 SSH 账号的完整终端权限),随时一键切换。
- 💳 **sudo 审批流**:AI 需要提权时调用单独的 `exec_sudo`,主机台自动弹窗展示**命令原文**,你批准后才执行。可选 30 分钟(默认,0–240 分钟可调)免询问窗口;sudo 密码由本地保险箱经 SSH 标准输入直接交给远端,**不进入命令文本、不进入终端记录、不进入 AI 上下文**。
- 🟢 **Agent 接入中心**:所有接入的 AI 以状态灯形式实时展示(在线 / 离线 / 正在控制),每个 Agent 带独立连接开关——关掉立即释放它的 SSH 控制权和 sudo 授权,不影响其他 Agent、不断开 SSH。
- 🧙 **一键接入向导**:自动识别并写入 Codex TOML、OpenCode JSONC、ZCode、WorkBuddy 及通用 JSON/JSONC 六种 MCP 配置格式,写入前可预览、自动生成带时间戳的备份。
- ✍️ **单写入租约**:同一时刻只有一个 Agent 能写入终端,其他 Agent 可见占用状态但无法插入命令;你明确说"接手 / 强制接管"才会转移。
- 🫸 **即时熔断**:「暂停 AI」立刻阻断操作但保持 SSH 连接;「断开连接」同时撤销授权、租约和 sudo 授权。
- 🖥️ **本机手动命令兜底**:AI 拒绝执行或需要交互输入时,界面内置命令输入框,你亲手敲。
- 🇨🇳 **全中文界面**:为中文用户打造,从权限模式到错误提示没有一个英文术语需要查翻译。
- ✅ **29 项安全测试**:凭据隔离、租约独占、sudo 生命周期、配置脱敏等核心安全声明全部有自动化测试兜底(`npm test`)。

## 快速开始

### 环境要求

- Windows 10/11
- [Node.js](https://nodejs.org) 20+(含 npm)

### 启动

```powershell
git clone https://github.com/tuweihuasheng/host-console.git
cd host-console
npm install
npm run desktop
```

> 应用窗口关闭后会驻留系统托盘,SSH 会话不会因此断开。

### 三步上手

1. **连接**:点「新建连接」,选择 SSH 密码 / 粘贴私钥 / 选择密钥文件;首次连接核对并固定主机 SHA-256 指纹(TOFU)。
2. **授权**:连接后在右侧选择「相对安全」或「完全开放」。
3. **召唤 AI**:对你已接入主机台的 AI 说——
   > 本机已连接「家里 NAS」的 SSH,请帮我检查磁盘和 Docker 容器状态。

   AI 会通过 MCP 自动发现已授权会话、获取控制权并开始干活。

## 接入你的 AI

主机台通过**本机命名管道**提供 MCP 服务(`\\.\pipe\host-console-mcp`),不监听任何 TCP 端口,云端 Agent 无法触达。

最简单的方式是在主机台里点「接入 Agent」按钮,用内置向导自动写入配置(支持自动备份与预览)。以下为手动配置参考:

**Codex(`~/.codex/config.toml`)**

```toml
[mcp_servers.host_console]
command = "node.exe 的完整路径"
args = ["C:\\path\\to\\host-console\\mcp\\server.mjs"]
startup_timeout_sec = 10
tool_timeout_sec = 60
```

**OpenCode(`~/.config/opencode/opencode.jsonc`)**

```jsonc
"mcp": {
  "host_console": {
    "type": "local",
    "command": ["node.exe 的完整路径", "C:\\path\\to\\host-console\\mcp\\server.mjs"],
    "enabled": true,
    "timeout": 60000,
    "environment": {
      "HOST_CONSOLE_AGENT_LABEL": "OpenCode",
      "HOST_CONSOLE_CLIENT_KIND": "opencode"
    }
  }
}
```

**ZCode(`~/.zcode/cli/config.json` 的 `mcp.servers`)、WorkBuddy(`~/.codebuddy/.mcp.json` 的 `mcpServers`)及任意通用 JSON/JSONC** 均可按同样结构接入,或直接用内置向导写入。

> 配置写入后需**完全退出并重启**对应 AI 客户端(MCP 客户端只在启动时加载配置)。接入成功后,主机台「Agent 接入中心」会出现绿色状态灯,并把已授权会话的别名与权限模式同步给 AI。

## 安全模型

### AI 能看到什么、不能看到什么

| | AI 可见 | AI 不可见 |
|---|---|---|
| **会话** | 别名(如「家里 NAS」)、连接状态、权限模式 | 主机地址、端口、用户名 |
| **凭据** | —— | SSH 密码、私钥、sudo 密码(全部加密存本地保险箱) |
| **操作** | 相对安全:7 类固定只读检查<br>完全开放:任意命令 + sudo 审批 | 绕过 sudo 审批的命令会被直接拒绝 |
| **终端** | 最近输出(可读文本) | 你的手动输入不回显 |

### 多重防线

1. **管道级隔离**:MCP 只绑定本机命名管道,不出网、不开端口;同一台电脑之外无人能连。
2. **单写入租约**:并发 Agent 只有一个能操作终端,接管需要用户明示。
3. **双因子确认**:多会话场景下,AI 必须同时提供会话 ID **和**准确别名才能获取控制权,不匹配即拒绝。
4. **sudo 生命周期**:临时授权只绑定当前会话与当前控制 Agent,暂停 / 断开 / 接管 / 降权 / 到期立即失效,也可随时手动提前结束。
5. **凭据不可逆**:更换凭据需先断开 SSH;旧凭据永不回显,新凭据加密覆盖。

### 已知边界

- 与主机台运行在**同一 Windows 用户**下的恶意本地进程理论上仍可连接命名管道——请勿在不可信本机环境中使用「完全开放」模式。
- 当前为 MVP,尚未提供签名安装包与自动更新。

## MCP 工具一览

AI 侧可调用的 9 个工具:

| 工具 | 用途 | 权限要求 |
|---|---|---|
| `get_bridge_status` | 查看接入的 AI 客户端与已授权会话(仅别名与状态) | 任意 |
| `list_authorized_sessions` | 发现已授权 SSH 会话 | 任意 |
| `get_session_status` | 查看连接、授权模式、暂停状态、当前控制者 | 任意 |
| `acquire_control` | 获取单 Agent 写入租约(多会话需 ID + 别名双确认) | 任意 |
| `release_control` | 释放租约(不断开 SSH、不撤销授权) | 任意 |
| `safe_inspect` | 7 类固定只读诊断(身份 / 系统 / 存储 / 进程 / 容器 / 服务 / 日志) | 相对安全 |
| `exec_terminal` | 执行任意 Shell 命令(含 sudo 检测,混入 sudo 会被拒绝) | 完全开放 |
| `exec_sudo` | 提权命令,经主机台审批框批准后执行 | 完全开放 + 审批 |
| `read_terminal` | 读取交互终端最近输出 | 完全开放 |

## 工作原理

```
主机台 (Electron)
├── src/                    全中文桌面界面(React 19)
├── electron/
│   ├── main.cjs            窗口、托盘、命名管道服务、IPC
│   ├── session-manager.cjs 加密保险箱、SSH 连接池、授权与租约、sudo 审批
│   ├── agent-config.cjs    6 种格式的 Agent 配置向导(预览 + 备份 + 原子写入)
│   └── policy.cjs          只读命令白名单、公开信息脱敏
├── mcp/server.mjs          MCP 桥接服务(stdio → 命名管道)
└── tests/                  29 项安全与行为测试
```

## FAQ

**Q:AI 怎么知道要调用主机台?**
接入 MCP 后,主机台会在初始化说明中把已授权会话的别名与权限模式主动同步给 AI。你只需像平常一样下任务:"本机已连接家里 NAS 的 SSH,请……"。

**Q:换个 AI 客户端还能用吗?**
能。授权绑定在 SSH 会话上,不绑定 Agent。任何已接入主机台 MCP 的本机 AI 都能发现并(在租约空闲时)接管同一会话。

**Q:同时连多台 SSH 会怎样?**
AI 必须同时提供会话 ID 和准确别名双重确认,防止操作错主机。

**Q:sudo 密码会不会被 AI 看到?**
不会。密码由本地保险箱解密后经 SSH 标准输入直接交给远端 sudo,全程不经过 AI、不进入命令文本和终端记录(有专门测试断言)。

**Q:断电 / 关机后凭据会丢吗?**
不会。保险箱文件持久化在 Windows 用户数据目录,由系统凭据保护能力加密;但请勿把保险箱文件复制到不受信任的机器。

**Q:支持 Linux / macOS 吗?**
界面与逻辑无平台假设,但目前在 Windows 上开发与验证;`safeStorage` 在其他平台依赖各自的系统钥匙串。欢迎测试反馈。

## 开发

```powershell
npm run dev      # 浏览器开发预览
npm run desktop  # 构建并启动 Electron 桌面版
npm test         # 29 项测试
```

参与开发请阅读 [AGENTS.md](AGENTS.md) 了解项目的产品决策约定。

## 许可证

[MIT](LICENSE) © 2026 host-console contributors