📖 Installation Guide — quick start, manual setup, and troubleshooting
FastMCP 3.2.0 MCP server and webapp for the Dreame D20 Pro Plus robot vacuum. Uses the DreameHome cloud API; local miio is optional (hybrid mode: see below). Protocol layer extracted from Tasshack/dreame-vacuum.
- MCP tools:
dreame(operation=...)status, map, start_clean, stop, pause, go_home, find_robot, battery - MCP tools:
dreame_help(category),dreame_agentic_workflow(goal)with SEP-1577 sampling - Prompts:
dreame_quick_start,dreame_diagnostics - Skills:
skills/dreame-operator.md - REST API: GET /api/v1/health, /api/v1/status, /api/v1/map; POST /api/v1/control/{cmd}
- Webapp: Dashboard, LIDAR Map, Status, Controls, Settings, Help, MCP Tools
- Backend: 10894 (REST + MCP SSE)
- Dashboard: 10895 (Vite dev server)
-
Clone this repo and enter it:
git clone https://github.com/sandraschi/dreame-mcp.git Set-Location dreame-mcp
-
Clone the Tasshack dreame-vacuum reference repo (protocol + map layer). Default ref path is
D:/Dev/repos/tasshack_dreame_vacuum_ref:Set-Location D:\Dev\repos git clone https://github.com/Tasshack/dreame-vacuum tasshack_dreame_vacuum_ref Set-Location dreame-mcp
(Adjust paths if your dev folder is not
D:\Dev\repos; setDREAME_REF_PATHaccordingly.) -
Install Python deps from the dreame-mcp repository root:
uv sync
| Variable | Required | Description |
|---|---|---|
DREAME_USER |
DreameHome email or phone | |
DREAME_PASSWORD |
DreameHome password | |
DREAME_COUNTRY |
Cloud region, default eu |
|
DREAME_DID |
Device ID, auto-discovered if single device | |
DREAME_AUTH_KEY |
Refresh token from previous login (speeds up startup) | |
DREAME_REF_PATH |
Path to tasshack ref clone (default: D:/Dev/repos/tasshack_dreame_vacuum_ref) |
|
DREAME_MCP_PORT |
Backend port (default: 10894) |
|
DREAME_IP / DREAME_TOKEN |
Local miio (null token if token empty); hybrid with cloud for maps |
- Python (repo root):
uv run ruff check src tests,uv run pytest(CI setsPYTHONPATH=src; on Windows:$env:PYTHONPATH = 'src'; uv run pytest tests). - MCP tool
dreame(operation=...)returns Markdown for LLM context. For structured dicts (same shapes as the REST handlers), importfetch_status_data,fetch_map_data, andexecute_control_datafromdreame_mcp.portmanteau(seetests/test_map.py). - Live tests (real robot + cloud):
DREAME_LIVE=1 uv run pytest tests --liveor--liveflag. - Webapp (
webapp/):npm cithennpm run biome:ciandnpm run build.
This server supports three operational modes depending on your .env configuration:
| Mode | Credentials | Commands | Lidar Map | Notes |
|---|---|---|---|---|
| Local | DREAME_IP |
⚡ Local | ❌ No | Uses the Null Token trick (000...000) |
| Cloud | USER + PWD |
☁️ Cloud | ✅ Yes | Subject to cloud latency and API rate limits |
| Hybrid | Both | ⚡ Local | ✅ Yes | Recommended: Fast control + Full visual map |
For users avoiding the DreameHome cloud for controls, you do not need to extract a secret 32-character token. By providing only the DREAME_IP, the backend automatically uses a Null Token (32 zeros). This works on many bridged or circumvention-ready firmwares (like those used with the Tasshack protocol).
git clone https://github.com/sandraschi/dreame-mcp
cd dreame-mcp
justThis opens an interactive dashboard showing all available commands. Run just bootstrap to install dependencies, then just serve or just dev to start.
If you don't have just installed:
-
Configure credentials: Copy
.env.exampleto.envand fill in your details.# Typical Hybrid Setup (.env) DREAME_IP=192.168.0.178 DREAME_USER=your@email.com DREAME_PASSWORD=yourpassword
-
Start the system:
# Start backend + webapp together .\webapp\start.ps1
{
"mcpServers": {
"dreame": {
"url": "http://localhost:10894/sse",
"transport": "sse"
}
}
}Map data does not require miIO on this server: it uses DreameHome cloud + the Tasshack ref at DREAME_REF_PATH. Local miIO is optional and often unavailable on DreameHome-only firmware.
- REST:
GET http://localhost:10894/api/v1/map(same JSON as MCPdreame(operation='map')). - Fields:
image(base64-encoded image when decode/render works),raw_b64(always on successful cloud fetch; use for custom decoders or robotics-mcp / yahboom-mcp), optionalmap_data, optionalrender_errorif the PNG path failed. - Dashboard: Map page at
http://localhost:10895shows the image whenimageis present.
Download path (cloud): matches Home Assistant’s Tasshack integration — resolve OBJECT_NAME (property 6.3) when available, then get_interim_file_url / get_file (signed object storage). get_device_file is only a fallback; it often returns 80001 if the cloud cannot reach the device at that moment.
Render path: raw bytes are decoded with DreameVacuumMapDecoder.decode_map and drawn with DreameVacuumMapRenderer.render_map (not DreameMapVacuumMapManager methods, which only orchestrate HA state). The ref clone’s custom_components.… packages are given proper __path__ at load time so map.py imports cleanly.
See docs/MAP_AND_ROBOTICS.md for fleet integration, the JSON contract, and operations.
The rendered image requires the Tasshack stack: py-mini-racer, numpy, Pillow, cryptography, and related pins from uv.lock. If dreame(operation='map') has render_error but raw_b64 is set, the fetch worked and only decode/render failed; check logs and dependencies.
GET /api/v1/health includes local_miot: true only after a successful UDP miio handshake to DREAME_IP (port 54321). If you see Unable to discover the device 192.168.x.x in logs or local_miot: false, the robot did not answer the standard miio discovery on the LAN. Typical causes: DreameHome-only firmware (no or limited LAN miio), wrong IP, null token not accepted (add a real DREAME_TOKEN), or cloud login failed (fix DREAME_USER / DREAME_PASSWORD / DREAME_COUNTRY, captcha, 2FA) so you get DREAME_DID and maps. Set DREAME_DID manually in .env when you know it from the app or cloud.
- Map and fleet robotics HTTP/MCP consumption, miIO vs cloud, yahboom / robotics integration
- PRD product context, ports, 5 Map API contract
- Token and Home Assistant historical miIO reference (v0.2+ uses cloud)
This project adheres to SOTA 14.1 industrial standards for high-fidelity agentic orchestration:
- Python (Core): Ruff for linting and formatting. Zero-tolerance for
printstatements in core handlers (T201). - Webapp (UI): Biome for sub-millisecond linting. Strict
noConsoleLogenforcement. - Protocol Compliance: Hardened
stdout/stderrisolation to ensure crash-resistant JSON-RPC communication. - Automation: Justfile recipes for all fleet operations (
just lint,just fix,just dev). - Security: Automated audits via
banditandsafety.