640 lines
13 KiB
Markdown
640 lines
13 KiB
Markdown
# Docker Deployment Guide for Home Assistant MCP Server
|
|
|
|
This guide explains how to run the Home Assistant MCP Server in Docker, similar to the MCP Toolkit in Docker Desktop.
|
|
|
|
## Table of Contents
|
|
|
|
- [Quick Start](#quick-start)
|
|
- [Docker Compose Setup](#docker-compose-setup)
|
|
- [Configuration](#configuration)
|
|
- [Using with Docker Desktop MCP Support](#using-with-docker-desktop-mcp-support)
|
|
- [Using with Claude Desktop](#using-with-claude-desktop)
|
|
- [Networking Considerations](#networking-considerations)
|
|
- [Building the Image](#building-the-image)
|
|
- [Troubleshooting](#troubleshooting)
|
|
- [Advanced Configuration](#advanced-configuration)
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- Docker installed (Docker Desktop 4.34+ for MCP support)
|
|
- Home Assistant instance running
|
|
- Home Assistant long-lived access token
|
|
|
|
### 1. Create Environment File
|
|
|
|
Create a `.env` file in the project root:
|
|
|
|
```bash
|
|
# Copy the example
|
|
cp .env.example .env
|
|
|
|
# Edit with your details
|
|
nano .env
|
|
```
|
|
|
|
Add your Home Assistant details:
|
|
|
|
```env
|
|
HA_BASE_URL=http://homeassistant.local:8123
|
|
HA_ACCESS_TOKEN=your_long_lived_access_token_here
|
|
```
|
|
|
|
### 2. Build and Run
|
|
|
|
```bash
|
|
# Build and start the container
|
|
docker-compose up -d
|
|
|
|
# Check logs
|
|
docker-compose logs -f
|
|
|
|
# Stop the container
|
|
docker-compose down
|
|
```
|
|
|
|
---
|
|
|
|
## Docker Compose Setup
|
|
|
|
The provided `docker-compose.yml` includes:
|
|
|
|
- **Multi-stage build** for optimized image size
|
|
- **Host networking** for easy Home Assistant access
|
|
- **Security hardening** (read-only filesystem, non-root user)
|
|
- **Resource limits** (256MB RAM, 0.5 CPU)
|
|
- **Health checks** for container monitoring
|
|
- **Automatic restarts** unless manually stopped
|
|
|
|
### Basic Usage
|
|
|
|
```bash
|
|
# Start in background
|
|
docker-compose up -d
|
|
|
|
# View logs
|
|
docker-compose logs -f ha-mcp-server
|
|
|
|
# Restart
|
|
docker-compose restart
|
|
|
|
# Stop
|
|
docker-compose down
|
|
|
|
# Rebuild after code changes
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
Configure via `.env` file or docker-compose environment section:
|
|
|
|
| Variable | Required | Default | Description |
|
|
|----------|----------|---------|-------------|
|
|
| `HA_BASE_URL` | Yes | - | Home Assistant URL (e.g., `http://homeassistant.local:8123`) |
|
|
| `HA_ACCESS_TOKEN` | Yes | - | Long-lived access token from HA |
|
|
| `NODE_ENV` | No | `production` | Node environment |
|
|
|
|
### Getting a Home Assistant Access Token
|
|
|
|
1. Log into Home Assistant
|
|
2. Click your profile (bottom left)
|
|
3. Scroll to "Long-Lived Access Tokens"
|
|
4. Click "Create Token"
|
|
5. Give it a name (e.g., "MCP Server")
|
|
6. Copy the token immediately (shown only once)
|
|
|
|
---
|
|
|
|
## Using with Docker Desktop MCP Support
|
|
|
|
Docker Desktop 4.34+ includes native MCP support in the AI tools section.
|
|
|
|
### Setup
|
|
|
|
1. **Build the image:**
|
|
```bash
|
|
docker-compose build
|
|
```
|
|
|
|
2. **Tag for Docker Desktop:**
|
|
```bash
|
|
docker tag ha-mcp-server:latest ha-mcp-server:latest
|
|
```
|
|
|
|
3. **Configure in Docker Desktop:**
|
|
|
|
Open Docker Desktop settings and add to MCP servers:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"home-assistant": {
|
|
"command": "docker",
|
|
"args": [
|
|
"run",
|
|
"--rm",
|
|
"-i",
|
|
"--network=host",
|
|
"-e", "HA_BASE_URL=http://homeassistant.local:8123",
|
|
"-e", "HA_ACCESS_TOKEN=your_token_here",
|
|
"ha-mcp-server:latest"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
4. **Restart Docker Desktop** to load the MCP server
|
|
|
|
### Verification
|
|
|
|
The MCP server should appear in Docker Desktop's AI tools section. You can then use it with any integrated AI assistant.
|
|
|
|
---
|
|
|
|
## Using with Claude Desktop
|
|
|
|
### Method 1: Using Docker Directly
|
|
|
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"home-assistant": {
|
|
"command": "docker",
|
|
"args": [
|
|
"run",
|
|
"--rm",
|
|
"-i",
|
|
"--network=host",
|
|
"-e", "HA_BASE_URL=http://homeassistant.local:8123",
|
|
"-e", "HA_ACCESS_TOKEN=your_long_lived_access_token",
|
|
"ha-mcp-server:latest"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Method 2: Using Docker Compose
|
|
|
|
Create a wrapper script `run-mcp.sh`:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
docker-compose run --rm ha-mcp-server
|
|
```
|
|
|
|
Make it executable:
|
|
```bash
|
|
chmod +x run-mcp.sh
|
|
```
|
|
|
|
Configure Claude Desktop:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"home-assistant": {
|
|
"command": "/Users/felix/Nextcloud/AI/projects/ha-mcp-server/run-mcp.sh"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Restart Claude Desktop
|
|
|
|
After configuration changes, fully quit and restart Claude Desktop.
|
|
|
|
---
|
|
|
|
## Networking Considerations
|
|
|
|
### Host Network Mode (Default)
|
|
|
|
The default configuration uses `network_mode: host`, which:
|
|
|
|
- ✅ Simplest setup
|
|
- ✅ Direct access to Home Assistant on local network
|
|
- ✅ No port mapping needed
|
|
- ⚠️ Linux-only feature (works differently on macOS/Windows)
|
|
|
|
### Bridge Network Mode
|
|
|
|
If your Home Assistant is also in Docker, use bridge networking:
|
|
|
|
1. **Update docker-compose.yml:**
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
ha-mcp-server:
|
|
build: .
|
|
environment:
|
|
- HA_BASE_URL=http://homeassistant:8123
|
|
- HA_ACCESS_TOKEN=${HA_ACCESS_TOKEN}
|
|
networks:
|
|
- ha-network
|
|
# Remove network_mode: host
|
|
|
|
networks:
|
|
ha-network:
|
|
external: true # If HA network exists
|
|
# Or create new network:
|
|
# driver: bridge
|
|
```
|
|
|
|
2. **Connect to Home Assistant network:**
|
|
|
|
```bash
|
|
# Find HA network
|
|
docker network ls
|
|
|
|
# Update docker-compose.yml with correct network name
|
|
# Then start
|
|
docker-compose up -d
|
|
```
|
|
|
|
### macOS/Windows Considerations
|
|
|
|
On macOS and Windows, Docker runs in a VM:
|
|
|
|
- `host` networking works differently
|
|
- Use explicit URLs like `http://host.docker.internal:8123`
|
|
- Or use bridge networking with proper network setup
|
|
|
|
---
|
|
|
|
## Building the Image
|
|
|
|
### Build Locally
|
|
|
|
```bash
|
|
# Using docker-compose
|
|
docker-compose build
|
|
|
|
# Using docker directly
|
|
docker build -t ha-mcp-server:latest .
|
|
|
|
# Build with no cache
|
|
docker-compose build --no-cache
|
|
```
|
|
|
|
### Build Arguments
|
|
|
|
The Dockerfile supports Node.js version customization:
|
|
|
|
```bash
|
|
docker build \
|
|
--build-arg NODE_VERSION=20 \
|
|
-t ha-mcp-server:latest \
|
|
.
|
|
```
|
|
|
|
### Multi-Architecture Builds
|
|
|
|
For running on different platforms (e.g., Raspberry Pi):
|
|
|
|
```bash
|
|
# Enable buildx
|
|
docker buildx create --use
|
|
|
|
# Build for multiple architectures
|
|
docker buildx build \
|
|
--platform linux/amd64,linux/arm64,linux/arm/v7 \
|
|
-t ha-mcp-server:latest \
|
|
--push \
|
|
.
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Container Won't Start
|
|
|
|
**Check logs:**
|
|
```bash
|
|
docker-compose logs ha-mcp-server
|
|
```
|
|
|
|
**Common issues:**
|
|
|
|
1. **Missing environment variables**
|
|
- Ensure `.env` file exists
|
|
- Check variable names match exactly
|
|
|
|
2. **Cannot reach Home Assistant**
|
|
- Verify `HA_BASE_URL` is correct
|
|
- Check network connectivity: `docker exec ha-mcp-server ping homeassistant.local`
|
|
- Try IP address instead of hostname
|
|
|
|
3. **Permission denied**
|
|
- Container runs as non-root user
|
|
- Check file permissions if mounting volumes
|
|
|
|
### Connection Errors
|
|
|
|
**Test Home Assistant connection:**
|
|
|
|
```bash
|
|
# Enter container
|
|
docker exec -it ha-mcp-server sh
|
|
|
|
# Test connection (requires curl installation for this test)
|
|
# Note: Base image is alpine, so use wget instead
|
|
wget -O- http://homeassistant.local:8123/api/
|
|
```
|
|
|
|
**Check environment variables:**
|
|
|
|
```bash
|
|
docker exec ha-mcp-server env | grep HA_
|
|
```
|
|
|
|
### MCP Communication Issues
|
|
|
|
**Verify stdio communication:**
|
|
|
|
The MCP server communicates via stdio (stdin/stdout), not network ports.
|
|
|
|
```bash
|
|
# Test directly
|
|
echo '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' | \
|
|
docker run -i --rm \
|
|
-e HA_BASE_URL=http://homeassistant.local:8123 \
|
|
-e HA_ACCESS_TOKEN=your_token \
|
|
ha-mcp-server:latest
|
|
```
|
|
|
|
### Performance Issues
|
|
|
|
**Check resource usage:**
|
|
|
|
```bash
|
|
docker stats ha-mcp-server
|
|
```
|
|
|
|
**Adjust resource limits** in docker-compose.yml:
|
|
|
|
```yaml
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0' # Increase CPU limit
|
|
memory: 512M # Increase memory limit
|
|
```
|
|
|
|
### Container Restarting Every 30 Seconds
|
|
|
|
**Symptom:** You see repeated connection messages in the logs:
|
|
```
|
|
Home Assistant MCP Server running on stdio
|
|
Successfully connected to Home Assistant
|
|
Home Assistant MCP Server running on stdio
|
|
Successfully connected to Home Assistant
|
|
...
|
|
```
|
|
|
|
**Cause:** MCP servers communicate via stdio (stdin/stdout). Docker healthchecks interfere with stdio, causing the healthcheck to fail and Docker to restart the container.
|
|
|
|
**Solution:** The healthcheck is now disabled by default in docker-compose.yml:
|
|
|
|
```yaml
|
|
# In docker-compose.yml
|
|
healthcheck:
|
|
disable: true
|
|
|
|
# And restart policy is set to "no" since MCP servers run on-demand
|
|
restart: "no"
|
|
```
|
|
|
|
If you have an older version, update your docker-compose.yml with these settings and rebuild:
|
|
|
|
```bash
|
|
docker-compose down
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
---
|
|
|
|
## Advanced Configuration
|
|
|
|
### Running Multiple Instances
|
|
|
|
Run multiple MCP servers for different Home Assistant instances:
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
ha-mcp-server-home:
|
|
build: .
|
|
container_name: ha-mcp-home
|
|
environment:
|
|
- HA_BASE_URL=http://home.local:8123
|
|
- HA_ACCESS_TOKEN=${HA_TOKEN_HOME}
|
|
network_mode: host
|
|
|
|
ha-mcp-server-cabin:
|
|
build: .
|
|
container_name: ha-mcp-cabin
|
|
environment:
|
|
- HA_BASE_URL=http://cabin.local:8123
|
|
- HA_ACCESS_TOKEN=${HA_TOKEN_CABIN}
|
|
network_mode: host
|
|
```
|
|
|
|
### Custom Logging
|
|
|
|
**Change log format:**
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "5"
|
|
labels: "ha-mcp-server"
|
|
```
|
|
|
|
**Use external logging:**
|
|
|
|
```yaml
|
|
logging:
|
|
driver: "syslog"
|
|
options:
|
|
syslog-address: "tcp://192.168.1.100:514"
|
|
```
|
|
|
|
### Monitoring with Prometheus
|
|
|
|
Add labels for monitoring:
|
|
|
|
```yaml
|
|
labels:
|
|
- "prometheus.scrape=true"
|
|
- "prometheus.port=9090"
|
|
```
|
|
|
|
### Read-Only Filesystem
|
|
|
|
The container uses a read-only root filesystem for security:
|
|
|
|
```yaml
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp # Allows temp file writes
|
|
```
|
|
|
|
To allow writes to specific locations:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ./data:/app/data:rw
|
|
read_only: true
|
|
```
|
|
|
|
### Custom Node.js Options
|
|
|
|
Pass Node.js flags:
|
|
|
|
```yaml
|
|
command: ["node", "--max-old-space-size=128", "build/index.js"]
|
|
```
|
|
|
|
---
|
|
|
|
## Docker Image Details
|
|
|
|
### Image Layers
|
|
|
|
1. **Base:** `node:20-alpine` (~40MB)
|
|
2. **Dependencies:** Production npm packages
|
|
3. **Application:** Compiled TypeScript code
|
|
4. **Total:** ~100-150MB
|
|
|
|
### Security Features
|
|
|
|
- ✅ Non-root user (nodejs:nodejs)
|
|
- ✅ Read-only root filesystem
|
|
- ✅ No new privileges
|
|
- ✅ Minimal base image (Alpine)
|
|
- ✅ Multi-stage build (no dev dependencies)
|
|
- ✅ No shell access required
|
|
|
|
### Optimization
|
|
|
|
- Multi-stage build reduces image size
|
|
- Alpine Linux base for minimal footprint
|
|
- Production dependencies only in final image
|
|
- No development tools included
|
|
|
|
---
|
|
|
|
## Integration Examples
|
|
|
|
### Docker Desktop AI Assistant
|
|
|
|
Once configured in Docker Desktop, use natural language:
|
|
|
|
```
|
|
You: "Turn on the living room lights"
|
|
AI: Uses home-assistant MCP tool to call service
|
|
→ Lights turn on
|
|
|
|
You: "What's the temperature in the bedroom?"
|
|
AI: Uses home-assistant resource to get state
|
|
→ Returns temperature
|
|
```
|
|
|
|
### CI/CD Pipeline
|
|
|
|
```yaml
|
|
# .github/workflows/docker.yml
|
|
name: Build and Push
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- name: Build Docker image
|
|
run: docker build -t ha-mcp-server:latest .
|
|
|
|
- name: Test
|
|
run: |
|
|
docker run --rm \
|
|
-e HA_BASE_URL=http://test:8123 \
|
|
-e HA_ACCESS_TOKEN=test \
|
|
ha-mcp-server:latest \
|
|
node -e "console.log('OK')"
|
|
```
|
|
|
|
---
|
|
|
|
## Comparison with Direct Installation
|
|
|
|
| Feature | Docker | Direct |
|
|
|---------|--------|--------|
|
|
| Setup Complexity | Medium | Easy |
|
|
| Isolation | ✅ Excellent | ⚠️ None |
|
|
| Resource Usage | ~150MB | ~100MB |
|
|
| Updates | Rebuild image | `npm update` |
|
|
| Portability | ✅ Excellent | ⚠️ Platform dependent |
|
|
| Debugging | Harder | Easier |
|
|
| Security | ✅ Sandboxed | ⚠️ Full system access |
|
|
| MCP Desktop Integration | ✅ Native | ✅ Native |
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. ✅ **Built and configured** the Docker container
|
|
2. ✅ **Set up environment** variables
|
|
3. ✅ **Started the service** with docker-compose
|
|
4. → **Configure Claude Desktop** or Docker Desktop to use it
|
|
5. → **Test with commands** like "turn on lights"
|
|
6. → **Monitor logs** for issues
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- **Docker Documentation:** https://docs.docker.com/
|
|
- **Docker Compose Reference:** https://docs.docker.com/compose/
|
|
- **MCP Specification:** https://modelcontextprotocol.io/
|
|
- **Home Assistant API:** https://developers.home-assistant.io/docs/api/rest/
|
|
- **Docker Desktop MCP:** https://docs.docker.com/desktop/mcp/
|
|
|
|
---
|
|
|
|
## Getting Help
|
|
|
|
If you encounter issues:
|
|
|
|
1. Check logs: `docker-compose logs -f`
|
|
2. Verify environment: `docker exec ha-mcp-server env`
|
|
3. Test HA connection from container
|
|
4. Review this documentation
|
|
5. Check Home Assistant logs for API errors
|
|
|
|
The MCP server is now fully containerized and ready for use with Docker Desktop's AI tools or Claude Desktop! 🐳🏠🤖
|