This guide covers deploying the MCP Context Server using Docker and Docker Compose. Docker deployment enables HTTP transport mode for remote client connections, making the server accessible to MCP clients across networks.
Key Features:
- HTTP transport mode for remote access (vs. stdio for local)
- Fifteen pre-configured deployment options (9 standard + 6 local-build alternatives)
- Support for Ollama (local), OpenAI (cloud), and mixed-provider (Ollama embeddings + OpenAI summary) configurations
- Health checks and container orchestration support
- Shared Ollama model volume across Ollama configurations
- Docker Engine: 20.10+ or Docker Desktop
- Docker Compose: V2 (included with Docker Desktop)
- Storage: ~2GB for images and models (~600MB for qwen3-embedding:0.6b with Ollama)
- Network: Port 8000 available for HTTP transport
- OpenAI API Key: Required for OpenAI embedding configurations
Fifteen Docker Compose configurations are provided, organized by provider combination:
| Configuration | File | Database | Use Case |
|---|---|---|---|
| SQLite + Ollama | docker-compose.sqlite.ollama.yml |
Local SQLite | Single-user, testing, development |
| PostgreSQL + Ollama | docker-compose.postgresql.ollama.yml |
Internal PostgreSQL | Multi-user, production |
| External PostgreSQL + Ollama | docker-compose.postgresql-external.ollama.yml |
Supabase, corporate DB | Existing database infrastructure |
| Configuration | File | Database | Use Case |
|---|---|---|---|
| SQLite + OpenAI | docker-compose.sqlite.openai.yml |
Local SQLite | Single-user, cloud embeddings |
| PostgreSQL + OpenAI | docker-compose.postgresql.openai.yml |
Internal PostgreSQL | Multi-user, cloud embeddings |
| External PostgreSQL + OpenAI | docker-compose.postgresql-external.openai.yml |
Supabase, corporate DB | Enterprise with cloud embeddings |
| Configuration | File | Database | Use Case |
|---|---|---|---|
| SQLite + Ollama/OpenAI | docker-compose.sqlite.ollama-openai.yml |
Local SQLite | Local embeddings, cloud summaries |
| PostgreSQL + Ollama/OpenAI | docker-compose.postgresql.ollama-openai.yml |
Internal PostgreSQL | Production with local embeddings |
| External PostgreSQL + Ollama/OpenAI | docker-compose.postgresql-external.ollama-openai.yml |
Supabase, corporate DB | Enterprise with local embeddings |
Choosing Between Ollama and OpenAI:
| Factor | Ollama | OpenAI |
|---|---|---|
| Cost | Free (self-hosted) | Pay-per-use API |
| Privacy | Data stays local | Data sent to OpenAI |
| Setup | Automatic model download | Requires API key |
| Performance | Depends on hardware | Consistent cloud performance |
| Model | qwen3-embedding:0.6b (1024 dim) | text-embedding-3-small (1536 dim) |
For users who want to build the MCP Context Server image from local source code instead of pulling from GHCR, .local variants are available for the Ollama-only configurations:
| Configuration | File | Database | Use Case |
|---|---|---|---|
| SQLite + Ollama (local build) | docker-compose.sqlite.ollama.local.yml |
Local SQLite | Development, testing with local code changes |
| PostgreSQL + Ollama (local build) | docker-compose.postgresql.ollama.local.yml |
Internal PostgreSQL | Testing PostgreSQL with local code |
| External PostgreSQL + Ollama (local) | docker-compose.postgresql-external.ollama.local.yml |
Supabase, corporate DB | Testing external DB with local code |
.local variants are also available for the mixed-provider (Ollama embeddings + OpenAI summary) configurations:
| Configuration | File | Database | Use Case |
|---|---|---|---|
| SQLite + Ollama/OpenAI (local build) | docker-compose.sqlite.ollama-openai.local.yml |
Local SQLite | Development, testing with local code changes |
| PostgreSQL + Ollama/OpenAI (local build) | docker-compose.postgresql.ollama-openai.local.yml |
Internal PostgreSQL | Testing PostgreSQL with local code |
| External PostgreSQL + Ollama/OpenAI (local build) | docker-compose.postgresql-external.ollama-openai.local.yml |
Supabase, corporate DB | Testing external DB with local code |
These .local files build the same Docker image as the published GHCR image but from local source code. Use them when you want to test local changes before pushing. The OpenAI-only compose files always build from source (no GHCR image exists for those configurations).
# Build and start
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml up -d
# Wait for embedding model download (first run only, ~2-3 minutes)
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml logs -f ollama
# Verify server is ready
curl http://localhost:8000/health# Build and start (includes PostgreSQL with pgvector)
docker compose -f deploy/docker/docker-compose.postgresql.ollama.yml up -d
# Wait for all services to be healthy
docker compose -f deploy/docker/docker-compose.postgresql.ollama.yml ps
# Verify server is ready
curl http://localhost:8000/health# 1. Copy and configure environment file
cp deploy/docker/.env-postgresql-external.ollama.example deploy/docker/.env
# 2. Edit .env with your PostgreSQL connection details
# See "External PostgreSQL Configuration" section below
# 3. Build and start
docker compose -f deploy/docker/docker-compose.postgresql-external.ollama.yml up -d
# Verify server is ready
curl http://localhost:8000/healthAll OpenAI configurations require an .env file with your OpenAI API key.
# 1. Copy and configure environment file
cp deploy/docker/.env-sqlite.openai.example deploy/docker/.env
# 2. Edit .env and add your OPENAI_API_KEY
# OPENAI_API_KEY=sk-your-openai-api-key-here
# 3. Build and start
docker compose -f deploy/docker/docker-compose.sqlite.openai.yml up -d
# Verify server is ready
curl http://localhost:8000/health# 1. Copy and configure environment file
cp deploy/docker/.env-postgresql.openai.example deploy/docker/.env
# 2. Edit .env and add your OPENAI_API_KEY
# OPENAI_API_KEY=sk-your-openai-api-key-here
# 3. Build and start
docker compose -f deploy/docker/docker-compose.postgresql.openai.yml up -d
# Verify server is ready
curl http://localhost:8000/health# 1. Copy and configure environment file
cp deploy/docker/.env-postgresql-external.openai.example deploy/docker/.env
# 2. Edit .env with your OpenAI API key AND PostgreSQL connection details
# See "External PostgreSQL Configuration" section below
# 3. Build and start
docker compose -f deploy/docker/docker-compose.postgresql-external.openai.yml up -d
# Verify server is ready
curl http://localhost:8000/healthMixed provider configurations use Ollama for local embedding generation and OpenAI for cloud-based summary generation. These configurations pull the pre-built ghcr.io/alex-feel/mcp-context-server:latest-ollama-openai image from GHCR. To build from local source code instead, use the .local variants (e.g., docker-compose.sqlite.ollama-openai.local.yml). All configurations require an .env file with your OpenAI API key.
# 1. Copy and configure environment file
cp deploy/docker/.env-sqlite.ollama-openai.example deploy/docker/.env
# 2. Edit .env and add your OPENAI_API_KEY
# OPENAI_API_KEY=sk-your-openai-api-key-here
# 3. Build and start
docker compose -f deploy/docker/docker-compose.sqlite.ollama-openai.yml up -d
# Wait for embedding model download (first run only, ~2-3 minutes)
docker compose -f deploy/docker/docker-compose.sqlite.ollama-openai.yml logs -f ollama
# Verify server is ready
curl http://localhost:8000/health# 1. Copy and configure environment file
cp deploy/docker/.env-postgresql.ollama-openai.example deploy/docker/.env
# 2. Edit .env and add your OPENAI_API_KEY
# OPENAI_API_KEY=sk-your-openai-api-key-here
# 3. Build and start
docker compose -f deploy/docker/docker-compose.postgresql.ollama-openai.yml up -d
# Wait for all services to be healthy
docker compose -f deploy/docker/docker-compose.postgresql.ollama-openai.yml ps
# Verify server is ready
curl http://localhost:8000/health# 1. Copy and configure environment file
cp deploy/docker/.env-postgresql-external.ollama-openai.example deploy/docker/.env
# 2. Edit .env with your OpenAI API key AND PostgreSQL connection details
# See "External PostgreSQL Configuration" section below
# 3. Build and start
docker compose -f deploy/docker/docker-compose.postgresql-external.ollama-openai.yml up -d
# Verify server is ready
curl http://localhost:8000/healthTwo GHCR-published images are available: ghcr.io/alex-feel/mcp-context-server:latest (Ollama embeddings + Ollama summary) and ghcr.io/alex-feel/mcp-context-server:latest-ollama-openai (Ollama embeddings + OpenAI summary).
Build from source when:
- Testing local code changes -- use the
.localvariants of compose files - Using OpenAI embeddings -- the OpenAI compose files build with
EMBEDDING_EXTRA=embeddings-openai
| Category | Files | image: |
pull_policy |
build: block |
|---|---|---|---|---|
| GHCR pull | *.ollama.yml |
ghcr.io/alex-feel/mcp-context-server:latest |
always |
None |
| GHCR pull (variant) | *.ollama-openai.yml |
ghcr.io/alex-feel/mcp-context-server:latest-ollama-openai |
always |
None |
| Local build (GHCR equivalent) | *.ollama.local.yml |
mcp-context-server |
build |
Yes (no custom args) |
| Local build (variant equivalent) | *.ollama-openai.local.yml |
mcp-context-server |
build |
Yes (with SUMMARY_EXTRA=summary-openai) |
| Local build (provider-specific) | *.openai.yml |
mcp-context-server |
build |
Yes (with EMBEDDING_EXTRA / SUMMARY_EXTRA args) |
Once deployed, connect MCP clients via HTTP transport:
Add to claude_desktop_config.json:
{
"mcpServers": {
"context-server": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}
}claude mcp add --transport http context-server http://localhost:8000/mcpReplace localhost with your server's IP or hostname for remote connections:
{
"mcpServers": {
"context-server": {
"type": "http",
"url": "http://your-server.example.com:8000/mcp"
}
}
}Ollama configurations define two or three services:
mcp-context-server:
- Production MCP server image
- HTTP transport on port 8000
- Health check endpoint at
/health - Non-root user (UID 10001) for security
ollama:
- Stock
ollama/ollama:latestimage with automatic model pulling via inline entrypoint - Downloads
qwen3-embedding:0.6bon first start - Health check waits for model availability
postgres (PostgreSQL configurations only):
- pgvector/pgvector:pg18-trixie image
- Pre-installed pgvector extension for semantic search
- Persistent volume for data
OpenAI configurations are simpler - no Ollama service required:
mcp-context-server:
- Same as above, but uses OpenAI API for embeddings
- Requires
OPENAI_API_KEYin.envfile
postgres (PostgreSQL configurations only):
- Same as Ollama configurations
| Volume | Purpose | Used By |
|---|---|---|
mcp-context-sqlite-ollama-data |
SQLite database | SQLite + Ollama |
mcp-context-sqlite-openai-data |
SQLite database | SQLite + OpenAI |
mcp-context-postgresql-ollama-data |
PostgreSQL data | PostgreSQL + Ollama |
mcp-context-postgresql-openai-data |
PostgreSQL data | PostgreSQL + OpenAI |
ollama-models |
Embedding models (~600MB) | All Ollama configurations |
flashrank-model-cache |
FlashRank reranking model (~34MB) | All configurations |
The ollama-models volume is shared across all Ollama configurations, so switching between SQLite and PostgreSQL does not re-download the embedding model. The flashrank-model-cache volume persists the FlashRank reranking model across container restarts.
Each Ollama-based Docker Compose file declares an inline entrypoint: block on the ollama service that:
- Starts the Ollama server in the background.
- Waits for the server to accept requests.
- Checks the configured embedding model (
EMBEDDING_MODEL) and pulls it if not already cached. - For Ollama-only configurations (where
SUMMARY_PROVIDERisollama), checks the summary model (SUMMARY_MODEL) and pulls it if missing and different from the embedding model. For mixed-provider configurations (ollama-openai), the summary model is not pulled because OpenAI handles summary generation. - Hands off to the running Ollama server for normal request handling.
The check-then-pull logic is idempotent: subsequent restarts skip the download when models are already cached in the ollama-models Docker volume. Models persist across container restarts and across all Ollama configurations sharing this volume.
All Docker Compose files use environment variables for configuration. Key settings:
Transport Settings:
| Variable | Default | Description |
|---|---|---|
MCP_TRANSPORT |
http |
Transport mode (set to http for Docker) |
FASTMCP_HOST |
0.0.0.0 |
HTTP bind address |
FASTMCP_PORT |
8000 |
HTTP port |
FASTMCP_STATELESS_HTTP |
true |
Stateless HTTP mode (enabled by default) |
Summary Generation Settings:
| Variable | Default | Description |
|---|---|---|
ENABLE_SUMMARY_GENERATION |
true |
Enable automatic LLM-based summary generation |
SUMMARY_PROVIDER |
ollama |
Summary provider: ollama, openai, or anthropic |
SUMMARY_MODEL |
qwen3:0.6b |
Summary model name (provider-specific) |
SUMMARY_MAX_TOKENS |
2000 |
Maximum output tokens for summary generation (50-5000) |
SUMMARY_TIMEOUT_S |
240.0 |
Timeout in seconds for summary generation API calls |
SUMMARY_RETRY_MAX_ATTEMPTS |
5 |
Maximum retry attempts on transient errors |
SUMMARY_RETRY_BASE_DELAY_S |
1.0 |
Base delay in seconds between retries (exponential backoff) |
SUMMARY_MAX_CONCURRENT |
3 |
Maximum concurrent summary generation operations (1-20) |
SUMMARY_PROMPT |
(built-in) | Custom system prompt; unset uses the optimized built-in default |
Search Features:
| Variable | Default | Description |
|---|---|---|
ENABLE_SEMANTIC_SEARCH |
true |
Enable vector similarity search |
ENABLE_FTS |
true |
Enable full-text search |
ENABLE_HYBRID_SEARCH |
true |
Enable combined FTS + semantic search |
ENABLE_CHUNKING |
true |
Enable text chunking for embeddings |
ENABLE_RERANKING |
true |
Enable cross-encoder reranking |
Embedding Settings (Ollama):
| Variable | Default | Description |
|---|---|---|
EMBEDDING_PROVIDER |
ollama |
Embedding provider |
EMBEDDING_MODEL |
qwen3-embedding:0.6b |
Ollama embedding model |
EMBEDDING_DIM |
1024 |
Embedding vector dimensions |
OLLAMA_HOST |
http://ollama:11434 |
Ollama API endpoint |
Embedding Settings (OpenAI):
| Variable | Default | Description |
|---|---|---|
EMBEDDING_PROVIDER |
openai |
Embedding provider |
EMBEDDING_MODEL |
text-embedding-3-small |
OpenAI embedding model |
EMBEDDING_DIM |
1536 |
Embedding vector dimensions |
OPENAI_API_KEY |
(required) | OpenAI API key (from .env file) |
Storage Settings (SQLite):
| Variable | Default | Description |
|---|---|---|
STORAGE_BACKEND |
sqlite |
Database backend |
DB_PATH |
/data/context_storage.db |
Database path inside container |
Storage Settings (PostgreSQL):
| Variable | Default | Description |
|---|---|---|
STORAGE_BACKEND |
postgresql |
Database backend |
POSTGRESQL_HOST |
postgres |
PostgreSQL hostname |
POSTGRESQL_PORT |
5432 |
PostgreSQL port |
POSTGRESQL_USER |
postgres |
PostgreSQL username |
POSTGRESQL_PASSWORD |
postgres |
PostgreSQL password |
POSTGRESQL_DATABASE |
mcp_context |
PostgreSQL database name |
Metadata Indexing Settings:
| Variable | Default | Description |
|---|---|---|
METADATA_INDEXED_FIELDS |
status,agent_name,... |
Comma-separated fields to index with optional type hints |
METADATA_INDEX_SYNC_MODE |
additive |
Index sync mode: strict, auto, warn, additive |
See the Metadata Guide for full details on configurable metadata indexing.
Chunking and Reranking:
Text chunking and cross-encoder reranking are enabled by default to improve search quality. These features work automatically without configuration.
| Variable | Default | Description |
|---|---|---|
ENABLE_CHUNKING |
true |
Text chunking for long document embedding |
CHUNK_SIZE |
1500 |
Target chunk size in characters |
ENABLE_RERANKING |
true |
Cross-encoder result reranking |
RERANKING_MODEL |
ms-marco-MiniLM-L-12-v2 |
FlashRank model (~34MB, downloads on startup) |
To disable these features, set the environment variables to false in your Docker Compose file:
environment:
- ENABLE_CHUNKING=false
- ENABLE_RERANKING=falseFor more configuration options, see Text Chunking and Cross-Encoder Reranking.
For external PostgreSQL (Supabase, corporate databases), copy the appropriate .env.example file to .env and configure:
For Ollama:
cp deploy/docker/.env-postgresql-external.ollama.example deploy/docker/.envFor OpenAI:
cp deploy/docker/.env-postgresql-external.openai.example deploy/docker/.envThen configure PostgreSQL connection:
# Option A: Individual variables (recommended)
POSTGRESQL_HOST=your-db-host.com
POSTGRESQL_PORT=5432
POSTGRESQL_USER=postgres
POSTGRESQL_PASSWORD='your-secure-password'
POSTGRESQL_DATABASE=mcp_context
POSTGRESQL_SSL_MODE=require
# Option B: Connection string
POSTGRESQL_CONNECTION_STRING=postgresql://user:password@host:5432/database?sslmode=requireImportant: Special Characters in Passwords
If your password contains special characters ($, #, &, *, etc.), wrap it in single quotes (not double quotes):
# WRONG - $ will be interpreted as a variable
POSTGRESQL_PASSWORD="pass$word"
# CORRECT - single quotes prevent variable interpolation
POSTGRESQL_PASSWORD='pass$word'For Supabase, use the Session Pooler connection (supports IPv4):
POSTGRESQL_HOST=aws-0-us-east-1.pooler.supabase.com
POSTGRESQL_PORT=5432
POSTGRESQL_USER=postgres.your-project-ref
POSTGRESQL_PASSWORD='your-database-password'
POSTGRESQL_DATABASE=postgres
POSTGRESQL_SSL_MODE=requireSee the Supabase section in README.md for detailed connection setup.
Ollama configurations work without any .env file. However, you can optionally create one for additional settings like LangSmith tracing:
# Copy the optional template
cp deploy/docker/.env-sqlite.ollama.example deploy/docker/.env
# or
cp deploy/docker/.env-postgresql.ollama.example deploy/docker/.env
# Edit .env to enable optional features
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=lsv2_your-langsmith-api-key# Check server health
curl http://localhost:8000/health
# Expected response
{"status": "ok"}# Ollama deployment
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml ps
# OpenAI deployment
docker compose -f deploy/docker/docker-compose.sqlite.openai.yml ps
# Expected output: all services "healthy"
NAME STATUS
context-server-mcp-context-server-1 Up (healthy)
context-server-ollama-1 Up (healthy) # Ollama only
context-server-postgres-1 Up (healthy) # PostgreSQL only# Check if embedding model is loaded
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml exec ollama ollama list
# Expected output includes:
# qwen3-embedding:0.6b ~600 MB# List available tools via MCP
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'Symptom: ollama container stays in "starting" state
Cause: Embedding model download takes longer than expected (slow network)
Solution:
# Check download progress
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml logs -f ollama
# The entrypoint shows: "Pulling model: qwen3-embedding:0.6b..."
# Wait for: "Model pulled successfully!"Symptom: Server fails to connect to PostgreSQL
Causes:
- PostgreSQL container not yet ready
- Incorrect credentials in
.env
Solutions:
# Check PostgreSQL logs
docker compose -f deploy/docker/docker-compose.postgresql.ollama.yml logs postgres
# Verify PostgreSQL is accepting connections
docker compose -f deploy/docker/docker-compose.postgresql.ollama.yml exec postgres pg_isready
# Test credentials manually
docker compose -f deploy/docker/docker-compose.postgresql.ollama.yml exec postgres \
psql -U postgres -d mcp_context -c "SELECT 1"Symptom: Cannot connect to Supabase Direct Connection
Cause: IPv6 not available on your system
Solution: Use Session Pooler connection instead (see Supabase Configuration above)
Symptom: Container fails to start, port binding error
Solution: Modify the port mapping in docker-compose file:
ports:
- "8001:8000" # Use port 8001 on hostThen connect clients to http://localhost:8001/mcp
Symptom: semantic_search_context tool not listed
Causes:
- Ollama not healthy yet
- Embedding model not downloaded
Solutions:
# Verify Ollama is healthy
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml ps ollama
# Check if model exists
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml exec ollama ollama list
# If model missing, trigger download
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml exec ollama ollama pull qwen3-embedding:0.6bSymptom: Server fails to start with OpenAI configuration
Cause: .env file missing or OPENAI_API_KEY not set
Solution:
# Ensure .env exists
cp deploy/docker/.env-sqlite.openai.example deploy/docker/.env
# Verify OPENAI_API_KEY is set
grep OPENAI_API_KEY deploy/docker/.envSymptom: summary field is an empty string in search results
Causes:
- Summary model not pulled into the Ollama container
ENABLE_SUMMARY_GENERATIONset tofalse
Solutions:
# Pull the summary model
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml exec ollama ollama pull qwen3:0.6b
# Verify model is available
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml exec ollama ollama list
# Check server logs for summary errors
docker compose -f deploy/docker/docker-compose.sqlite.ollama.yml logs mcp-context-server | grep -i summaryNote: Summaries are generated before the database transaction during store_context and update_context operations (in parallel with embedding generation). The summary is available immediately in the response and in subsequent search results.
Symptom: Ollama container enters infinite restart loop when using SUMMARY_PROVIDER=openai with an Ollama compose file
Cause: Existing Ollama compose files (e.g., docker-compose.sqlite.ollama.yml) pass SUMMARY_MODEL to the Ollama sidecar. When the summary model is an OpenAI model name (e.g., gpt-5.4-nano), the entrypoint fails trying to pull it from Ollama. Additionally, the healthcheck requires both embedding and summary models to be present in Ollama.
Solution: Use the dedicated mixed-provider compose files instead:
# SQLite + Ollama Embeddings + OpenAI Summary
docker compose -f deploy/docker/docker-compose.sqlite.ollama-openai.yml up -d
# PostgreSQL + Ollama Embeddings + OpenAI Summary
docker compose -f deploy/docker/docker-compose.postgresql.ollama-openai.yml up -d
# External PostgreSQL + Ollama Embeddings + OpenAI Summary
docker compose -f deploy/docker/docker-compose.postgresql-external.ollama-openai.yml up -dThese files are specifically designed for mixed providers: the Ollama sidecar only handles embedding models, and the OpenAI summary provider is configured on the MCP server service.
| Error | Cause | Solution |
|---|---|---|
connection refused |
Service not running | Check container status with docker compose ps |
model not found |
Embedding model not pulled | Wait for automatic download or pull manually |
permission denied |
Volume permission issue | Check volume ownership matches UID 10001 |
database is locked |
SQLite concurrent access | Expected for SQLite; use PostgreSQL for concurrency |
Invalid API Key |
OpenAI key incorrect | Verify OPENAI_API_KEY in .env file |
password authentication failed |
Wrong PostgreSQL password | Fix POSTGRESQL_PASSWORD and restart (exit 78) |
database "..." does not exist |
PostgreSQL database not found | Create database or fix POSTGRESQL_DATABASE (exit 78) |
pgvector extension is not installed |
pgvector not enabled | Enable via dashboard or CREATE EXTENSION (exit 78) |
insufficient privileges |
Cannot create pgvector | Grant permissions via dashboard (exit 78) |
[Errno 111] Connection refused |
PostgreSQL not running | Wait for PostgreSQL to start (exit 69, will retry) |
summary field is empty |
Summary model not pulled | Run ollama pull qwen3:0.6b in the ollama container |
To use a different Ollama embedding model, update both services:
# In docker-compose file
services:
mcp-context-server:
environment:
- EMBEDDING_MODEL=nomic-embed-text
- EMBEDDING_DIM=1024
ollama:
environment:
- EMBEDDING_MODEL=nomic-embed-textTo use a different OpenAI embedding model:
# In docker-compose file
services:
mcp-context-server:
environment:
- EMBEDDING_MODEL=text-embedding-3-large
- EMBEDDING_DIM=3072 # Adjust for modelGPU acceleration enables faster embedding generation and summary inference. Docker Compose files include commented GPU configuration sections for NVIDIA, AMD (ROCm), and Intel (Vulkan) GPUs.
For complete setup instructions, troubleshooting, and vendor-specific details, see the GPU Acceleration Guide.
Quick start (NVIDIA example):
Uncomment the NVIDIA GPU section in your Docker Compose file:
services:
ollama:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]AMD ROCm:
Override the Ollama image to the ROCm-tagged variant and uncomment the AMD GPU section:
services:
ollama:
image: ollama/ollama:rocmSee the GPU Acceleration Guide for AMD and Intel/Vulkan configuration.
The MCP Context Server image is built from the repository root Dockerfile:
docker build -t mcp-context-server .The Ollama service uses the published ollama/ollama:latest image directly (or ollama/ollama:rocm for AMD GPUs); no local Ollama image build is required.
The Dockerfile supports building with different embedding providers via build arguments:
# Build with Ollama embeddings (default)
docker build -t mcp-context-server .
# Build with OpenAI embeddings
docker build --build-arg EMBEDDING_EXTRA=embeddings-openai -t mcp-context-server-openai .
# Build with Azure OpenAI embeddings
docker build --build-arg EMBEDDING_EXTRA=embeddings-azure -t mcp-context-server-azure .
# Build with HuggingFace embeddings
docker build --build-arg EMBEDDING_EXTRA=embeddings-huggingface -t mcp-context-server-huggingface .
# Build with Voyage embeddings
docker build --build-arg EMBEDDING_EXTRA=embeddings-voyage -t mcp-context-server-voyage .
# Build with all embedding providers
docker build --build-arg EMBEDDING_EXTRA=embeddings-all -t mcp-context-server-all .Available Embedding Extras:
| Extra | Provider | Package |
|---|---|---|
embeddings-ollama |
Ollama (default) | langchain-ollama |
embeddings-openai |
OpenAI | langchain-openai |
embeddings-azure |
Azure OpenAI | langchain-openai |
embeddings-huggingface |
HuggingFace | langchain-huggingface |
embeddings-voyage |
Voyage AI | langchain-voyageai |
embeddings-all |
All providers | All packages |
Note: The OpenAI and mixed-provider Docker Compose configurations automatically pass the correct build arguments. If using Ollama configurations, no build argument is needed (default is embeddings-ollama).
The Dockerfile supports building with different summary providers via the SUMMARY_EXTRA build argument:
# Build with Ollama summaries (default)
docker build -t mcp-context-server .
# Build with OpenAI summaries
docker build --build-arg SUMMARY_EXTRA=summary-openai -t mcp-context-server-openai-summary .
# Build with Anthropic summaries
docker build --build-arg SUMMARY_EXTRA=summary-anthropic -t mcp-context-server-anthropic-summary .
# Combine embedding and summary build args
docker build \
--build-arg EMBEDDING_EXTRA=embeddings-openai \
--build-arg SUMMARY_EXTRA=summary-openai \
-t mcp-context-server-openai .
# Mixed provider: Ollama embeddings + OpenAI summaries
docker build \
--build-arg EMBEDDING_EXTRA=embeddings-ollama \
--build-arg SUMMARY_EXTRA=summary-openai \
-t mcp-context-server-ollama-openai .Available Summary Extras:
| Extra | Provider | Package | Default Model |
|---|---|---|---|
summary-ollama |
Ollama (default) | langchain-ollama | qwen3:0.6b |
summary-openai |
OpenAI | langchain-openai | gpt-5.4-nano |
summary-anthropic |
Anthropic | langchain-anthropic | claude-haiku-4-5 |
To disable summary generation entirely (no SUMMARY_EXTRA needed):
environment:
- ENABLE_SUMMARY_GENERATION=falseFor detailed summary generation configuration, see the Summary Generation Guide.
For horizontal scaling with Docker Compose, use a PostgreSQL configuration. Stateless HTTP mode is enabled by default:
services:
mcp-context-server:
deploy:
replicas: 3Requirements:
- PostgreSQL backend (
STORAGE_BACKEND=postgresql) -- SQLite does not support multiple writers - Stateless HTTP mode is enabled by default; no additional configuration needed
For production horizontal scaling, Kubernetes with Helm is recommended. See the Kubernetes Deployment Guide.
The MCP Context Server uses BSD sysexits.h exit codes to signal different failure types to container supervisors:
| Exit Code | Meaning | Docker Restart Behavior |
|---|---|---|
| 0 | Normal shutdown | No restart |
| 1 | General error | Restart if policy allows |
| 69 | Dependency unavailable | Restart with backoff (may recover) |
| 78 | Configuration error | Container halted (prevents restart loops) |
Exit Code 69 (EX_UNAVAILABLE) indicates external dependencies are temporarily unavailable:
- Ollama service not running (may start later)
- Database temporarily unreachable (PostgreSQL connection refused, network timeout)
- Network connectivity issues
Exit Code 78 (EX_CONFIG) indicates configuration problems requiring human intervention:
- Missing API keys (OPENAI_API_KEY, VOYAGE_API_KEY, etc.)
- Missing required packages
- Invalid configuration values
- Embedding model not found (requires
ollama pullor fix EMBEDDING_MODEL) - PostgreSQL authentication errors (wrong password, database doesn't exist, missing pgvector extension)
For detailed PostgreSQL error scenarios, see PostgreSQL Backend Error Scenarios below.
The Docker image includes an entrypoint wrapper script (docker-entrypoint.sh) that intercepts exit codes to prevent infinite restart loops:
How it works:
Docker starts container
|
v
docker-entrypoint.sh runs Python server
|
v
Server exits with code (0, 69, 78, or other)
|
v
Entrypoint interprets exit code:
- Code 0: Normal exit
- Code 78: Configuration error -> exec sleep infinity (container stays running but idle)
- Code 69: Dependency error -> exit 69 (Docker may restart)
- Other: Pass through exit code
Configuration errors (exit code 78) - Container halted:
When the server encounters a configuration error (e.g., embedding model not found), the entrypoint:
- Prints a clear error message with troubleshooting steps
- Replaces itself with
sleep infinity - Container remains "Running" (but idle) instead of entering a restart loop
This allows you to:
- Inspect logs with
docker logs <container> - Fix the configuration
- Stop and restart manually:
docker stop <container> && docker compose up -d
Dependency errors (exit code 69) - May retry:
When the server encounters a dependency error (e.g., Ollama not running yet), the entrypoint:
- Prints an informational message
- Exits with code 69
- Docker's
on-failure:5policy may restart the container (up to 5 times)
Default restart policy:
All Docker Compose configurations use restart: "on-failure:5" for the MCP Context Server:
services:
mcp-context-server:
restart: "on-failure:5" # Restart up to 5 times on failureThis provides defense in depth:
- Entrypoint handles configuration errors (code 78) by halting
- Restart policy limits dependency error retries (code 69) to 5 attempts
For production, the built-in health check is already configured:
services:
mcp-context-server:
restart: "on-failure:5"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health').read()"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3When using the PostgreSQL backend, the server classifies initialization errors to control container restart behavior. This prevents infinite restart loops on configuration errors while allowing retry for transient connectivity issues.
Error Classification:
| Error Scenario | Exception Type | Exit Code | Container Behavior | Fix Required |
|---|---|---|---|---|
| PostgreSQL not running | Connection refused (Errno 111) | 69 (DependencyError) | Retry with backoff | Wait for PostgreSQL to start |
| Network timeout | TimeoutError, InterfaceError |
69 (DependencyError) | Retry with backoff | Check network connectivity |
| Too many connections | TooManyConnectionsError |
69 (DependencyError) | Retry with backoff | Increase max_connections or wait |
| Wrong password | InvalidPasswordError |
78 (ConfigurationError) | Halt (sleep infinity) | Fix POSTGRESQL_PASSWORD |
| Database does not exist | InvalidCatalogNameError |
78 (ConfigurationError) | Halt (sleep infinity) | Create database or fix POSTGRESQL_DATABASE |
| pgvector not installed | Extension check failure | 78 (ConfigurationError) | Halt (sleep infinity) | Enable pgvector extension |
| Insufficient privileges | InsufficientPrivilegeError |
78 (ConfigurationError) | Halt (sleep infinity) | Grant permissions via dashboard |
| Codec registration failed | pgvector codec error | 78 (ConfigurationError) | Halt (sleep infinity) | Check pgvector installation |
Examples:
Scenario 1: PostgreSQL Not Running (Exit 69)
[ERROR] Failed to connect to PostgreSQL: [Errno 111] Connection refused
[docker-entrypoint] Server exited with code 69
- Container behavior: Restarts up to 5 times (restart policy)
- Why retry makes sense: PostgreSQL service may start soon
- Fix: Ensure PostgreSQL container is running and healthy
Scenario 2: Wrong Database Password (Exit 78)
[ERROR] PostgreSQL authentication failed: password authentication failed
[docker-entrypoint] CONFIGURATION ERROR - CONTAINER HALTED
[docker-entrypoint] Server exited with code 78
- Container behavior: Halts (remains running but idle with
sleep infinity) - Why halt: Password won't fix itself - requires human intervention
- Fix: Update
POSTGRESQL_PASSWORDin.envfile and restart container
Scenario 3: pgvector Extension Not Installed (Exit 78)
[ERROR] pgvector extension is not installed
[docker-entrypoint] CONFIGURATION ERROR - CONTAINER HALTED
[docker-entrypoint] Server exited with code 78
- Container behavior: Halts (remains running but idle)
- Why halt: Extension must be manually enabled
- Fix: Enable pgvector via Supabase Dashboard → Extensions or
CREATE EXTENSION vector;
Scenario 4: Database Does Not Exist (Exit 78)
[ERROR] PostgreSQL database does not exist: database "mcp_context" does not exist
[docker-entrypoint] CONFIGURATION ERROR - CONTAINER HALTED
[docker-entrypoint] Server exited with code 78
- Container behavior: Halts (remains running but idle)
- Why halt: Database must be created manually
- Fix: Create database or fix
POSTGRESQL_DATABASEenvironment variable
Recovery Steps for Configuration Errors (Exit 78):
-
Check container logs to identify specific error:
docker logs <container_name>
-
Fix the configuration based on error message:
- Wrong password: Update
.envfile with correctPOSTGRESQL_PASSWORD - Missing database: Create database or fix
POSTGRESQL_DATABASE - Missing extension: Enable pgvector via dashboard or SQL
- Permission denied: Grant required permissions (Supabase: use dashboard)
- Wrong password: Update
-
Stop and restart the container:
docker stop <container_name> docker compose -f <your-compose-file>.yml up -d
Understanding Exit Code 69 vs 78:
-
Exit 69 (Dependency Error): External dependency temporarily unavailable
- Examples: PostgreSQL starting up, network hiccup, connection pool exhausted
- Container restarts automatically (may succeed when dependency becomes available)
- No human intervention needed
-
Exit 78 (Configuration Error): Configuration problem requiring human fix
- Examples: Wrong password, missing database, missing extension
- Container halts to prevent infinite restart loop
- Requires manual fix and restart
If your container shows "Running" but the server is not responding:
-
Check container logs:
docker logs <container_name>
-
Look for "CONFIGURATION ERROR - CONTAINER HALTED" message:
============================================== [FATAL] CONFIGURATION ERROR - CONTAINER HALTED ============================================== -
Fix the configuration based on the error message (e.g., pull missing model, set API key)
-
Restart the container:
docker stop <container_name> docker compose -f <your-compose-file>.yml up -d
- Change default PostgreSQL password in production deployments
- Use named volumes for data persistence (already configured)
- Configure resource limits for container memory/CPU
- Set up monitoring using the
/healthendpoint - Use reverse proxy (nginx, traefik) for TLS termination
- Secure OpenAI API key - never commit
.envfiles to version control - Set restart policies with limited retry count to prevent infinite loops
| File | Description | Image Source |
|---|---|---|
docker-compose.sqlite.ollama.yml |
SQLite + Ollama embeddings | GHCR |
docker-compose.sqlite.ollama.local.yml |
SQLite + Ollama embeddings (local build) | Local |
docker-compose.postgresql.ollama.yml |
PostgreSQL + Ollama embeddings | GHCR |
docker-compose.postgresql.ollama.local.yml |
PostgreSQL + Ollama embeddings (local build) | Local |
docker-compose.postgresql-external.ollama.yml |
External PostgreSQL + Ollama embeddings | GHCR |
docker-compose.postgresql-external.ollama.local.yml |
External PostgreSQL + Ollama embeddings (local build) | Local |
docker-compose.sqlite.openai.yml |
SQLite + OpenAI embeddings | Local |
docker-compose.postgresql.openai.yml |
PostgreSQL + OpenAI embeddings | Local |
docker-compose.postgresql-external.openai.yml |
External PostgreSQL + OpenAI embeddings | Local |
docker-compose.sqlite.ollama-openai.yml |
SQLite + Ollama embeddings + OpenAI summary | GHCR |
docker-compose.sqlite.ollama-openai.local.yml |
SQLite + Ollama embeddings + OpenAI summary (local build) | Local |
docker-compose.postgresql.ollama-openai.yml |
PostgreSQL + Ollama embeddings + OpenAI summary | GHCR |
docker-compose.postgresql.ollama-openai.local.yml |
PostgreSQL + Ollama embeddings + OpenAI summary (local) | Local |
docker-compose.postgresql-external.ollama-openai.yml |
External PostgreSQL + Ollama embeddings + OpenAI summary | GHCR |
docker-compose.postgresql-external.ollama-openai.local.yml |
External PostgreSQL + Ollama embeddings + OpenAI summary (local) | Local |
| File | Description | Required |
|---|---|---|
.env-sqlite.ollama.example |
Optional config for SQLite + Ollama | No |
.env-postgresql.ollama.example |
Optional config for PostgreSQL + Ollama | No |
.env-postgresql-external.ollama.example |
PostgreSQL connection for external DB + Ollama | Yes |
.env-sqlite.openai.example |
OpenAI API key for SQLite + OpenAI | Yes |
.env-postgresql.openai.example |
OpenAI API key for PostgreSQL + OpenAI | Yes |
.env-postgresql-external.openai.example |
OpenAI + PostgreSQL for external DB | Yes |
.env-sqlite.ollama-openai.example |
OpenAI API key for SQLite + Ollama/OpenAI | Yes |
.env-postgresql.ollama-openai.example |
OpenAI API key for PostgreSQL + Ollama/OpenAI | Yes |
.env-postgresql-external.ollama-openai.example |
OpenAI + PostgreSQL for external DB + Ollama/OpenAI | Yes |
| File | Description |
|---|---|
Dockerfile |
Multi-stage MCP server image (repository root) |
deploy/docker/docker-entrypoint.sh |
Exit code handler to prevent infinite restart |
.dockerignore |
Build context optimization (repository root) |
- API Reference: API Reference - complete tool documentation
- Database Backends: Database Backends Guide - database configuration
- Semantic Search: Semantic Search Guide - vector similarity search configuration
- Full-Text Search: Full-Text Search Guide - FTS configuration and usage
- Hybrid Search: Hybrid Search Guide - combined search with RRF fusion
- Metadata Filtering: Metadata Guide - metadata filtering with operators
- Authentication: Authentication Guide - bearer token authentication
- Main Documentation: README.md - overview and quick start
- GPU Setup: GPU Acceleration Guide - NVIDIA, AMD, and Intel GPU setup
For Kubernetes deployments, see:
- Helm Chart: Helm Deployment Guide
- Raw Manifests: Kubernetes Guide