This guide covers deploying Countly MCP Server using Docker in various environments.
- Quick Start
- Docker Hub
- Local Build
- Docker Compose
- Docker Swarm
- Kubernetes
- Configuration
- Health Checks
- Troubleshooting
The fastest way to get started:
# 1. Clone and navigate to the repository
git clone https://github.com/countly/countly-mcp-server.git
cd countly-mcp-server
# 2. Run the quick start script
./docker-start.shThe script will guide you through:
- Creating environment configuration
- Setting up authentication token
- Building and starting the server
docker pull countly/countly-mcp-server:latestdocker run -d \
--name countly-mcp-server \
-p 3000:3000 \
-e COUNTLY_SERVER_URL=https://your-countly-instance.com \
-e COUNTLY_AUTH_TOKEN=your-token-here \
countly/countly-mcp-server:latest# Build with tag
docker build -t countly-mcp-server:local .
# Build with specific version
docker build -t countly-mcp-server:1.0.0 .docker run -d \
--name countly-mcp-server \
-p 3000:3000 \
-e COUNTLY_SERVER_URL=https://your-countly-instance.com \
-e COUNTLY_AUTH_TOKEN=your-token-here \
countly-mcp-server:local-
Create token file:
echo "your-auth-token" > countly_token.txt chmod 600 countly_token.txt
-
Create/edit .env file:
cp .env.example .env # Edit COUNTLY_SERVER_URL in .env -
Start services:
docker-compose up -d
For development with hot reload:
# docker-compose.dev.yml
version: '3.8'
services:
countly-mcp-server:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./src:/app/src:ro
- ./package.json:/app/package.json:ro
environment:
- COUNTLY_SERVER_URL=${COUNTLY_SERVER_URL}
- COUNTLY_AUTH_TOKEN=${COUNTLY_AUTH_TOKEN}
ports:
- "3000:3000"
command: npm run devRun with:
docker-compose -f docker-compose.dev.yml upThe provided docker-compose.yml uses Docker secrets:
# Start with secrets
docker-compose up -d
# View logs
docker-compose logs -f
# Check status
docker-compose ps
# Stop
docker-compose downdocker swarm initecho "your-auth-token" | docker secret create countly_token -# Update docker-compose.yml to use external secret
# Then deploy
docker stack deploy -c docker-compose.yml countly# List services
docker service ls
# View logs
docker service logs countly_countly-mcp-server
# Scale service
docker service scale countly_countly-mcp-server=3
# Remove stack
docker stack rm countlykubectl create namespace countly-mcpkubectl create secret generic countly-token \
--from-literal=token=your-auth-token \
-n countly-mcp# kubernetes-deployment.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: countly-mcp-config
namespace: countly-mcp
data:
COUNTLY_SERVER_URL: "https://your-countly-instance.com"
COUNTLY_TIMEOUT: "30000"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: countly-mcp-server
namespace: countly-mcp
labels:
app: countly-mcp-server
spec:
replicas: 2
selector:
matchLabels:
app: countly-mcp-server
template:
metadata:
labels:
app: countly-mcp-server
spec:
containers:
- name: countly-mcp-server
image: countly/countly-mcp-server:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
env:
- name: COUNTLY_SERVER_URL
valueFrom:
configMapKeyRef:
name: countly-mcp-config
key: COUNTLY_SERVER_URL
- name: COUNTLY_TIMEOUT
valueFrom:
configMapKeyRef:
name: countly-mcp-config
key: COUNTLY_TIMEOUT
- name: COUNTLY_AUTH_TOKEN_FILE
value: "/run/secrets/countly_token"
volumeMounts:
- name: token
mountPath: /run/secrets
readOnly: true
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: token
secret:
secretName: countly-token
items:
- key: token
path: countly_token
---
apiVersion: v1
kind: Service
metadata:
name: countly-mcp-server
namespace: countly-mcp
spec:
selector:
app: countly-mcp-server
ports:
- name: http
port: 3000
targetPort: 3000
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: countly-mcp-server
namespace: countly-mcp
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: countly-mcp.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: countly-mcp-server
port:
number: 3000kubectl apply -f kubernetes-deployment.yml
# Check status
kubectl get pods -n countly-mcp
kubectl get svc -n countly-mcp
# View logs
kubectl logs -f deployment/countly-mcp-server -n countly-mcp| Variable | Description | Default |
|---|---|---|
COUNTLY_SERVER_URL |
Countly server URL | https://api.count.ly |
COUNTLY_AUTH_TOKEN |
Direct auth token | - |
COUNTLY_AUTH_TOKEN_FILE |
Path to token file | - |
COUNTLY_TIMEOUT |
Request timeout (ms) | 30000 |
For token files or custom configurations:
docker run -d \
-v $(pwd)/countly_token.txt:/run/secrets/countly_token:ro \
-v $(pwd)/custom.env:/app/.env:ro \
-e COUNTLY_AUTH_TOKEN_FILE=/run/secrets/countly_token \
countly-mcp-serverThe Docker image includes a health check:
# Check container health
docker ps
# Manual health check
curl http://localhost:3000/healthResponse:
{
"status": "healthy",
"timestamp": "2025-10-10T12:00:00.000Z"
}Override the default health check:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s# Check logs
docker logs countly-mcp-server
# Check if port is already in use
lsof -i :3000
# Run in foreground for debugging
docker run -it --rm \
-p 3000:3000 \
-e COUNTLY_SERVER_URL=https://your-instance.com \
-e COUNTLY_AUTH_TOKEN=your-token \
countly-mcp-server# Verify token
docker exec countly-mcp-server cat /run/secrets/countly_token
# Test token manually
curl "https://your-instance.com/o/apps/mine?auth_token=your-token"# Test from container
docker exec countly-mcp-server wget -O- http://localhost:3000/health
# Check network
docker network ls
docker network inspect bridge# Check resource usage
docker stats countly-mcp-server
# Increase memory limit
docker run -m 1g countly-mcp-server
# Or in docker-compose.yml
deploy:
resources:
limits:
memory: 1GRun with verbose logging:
docker run -it --rm \
-e NODE_ENV=development \
-e DEBUG=* \
countly-mcp-server- Use secrets for tokens in production
- Enable health checks for automatic recovery
- Set resource limits to prevent resource exhaustion
- Use read-only mounts for sensitive files
- Run as non-root user (built into image)
- Enable logging with proper rotation
- Use specific image tags instead of
latestin production - Implement backup strategies for configuration
- Monitor container health with external tools
- Keep images updated for security patches
# Secure token file
chmod 600 countly_token.txt
chown 1001:1001 countly_token.txt # Match container user# Create isolated network
docker network create --internal countly-network
docker run --network countly-network countly-mcp-serverdocker run --read-only \
--tmpfs /tmp \
countly-mcp-serverAdd metrics endpoint (extend the server):
# docker-compose.monitoring.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3001:3000"logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: countly-mcp-server- Issues: GitHub Issues
- Community: Countly Community
- Documentation: README.md