内容
# 吸尘器 MCP 服务器
<p align="center">
<a href="https://github.com/casey/just"><img src="https://img.shields.io/badge/just-ready_to_go-7c5cfc?style=flat-square&logo=just&logoColor=white" alt="Just"></a>
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
<a href="https://python.org"><img src="https://img.shields.io/badge/Python-3.13+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"></a>
<a href="https://biomejs.dev"><img src="https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat-square&logo=biome&logoColor=white" alt="Biome"></a>
<a href="https://github.com/PrefectHQ/fastmcp"><img src="https://img.shields.io/badge/FastMCP-3.2-7c5cfc?style=flat-square" alt="FastMCP"></a>
</p>
> 📖 **[安装指南](INSTALL.md)** — 快速开始,手动设置和故障排除
FastMCP 3.2.0 MCP 服务器和网页应用,适用于 **Dreame D20 Pro Plus** 机器人吸尘器。使用 **DreameHome 云 API**;本地 **miio** 是可选的(混合模式:见下文)。
协议层从 [Tasshack/dreame-vacuum](https://github.com/Tasshack/dreame-vacuum) 提取。
## 功能
- **MCP 工具**:`dreame(operation=...)` 状态,地图,开始清洁,停止,暂停,回家,查找机器人,电池
- **MCP 工具**:`dreame_help(category)`,`dreame_agentic_workflow(goal)`,带有 SEP-1577 采样
- **提示**:`dreame_quick_start`,`dreame_diagnostics`
- **技能**:`skills/dreame-operator.md`
- **REST API**:GET /api/v1/health,/api/v1/status,/api/v1/map;POST /api/v1/control/{cmd}
- **网页应用**:仪表盘,LIDAR 地图,状态,控制,设置,帮助,MCP 工具
## 端口
- 后端:**10894** (REST + MCP SSE)
- 仪表盘:**10895** (Vite 开发服务器)
## 先决条件
1. 克隆 **此** 仓库并进入:
```powershell
git clone https://github.com/sandraschi/dreame-mcp.git
Set-Location dreame-mcp
```
2. 克隆 Tasshack dreame-vacuum 参考仓库(协议 + 地图层)。默认引用路径为 `D:/Dev/repos/tasshack_dreame_vacuum_ref`:
```powershell
Set-Location D:\Dev\repos
git clone https://github.com/Tasshack/dreame-vacuum tasshack_dreame_vacuum_ref
Set-Location dreame-mcp
```
(调整路径如果您的开发文件夹不是 `D:\Dev\repos`;相应设置 `DREAME_REF_PATH`。)
3. 从 **dreame-mcp** 仓库根目录安装 Python 依赖:
```powershell
uv sync
```
## 环境变量
| 变量 | 必需 | 描述 |
|---|---|---|
| `DREAME_USER` | | DreameHome 电子邮件或电话 |
| `DREAME_PASSWORD` | | DreameHome 密码 |
| `DREAME_COUNTRY` | | 云区域,默认 `eu` |
| `DREAME_DID` | | 设备 ID,如果单个设备则自动发现 |
| `DREAME_AUTH_KEY` | | 上次登录的刷新令牌(加速启动) |
| `DREAME_REF_PATH` | | tasshack 参考克隆的路径(默认:`D:/Dev/repos/tasshack_dreame_vacuum_ref`) |
| `DREAME_MCP_PORT` | | 后端端口(默认:`10894`) |
| `DREAME_IP` / `DREAME_TOKEN` | | 本地 miio(令牌为空则为空令牌);与云的混合用于地图 |
## 开发和测试
- **Python** (仓库根目录):`uv run ruff check src tests`,`uv run pytest` (CI 设置 `PYTHONPATH=src`;在 Windows 上: `$env:PYTHONPATH = 'src'; uv run pytest tests`)。
- **MCP 工具 `dreame(operation=...)`** 返回 **Markdown** 以供 LLM 上下文使用。对于 **结构化字典** (与 REST 处理程序相同的形状),从 `dreame_mcp.portmanteau` 导入 `fetch_status_data`,`fetch_map_data` 和 `execute_control_data` (参见 `tests/test_map.py`)。
- **实时测试** (真实机器人 + 云):`DREAME_LIVE=1 uv run pytest tests --live` 或 `--live` 标志。
- **网页应用** (`webapp/`):`npm ci` 然后 `npm run biome:ci` 和 `npm run build`。
## 连接模式
此服务器根据您的 `.env` 配置支持三种操作模式:
| 模式 | 凭证 | 命令 | 激光雷达地图 | 备注 |
| :--- | :--- | :---: | :---: | :--- |
| **本地** | `DREAME_IP` | ⚡️ 本地 | ❌ 否 | 使用 **空令牌技巧** (`000...000`) |
| **云** | `USER` + `PWD` | ☁️ 云 | ✅ 是 | 受云延迟和 API 速率限制 |
| **混合** | **两者** | ⚡️ **本地** | ✅ **是** | **推荐**:快速控制 + 完整视觉地图 |
### “空令牌”技巧(绕过)
对于避免使用 DreameHome 云进行控制的用户,您不需要提取 32 个字符的机密令牌。通过仅提供 `DREAME_IP`,后端会自动使用 **空令牌** (`32 个零`)。这适用于许多桥接或规避准备好的固件(例如 Tasshack 协议使用的固件)。
## 快速开始
```powershell
git clone https://github.com/sandraschi/dreame-mcp
cd dreame-mcp
just
```
这将打开一个交互式仪表盘,显示所有可用的命令。运行 `just bootstrap` 以安装依赖,然后运行 `just serve` 或 `just dev` 以启动。
### 手动设置
如果您没有安装 `just`:
## 设置
1. **配置凭证**:复制 `.env.example` 到 `.env` 并填写您的详细信息。
```powershell
# 典型混合设置 (.env)
DREAME_IP=192.168.0.178
DREAME_USER=your@email.com
DREAME_PASSWORD=yourpassword
```
2. **启动系统**:
```powershell
# 同时启动后端 + 网页应用
.\webapp\start.ps1
```
## MCP 客户端配置
```json
{
"mcpServers": {
"dreame": {
"url": "http://localhost:10894/sse",
"transport": "sse"
}
}
}
```
## 地图(激光雷达 / 地板计划)
**地图数据不需要 miIO** 在此服务器上:它使用 DreameHome 云 + Tasshack 参考路径处的 `DREAME_REF_PATH`。本地 miIO 是可选的,通常在仅限 DreameHome 的固件上不可用。
- **REST:** `GET http://localhost:10894/api/v1/map` (与 MCP `dreame(operation='map')` 相同的 JSON)。
- **字段:** `image` (base64 编码图像,当解码/渲染有效时),`raw_b64` (始终在云端成功获取时;用于自定义解码器或 **robotics-mcp / yahboom-mcp**),可选 `map_data`,如果 PNG 路径失败,则可选 `render_error`。
- **仪表盘:** `http://localhost:10895` 上的 **地图** 页面在 `image` 存在时显示图像。
**下载路径(云):** 与 Home Assistant 的 Tasshack 集成相匹配 — 在可用时解析 **`OBJECT_NAME`** (属性 6.3),然后解析 **`get_interim_file_url` / `get_file`** (签名对象存储)。 **`get_device_file`** 仅作为后备;如果云无法在那一刻访问设备,则经常返回 `80001`。
**渲染路径:** 原始字节使用 **`DreameVacuumMapDecoder.decode_map`** 解码,并使用 **`DreameVacuumMapRenderer.render_map`** 绘制(不是 `DreameMapVacuumMapManager` 方法,它们仅协调 HA 状态)。引用克隆的 `custom_components.…` 包在加载时获得正确的 `__path__`,因此 `map.py` 可以干净地导入。
参见 **[docs/MAP_AND_ROBOTICS.md](docs/MAP_AND_ROBOTICS.md)** 以获取车队集成,JSON 合同和操作。
### 地图渲染(依赖)
渲染图像需要 Tasshack 堆栈:`py-mini-racer`,`numpy`,`Pillow`,`cryptography` 和 `uv.lock` 中的相关 pins。如果 `dreame(operation='map')` 有 `render_error` 但 `raw_b64` 已设置,则获取成功且仅解码/渲染失败;检查日志和依赖。
## 故障排除:`无法发现设备` / 状态 502
`GET /api/v1/health` 包括 **`local_miot`:** 仅在 UDP miio 与 `DREAME_IP` (端口 54321)成功握手后为 `true`。如果您在日志中看到 **`无法发现设备` `192.168.x.x`** 或 **`local_miot: false`**,则机器人未在 LAN 上回答标准的 miio 发现。典型原因: **仅限 DreameHome 的固件** (无或有限的 LAN miio),**错误的 IP**,**空令牌不被接受** (添加真正的 **`DREAME_TOKEN`**),或 **云登录失败** (修复 **`DREAME_USER` / `DREAME_PASSWORD` / `DREAME_COUNTRY`**,验证码,2FA),因此您获得 **`DREAME_DID`** 和地图。在 `.env` 中手动设置 **`DREAME_DID`**,当您从应用或云中知道它时。
## 文档
- [地图和机器人](docs/MAP_AND_ROBOTICS.md) HTTP/MCP 消费,miIO 与云,yahboom / 机器人集成
- [PRD](docs/PRD.md) 产品上下文,端口,**5 地图 API 合同**
- [令牌和 Home Assistant](docs/TOKEN_AND_HOME_ASSISTANT.md) 历史 miIO 参考(v0.2+ 使用云)
## 🛡️ 工业质量栈
该项目遵循 **SOTA 14.1** 工业标准,用于高保真代理编排:
- **Python(核心)**: [Ruff](https://astral.sh/ruff) 用于 linting 和格式化。对核心处理程序中的 `print` 语句采取零容忍政策 (`T201`)。
- **网页应用(UI)**: [Biome](https://biomejs.dev/) 用于毫秒级 linting。严格执行 `noConsoleLog`。
- **协议合规性**:强化 `stdout/stderr` 隔离,以确保抗崩溃的 JSON-RPC 通信。
- **自动化**: [Justfile](./justfile) 适用于所有车队操作的配方(`just lint`,`just fix`,`just dev`)。
- **安全**:通过 `bandit` 和 `safety` 进行自动审计。