Skip to main content
Glama
sandraschi

Dreame D20 Pro Plus MCP Server

by sandraschi

Dreame D20 Pro Plus MCP Server

📖 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.

Features

  • MCP tools: dreame_tool(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, dreame_shutdown(), show_dreame_status_app() (Prefab card)

  • Prompts: dreame_quick_start, dreame_diagnostics

  • Skills: skill://dreame-operator/SKILL.md (also GET /api/skills)

  • Resources: dreame://status

  • REST API: GET /api/v1/health, /api/v1/status, /api/v1/map (+ png/pgm/yaml), /api/v1/diagnostics; POST /api/v1/control/{cmd}, /api/v1/shutdown

  • Webapp: Dashboard, LIDAR Map, Status, Controls, Settings, Help, MCP Tools, Logs

Related MCP server: Ecovacs MCP Server

Ports

  • Backend: 10894 (REST + MCP SSE)

  • Dashboard: 10895 (Vite dev server)

Prerequisites

  1. Clone this repo and enter it:

    git clone https://github.com/sandraschi/dreame-mcp.git
    Set-Location dreame-mcp
  2. 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; set DREAME_REF_PATH accordingly.)

  3. Install Python deps from the dreame-mcp repository root:

    uv sync

Environment variables

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

Development and tests

  • Python (repo root): uv run ruff check src tests, uv run pytest (CI sets PYTHONPATH=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), import fetch_status_data, fetch_map_data, and execute_control_data from dreame_mcp.portmanteau (see tests/test_map.py).

  • Live tests (real robot + cloud): DREAME_LIVE=1 uv run pytest tests --live or --live flag.

  • Webapp (webapp/): npm ci then npm run biome:ci and npm run build.

Connection Modes

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

The "Null Token" Trick (Bypass)

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).

Quick Start

git clone https://github.com/sandraschi/dreame-mcp
cd dreame-mcp
just

This opens an interactive dashboard showing all available commands. Run just bootstrap to install dependencies, then just serve to start the full stack, or just test for the mocked suite.

Manual Setup

If you don't have just installed:

Setup

  1. Configure credentials: Copy .env.example to .env and fill in your details.

    # Typical Hybrid Setup (.env)
    DREAME_IP=192.168.0.178
    DREAME_USER=your@email.com
    DREAME_PASSWORD=yourpassword
  2. Start the system:

    # Start backend + webapp together
    .\webapp\start.ps1

MCP client config

{
  "mcpServers": {
    "dreame": {
      "url": "http://localhost:10894/sse",
      "transport": "sse"
    }
  }
}

Map (LIDAR / floor plan)

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 MCP dreame_tool(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), optional map_data, optional render_error if the PNG path failed.

  • Dashboard: Map page at http://localhost:10895 shows the image when image is 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.

Map rendering (dependencies)

The rendered image requires the Tasshack stack: py-mini-racer, numpy, Pillow, cryptography, and related pins from uv.lock. If dreame_tool(operation='map') has render_error but raw_b64 is set, the fetch worked and only decode/render failed; check logs and dependencies.

Troubleshooting: Unable to discover the device / status 502

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.

Docs

🛡️ Industrial Quality Stack

This project adheres to SOTA industrial standards for high-fidelity agentic orchestration:

  • Python (Core): Ruff for linting and formatting. Zero-tolerance for print statements in core handlers (T20).

  • Python (Types): Pyright static type checking (five-gate CI).

  • Webapp (UI): Biome for sub-millisecond linting. Strict noConsoleLog enforcement.

  • Protocol Compliance: Hardened stdout/stderr isolation to ensure crash-resistant JSON-RPC communication.

  • Automation: Justfile recipes for all fleet operations (just lint, just fix, just serve).

  • Security: Automated audits via bandit and safety.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server wrapping the Tesla Fleet API and TeslaMate API

  • MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sandraschi/dreame-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server