Deploy MemPalace, a local-first AI memory system, as a production-ready Model Context Protocol (MCP) server on Red Hat OpenShift AI.
What this provides:
- HTTP/WebSocket wrapper for MemPalace's MCP protocol (enables Kubernetes deployment)
- UBI 9-based container image with ChromaDB support
- Kubernetes health probes (liveness/readiness)
- OpenShift Security Context Constraint compliance (
restricted-v2) - Complete deployment manifests
Architecture:
graph TB
subgraph cluster["OpenShift Cluster"]
subgraph pod["MemPalace Pod (UBI 9 Python 3.11)"]
http["FastAPI HTTP Server (Port 8000)"]
health["GET /health → Liveness probe"]
ready["GET /ready → Readiness (ChromaDB)"]
ws["WS /mcp → WebSocket MCP endpoint"]
http --> health
http --> ready
http --> ws
mcp["MCP Server Core<br/>JSON-RPC 2.0 protocol<br/>Tools: store, search, tag, clear"]
chroma["ChromaDB Vector Store<br/>Semantic memory search<br/>Persistent storage"]
ws --> mcp
mcp --> chroma
end
storage["PersistentVolumeClaim<br/>10Gi RWO storage<br/>ChromaDB data"]
pod -.->|"mounts"| storage
end
clients["MCP Clients<br/>(AI agents, applications)"] -->|"WebSocket"| route["OpenShift Route<br/>TLS termination"]
route --> http
k8s["Kubernetes Probes"] -.->|"health checks"| health
k8s -.->|"readiness checks"| ready
style cluster fill:#f5f5f5,stroke:#333,stroke-width:2px
style pod fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
style http fill:#fff,stroke:#666
style health fill:#fff,stroke:#666
style ready fill:#fff,stroke:#666
style ws fill:#fff,stroke:#666
style mcp fill:#fff,stroke:#666
style chroma fill:#fff,stroke:#666
style storage fill:#fff3e0,stroke:#f57c00
style clients fill:#fff,stroke:#666
style route fill:#fff,stroke:#666
style k8s fill:#e3f2fd,stroke:#1976d2
The deployment consists of:
- FastAPI HTTP Server with health probes and WebSocket MCP endpoint
- MCP Server Core providing 29 tools (search, mine, query, tag, clear)
- ChromaDB Vector Store for semantic memory search
- PersistentVolumeClaim (20Gi) for durable storage
- OpenShift Route with TLS termination for external access
- Red Hat OpenShift 4.x cluster
ocCLI authenticated to cluster- 20Gi available storage
# Clone repository
git clone https://github.com/aicatalyst-team/mempalace-openshift
cd mempalace-openshift
# Deploy to OpenShift
oc apply -k manifests/
# Wait for pod to be ready
oc get pods -n mempalace -w
# Test deployment
oc run test-mempalace --rm -i --image=curlimages/curl -- \
curl -s http://mempalace.mempalace.svc.cluster.local:8000/healthExpected output:
{"status":"healthy","protocol":"mcp-over-websocket"}From within cluster:
ws://mempalace.mempalace.svc.cluster.local:8000/mcp
From external (if Route is deployed):
wss://mempalace-mempalace.apps.your-cluster.com/mcp
01-namespace.yaml- Createsmempalacenamespace02-pvc.yaml- 20Gi PersistentVolumeClaim for palace storage03-deployment.yaml- MemPalace Deployment with health probes04-service.yaml- ClusterIP Service on port 800005-route.yaml- (Optional) OpenShift Route with TLS edge termination
Pre-built image: quay.io/aicatalyst/mempalace:latest
Built from Dockerfile.ubi (UBI 9 Python 3.11) with:
- MemPalace 3.3.3 + HTTP wrapper
- ChromaDB with sqlite3 compatibility fix
- FastAPI + uvicorn + websockets
mcp_http_server.py - Novel contribution that wraps MemPalace's stdio-based MCP server with HTTP/WebSocket transport.
Key features:
- Preserves existing
mempalace-mcpstdio interface - Enables Kubernetes deployment with health probes
- Supports concurrent WebSocket clients
- Runs
handle_request()in thread pool (ChromaDB not async-safe)
cd examples
python3 test-connection.pyimport asyncio
import json
import websockets
async def search():
uri = "ws://mempalace.mempalace.svc.cluster.local:8000/mcp"
async with websockets.connect(uri) as ws:
# Initialize
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "initialize",
"params": {"protocolVersion": "2025-11-25"},
"id": 1
}))
await ws.recv()
# Search
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "mempalace_search",
"arguments": {"query": "authentication"}
},
"id": 2
}))
result = json.loads(await ws.recv())
print(result)
asyncio.run(search())Edit manifests/02-pvc.yaml:
resources:
requests:
storage: 50Gi # Increase as neededDeploy the Route:
oc apply -f manifests/05-route.yamlGet external URL:
oc get route mempalace -n mempalace -o jsonpath='{.spec.host}'# Build locally
podman build -f Dockerfile.ubi -t quay.io/your-org/mempalace:latest --platform linux/amd64 .
# Push to registry
podman push quay.io/your-org/mempalace:latest
# Update manifest
# Edit manifests/03-deployment.yaml and change image: lineMemPalace's MCP server traditionally uses stdin/stdout (JSON-RPC 2.0). This works for local CLI but breaks in Kubernetes:
| Aspect | Stdio MCP | HTTP/WebSocket MCP |
|---|---|---|
| Transport | stdin/stdout | WebSocket over HTTP |
| Deployment | Local CLI only | Kubernetes/OpenShift |
| Concurrent clients | Single process | Multiple connections |
| Health checks | Not supported | /health, /ready |
| Service mesh | Impossible | Full compatibility |
Runs under restricted-v2 SCC:
runAsNonRoot: trueallowPrivilegeEscalation: false- All capabilities dropped
seccompProfile: RuntimeDefault
Permissions set via chgrp -R 0 and chmod -R g=u (OpenShift uses arbitrary UID, always GID 0).
UBI 9 ships with sqlite3 3.34.x, but ChromaDB requires >= 3.35.0.
Solution: Install pysqlite3-binary and override via sitecustomize.py:
__import__("pysqlite3")
import sys
sys.modules["sqlite3"] = sys.modules.pop("pysqlite3")This works because Python checks sys.modules before filesystem imports.
Check logs:
POD=$(oc get pods -n mempalace -l app=mempalace -o jsonpath='{.items[0].metadata.name}')
oc logs $POD -n mempalaceCommon issues:
- ChromaDB connection failed (check PVC is bound)
- sqlite3 version error (verify Dockerfile has sitecustomize.py)
If using private registry:
oc create secret docker-registry quay-pull \
--docker-server=quay.io \
--docker-username=YOUR-USERNAME \
--docker-password=YOUR-PASSWORD \
-n mempalace
oc secrets link default quay-pull --for=pull -n mempalaceCheck readiness:
oc run test-ready --rm -i --image=curlimages/curl -- \
curl -s http://mempalace.mempalace.svc.cluster.local:8000/readyShould return {"status":"ready"}. If not, ChromaDB backend is not accessible.
# Install with HTTP server dependencies
cd /path/to/mempalace
pip install -e ".[dev,server]"
# Run HTTP server
mempalace-mcp-http --palace ~/.mempalace --port 8000
# Test
curl http://localhost:8000/healthcd examples
python3 test-connection.pyThis repository contains the HTTP/WebSocket wrapper and deployment manifests. The wrapper will be contributed to upstream MemPalace.
Components:
- HTTP wrapper (
mcp_http_server.py) - Novel contribution for production Kubernetes deployment - UBI 9 Dockerfile - Enterprise-ready container image
- OpenShift manifests - Kustomize-based deployment
- MemPalace GitHub: https://github.com/MemPalace/mempalace
- MCP Specification: https://modelcontextprotocol.io
- Red Hat OpenShift AI: https://www.redhat.com/en/technologies/cloud-computing/openshift/openshift-ai
- Blog Post: Deploying MemPalace MCP Server on Red Hat OpenShift AI
- MemPalace: MIT License
- HTTP wrapper and deployment manifests: Apache 2.0 License
Maintained by: Red Hat AI Catalyst Team