内容
# MoeReview
<p align="center">
<strong>给 MCP Agent 用的本地优先学习工作台。</strong><br />
让 Agent 负责思考,让浏览器负责稳定承载学习流程。
</p>
<p align="center">
<a href="./README.en.md">English</a>
·
简体中文
</p>
<p align="center">
<img alt="Node.js >= 18" src="https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white" />
<img alt="React" src="https://img.shields.io/badge/react-19-61DAFB?logo=react&logoColor=111" />
<img alt="Vite" src="https://img.shields.io/badge/vite-8-646CFF?logo=vite&logoColor=white" />
<img alt="MCP" src="https://img.shields.io/badge/MCP-agent%20tools-8A2BE2" />
<img alt="Local first" src="https://img.shields.io/badge/storage-local--first-blue" />
<img alt="License: GPL v3" src="https://img.shields.io/badge/license-GPLv3-blue" />
</p>
> 这不是又一个“聊天窗口套壳”。MoeReview 更像一台学习机甲的驾驶舱:Agent 负责推理和教学,Hub 负责稳定连接,Web UI 负责沉淀、做题、回看和交互。
## 目录
- [它解决什么问题](#它解决什么问题)
- [功能亮点](#功能亮点)
- [架构](#架构)
- [目录结构](#目录结构)
- [环境要求](#环境要求)
- [快速启动](#快速启动)
- [安装与构建](#安装与构建)
- [启动 Hub](#启动-hub)
- [配置 MCP Adapter](#配置-mcp-adapter)
- [可选 Agent Skill](#可选-agent-skill)
- [核心交互模型](#核心交互模型)
- [常用命令](#常用命令)
- [本地数据](#本地数据)
- [常见问题](#常见问题)
- [开源前状态](#开源前状态)
## 它解决什么问题
很多 AI 学习工具把所有东西都塞进聊天记录里:讲解、题目、答案、状态、提醒混在一起。MoeReview 的思路是把学习流程拆成更稳定的界面层:
- 长期有价值的内容进入学习分页。
- 临时说明和下一步建议进入右侧引导面板。
- Agent 可以等待用户在网页里答题或发消息。
- Agent 下线后,网页仍然能打开并回看历史。
换句话说:不要让 Agent 的生命周期绑架学习界面的稳定性。
## 功能亮点
- 常驻 `MoeReview Hub`,Web 页面不依赖 Agent 启动。
- 临时 `MCP Agent Adapter`,只负责把 MCP 工具调用转发给 Hub。
- 会话级历史:学习分页、收藏、错题、问答历史、活动日志。
- 测验页面、答案收集、结果页和错题沉淀。
- 右侧 `Guidance Panel` 展示临时状态、短建议和下一步。
- 无 Agent 时也能进入欢迎页和回看历史。
- 默认本地存储,不需要账号或云服务。
## 架构
```text
Browser UI <-- HTTP / WebSocket --> MoeReview Hub <-- HTTP --> MCP Agent Adapter <-- stdio --> Agent
```
MoeReview 后端拆成两个角色:
- `MoeReview Hub`:常驻 HTTP/WebSocket 服务,负责网页、会话、历史、连接状态和事件路由。
- `MCP Agent Adapter`:临时 MCP stdio 服务,负责注册 Agent,并把工具调用转发到 Hub。
这样做的直接收益是:重启 Agent、切换 Agent、结束 Agent 对话,都不会导致网站不可访问。
## 目录结构
```text
.
+-- mcp-server/ # MoeReview Hub 和 MCP Agent Adapter
| +-- src/hub.ts # Hub 入口
| +-- src/index.ts # MCP Adapter 入口
| +-- src/ws/server.ts # HTTP / WebSocket / API / 路由
| +-- src/tools/ # MCP 工具实现
+-- web/ # React + Vite 前端
+-- skills/
| +-- moereview-agent/ # 可选 Codex skill:约束 Agent 正确使用 MoeReview
+-- docs/ # 设计文档
+-- scripts/ # 本地快速启动与检查脚本
+-- start.cmd # Windows 双击启动入口
+-- README.md # 中文文档
+-- README.en.md # 英文文档
```
## 环境要求
- Node.js 18+
- npm
- 一个支持 MCP 的 Agent / 客户端
当前项目优先服务本地单用户场景。账号系统、云同步、权限模型都还没引入。
## 快速启动
Windows 用户可以直接双击:
```text
start.cmd
```
或者在仓库根目录运行:
```powershell
npm run start
```
这会自动:
1. 检查 Node.js 和 npm。
2. 安装缺失的 `web` / `mcp-server` 依赖。
3. 构建前端和后端。
4. 检查 `3456` 端口。
5. 打开浏览器。
6. 启动 MoeReview Hub。
如果只想检查环境:
```powershell
npm run check
```
如果不想自动打开浏览器:
```powershell
npm run start:no-open
```
快速启动脚本不会自动 kill 端口占用者。如果 `3456` 被占用,请手动停止旧进程,或者使用:
```powershell
.\scripts\start.ps1 -Port 4567
```
## 安装与构建
安装依赖:
```powershell
cd mcp-server
npm install
cd ../web
npm install
```
构建前端:
```powershell
cd web
npm run build
```
构建 Hub / MCP Adapter:
```powershell
cd ../mcp-server
npm run build
```
如果你从仓库根目录开始,可以按这个顺序执行:
```powershell
cd web
npm run build
cd ../mcp-server
npm run build
```
## 启动 Hub
Hub 默认监听 `3456` 端口,并托管已经构建好的 `web/dist`。
```powershell
cd mcp-server
npm run hub
```
然后打开:
```text
http://localhost:3456
```
没有 Agent 连接时,MoeReview 仍然可以正常打开,进入欢迎页或回看历史会话。
如果要换端口:
```powershell
$env:MOEREVIEW_HUB_PORT="4567"
npm run hub
```
## 配置 MCP Adapter
构建 `mcp-server` 后,在你的 MCP 客户端里配置:
```text
node <repo>/mcp-server/dist/index.js
```
示例:
```json
{
"mcpServers": {
"moereview": {
"command": "node",
"args": ["<absolute-path-to-repo>/mcp-server/dist/index.js"]
}
}
}
```
把 `<absolute-path-to-repo>` 替换成你本地 clone 的仓库路径。
推荐启动顺序:
1. 构建 `web` 和 `mcp-server`。
2. 运行 `npm run hub` 启动 Hub。
3. 启动支持 MCP 的 Agent / 客户端。
4. 打开 `http://localhost:3456`。
## 可选 Agent Skill
仓库内提供了一个可选 Codex skill:
```text
skills/moereview-agent/
```
它不规定教学方法,不干涉讲解风格。它只约束 Agent 如何正确使用 MoeReview:
- 显式绑定会话。
- 每轮开始读取 pending messages。
- 真实地区分 `idle` / `waiting` / `working` / `disconnected`。
- 只有有长期回看价值的内容才创建 page。
- 临时状态和下一步建议放到侧边栏 guidance。
如果你的 Agent 支持显式 skill 调用,可以使用:
```text
Use $moereview-agent
```
或者直接指向:
```text
skills/moereview-agent/SKILL.md
```
## 核心交互模型
### Pages:长期学习记录
适合放进 page 的内容:
- 知识点讲解
- 结构化总结
- 测验题
- 测验结果
- 错题复盘
- 学习计划
- 重要修订
不适合放进 page 的内容:
- “好的”
- “我正在处理”
- 临时建议
- 工具状态
- 一句话提醒
### Guidance Panel:右侧临时引导
适合放到侧栏的内容:
- 当前状态
- 下一步建议
- 操作提示
- 等待用户输入的说明
- 轻量警告
目标是让用户不打开 Agent 聊天窗口,也知道当前该做什么。
### Agent 等待与唤醒
MCP 不能反向唤醒一个已经结束的 Agent turn。MoeReview 因此明确区分状态:
| 状态 | 含义 |
|---|---|
| `offline` | 当前会话没有 Agent |
| `idle` | Adapter 在线,但 Agent 没有主动等待 |
| `waiting` | Agent 正在 `wait_for_response` / `ask_choice` / `enter_standby` |
| `working` | Agent 正在处理或调用工具 |
| `disconnected` | Agent 心跳过期或连接断开 |
只有 `waiting` 可以被 Web 输入立即唤醒。
`idle` 和 `working` 状态下,Web 消息会进入队列,等待 Agent 下一轮调用 `get_pending_messages`。
## 常用命令
前端:
```powershell
cd web
npm run dev
npm run build
npm run lint
```
后端:
```powershell
cd mcp-server
npm run build
npm run hub
npm run dev:hub
npm run start
```
注意:`npm run start` 启动的是 MCP Adapter,不是 Hub。
## 本地数据
MoeReview 默认把运行时数据放在用户目录:
```text
~/.examforge/
```
会话数据包括:
- `meta.json`
- `pages.json`
- `favorites.json`
- `wrong_answers.json`
- `qa_memory.json`
- `activity_log.json`
- `message_queue.json`
- `guidance.json`
这些数据不应该提交到 Git。
## 常见问题
### 3456 端口被占用
Hub 不会自动 kill 端口占用者。请手动停止旧进程,或者设置 `MOEREVIEW_HUB_PORT`。
### Hub 打开了,但不是完整 Web UI
通常是还没构建前端:
```powershell
cd web
npm run build
```
然后重启 Hub。
### MCP 工具提示 Hub 未启动
先启动 Hub,再启动 MCP Adapter:
```powershell
cd mcp-server
npm run hub
```
### 前端发消息后 Agent 没反应
看会话状态:
- `waiting`:应该能立即唤醒。
- `idle`:消息已入队,Agent 下一轮读取。
- `working`:消息已入队,等待 Agent 忙完。
- `disconnected`:需要重启 MCP Adapter。
## 开源前状态
MoeReview 仍在快速迭代中,API 和目录结构可能继续变化。当前最重要的设计原则是:
> Web 工作台必须独立于 Agent 生命周期稳定运行。
后续适合补:
- 一键启动脚本
- 连接诊断面板
- pending message 数量提示
- standby 取消 / 延长机制
- 自动生成 MCP 工具文档
## License
本项目使用 [GNU General Public License v3.0](./LICENSE)。