cforge gateway - Deployment Tool
Overview
The cforge gateway command is a powerful deployment tool for ContextForge and its external plugins. It provides a unified, declarative way to build, configure, and deploy the complete MCP stack from a single YAML configuration file.
Quick Start
Installation
The cforge CLI is installed with ContextForge package:
pip install -e .
Verify installation:
cforge --help
cforge gateway --help
Basic Workflow
# 1. Validate your configuration
cforge gateway validate examples/deployment-configs/deploy-compose.yaml
# 2. Build containers (if building from source)
cforge gateway build examples/deployment-configs/deploy-compose.yaml
# 3. Generate mTLS certificates (if needed)
cforge gateway certs examples/deployment-configs/deploy-compose.yaml
# 4. Deploy the stack
cforge gateway deploy examples/deployment-configs/deploy-compose.yaml
# 5. Verify deployment health
cforge gateway verify examples/deployment-configs/deploy-compose.yaml
# 6. (Optional) Tear down
cforge gateway destroy examples/deployment-configs/deploy-compose.yaml
Simple Configuration Example
The cforge gateway tool uses custom YAML configuration files to describe your deployment. These are not standard Docker Compose or Kubernetes manifests - instead, cforge reads these configuration files and generates the actual deployment manifests for your target environment.
Here's a minimal example configuration that demonstrates the key components:
deployment:
type: compose # Target: 'compose' or 'kubernetes'
project_name: mcp-stack-test
gateway:
image: mcpgateway/mcpgateway:latest # Use pre-built image
port: 4444
host_port: 4444 # Expose on localhost:4444
env_vars:
LOG_LEVEL: DEBUG
MCPGATEWAY_UI_ENABLED: "true"
AUTH_REQUIRED: "false" # Simplified for testing
mtls_enabled: false # Disable mTLS for simple setup
plugins:
- name: OPAPluginFilter
repo: https://github.com/terylt/mcp-context-forge.git
ref: feat/use_mtls_plugins # Git branch/tag/commit
context: plugins/external/opa # Build context path
containerfile: Containerfile
expose_port: true
mtls_enabled: false
plugin_overrides:
priority: 10
mode: "enforce"
description: "OPA policy enforcement"
certificates:
auto_generate: true # Auto-generate certs if needed
Key sections explained:
- deployment: Specifies the target environment (Docker Compose or Kubernetes) and basic settings
- gateway: Defines ContextForge configuration - can use a pre-built image or build from a Git repository
- plugins: Array of external plugins to deploy. Each plugin can be built from source or use pre-built images
- certificates: mTLS certificate configuration (auto-generated by default)
How it works:
When you run cforge gateway deploy <config-file>, the tool:
Reads your custom configuration YAML
Builds container images (if building from source)
Generates mTLS certificates (if needed)
Generates actual deployment files:
- For
type: compose→deploy/docker-compose.yaml - For
type: kubernetes→deploy/manifests/*.yaml(Deployment, Service, ConfigMap, etc.)
- For
Deploys the generated manifests to your target environment
Additional example configurations are available in examples/deployment-configs/:
deploy-compose.yaml- Docker Compose without mTLSdeploy-compose.mtls.yaml- Docker Compose with mTLSdeploy-k8s.yaml- Kubernetes with pre-built imagesdeploy-k8s-cert-manager.yaml- Kubernetes with cert-manager integration- More examples for OpenShift, registry integration, and advanced scenarios
See the Example Configurations section below for detailed examples with full explanations.
Commands
cforge gateway validate
Validates the deployment configuration file without making any changes.
cforge gateway validate <config-file>
Example:
cforge gateway validate deploy.yaml
Output:
- ✅ Configuration syntax validation
- ✅ Plugin name uniqueness check
- ✅ Required field verification
- ✅ Build configuration validation (image XOR repo)
cforge gateway build
Builds container images for gateway and/or plugins from source repositories.
cforge gateway build <config-file> [OPTIONS]
Options:
| Option | Description | Default |
|---|---|---|
--plugins-only |
Only build plugin containers, skip gateway | false |
--plugin NAME, -p NAME |
Build specific plugin(s) only (can specify multiple) | All plugins |
--no-cache |
Disable Docker build cache | false |
--copy-env-templates |
Copy .env.template files from plugin repos |
true |
Examples:
# Build everything
cforge gateway build deploy.yaml
# Build only plugins
cforge gateway build deploy.yaml --plugins-only
# Build specific plugin
cforge gateway build deploy.yaml --plugin OPAPluginFilter
# Build multiple plugins with no cache
cforge gateway build deploy.yaml --plugin OPAPluginFilter --plugin LLMGuardPlugin --no-cache
What it does:
- Clones Git repositories (if
repospecified) - Checks out specified branch/tag/commit (
ref) - Builds Docker images from
containerfileincontextdirectory - Tags images appropriately for deployment
- Copies
.env.templatefiles todeploy/env/for customization
cforge gateway certs
Generates mTLS certificate hierarchy for secure gateway ↔ plugin communication.
cforge gateway certs <config-file>
Example:
cforge gateway certs deploy.yaml
What it generates:
certs/mcp/
├── ca/
│ ├── ca.crt # Root CA certificate
│ └── ca.key # Root CA private key
├── gateway/
│ ├── client.crt # Gateway client certificate
│ ├── client.key # Gateway client private key
│ └── ca.crt # CA cert (for verification)
└── plugins/
├── PluginName1/
│ ├── server.crt # Plugin server certificate
│ ├── server.key # Plugin server private key
│ └── ca.crt # CA cert (for verification)
└── PluginName2/
├── server.crt
├── server.key
└── ca.crt
Certificate Properties:
- Validity: Configurable (default: 825 days)
- CN for gateway:
mcp-gateway - CN for plugins:
mcp-plugin-{PluginName} - SANs:
{PluginName}, mcp-plugin-{PluginName}, localhost
cforge gateway deploy
Deploys the complete MCP stack to the target environment.
cforge gateway deploy <config-file> [OPTIONS]
Options:
| Option | Description | Default |
|---|---|---|
--output-dir DIR, -o DIR |
Custom output directory for manifests | deploy/ |
--dry-run |
Generate manifests without deploying | false |
--skip-build |
Skip container build step | false |
--skip-certs |
Skip certificate generation | false |
Examples:
# Full deployment
cforge gateway deploy deploy.yaml
# Dry-run (generate manifests only)
cforge gateway deploy deploy.yaml --dry-run
# Deploy with existing images and certs
cforge gateway deploy deploy.yaml --skip-build --skip-certs
# Custom output directory
cforge gateway deploy deploy.yaml --output-dir ./my-deployment
Deployment Process:
Validate configuration
Build containers (unless
--skip-build)Generate certificates (unless
--skip-certsor already exist)Generate manifests (Kubernetes or Docker Compose)
Apply to target environment:
- Kubernetes:
kubectl apply -f - Docker Compose:
docker-compose up -d
- Kubernetes:
Generated Files:
deploy/
├── env/ # Environment files
│ ├── .env.gateway
│ ├── .env.PluginName1
│ └── .env.PluginName2
├── manifests/ # Kubernetes OR
│ ├── namespace.yaml
│ ├── configmaps.yaml
│ ├── secrets.yaml
│ ├── gateway-deployment.yaml
│ ├── gateway-service.yaml
│ ├── plugin-deployments.yaml
│ └── plugin-services.yaml
└── docker-compose.yaml # Docker Compose
cforge gateway verify
Verifies that the deployed stack is healthy and running.
cforge gateway verify <config-file> [OPTIONS]
Options:
| Option | Description | Default |
|---|---|---|
--wait |
Wait for deployment to be ready | true |
--timeout SECONDS |
Wait timeout in seconds | 300 |
Examples:
# Verify deployment (wait up to 5 minutes)
cforge gateway verify deploy.yaml
# Quick check without waiting
cforge gateway verify deploy.yaml --no-wait
# Custom timeout
cforge gateway verify deploy.yaml --timeout 600
Checks:
- Container/pod readiness
- Health endpoint responses
- Service connectivity
- mTLS handshake (if enabled)
cforge gateway destroy
Tears down the deployed MCP stack.
cforge gateway destroy <config-file> [OPTIONS]
Options:
| Option | Description | Default |
|---|---|---|
--force |
Skip confirmation prompt | false |
Examples:
# Destroy with confirmation
cforge gateway destroy deploy.yaml
# Force destroy without prompt
cforge gateway destroy deploy.yaml --force
What it removes:
- Kubernetes: Deletes all resources in namespace
- Docker Compose: Stops and removes containers, networks, volumes
⚠️ Note: This does NOT delete generated certificates or build artifacts. To clean those:
rm -rf certs/ deploy/
cforge gateway generate
Generates deployment manifests without deploying them.
cforge gateway generate <config-file> [OPTIONS]
Options:
| Option | Description | Default |
|---|---|---|
--output DIR, -o DIR |
Output directory for manifests | deploy/ |
Examples:
# Generate manifests
cforge gateway generate deploy.yaml
# Custom output directory
cforge gateway generate deploy.yaml --output ./manifests
Use cases:
- GitOps workflows (commit generated manifests)
- Manual review before deployment
- Integration with external deployment tools
- CI/CD pipeline artifact generation
cforge gateway version
Shows version and runtime information.
cforge gateway version
Output:
┌─ Version Info ─────────────────┐
│ MCP Deploy │
│ Version: 1.0.0 │
│ Mode: dagger │
│ Environment: local │
└────────────────────────────────┘
Global Options
These options apply to all commands:
| Option | Description | Default |
|---|---|---|
--dagger |
Enable Dagger mode (auto-downloads CLI if needed) | false (uses plain Python) |
--verbose, -v |
Verbose output | false |
Examples:
# Use plain Python mode (default)
cforge gateway deploy deploy.yaml
# Enable Dagger mode for optimized builds
cforge gateway --dagger deploy deploy.yaml
# Verbose mode
cforge gateway -v build deploy.yaml
# Combine options
cforge gateway --dagger -v deploy deploy.yaml
Configuration Reference
Deployment Configuration
Top-level deployment settings:
deployment:
type: kubernetes | compose # Required: Deployment target
project_name: my-project # Docker Compose only
namespace: mcp-gateway # Kubernetes only
container_engine: podman | docker # Container runtime (auto-detected if not specified)
# OpenShift-specific configuration (optional)
openshift:
create_routes: true # Create OpenShift Route resources
domain: apps-crc.testing # OpenShift apps domain (auto-detected if omitted)
tls_termination: edge # TLS termination mode: edge, passthrough, or reencrypt
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
type |
string | ✅ | Deployment type: kubernetes or compose |
- |
project_name |
string | ❌ | Docker Compose project name | - |
namespace |
string | ❌ | Kubernetes namespace | - |
container_engine |
string | ❌ | Container runtime: docker or podman |
Auto-detected |
openshift |
object | ❌ | OpenShift-specific configuration (see below) | - |
OpenShift Configuration
OpenShift Routes provide native external access to services, with built-in TLS termination and integration with OpenShift's router/HAProxy infrastructure.
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
create_routes |
boolean | ❌ | Create OpenShift Route resources for external access | false |
domain |
string | ❌ | OpenShift apps domain for route hostnames | Auto-detected from cluster |
tls_termination |
string | ❌ | TLS termination mode: edge, passthrough, or reencrypt |
edge |
Example:
deployment:
type: kubernetes
namespace: mcp-gateway-test
openshift:
create_routes: true
domain: apps-crc.testing
tls_termination: edge
When create_routes: true, the tool generates an OpenShift Route for the gateway:
- Host:
mcpgateway-admin-{namespace}.{domain} - Path:
/ - TLS: Edge termination (default)
- Target: Gateway service on HTTP port
Access the gateway:
# OpenShift Local (CRC) example
https://mcpgateway-admin-mcp-gateway-test.apps-crc.testing
Domain auto-detection:
If domain is not specified, the tool attempts to auto-detect the OpenShift apps domain from the cluster:
kubectl get ingresses.config.openshift.io cluster -o jsonpath='{.spec.domain}'
If auto-detection fails, it defaults to apps-crc.testing (OpenShift Local).
Gateway Configuration
Gateway server settings:
gateway:
# Build Configuration (choose ONE)
image: mcpgateway/mcpgateway:latest # Pre-built image
# OR
repo: https://github.com/org/repo.git # Build from source
ref: main # Git branch/tag/commit
context: . # Build context directory
containerfile: Containerfile # Dockerfile path
target: production # Multi-stage build target
# Runtime Configuration
port: 4444 # Internal port
host_port: 4444 # Host port mapping (compose only)
# mTLS Client Configuration (gateway → plugins)
mtls_enabled: true # Enable mTLS
mtls_verify: true # Verify server certs
mtls_check_hostname: false # Verify hostname
# Container Registry Configuration (optional)
registry:
enabled: true # Enable registry push
url: registry.example.com # Registry URL
namespace: myproject # Registry namespace/org
push: true # Push after build
image_pull_policy: IfNotPresent # Kubernetes imagePullPolicy
# Environment Variables
env_vars:
LOG_LEVEL: INFO
MCPGATEWAY_UI_ENABLED: "true"
AUTH_REQUIRED: "true"
# ... (see full reference below)
# Kubernetes-specific
replicas: 2 # Number of replicas
service_type: ClusterIP # Service type
service_port: 4444 # Service port
memory_request: 256Mi # Memory request
memory_limit: 512Mi # Memory limit
cpu_request: 100m # CPU request
cpu_limit: 500m # CPU limit
image_pull_policy: IfNotPresent # Image pull policy
Build Configuration Fields:
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
image |
string | ❌* | Pre-built Docker image | - |
repo |
string | ❌* | Git repository URL | - |
ref |
string | ❌ | Git branch/tag/commit | main |
context |
string | ❌ | Build context subdirectory | . |
containerfile |
string | ❌ | Containerfile/Dockerfile path | Containerfile |
target |
string | ❌ | Multi-stage build target | - |
* Either image OR repo must be specified
Runtime Configuration Fields:
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
port |
integer | ❌ | Internal container port | 4444 |
host_port |
integer | ❌ | Host port mapping (compose only) | - |
env_vars |
object | ❌ | Environment variables | {} |
mtls_enabled |
boolean | ❌ | Enable mTLS client | true |
mtls_verify |
boolean | ❌ | Verify server certificates | true |
mtls_check_hostname |
boolean | ❌ | Verify hostname in cert | false |
registry |
object | ❌ | Container registry configuration | - |
Container Registry Configuration Fields:
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
enabled |
boolean | ❌ | Enable registry integration | false |
url |
string | ❌* | Registry URL (e.g., docker.io, quay.io, OpenShift registry) |
- |
namespace |
string | ❌* | Registry namespace/organization/project | - |
push |
boolean | ❌ | Push image to registry after build | true |
image_pull_policy |
string | ❌ | Kubernetes imagePullPolicy (Always, IfNotPresent, Never) |
IfNotPresent |
* Required when enabled: true
Kubernetes-specific Fields:
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
replicas |
integer | ❌ | Number of pod replicas | 1 |
service_type |
string | ❌ | Service type (ClusterIP, NodePort, LoadBalancer) | ClusterIP |
service_port |
integer | ❌ | Service port | 4444 |
memory_request |
string | ❌ | Memory request | 256Mi |
memory_limit |
string | ❌ | Memory limit | 512Mi |
cpu_request |
string | ❌ | CPU request | 100m |
cpu_limit |
string | ❌ | CPU limit | 500m |
image_pull_policy |
string | ❌ | Image pull policy | IfNotPresent |
Plugin Configuration
External plugin settings (array of plugin objects):
plugins:
- name: MyPlugin # Required: Unique plugin name
# Build Configuration (choose ONE)
image: myorg/myplugin:latest # Pre-built image
# OR
repo: https://github.com/org/repo.git # Build from source
ref: main
context: plugins/myplugin
containerfile: Containerfile
target: builder
# Runtime Configuration
port: 8000 # Internal port
expose_port: true # Expose on host (compose only)
# mTLS Server Configuration (plugin server)
mtls_enabled: true # Enable mTLS server
# Container Registry Configuration (optional)
registry:
enabled: true # Enable registry push
url: registry.example.com # Registry URL
namespace: myproject # Registry namespace/org
push: true # Push after build
image_pull_policy: IfNotPresent # Kubernetes imagePullPolicy
# Environment Variables
env_vars:
LOG_LEVEL: DEBUG
CUSTOM_SETTING: value
# Plugin Manager Overrides (client-side)
plugin_overrides:
priority: 10
mode: enforce
description: "My custom plugin"
tags: ["security", "filter"]
# Kubernetes-specific
replicas: 1
service_type: ClusterIP
service_port: 8000
memory_request: 128Mi
memory_limit: 256Mi
cpu_request: 50m
cpu_limit: 200m
image_pull_policy: IfNotPresent
Required Fields:
| Field | Type | Description |
|---|---|---|
name |
string | Unique plugin identifier (used for cert CN, service names, etc.) |
Build Configuration: Same as Gateway (see above)
Runtime Configuration:
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
port |
integer | ❌ | Internal container port | 8000 |
expose_port |
boolean | ❌ | Expose port on host (compose only) | false |
env_vars |
object | ❌ | Environment variables | {} |
mtls_enabled |
boolean | ❌ | Enable mTLS server | true |
registry |
object | ❌ | Container registry configuration (same fields as gateway) | - |
plugin_overrides |
object | ❌ | Plugin manager config overrides | {} |
Plugin Overrides:
| Field | Type | Description | Default |
|---|---|---|---|
priority |
integer | Plugin execution priority (lower = earlier) | - |
mode |
string | enforce, monitor, or dry-run |
- |
description |
string | Plugin description | - |
tags |
array | Plugin tags for categorization | - |
hooks |
array | Enabled hooks: prompt_pre_fetch, tool_pre_invoke, etc. |
All hooks |
Kubernetes-specific: Same as Gateway (see above)
Certificate Configuration
mTLS certificate generation settings:
certificates:
# Local certificate generation (default)
validity_days: 825 # Certificate validity period
auto_generate: true # Auto-generate if missing
ca_path: ./certs/mcp/ca # CA certificate directory
gateway_path: ./certs/mcp/gateway # Gateway cert directory
plugins_path: ./certs/mcp/plugins # Plugins cert directory
# OR use cert-manager (Kubernetes only)
use_cert_manager: true # Use cert-manager for certificates
cert_manager_issuer: mcp-ca-issuer # Issuer/ClusterIssuer name
cert_manager_kind: Issuer # Issuer or ClusterIssuer
| Field | Type | Required | Description | Default |
|---|---|---|---|---|
validity_days |
integer | ❌ | Certificate validity in days | 825 |
auto_generate |
boolean | ❌ | Auto-generate certificates locally if missing | true |
ca_path |
string | ❌ | CA certificate directory (local mode) | ./certs/mcp/ca |
gateway_path |
string | ❌ | Gateway client cert directory (local mode) | ./certs/mcp/gateway |
plugins_path |
string | ❌ | Plugin server certs base directory (local mode) | ./certs/mcp/plugins |
use_cert_manager |
boolean | ❌ | Use cert-manager for certificate management (Kubernetes only) | false |
cert_manager_issuer |
string | ❌ | cert-manager Issuer/ClusterIssuer name | mcp-ca-issuer |
cert_manager_kind |
string | ❌ | cert-manager issuer kind: Issuer or ClusterIssuer |
Issuer |
cert-manager Integration (Kubernetes Only)
cert-manager is a Kubernetes-native certificate management controller that automates certificate issuance and renewal.
Benefits:
- ✅ Automatic Renewal: Certificates renewed before expiry (default: at 2/3 of lifetime)
- ✅ Native Kubernetes: Certificates defined as Kubernetes Custom Resources
- ✅ Simplified Operations: No manual certificate generation or rotation
- ✅ GitOps Friendly: Certificate definitions version-controlled
Prerequisites:
Install cert-manager in your cluster:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yamlCreate namespace and CA Issuer (one-time setup):
# Create namespace first kubectl create namespace mcp-gateway-test # Apply CA Issuer kubectl apply -f examples/deployment-configs/cert-manager-issuer-example.yaml
Configuration:
certificates:
use_cert_manager: true
cert_manager_issuer: mcp-ca-issuer
cert_manager_kind: Issuer
validity_days: 825
When use_cert_manager: true:
- Local certificate generation is skipped
- cert-manager Certificate CRDs are generated for gateway and plugins
- cert-manager automatically creates Kubernetes TLS secrets
- Certificates are auto-renewed before expiry
Important: The cert-manager Issuer and CA certificate are long-lived infrastructure. When you destroy your MCP deployment, the Issuer remains (by design) for reuse across deployments.
Infrastructure Services
PostgreSQL and Redis are automatically deployed with ContextForge stack using hardcoded defaults:
PostgreSQL (always deployed):
- Image:
postgres:17 - Database:
mcp - User:
postgres - Password:
mysecretpassword(override withPOSTGRES_PASSWORDenv var) - Port:
5432 - Kubernetes: Uses 10Gi PVC
Redis (always deployed):
- Image:
redis:latest - Port:
6379
Connection strings (auto-configured):
DATABASE_URL=postgresql+psycopg://postgres:${POSTGRES_PASSWORD}@postgres:5432/mcp
REDIS_URL=redis://redis:6379/0
These services are included in all deployments and cannot currently be disabled or customized via the deployment YAML. To customize PostgreSQL password:
# Set before deploying
export POSTGRES_PASSWORD=your-secure-password
cforge gateway deploy deploy.yaml
Example Configurations
Example 1: Docker Compose (No mTLS)
File: examples/deployment-configs/deploy-compose.yaml
Simple local deployment for development and testing:
deployment:
type: compose
project_name: mcp-stack-test
gateway:
image: mcpgateway/mcpgateway:latest
port: 4444
host_port: 4444
env_vars:
LOG_LEVEL: DEBUG
MCPGATEWAY_UI_ENABLED: "true"
AUTH_REQUIRED: "false"
mtls_enabled: false
plugins:
- name: OPAPluginFilter
repo: https://github.com/terylt/mcp-context-forge.git
ref: feat/use_mtls_plugins
context: plugins/external/opa
expose_port: true
mtls_enabled: false
plugin_overrides:
priority: 10
mode: "enforce"
certificates:
auto_generate: true
Use case: Quick local testing without security overhead
Deploy:
cforge gateway deploy examples/deployment-configs/deploy-compose.yaml
Access:
- Gateway: http://localhost:4444
- Admin UI: http://localhost:4444/admin
- Plugin (exposed): http://localhost:8000
Example 2: Docker Compose (With mTLS)
File: examples/deployment-configs/deploy-compose.mtls.yaml
Secure local deployment with mutual TLS:
deployment:
type: compose
project_name: mcp-stack-test
gateway:
image: mcpgateway/mcpgateway:latest
port: 4444
host_port: 4444
mtls_enabled: true # ← Enable mTLS client
mtls_verify: true
mtls_check_hostname: false # Don't verify hostname for localhost
plugins:
- name: OPAPluginFilter
repo: https://github.com/terylt/mcp-context-forge.git
ref: feat/use_mtls_plugins
context: plugins/external/opa
mtls_enabled: true # ← Enable mTLS server
plugin_overrides:
priority: 10
mode: "enforce"
certificates:
validity_days: 825
auto_generate: true # Auto-generate mTLS certs
Use case: Local testing with production-like security
Deploy:
# Certificates are auto-generated during deploy
cforge gateway deploy examples/deployment-configs/deploy-compose.mtls.yaml
How mTLS works:
cforge gateway certsgenerates CA + gateway client cert + plugin server certs- Gateway connects to plugins using client certificate
- Plugins verify gateway's client certificate against CA
- All communication is encrypted and mutually authenticated
Example 3: Kubernetes (Pre-built Images)
File: examples/deployment-configs/deploy-k8s.yaml
Production-ready Kubernetes deployment using pre-built images:
deployment:
type: kubernetes
namespace: mcp-gateway-prod
gateway:
image: mcpgateway/mcpgateway:latest
image_pull_policy: IfNotPresent
replicas: 2 # High availability
service_type: LoadBalancer
service_port: 4444
memory_request: 256Mi
memory_limit: 512Mi
cpu_request: 100m
cpu_limit: 500m
mtls_enabled: true
plugins:
- name: OPAPluginFilter
image: mcpgateway-opapluginfilter:latest
image_pull_policy: IfNotPresent
replicas: 2
service_type: ClusterIP
memory_request: 128Mi
memory_limit: 256Mi
cpu_request: 50m
cpu_limit: 200m
mtls_enabled: true
plugin_overrides:
priority: 10
mode: "enforce"
infrastructure:
postgres:
enabled: true
storage_size: 20Gi
storage_class: fast-ssd
redis:
enabled: true
certificates:
auto_generate: true
Use case: Production deployment with HA and resource limits
Deploy:
# Deploy to Kubernetes
cforge gateway deploy examples/deployment-configs/deploy-k8s.yaml
# Verify
kubectl get all -n mcp-gateway-prod
# Check logs
kubectl logs -n mcp-gateway-prod -l app=mcp-gateway
Example 4: Kubernetes (Build from Source)
Building plugins from Git repositories in Kubernetes:
deployment:
type: kubernetes
namespace: mcp-gateway-dev
gateway:
image: mcpgateway/mcpgateway:latest
plugins:
- name: OPAPluginFilter
# Build from source
repo: https://github.com/terylt/mcp-context-forge.git
ref: feat/use_mtls_plugins
context: plugins/external/opa
containerfile: Containerfile
# Push to registry (configure with env vars)
# See DOCKER_REGISTRY in deploy process
replicas: 1
mtls_enabled: true
certificates:
auto_generate: true
Deploy:
# Build locally and push to registry
export DOCKER_REGISTRY=myregistry.io/myorg
cforge gateway build deploy-k8s-build.yaml
# Deploy to Kubernetes
cforge gateway deploy deploy-k8s-build.yaml --skip-build
Example 5: Kubernetes with cert-manager
File: examples/deployment-configs/deploy-k8s-cert-manager.yaml
Production deployment using cert-manager for automated certificate management:
deployment:
type: kubernetes
namespace: mcp-gateway-test
gateway:
image: mcpgateway/mcpgateway:latest
image_pull_policy: IfNotPresent
port: 4444
service_type: ClusterIP
service_port: 4444
replicas: 1
memory_request: 256Mi
memory_limit: 512Mi
cpu_request: 100m
cpu_limit: 500m
env_vars:
LOG_LEVEL: DEBUG
MCPGATEWAY_UI_ENABLED: "true"
mtls_enabled: true
mtls_verify: true
mtls_check_hostname: false
plugins:
- name: OPAPluginFilter
image: mcpgateway-opapluginfilter:latest
image_pull_policy: IfNotPresent
port: 8000
service_type: ClusterIP
replicas: 1
memory_request: 128Mi
memory_limit: 256Mi
mtls_enabled: true
plugin_overrides:
priority: 10
mode: "enforce"
# cert-manager configuration
certificates:
# Use cert-manager for automatic certificate management
use_cert_manager: true
# Reference the Issuer created in prerequisites
cert_manager_issuer: mcp-ca-issuer
cert_manager_kind: Issuer
# Certificate validity (auto-renewed at 2/3 of lifetime)
validity_days: 825
# Local paths not used when use_cert_manager=true
auto_generate: false
Prerequisites:
Install cert-manager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yamlCreate namespace and CA Issuer (one-time setup):
# Create namespace first kubectl create namespace mcp-gateway-test # Apply CA Issuer kubectl apply -f examples/deployment-configs/cert-manager-issuer-example.yaml
Deploy:
# Deploy (no need to generate certificates manually)
cforge gateway deploy examples/deployment-configs/deploy-k8s-cert-manager.yaml
# Verify cert-manager created certificates
kubectl get certificates -n mcp-gateway-test
kubectl get secrets -n mcp-gateway-test | grep mcp-
How it works:
cforge gateway deployskips local certificate generation- Generates cert-manager Certificate CRDs for gateway and plugins
- Applies Certificate CRDs to Kubernetes
- cert-manager automatically creates TLS secrets
- Pods use the secrets created by cert-manager
- cert-manager auto-renews certificates before expiry
Certificate lifecycle:
- Creation: cert-manager generates certificates when CRDs are applied
- Renewal: Automatic renewal at 2/3 of lifetime (550 days for 825-day cert)
- Deletion: Certificates deleted when stack is destroyed, Issuer remains
mTLS Configuration Guide
Understanding mTLS in ContextForge
mTLS (Mutual TLS) provides:
- Encryption: All gateway ↔ plugin traffic is encrypted
- Authentication: Both parties prove their identity
- Authorization: Only trusted certificates can communicate
Certificate Hierarchy
CA (Root Certificate Authority)
├── Gateway Client Certificate
│ └── Used by gateway to connect to plugins
└── Plugin Server Certificates (one per plugin)
└── Used by plugins to authenticate gateway
Enabling mTLS
In your configuration:
gateway:
mtls_enabled: true # Enable mTLS client
mtls_verify: true # Verify server certificates
mtls_check_hostname: false # Skip hostname verification (for localhost/IPs)
plugins:
- name: MyPlugin
mtls_enabled: true # Enable mTLS server
Certificate Generation
Automatic (recommended):
certificates:
auto_generate: true # Auto-generate during deploy
validity_days: 825 # ~2.3 years
Manual:
# Generate certificates explicitly
cforge gateway certs deploy.yaml
# Certificates are created in:
# - certs/mcp/ca/ (CA)
# - certs/mcp/gateway/ (gateway client cert)
# - certs/mcp/plugins/*/ (plugin server certs)
Environment Variables
The deployment tool automatically sets these environment variables:
Gateway (client):
PLUGINS_CLIENT_MTLS_CERTFILE=/certs/gateway/client.crt
PLUGINS_CLIENT_MTLS_KEYFILE=/certs/gateway/client.key
PLUGINS_CLIENT_MTLS_CA_BUNDLE=/certs/gateway/ca.crt
PLUGINS_CLIENT_MTLS_VERIFY=true
PLUGINS_CLIENT_MTLS_CHECK_HOSTNAME=false
Plugin (server):
PLUGINS_SERVER_SSL_CERTFILE=/certs/server.crt
PLUGINS_SERVER_SSL_KEYFILE=/certs/server.key
PLUGINS_SERVER_SSL_CA_CERTS=/certs/ca.crt
PLUGINS_SERVER_SSL_CERT_REQS=2 # CERT_REQUIRED
Troubleshooting mTLS
Problem: Certificate verification fails
Check certificate validity:
openssl x509 -in certs/mcp/gateway/client.crt -noout -dates
openssl x509 -in certs/mcp/plugins/MyPlugin/server.crt -noout -dates
Problem: Hostname mismatch errors
Solution: Set mtls_check_hostname: false in gateway config, or use service DNS names
Problem: Connection refused
- Verify plugin has
mtls_enabled: true - Check plugin logs for certificate errors
- Ensure certificates are mounted correctly
Problem: Expired certificates
Regenerate:
rm -rf certs/
cforge gateway certs deploy.yaml
Then redeploy to distribute new certificates.
Container Registry Integration
Overview
The container registry feature allows you to build images locally and automatically push them to container registries (Docker Hub, Quay.io, OpenShift internal registry, private registries, etc.). This is essential for:
✅ Kubernetes/OpenShift deployments - Avoid ImagePullBackOff errors ✅ Team collaboration - Share images across developers and environments ✅ CI/CD pipelines - Build once, deploy everywhere ✅ Production deployments - Use trusted registry sources
How It Works
- Build: Images are built locally using docker/podman
- Tag: Images are automatically tagged with the registry path
- Push: Images are pushed to the registry (if
push: true) - Deploy: Kubernetes manifests reference the registry images
Configuration
Add a registry section to your gateway and/or plugin configurations:
gateway:
repo: https://github.com/yourorg/yourrepo.git
# Container registry configuration
registry:
enabled: true # Enable registry integration
url: registry.example.com # Registry URL
namespace: myproject # Registry namespace/org/project
push: true # Push after build (default: true)
image_pull_policy: IfNotPresent # Kubernetes imagePullPolicy
Configuration Fields:
| Field | Required | Description | Example |
|---|---|---|---|
enabled |
Yes | Enable registry push | true |
url |
Yes* | Registry URL | docker.io, quay.io, registry.mycompany.com |
namespace |
Yes* | Registry namespace/organization/project | myusername, myorg, mcp-gateway-test |
push |
No | Push image after build | true (default) |
image_pull_policy |
No | Kubernetes imagePullPolicy | IfNotPresent (default) |
* Required when enabled: true
Common Registry Examples
Docker Hub
registry:
enabled: true
url: docker.io
namespace: myusername
push: true
image_pull_policy: IfNotPresent
Authentication:
docker login
Quay.io
registry:
enabled: true
url: quay.io
namespace: myorganization
push: true
image_pull_policy: IfNotPresent
Authentication:
podman login quay.io
OpenShift Internal Registry
registry:
enabled: true
url: default-route-openshift-image-registry.apps-crc.testing
namespace: mcp-gateway-test
push: true
image_pull_policy: Always
Authentication:
# OpenShift Local (CRC)
podman login $(oc registry info) -u $(oc whoami) -p $(oc whoami -t)
# OpenShift on cloud
oc registry login
Private Registry
registry:
enabled: true
url: registry.mycompany.com
namespace: devteam
push: true
image_pull_policy: IfNotPresent
Authentication:
podman login registry.mycompany.com -u myusername
Image Naming
When registry is enabled, images are automatically tagged with the full registry path:
Local tag (without registry):
mcpgateway-gateway:latest
mcpgateway-opapluginfilter:latest
Registry tag (with registry enabled):
registry.example.com/myproject/mcpgateway-gateway:latest
registry.example.com/myproject/mcpgateway-opapluginfilter:latest
Image Pull Policies
Choose the appropriate policy for your use case:
| Policy | Description | Best For |
|---|---|---|
Always |
Pull image every time pod starts | Development, testing latest changes |
IfNotPresent |
Pull only if image doesn't exist locally | Production, stable releases |
Never |
Never pull, only use local images | Air-gapped environments |
Workflow Example
OpenShift Local Deployment
# 1. Authenticate to OpenShift registry
podman login $(oc registry info) -u $(oc whoami) -p $(oc whoami -t)
# 2. Build and push images
cforge gateway deploy examples/deployment-configs/deploy-openshift-local-registry.yaml
# The tool will:
# - Build images locally
# - Tag with registry paths
# - Push to OpenShift internal registry
# - Generate manifests with registry image references
# - Deploy to cluster
# 3. Verify images were pushed
oc get imagestreams -n mcp-gateway-test
# Output:
# NAME IMAGE REPOSITORY
# mcpgateway-gateway default-route-.../mcp-gateway-test/mcpgateway-gateway
# mcpgateway-opapluginfilter default-route-.../mcp-gateway-test/mcpgateway-opapluginfilter
CI/CD Pipeline Example
# In your CI/CD pipeline:
# 1. Authenticate to registry
echo "$REGISTRY_PASSWORD" | docker login $REGISTRY_URL -u $REGISTRY_USER --password-stdin
# 2. Build and push
cforge gateway build deploy-prod.yaml
# 3. Images are automatically pushed to registry
# 4. Deploy to Kubernetes (manifests already reference registry images)
cforge gateway deploy deploy-prod.yaml --skip-build --skip-certs
Per-Component Configuration
Each component (gateway and plugins) can have different registry settings:
gateway:
repo: htt
…(truncated)