Initial commit
This commit is contained in:
639
DOCKER.md
Normal file
639
DOCKER.md
Normal file
@@ -0,0 +1,639 @@
|
||||
# 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! 🐳🏠🤖
|
||||
Reference in New Issue
Block a user