Docker Setup
Overview
The project includes Docker support for running Elasticsearch and the MCP server. This is the recommended way to run the infrastructure.
Quick Start
Download the docker-compose.yml and start all services:
# Create a directory and download docker-compose.yml
mkdir mail-mcp && cd mail-mcp
curl -O https://raw.githubusercontent.com/support-and-care-labs/mail-mcp/main/docker-compose.yml
# Create data directory
mkdir -p data
# Start all services
docker compose up -d
# Wait for services to be healthy
docker compose ps
# Check MCP server health
curl http://localhost:58080/health
|
The docker-compose.yml is also available for download: docker-compose.yml |
Prerequisites
- Docker Desktop
-
Version with Docker Compose V2 integrated
|
This project uses |
Services
Elasticsearch
Storage backend for indexed email data.
- Image
-
docker.elastic.co/elasticsearch/elasticsearch:8.11.0 - Ports
-
9200 (HTTP API), 9300 (transport)
- Configuration
-
Single-node cluster, security disabled for local development
Kibana (Optional)
Web UI for exploring and visualizing Elasticsearch data.
Kibana is not started by default - use the analysis profile to start it on demand.
- Image
-
docker.elastic.co/kibana/kibana:8.11.0 - Ports
-
5601 (HTTP)
- Access
- Profile
-
analysis(start withdocker compose --profile analysis up -d kibana) - Features
-
-
Discover - Search and filter documents
-
Visualizations - Create charts and graphs
-
Dashboards - Combined visualizations
-
Dev Tools - Run Elasticsearch queries directly
-
mail-mcp
MCP server application providing Streamable HTTP transport.
- Image
-
ghcr.io/support-and-care-labs/mail-mcp:latest - Platforms
-
linux/amd64, linux/arm64
- Ports
-
58080 (Streamable HTTP)
- Access
-
http://localhost:58080/mcp (for MCP clients)
- Health check
Docker Compose File
The complete docker-compose.yml for running all services:
#
# Copyright 2025 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Docker Compose configuration for mail-mcp
#
# Quick Start:
# mkdir -p data && docker compose up -d
#
# For development (build from source):
# docker compose build && docker compose up -d
services:
# Elasticsearch for storing and searching email data
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
container_name: mail-mcp-elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- cluster.name=mail-mcp-cluster
- node.name=mail-mcp-node
ports:
- "59200:9200"
- "59300:9300"
volumes:
- es-data:/usr/share/elasticsearch/data
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
interval: 10s
timeout: 5s
retries: 5
networks:
- mail-mcp-network
restart: unless-stopped
# Kibana for data visualization and exploration (optional, start manually)
# Start with: docker compose --profile analysis up -d kibana
kibana:
profiles:
- analysis
image: docker.elastic.co/kibana/kibana:8.11.0
container_name: mail-mcp-kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- SERVER_NAME=mail-mcp-kibana
- SERVER_HOST=0.0.0.0
ports:
- "55601:5601"
depends_on:
elasticsearch:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:5601/api/status || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- mail-mcp-network
restart: unless-stopped
# mail-mcp MCP server
mail-mcp:
image: ghcr.io/support-and-care-labs/mail-mcp:latest
build:
context: .
dockerfile: Dockerfile
container_name: mail-mcp-server
environment:
- MAIL_MCP_ELASTICSEARCH_URL=http://elasticsearch:9200
- MAIL_MCP_ELASTICSEARCH_INDEX_PREFIX=maven
- MAIL_MCP_DATA_PATH=/app/data
- MAIL_MCP_LOG_LEVEL=INFO
- PYTHONUNBUFFERED=1
volumes:
# Mount data directory for mbox files
- ./data:/app/data:ro
# Mount source code for development (optional)
- ./src:/app/src:ro
# Mount maven-jira-projects.toml
- ./maven-jira-projects.toml:/app/maven-jira-projects.toml:ro
depends_on:
elasticsearch:
condition: service_healthy
networks:
- mail-mcp-network
restart: unless-stopped
# HTTP transport exposed on port 58080
ports:
- "58080:8080"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health').read()"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# Scheduler for periodic mbox updates
# Runs hourly to fetch the current month's mbox and re-index into Elasticsearch
scheduler:
image: ghcr.io/support-and-care-labs/mail-mcp:latest
build:
context: .
dockerfile: Dockerfile
container_name: mail-mcp-scheduler
environment:
- MAIL_MCP_ELASTICSEARCH_URL=http://elasticsearch:9200
- MAIL_MCP_ELASTICSEARCH_INDEX_PREFIX=maven
- MAIL_MCP_DATA_PATH=/app/data
- MAIL_MCP_MAILING_LISTS=dev@maven.apache.org,users@maven.apache.org
- MAIL_MCP_LOG_LEVEL=INFO
- PYTHONUNBUFFERED=1
volumes:
# Mount data directory as writable for scheduler to update mbox files
- ./data:/app/data:rw
# Mount source code for development (optional)
- ./src:/app/src:ro
depends_on:
elasticsearch:
condition: service_healthy
networks:
- mail-mcp-network
restart: unless-stopped
# Override default command to run supercronic scheduler
command: ["/usr/local/bin/supercronic", "-json", "/app/crontab"]
volumes:
es-data:
driver: local
networks:
mail-mcp-network:
driver: bridge
Connecting MCP Clients
Once services are running, configure your MCP client:
The Mail MCP server runs as a persistent Docker service and is accessed via Streamable HTTP transport.
Common Commands
Start Services
# Start all services (Elasticsearch, mail-mcp, scheduler)
# Note: Kibana is NOT started by default
docker compose up -d
# Start Elasticsearch only
docker compose up -d elasticsearch
# Start Kibana for data exploration (optional, on-demand)
docker compose --profile analysis up -d kibana
# View logs
docker compose logs -f mail-mcp
docker compose logs -f scheduler
docker compose logs -f elasticsearch
|
All services have |
Stop Services
# Stop all services
docker compose down
# Stop and remove volumes (clears all Elasticsearch data)
docker compose down -v
Check Status
# List running containers
docker compose ps
# Check mail-mcp health
curl http://localhost:58080/health
# Check Elasticsearch health
curl http://localhost:59200/_cluster/health
# View cluster info
curl http://localhost:59200/
# Check Kibana status (if running)
curl http://localhost:55601/api/status
# Open Kibana in browser
open http://localhost:55601
Configuration
Data Persistence
Elasticsearch data is stored in a named Docker volume.
# List volumes
docker volume ls | grep mail-mcp
# Inspect volume
docker volume inspect mail-mcp_es-data
# Remove volume (deletes all indexed data)
docker volume rm mail-mcp_es-data
Using Kibana
Kibana provides a web-based interface for exploring your indexed email data.
|
Kibana is not started by default.
Start it with: |
First Time Setup
After starting Kibana and indexing some data:
-
Access Kibana: Open http://localhost:55601 in your browser
-
Create Data View:
-
Navigate to Management → Stack Management → Data Views
-
Click "Create data view"
-
Pattern:
maven-*(matches all Maven indices) -
Time field:
date -
Click "Save data view to Kibana"
-
Discover
Use Discover to search and explore emails:
-
Navigate to Analytics → Discover
-
Select your
maven-*data view -
Use the search bar for queries:
-
subject:"release"- Find release discussions -
from_name:"Tamás"- Emails from Tamás -
has_vote:true- Emails with votes -
jira_references:*- Emails mentioning JIRA issues
-
Dev Tools
Use Dev Tools for direct Elasticsearch queries:
-
Navigate to Management → Dev Tools
-
Run queries in the Console:
GET maven-dev/_search
{
"query": {
"match": {
"subject": "maven 4"
}
}
}
Common Kibana Queries
Find emails by contributor:
GET maven-dev/_search
{
"query": {
"wildcard": {
"from_address": "*cstamas*"
}
}
}
Find voting threads:
GET maven-dev/_search
{
"query": {
"bool": {
"must": [
{ "term": { "has_vote": true } }
]
}
}
}
Find emails with JIRA references:
GET maven-dev/_search
{
"query": {
"exists": {
"field": "jira_references"
}
}
}
Development Workflow
Typical Development Session
# Start core services (Elasticsearch, mail-mcp, scheduler)
docker compose up -d
# Wait for Elasticsearch to be ready
curl --retry 10 --retry-delay 2 http://localhost:59200/_cluster/health
# Work with the application
poetry shell
python -m mail_mcp.storage.elasticsearch # Example
# Start Kibana for data exploration (when needed)
docker compose --profile analysis up -d kibana
curl --retry 10 --retry-delay 2 http://localhost:55601/api/status
open http://localhost:55601
# Stop Kibana when done with analysis
docker compose stop kibana
# Stop all services when done
docker compose down
Troubleshooting
Elasticsearch won’t start
- Check Docker Desktop resources
-
Elasticsearch needs at least 512MB RAM.
- View logs
docker compose logs elasticsearch
Port already in use
- Check for existing Elasticsearch instances
lsof -i :9200
- Change ports in docker-compose.yml
ports:
- "9201:9200" # Map to different host port
Production Deployment
The current Docker setup is optimized for local development. For production deployment:
-
Enable Elasticsearch security (xpack.security.enabled=true)
-
Use proper TLS certificates
-
Configure appropriate heap sizes
-
Set up proper networking
-
Use Docker secrets for sensitive configuration
-
Configure backup/restore procedures
See Elasticsearch documentation for production best practices.