Files
ha-mcp-server/DOCKER.md
Felix Zösch 1761c3cdd3 Initial commit
2025-12-11 20:29:51 +01:00

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! 🐳🏠🤖