Buva EcoStream MCP Server
by kalmma
README.md
# Buva EcoStream MCP Server
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that connects Claude to a **Buva EcoStream WTW ventilation unit** over your local network.
Once installed, you can control your ventilation and read air quality data directly in conversation with Claude — no app needed.
> **Note:** The EcoStream does not use a native WebSocket. It streams JSON state updates over a persistent HTTP long-poll connection. This server handles that automatically and falls back to polling if needed.
---
## Features
- Read live sensor data: CO₂, TVOC, humidity, temperatures (ETA/EHA/ODA), fan RPM, bypass position, heat recovery efficiency, WiFi info
- Control fan presets (low / mid / high)
- Set a custom airflow in m³/h with optional duration
- Start/stop boost mode
- Open/close bypass valve
- Enable/disable schedule and summer comfort mode
- Reset filter timer
- Built-in endpoint discovery tool for diagnosing your specific device firmware
---
## Requirements
- Python 3.11+
- Claude Desktop (or any MCP-compatible host)
- Buva EcoStream on your local network with a known IP address
---
## Installation
**1. Clone or download this repository**
```bash
git clone https://github.com/YOUR_USERNAME/ecostream-mcp.git
cd ecostream-mcp
```
**2. Install dependencies**
```bash
pip3 install -r requirements.txt
```
**3. Configure Claude Desktop**
Open your Claude Desktop config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
Add the following (adjust the path and IP address):
```json
{
"mcpServers": {
"ecostream": {
"command": "python3",
"args": ["/absolute/path/to/ecostream-mcp/server.py"],
"env": {
"ECOSTREAM_HOST": "192.168.X.X",
"ECOSTREAM_PORT": "80",
"ECOSTREAM_STREAM": "/stream",
"ECOSTREAM_CONFIG": "/config"
}
}
}
}
```
**4. Restart Claude Desktop**
The EcoStream tools will now appear automatically in Claude.
---
## Configuration
All settings are passed as environment variables:
| Variable | Default | Description |
|---|---|---|
| `ECOSTREAM_HOST` | `192.168.1.100` | IP address of your EcoStream |
| `ECOSTREAM_PORT` | `80` | HTTP port |
| `ECOSTREAM_STREAM` | `/stream` | Endpoint for reading state |
| `ECOSTREAM_CONFIG` | `/config` | Endpoint for sending commands |
If you're unsure which endpoints your firmware uses, run the `discover_endpoints` tool in Claude after installation — it probes all known paths and shows which ones respond.
---
## Available Tools
| Tool | Description |
|---|---|
| `get_status` | Returns all current sensor values: CO₂, temperatures, airflow, fan speed, bypass, modes, WiFi |
| `set_preset` | Set ventilation to `low`, `mid`, or `high` preset |
| `set_airflow` | Set a custom airflow in m³/h with an optional duration in minutes |
| `set_boost` | Turn boost mode on or off (5, 10, 15, 30, or 60 minutes) |
| `set_bypass` | Open or close the bypass valve |
| `set_schedule` | Enable or disable the built-in ventilation schedule |
| `set_summer_comfort` | Enable or disable summer comfort mode (auto-bypass on warm days) |
| `reset_filter` | Reset the filter replacement timer after changing the filter |
| `discover_endpoints` | Scan the device for working HTTP endpoints — useful for initial setup or debugging |
---
## Example prompts
Once connected, you can ask Claude things like:
- *"What's the CO₂ level right now?"*
- *"Turn on boost mode for 15 minutes, it's stuffy in here."*
- *"Set ventilation to low for the night."*
- *"Is the bypass open? What's the outside temperature?"*
- *"Reset the filter timer, I just replaced the filter."*
- *"Scan which endpoints the EcoStream responds to."*
---
## How it works
The EcoStream device exposes a local HTTP server. When polled, it returns JSON containing the full device state (sensor readings, active modes, setpoints). Configuration changes are sent as HTTP POST requests with a JSON body.
This server implements the MCP stdio transport, meaning Claude Desktop launches it as a subprocess and communicates over stdin/stdout.
State is fetched on demand when you call `get_status`. The server tries the configured streaming endpoint first, then falls back to `/Status` and `/api/status` if that fails.
For sending commands, the server tries the EcoStream JSON format (`{"config": {...}}`) and, if that doesn't respond, falls back to the older Q-Stream `{"Value": "TIMER ..."}` format.
---
## Troubleshooting
**"Cannot reach EcoStream"**
- Confirm the device IP with your router's DHCP table
- Make sure your computer and the EcoStream are on the same network/VLAN
- Try `curl http://192.168.x.x/Status` in a terminal to test basic connectivity
**Tools appear but return errors**
- Run `discover_endpoints` in Claude to see which paths actually respond
- Adjust `ECOSTREAM_STREAM` and `ECOSTREAM_CONFIG` in your config accordingly
**Sensor values are missing or labeled "unknown"**
- Your firmware may use different JSON field names
- Run `get_status` and look at the "Overige velden" section — those are unrecognised fields from the device
- Open an issue with the raw output and I'll add support
---
## Protocol notes
The reverse-engineered protocol is based on the community Home Assistant integration by [@epodegrid](https://github.com/epodegrid/ecostream_homeassistant_integration) and [@Recognition2](https://github.com/Recognition2/buva-ecostream-hacs). This MCP server is an independent implementation and is not affiliated with BUVA.
Supported devices:
| Device | Status |
|---|---|
| BUVA EcoStream | ✅ Supported |
| BUVA EcoStream+ | ✅ Supported |
| BUVA Q-Stream 2.0 | ⚠️ Partial (different protocol, timer commands only) |
| Other BUVA models | ❌ Not supported |
---
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues