Deploy the reShapr MCP platform on OpenShift using Helm and native OpenShift Routes.
This document is the manual operator guide. If you want an agent to perform the workflow for you, use SKILL.md.
reshapr-system: PostgreSQL 17, the reShapr control plane, and the web UIreshapr-proxies: the MCP proxy- Public OpenShift Routes:
reshapr-ctrlreshapr-uireshapr-mcpcamara-mock(optional, only for demo and verification)
- Optional demo assets:
- a Prism-based CAMARA mock
- three imported CAMARA APIs backed by the in-cluster mock
flowchart LR
routeCtrl["Route: reshapr-ctrl"]
routeUi["Route: reshapr-ui"]
routeProxy["Route: reshapr-mcp"]
routeMock["Route: camara-mock (optional)"]
subgraph openShiftCluster [OpenShift Cluster]
subgraph reshaprSystem [reshapr-system]
postgres["PostgreSQL 17"]
controlPlane["Control Plane :5555"]
webUi["Web UI :3333"]
postgres --> controlPlane
controlPlane --> webUi
end
subgraph reshaprProxies [reshapr-proxies]
mcpProxy["MCP Proxy :7777"]
camaraMock["CAMARA Mock (Prism, optional)"]
simSwap["SIM Swap :4010"]
locationRetrieval["Location Retrieval :4011"]
locationVerification["Location Verification :4012"]
camaraMock --> simSwap
camaraMock --> locationRetrieval
camaraMock --> locationVerification
end
controlPlane -->|"gRPC :5555"| mcpProxy
end
routeCtrl --> controlPlane
routeUi --> webUi
routeProxy --> mcpProxy
routeMock --> camaraMock
deploy-openshift/routes/: Route manifests for the control plane, web UI, and MCP proxydeploy-openshift/mock/deployment-prism.yaml: optional demo/verification ConfigMap, Deployment, and Service for the CAMARA mockdeploy-openshift/mock/route-camara-mock.yaml: optional external Route for the CAMARA mockSKILL.md: agent workflow guidance for the same deployment path
All commands below use committed repository content.
| Requirement | Notes |
|---|---|
| OpenShift cluster | 4.12+ |
oc CLI |
Authenticated to the target cluster |
| Helm | 3.8+ |
curl |
Required for login, health checks, and API import |
| Permissions | Ability to create namespaces, Routes, Deployments, Services, ConfigMaps, PVCs, and Helm releases |
| Network egress | Access to quay.io; access to registry.access.redhat.com, docker.io, and raw.githubusercontent.com is only needed for the optional CAMARA mock |
Verify access:
oc whoami
helm version --shortExport these variables before running the manual workflow:
export CLUSTER_DOMAIN=<cluster-domain> # e.g. ocp.example.com
export NS_SYSTEM=reshapr-system
export NS_PROXIES=reshapr-proxies
export CHART_VERSION=0.0.6
export IMAGE_TAG=0.1.0
export PG_PASSWORD=<postgres-password>
export API_KEY=<control-plane-api-key>
export ENCRYPTION_KEY=<32-char-encryption-key>
export ADMIN_NAME=admin
export ADMIN_PASSWORD=<admin-password>
export ADMIN_EMAIL=reshapr@example.com
export GATEWAY_TOKEN=<gateway-token>
export MCP_API_KEY=<mcp-client-api-key> # Optional; used only if your MCP clients require it
export PROXY_FQDN=reshapr-mcp-${NS_PROXIES}.apps.${CLUSTER_DOMAIN}Notes:
ENCRYPTION_KEYmust be exactly 16, 24, or 32 characters.API_KEYsecures the reShapr control-plane API.GATEWAY_TOKENis stored by the Helm release with thereshapr-prefix.MCP_API_KEYis not needed for deployment itself; it is only used later if your MCP clients authenticate withx-reshapr-key.- The committed manifests under
deploy-openshift/routes/anddeploy-openshift/mock/target the default namespacesreshapr-systemandreshapr-proxies. If you changeNS_SYSTEMorNS_PROXIES, update the manifest namespaces before applying them.
helm install reshapr-control-plane \
oci://quay.io/reshapr/reshapr-helm-charts/reshapr-control-plane \
--version "${CHART_VERSION}" \
--create-namespace --namespace "${NS_SYSTEM}" \
--set ctrl.image.tag="${IMAGE_TAG}" \
--set ctrl.podSecurityContext.runAsUser=null \
--set ctrl.podSecurityContext.runAsGroup=null \
--set ctrl.podSecurityContext.fsGroup=null \
--set postgresql.enabled=true \
--set postgresql.auth.password="${PG_PASSWORD}" \
--set postgresql.primary.podSecurityContext.enabled=false \
--set postgresql.primary.containerSecurityContext.enabled=false \
--set apiKey.value="${API_KEY}" \
--set encryptionKey.value="${ENCRYPTION_KEY}" \
--set admin.nameValue="${ADMIN_NAME}" \
--set admin.passwordValue="${ADMIN_PASSWORD}" \
--set admin.emailValue="${ADMIN_EMAIL}" \
--set admin.defaultGatewayTokensValue="reshapr-${GATEWAY_TOKEN}" \
--set ingress.enabled=false \
--set reshapr-web-ui.enabled=true \
--set reshapr-web-ui.image.tag="${IMAGE_TAG}" \
--set reshapr-web-ui.podSecurityContext.runAsUser=null \
--set reshapr-web-ui.podSecurityContext.runAsGroup=null \
--set reshapr-web-ui.podSecurityContext.fsGroup=null \
--set reshapr-web-ui.ingress.enabled=falseWait for the control plane:
oc rollout status deployment/reshapr-control-plane-ctrl -n "${NS_SYSTEM}" --timeout=180s
oc wait --for=condition=ready pod -l app.kubernetes.io/name=reshapr-control-plane -n "${NS_SYSTEM}" --timeout=180shelm install reshapr-proxy \
oci://quay.io/reshapr/reshapr-helm-charts/reshapr-proxy \
--version "${CHART_VERSION}" \
--create-namespace --namespace "${NS_PROXIES}" \
--set image.tag="${IMAGE_TAG}" \
--set podSecurityContext.runAsUser=null \
--set podSecurityContext.runAsGroup=null \
--set podSecurityContext.fsGroup=null \
--set gateway.idPrefix="openshift-demo" \
--set gateway.labels="env=demo;platform=openshift;team=reshapr" \
--set gateway.fqdns="${PROXY_FQDN}" \
--set gateway.controlPlane.host="reshapr-control-plane-ctrl.${NS_SYSTEM}.svc.cluster.local" \
--set gateway.controlPlane.port=5555 \
--set gateway.controlPlane.token="reshapr-${GATEWAY_TOKEN}" \
--set ingress.enabled=falseWait for the proxy:
oc rollout status deployment/reshapr-proxy -n "${NS_PROXIES}" --timeout=120soc apply -f deploy-openshift/routes/This creates the following Routes from the committed manifests:
reshapr-ctrlreshapr-uireshapr-mcp
You only need this section if you want to:
- verify the platform with mocked CAMARA upstreams
- import demo CAMARA APIs into reShapr
- configure an MCP client against those demo APIs
oc apply -f deploy-openshift/mock/The committed mock deployment does the following:
- creates a
ConfigMapplaceholder for the CAMARA specs - downloads the current CAMARA OpenAPI definitions at pod startup
- runs three Prism mock containers on ports
4010,4011, and4012 - exposes an in-cluster
camara-mockService - creates an external
camara-mockRoute
Wait for the mock deployment:
oc rollout status deployment/camara-mock -n "${NS_PROXIES}" --timeout=120sThis section verifies the core reShapr install: control plane, web UI, MCP proxy, and the required Routes.
Check the pods:
oc get pods -n "${NS_SYSTEM}" -o wide
oc get pods -n "${NS_PROXIES}" -o wideList the Routes:
oc get routes -n "${NS_SYSTEM}"
oc get routes -n "${NS_PROXIES}"Test the main health endpoints:
CTRL_HOST=$(oc get route reshapr-ctrl -n "${NS_SYSTEM}" -o jsonpath='{.spec.host}')
UI_HOST=$(oc get route reshapr-ui -n "${NS_SYSTEM}" -o jsonpath='{.spec.host}')
PROXY_HOST=$(oc get route reshapr-mcp -n "${NS_PROXIES}" -o jsonpath='{.spec.host}')
curl -sk "https://${CTRL_HOST}/q/health/ready"
curl -sk -o /dev/null -w "%{http_code}\n" "https://${UI_HOST}/"
curl -sk "https://${PROXY_HOST}/q/health/ready"Expected results:
- control plane returns a ready response
- web UI returns
200 - MCP proxy returns a ready response
- all pods are
RunningorCompleted
You can stop here if you only need the base reShapr platform.
If you deployed the optional CAMARA mock, also confirm deployment/camara-mock is ready and that the camara-mock Route exists. The demo API imports still use the in-cluster camara-mock.${NS_PROXIES}.svc.cluster.local service addresses.
This section is only required if you deployed the optional CAMARA mock and want demo APIs wired to mocked upstreams.
Log in to the control plane:
CTRL_HOST=$(oc get route reshapr-ctrl -n "${NS_SYSTEM}" -o jsonpath='{.spec.host}')
CTRL_URL="https://${CTRL_HOST}"
TOKEN=$(curl -sk -X POST "${CTRL_URL}/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"${ADMIN_NAME}\",\"password\":\"${ADMIN_PASSWORD}\"}" \
| grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4)
if [[ -z "${TOKEN}" ]]; then
echo "Failed to obtain an auth token. Check the control-plane Route and admin credentials."
exit 1
fiImport the three CAMARA specs and point them at the in-cluster mock service:
curl -sk -X POST "${CTRL_URL}/api/v1/api-specs/import" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{
\"name\": \"CAMARA SIM Swap\",
\"type\": \"OPENAPI\",
\"url\": \"https://raw.githubusercontent.com/camaraproject/SimSwap/r3.3/code/API_definitions/sim-swap.yaml\",
\"upstream\": \"http://camara-mock.${NS_PROXIES}.svc.cluster.local:4010\"
}"
curl -sk -X POST "${CTRL_URL}/api/v1/api-specs/import" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{
\"name\": \"CAMARA Device Location Retrieval\",
\"type\": \"OPENAPI\",
\"url\": \"https://raw.githubusercontent.com/camaraproject/DeviceLocation/r3.2/code/API_definitions/location-retrieval.yaml\",
\"upstream\": \"http://camara-mock.${NS_PROXIES}.svc.cluster.local:4011\"
}"
curl -sk -X POST "${CTRL_URL}/api/v1/api-specs/import" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{
\"name\": \"CAMARA Device Location Verification\",
\"type\": \"OPENAPI\",
\"url\": \"https://raw.githubusercontent.com/camaraproject/DeviceLocation/r3.2/code/API_definitions/location-verification.yaml\",
\"upstream\": \"http://camara-mock.${NS_PROXIES}.svc.cluster.local:4012\"
}"After the import, confirm the new APIs and generated MCP server names in the reShapr UI.
These examples assume you completed the optional CAMARA import flow above.
Get the MCP proxy hostname:
PROXY_HOST=$(oc get route reshapr-mcp -n "${NS_PROXIES}" -o jsonpath='{.spec.host}')Every reShapr MCP server URL follows this pattern:
https://<proxy-host>/mcp/reshapr/<server-name>
The <server-name> values are generated by reShapr from the imported APIs and plans. Use the names shown in the reShapr UI rather than hard-coding guesses.
{
"mcpServers": {
"camara-sim-swap": {
"url": "https://<proxy-host>/mcp/reshapr/<sim-swap-server-name>"
},
"camara-location-retrieval": {
"url": "https://<proxy-host>/mcp/reshapr/<location-retrieval-server-name>"
},
"camara-location-verification": {
"url": "https://<proxy-host>/mcp/reshapr/<location-verification-server-name>"
}
}
}If your deployment requires MCP client auth, add this header to each server entry:
{
"headers": {
"x-reshapr-key": "<mcp-api-key>"
}
}Paste the JSON above into your MCP client's configuration, then replace:
<proxy-host>with the hostname from thereshapr-mcpRoute- each
<...-server-name>placeholder with the actual name generated by reShapr <mcp-api-key>only if your deployment requiresx-reshapr-key
Try these prompts with your AI client after the MCP servers are configured:
- "Check if phone number +99012345678 had a recent SIM swap"
- "Where is the device with number +99012345678 located?"
- "Verify if +99012345678 is within 2km of Lyon, France"
Remove the tracked mock and Route resources:
oc delete -f deploy-openshift/mock/ --ignore-not-found=true
oc delete -f deploy-openshift/routes/ --ignore-not-found=trueIf you skipped the optional CAMARA mock, deleting deploy-openshift/mock/ is a harmless no-op.
Uninstall the Helm releases:
helm uninstall reshapr-proxy -n "${NS_PROXIES}" --wait
helm uninstall reshapr-control-plane -n "${NS_SYSTEM}" --waitDelete the PostgreSQL PVC and the namespaces:
oc delete pvc data-reshapr-control-plane-postgresql-0 -n "${NS_SYSTEM}" --ignore-not-found
oc delete namespace "${NS_PROXIES}" --ignore-not-found
oc delete namespace "${NS_SYSTEM}" --ignore-not-found-
Pods do not become ready: Check
oc get pods -n "${NS_SYSTEM}"andoc get pods -n "${NS_PROXIES}", then inspect events and logs withoc describe pod ...andoc logs .... -
The CAMARA mock init container fails: Only relevant if you deployed the optional mock. It downloads specs from
raw.githubusercontent.comat startup and also depends on pullingregistry.access.redhat.com/ubi9/ubi:latestandstoplight/prism:latest. Verify cluster egress and image pull access. -
The Route manifests deploy into the wrong namespaces: The committed manifests use
reshapr-systemandreshapr-proxies. If you choose different namespaces, update the manifestmetadata.namespacevalues before applying them. -
Login does not return a token: Verify the
reshapr-ctrlRoute, confirm the control plane is healthy, and re-checkADMIN_NAMEandADMIN_PASSWORD. -
An MCP client gets
404: Confirm the client is using the server name generated by reShapr after import, not a guessed slug. -
An MCP client gets
401or403: If client auth is enabled, add thex-reshapr-keyheader with your MCP API key.
| Variable | Description | Constraint |
|---|---|---|
CLUSTER_DOMAIN |
OpenShift cluster base domain | Used to compute Route hostnames |
NS_SYSTEM |
Namespace for control plane and database | Default manifests assume reshapr-system |
NS_PROXIES |
Namespace for MCP proxy and optional mock server | Default manifests assume reshapr-proxies |
CHART_VERSION |
Helm chart version | Default: 0.0.6 |
IMAGE_TAG |
Application image tag | Default: 0.1.0 |
PG_PASSWORD |
PostgreSQL password | Required |
API_KEY |
reShapr control-plane API key | Required |
ENCRYPTION_KEY |
Encryption key for stored secrets | Must be exactly 16, 24, or 32 characters |
ADMIN_NAME |
Admin username | Default: admin |
ADMIN_PASSWORD |
Admin password | Required |
ADMIN_EMAIL |
Admin email | Default: reshapr@example.com |
GATEWAY_TOKEN |
Proxy-to-control-plane auth token | Stored with a reshapr- prefix |
MCP_API_KEY |
Client key used by MCP consumers | Optional; only if your deployment requires MCP client auth |
PROXY_FQDN |
External FQDN for the MCP proxy Route | Usually reshapr-mcp-${NS_PROXIES}.apps.${CLUSTER_DOMAIN} |