Skip to main content
Glama
kalmma

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