A comprehensive orchestration tool for managing Model Context Protocol (MCP) servers with container and proxy capabilities. MCP-Compose provides a Docker Compose-style interface for deploying, configuring, and managing multiple MCP servers through a unified HTTP proxy.
MCP-Compose bridges the gap between traditional MCP STDIO servers and modern HTTP-based architectures. It combines the simplicity of Docker Compose configuration with robust MCP protocol support, enabling seamless integration with clients like Claude Desktop, OpenWebUI, and custom applications.
- Docker Compose-Style Configuration: Familiar YAML syntax for defining MCP server infrastructure
- Multi-Transport Protocol Support: Native support for STDIO, HTTP, and SSE (Server-Sent Events) transports
- Unified HTTP Proxy: Single endpoint exposing all MCP servers via RESTful HTTP interface
- Container & Process Management: Run servers as Docker containers, Podman containers, or native processes
- Network Orchestration: Automatic Docker network management for inter-server communication
- Session Management: Persistent MCP sessions with automatic connection pooling and health monitoring
- Built-in MCP Inspector: Interactive debugging tool for MCP protocol communication
- Real-time Monitoring: Health checks, connection status, and performance metrics
- Auto-generated Documentation: OpenAPI specifications and interactive docs for each server
- Hot Configuration Reload: Update server configurations without full restart
- Comprehensive Logging: Structured logging with configurable levels and formats
- OpenWebUI Compatibility: Direct OpenAPI spec integration with authentication
- Claude Desktop Support: Streamlined configuration generation and HTTP endpoint support
- Custom Client Ready: RESTful API with proper CORS, authentication, and error handling
- Tool Discovery: Automatic tool enumeration and caching across all servers
- Direct Tool Calls: FastAPI-style direct tool invocation endpoints
- Claude Desktop: Full HTTP transport support with session management
- OpenWebUI: Native OpenAPI specification compatibility with individual server endpoints
- Custom MCP Clients: Complete MCP protocol compliance over HTTP with JSON-RPC 2.0
- Development Tools: Built-in inspector compatible with standard MCP debugging workflows
- Docker: Full support with automatic network creation and management
- Podman: Complete compatibility with rootless containers
- Native Processes: Process-based servers for lightweight deployments
- Hybrid Deployments: Mix containers and processes in the same configuration
- STDIO: Direct process communication with automatic socat TCP bridging
- HTTP: Native HTTP MCP servers with connection pooling
- SSE (Server-Sent Events): Real-time bidirectional communication
- TCP: Raw TCP connections for specialized MCP implementations
- OpenAPI 3.1.0: Full specification compliance for tool definitions
- FastAPI Compatibility: Direct tool invocation with automatic request/response validation
- Swagger UI Integration: Interactive API documentation for each server
- Schema Generation: Automatic parameter and response schema inference
Before using MCP-Compose, please review these security requirements:
- Never commit secrets to version control: All API keys, passwords, and tokens must be stored in environment variables
- Use strong credentials: Generate secure random strings for all API keys and passwords
- Follow the principle of least privilege: Run containers as non-root users and drop unnecessary capabilities
- Use the provided security templates: See
mcp-compose_example.yaml
for secure configuration patterns
Copy .env.example
to .env
and configure:
# Core authentication
MCP_API_KEY=your-secure-random-api-key-here
POSTGRES_PASSWORD=your-secure-database-password
# Optional external services
GITHUB_TOKEN=ghp_your-github-token-here
OPENROUTER_API_KEY=sk-or-v1-your-openrouter-api-key-here
OAUTH_CLIENT_SECRET=your-oauth-client-secret-here
Generate secure keys:
# Generate a secure API key
openssl rand -hex 32
# Or using /dev/urandom
head -c 32 /dev/urandom | base64
- Getting Started Guide - Complete 10-minute tutorial
- Basic Configuration - Simple 3-server example
- Quickstart - Minimal 1-server example
- Migration Guide - Step-by-step migration instructions
- From Docker Compose - Convert existing setups
- From Individual Servers - Centralize management
- Advanced Configuration - OAuth, audit logging, monitoring
- Security Best Practices - Production security guide
- Performance Tuning - Optimization and debugging
Create a mcp-compose.yaml
file:
version: '1'
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
Run with:
export MCP_API_KEY="your-secure-key-here"
./mcp-compose up
./mcp-compose proxy --port 9876
Your MCP servers are now available at http://localhost:9876
!
For a more complete setup with file access, memory, and search:
version: '1'
# Simple authentication
proxy_auth:
enabled: true
api_key: "${MCP_API_KEY}"
servers:
# File system access
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
volumes:
- "${HOME}/Documents:/workspace:ro"
# Persistent memory/notes
memory:
image: "mcp/memory:latest"
capabilities: [tools, resources]
env:
DATABASE_URL: "sqlite:///data/memory.db"
volumes:
- "mcp-memory-data:/data"
# Web search
search:
image: "mcp/search:latest"
capabilities: [tools]
env:
SEARCH_ENGINE: "duckduckgo"
volumes:
mcp-memory-data:
driver: local
For enterprise features like OAuth, audit logging, and complex deployments, see Advanced Configuration.
# Download for your platform
curl -LO https://github.com/phildougherty/mcp-compose/releases/latest/download/mcp-compose-linux-amd64
chmod +x mcp-compose-linux-amd64
sudo mv mcp-compose-linux-amd64 /usr/local/bin/mcp-compose
git clone https://github.com/phildougherty/mcp-compose.git
cd mcp-compose
make build
sudo cp build/mcp-compose /usr/local/bin/
# mcp-compose.yaml for developers
version: '1'
proxy_auth:
enabled: true
api_key: "${MCP_API_KEY}"
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
volumes:
- "${HOME}/code:/workspace:rw"
git:
image: "mcp/git:latest"
capabilities: [tools]
volumes:
- "${HOME}/.gitconfig:/root/.gitconfig:ro"
- "${HOME}/code:/workspace:rw"
# mcp-compose.yaml for writers/researchers
version: '1'
proxy_auth:
enabled: true
api_key: "${MCP_API_KEY}"
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
volumes:
- "${HOME}/Documents:/documents:rw"
search:
image: "mcp/search:latest"
capabilities: [tools]
env:
SEARCH_ENGINE: "duckduckgo"
memory:
image: "mcp/memory:latest"
capabilities: [tools, resources]
env:
DATABASE_URL: "sqlite:///data/notes.db"
volumes:
- "content-memory:/data"
volumes:
content-memory:
driver: local
For production deployments with OAuth, audit logging, monitoring, and advanced security, see mcp-compose-advanced.yaml.
# 1. Install mcp-compose (see Installation section above)
# 2. Create your first configuration
cat > mcp-compose.yaml << 'EOF'
version: '1'
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
EOF
# 3. Set your API key
export MCP_API_KEY=$(openssl rand -hex 32)
echo "Your API key: $MCP_API_KEY"
# 4. Start the servers
./mcp-compose up
# 5. Start the proxy in another terminal
./mcp-compose proxy --port 9876 --api-key "$MCP_API_KEY"
Your MCP servers are now running! Test with:
curl -H "Authorization: Bearer $MCP_API_KEY" http://localhost:9876/api/servers
# Stop current setup
./mcp-compose down
# Update configuration to add memory and search
cat > mcp-compose.yaml << 'EOF'
version: '1'
proxy_auth:
enabled: true
api_key: "${MCP_API_KEY}"
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
volumes:
- "${HOME}/Documents:/workspace:ro"
memory:
image: "mcp/memory:latest"
capabilities: [tools, resources]
env:
DATABASE_URL: "sqlite:///data/memory.db"
volumes:
- "mcp-memory:/data"
search:
image: "mcp/search:latest"
capabilities: [tools]
volumes:
mcp-memory:
driver: local
EOF
# Restart with new configuration
./mcp-compose up
./mcp-compose proxy --port 9876
# Generate Claude Desktop configuration
./mcp-compose create-config --type claude --output ./claude-config
# Copy the generated config to Claude Desktop settings
# Location varies by OS:
# - macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
# - Linux: ~/.config/Claude/claude_desktop_config.json
# - Windows: %APPDATA%\Claude\claude_desktop_config.json
If you're currently running individual MCP servers, migration is straightforward:
Before (individual servers):
npx @modelcontextprotocol/server-filesystem /path/to/files
npx @modelcontextprotocol/server-memory
After (mcp-compose):
version: '1'
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
volumes:
- "/path/to/files:/workspace:ro"
memory:
image: "mcp/memory:latest"
capabilities: [tools, resources]
If you're already using Docker Compose for MCP servers:
Before (docker-compose.yml):
version: '3.8'
services:
mcp-filesystem:
image: mcp/filesystem
ports:
- "3000:3000"
After (mcp-compose.yaml):
version: '1'
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
Benefits of migrating:
- ✅ Built-in MCP protocol support
- ✅ Automatic service discovery
- ✅ Unified HTTP proxy
- ✅ Claude Desktop integration
- ✅ Health monitoring and restarts
Before (manual Claude Desktop config):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem", "/path"],
"env": {}
}
}
}
After (with mcp-compose):
- Create
mcp-compose.yaml
(see examples above) - Run
./mcp-compose create-config --type claude
- Replace your Claude Desktop config with the generated one
version: '1'
proxy_auth:
enabled: true
api_key: "${MCP_API_KEY}" # Set via environment variable
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
version: '1'
# No proxy_auth section = no authentication required
servers:
filesystem:
image: "mcp/filesystem:latest"
capabilities: [resources, tools]
For OAuth 2.1, RBAC, audit logging, and enterprise features, see mcp-compose-advanced.yaml.
# Generate configuration
./mcp-compose create-config --type claude --output ./claude-config
# Your servers will be available as:
# - http://localhost:9876/filesystem
# - http://localhost:9876/memory
# - http://localhost:9876/search
Each server provides its own OpenAPI endpoint:
# Filesystem server API docs
curl http://localhost:9876/filesystem/openapi.json
# Memory server API docs
curl http://localhost:9876/memory/openapi.json
Direct HTTP API access:
# List available tools
curl -H "Authorization: Bearer $MCP_API_KEY" \
http://localhost:9876/filesystem -X POST \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Call a tool
curl -H "Authorization: Bearer $MCP_API_KEY" \
http://localhost:9876/filesystem -X POST \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"read_file","arguments":{"path":"/workspace/README.md"}}}'
"Server not found" error:
# Check if servers are running
./mcp-compose ls
# Check logs for errors
./mcp-compose logs filesystem
"Connection refused" error:
# Ensure proxy is running
./mcp-compose proxy --port 9876
# Check if port is already in use
lsof -i :9876
Authentication errors:
# Verify API key is set
echo $MCP_API_KEY
# Check proxy authentication config
grep -A5 "proxy_auth:" mcp-compose.yaml
# Enable debug logging
export MCP_LOG_LEVEL=debug
./mcp-compose up
# View detailed proxy logs
./mcp-compose proxy --port 9876 --debug
# Add connection timeouts (optional)
connections:
default:
timeouts:
connect: "10s"
read: "30s"
write: "30s"
idle: "60s"
For complete configuration reference, see mcp-compose-advanced.yaml
Client → HTTP Proxy → [Protocol Translation] → MCP Server
↓
[STDIO|HTTP|SSE|TCP]
Docker Network (mcp-net)
├── mcp-compose-filesystem (HTTP:3000)
├── mcp-compose-memory (STDIO→TCP:12347)
├── mcp-compose-cron (SSE:8080)
└── mcp-compose-postgres (TCP:5432)
- Persistent HTTP connections with connection pooling
- Automatic MCP session initialization and cleanup
- Cross-request session state preservation
- Health monitoring with automatic reconnection
- Fork the repository
- Create a feature branch
- Follow Go coding standards and add tests
- Update documentation for new features
- Submit a pull request with detailed description
# Install dependencies
go mod download
# Run tests
go test ./...
# Build with development flags
go build -tags dev -o mcp-compose-dev cmd/mcp-compose/main.go
# Run linter
golangci-lint run
This project is licensed under the MIT License - see the LICENSE file for details.