Installation
IBM Verify MCP Server - Installation Guide
Overview
This guide covers the installation and deployment of the IBM Verify MCP Server. You can deploy the server in two ways:
- Kubernetes Deployment - For production environments (Currenly Single pod deployment is supported)
- Local Docker Deployment - For development and testing
Prerequisites
Before proceeding with installation, ensure you have completed the Tenant Setup Prerequisites and have:
- ✅ IBM Verify tenant configured with MCP Server applications
- ✅
setup-env.shfile with all credentials - ✅ Users entitled to "MCP Server Subject" application
- ✅ Docker or Kubernetes environment ready
- ✅ Nginx setup in case Verify MCP Server is setup on VM or Fyre
Step 1: Pull the Docker Image
The IBM Verify MCP Server is distributed as a Docker image from IBM Container Registry.
1.1 Image Details
- Registry:
icr.io/ibm-verify - Image:
verify-mcp-server - Tag:
26.07.20 - Full Image:
icr.io/ibm-verify/verify-mcp-server:latest
1.2 Pull the Image
# Pull the latest image
docker pull icr.io/ibm-verify/verify-mcp-server:latest
# Verify the image
docker images | grep verify-mcp-serverExpected Output:
icr.io/ibm-verify/verify-mcp-server latest <image-id> <size> <time>
Step 2: Choose Your Deployment Method
Select the deployment method that best fits your needs:
| Method | Use Case | Complexity | Scalability |
|---|---|---|---|
| Kubernetes | Production, multi-instance | Medium | High |
| Local Docker | Development, testing, demos | Low | Low |
Option A: Kubernetes Deployment
Deploy the MCP Server to a Kubernetes cluster for production use.
A.1 Prerequisites
- Kubernetes cluster (v1.19+)
kubectlconfigured to access your cluster- Ingress controller installed (nginx, traefik, etc.) OR OpenShift cluster
- Credentials from tenant setup (
setup-env.sh)
A.2 Prepare Deployment Directory
Create a directory to store your Kubernetes manifests:
# Create a directory for Kubernetes manifests
mkdir -p ~/mcp-server-k8s
cd ~/mcp-server-k8sDeployment Steps Overview:
- Create namespace
- Create secret with credentials
- Create configmap with configuration
- Deploy the application
- Create service
- Expose via Ingress or Route
You can create each YAML file by copying the content from the following steps.
A.3 Step 1: Create Namespace
Create a file named 01-namespace.yaml:
cat > 01-namespace.yaml <<'EOF'
---
# Namespace for IBM Verify MCP Server
apiVersion: v1
kind: Namespace
metadata:
name: verify-mcp-server
labels:
app: verify-mcp-server
environment: production
EOFApply the namespace:
# Create namespace
kubectl apply -f 01-namespace.yaml
# Verify namespace creation
kubectl get namespace verify-mcp-serverExpected Output:
NAME STATUS AGE
verify-mcp-server Active 5s
A.4 Step 2: Create Secret
Create a file named 02-secret.yaml with your credentials from setup-env.sh:
IMPORTANT: Replace the placeholder values with actual credentials from your setup-env.sh file.
# Source your environment file to get the values
source ~/mcp-server-setup/setup-env.sh
# Create the secret file with your actual credentials
cat > 02-secret.yaml <<EOF
---
# Secret for sensitive credentials
apiVersion: v1
kind: Secret
metadata:
name: verify-mcp-credentials
namespace: verify-mcp-server
type: Opaque
stringData:
# From setup-env.sh: IBM_VERIFY_CLIENT_SECRET
client-secret: "${IBM_VERIFY_CLIENT_SECRET}"
# From setup-env.sh: IBM_VERIFY_STS_CLIENT_SECRET
sts-client-secret: "${IBM_VERIFY_STS_CLIENT_SECRET}"
# From setup-env.sh: IBM_VERIFY_ACTOR_CLIENT_SECRET
actor-client-secret: "${IBM_VERIFY_ACTOR_CLIENT_SECRET}"
EOFApply the secret:
# Create the secret
kubectl apply -f 02-secret.yaml
# Verify secret creation
kubectl get secret verify-mcp-credentials -n verify-mcp-serverExpected Output:
NAME TYPE DATA AGE
verify-mcp-credentials Opaque 3 5s
A.5 Step 3: Create ConfigMap
Create a file named 03-configmap.yaml with your tenant configuration:
IMPORTANT: Update IBM_VERIFY_BASE_URL with your actual external URL (from Ingress/Route).
# Source your environment file
source ~/mcp-server-setup/setup-env.sh
# Set your external URL (update this with your actual domain)
EXTERNAL_URL="https://verify-mcp-server.example.com"
# Create the configmap file
cat > 03-configmap.yaml <<EOF
---
# ConfigMap for non-sensitive configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: verify-mcp-config
namespace: verify-mcp-server
data:
# Transport configuration (REQUIRED)
MCP_TRANSPORT: "streamable-http"
# IBM Verify tenant configuration (REQUIRED)
IBM_VERIFY_TENANT_URL: "${IBM_VERIFY_TENANT_URL}"
IBM_VERIFY_CLIENT_ID: "${IBM_VERIFY_CLIENT_ID}"
IBM_VERIFY_BASE_URL: "${EXTERNAL_URL}"
IBM_VERIFY_STS_CLIENT_ID: "${IBM_VERIFY_STS_CLIENT_ID}"
IBM_VERIFY_ACTOR_CLIENT_ID: "${IBM_VERIFY_ACTOR_CLIENT_ID}"
# OAuth endpoints
IBM_VERIFY_OIDC_CONFIG_URL: "${IBM_VERIFY_TENANT_URL}/oidc/endpoint/default/.well-known/openid-configuration"
IBM_VERIFY_TOKEN_EXCHANGE_URL: "${IBM_VERIFY_TENANT_URL}/v1.0/endpoint/default/token"
# OAuth scopes
IBM_VERIFY_SCOPES: "openid profile email"
# Server configuration
IBM_VERIFY_MCP_HOST: "0.0.0.0"
IBM_VERIFY_MCP_PORT: "8000"
# Logging configuration
IBM_VERIFY_LOG_LEVEL: "INFO"
IBM_VERIFY_LOG_FILE: "/app/logs/mcp.log"
IBM_VERIFY_LOG_MAX_BYTES: "10485760"
IBM_VERIFY_LOG_BACKUP_COUNT: "5"
# Cache configuration
IBM_VERIFY_CACHE_TTL: "900"
IBM_VERIFY_CACHE_MAXSIZE: "1000"
EOFApply the configmap:
# Create the configmap
kubectl apply -f 03-configmap.yaml
# Verify configmap creation
kubectl get configmap verify-mcp-config -n verify-mcp-serverExpected Output:
NAME DATA AGE
verify-mcp-config 17 5s
A.6 Step 4: Create Deployment
Create a file named 04-deployment.yaml:
cat > 04-deployment.yaml <<'EOF'
---
# Deployment for IBM Verify MCP Server
apiVersion: apps/v1
kind: Deployment
metadata:
name: verify-mcp-server
namespace: verify-mcp-server
labels:
app: verify-mcp-server
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: verify-mcp-server
template:
metadata:
labels:
app: verify-mcp-server
version: v1
annotations:
instana.io/instrumentation: "false"
spec:
securityContext: {}
containers:
- name: verify-mcp-server
image: icr.io/ibm-verify/verify-mcp-server:latest
imagePullPolicy: Always
command: ["/usr/local/bin/start-mcp.sh"]
ports:
- name: http
containerPort: 8000
protocol: TCP
envFrom:
- configMapRef:
name: verify-mcp-config
env:
- name: IBM_VERIFY_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: verify-mcp-credentials
key: client-secret
- name: IBM_VERIFY_STS_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: verify-mcp-credentials
key: sts-client-secret
- name: IBM_VERIFY_ACTOR_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: verify-mcp-credentials
key: actor-client-secret
- name: OPENSSL_CONF
value: "/dev/null"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: logs
mountPath: /app/logs
volumes:
- name: logs
emptyDir: {}
restartPolicy: Always
EOFApply the deployment:
# Create the deployment
kubectl apply -f 04-deployment.yaml
# Verify deployment creation
kubectl get deployment verify-mcp-server -n verify-mcp-serverExpected Output:
NAME READY UP-TO-DATE AVAILABLE AGE
verify-mcp-server 1/1 1 1 30s
A.7 Step 5: Create Service
Create a file named 05-service.yaml:
cat > 05-service.yaml <<'EOF'
---
# Service for IBM Verify MCP Server
apiVersion: v1
kind: Service
metadata:
name: verify-mcp-server
namespace: verify-mcp-server
labels:
app: verify-mcp-server
spec:
type: ClusterIP
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
selector:
app: verify-mcp-server
EOFApply the service:
# Create the service
kubectl apply -f 05-service.yaml
# Verify service creation
kubectl get service verify-mcp-server -n verify-mcp-serverExpected Output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
verify-mcp-server ClusterIP 10.96.xxx.xxx <none> 8000/TCP 5s
A.8 Step 6: Expose via Ingress or Route
For Standard Kubernetes (Ingress):
Create a file named 06-ingress.yaml:
# Update with your actual domain
EXTERNAL_DOMAIN="verify-mcp-server.example.com"
cat > 06-ingress.yaml <<EOF
---
# Ingress for standard Kubernetes
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: verify-mcp-server
namespace: verify-mcp-server
labels:
app: verify-mcp-server
annotations:
# Uncomment and configure based on your ingress controller
# nginx.ingress.kubernetes.io/rewrite-target: /
# cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx # Change based on your ingress controller
rules:
- host: ${EXTERNAL_DOMAIN}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: verify-mcp-server
port:
number: 8000
# Uncomment for TLS
# tls:
# - hosts:
# - ${EXTERNAL_DOMAIN}
# secretName: verify-mcp-server-tls
EOFApply the ingress:
kubectl apply -f 06-ingress.yamlFor OpenShift (Route):
Create a file named 06-route.yaml:
# Update with your actual domain
EXTERNAL_DOMAIN="verify-mcp-server.example.com"
cat > 06-route.yaml <<EOF
---
# Route for OpenShift
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: verify-mcp-server
namespace: verify-mcp-server
labels:
app: verify-mcp-server
spec:
host: ${EXTERNAL_DOMAIN}
to:
kind: Service
name: verify-mcp-server
weight: 100
port:
targetPort: http
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
wildcardPolicy: None
EOFApply the route:
oc apply -f 06-route.yamlA.9 Step 7: Verify All Resources Created
Check that all resources are created successfully:
# Check all resources in the namespace
kubectl get all -n verify-mcp-server
# Check configmap and secret
kubectl get configmap,secret -n verify-mcp-serverExpected Output:
NAME READY STATUS RESTARTS AGE
pod/verify-mcp-server-xxxxxxxxxx-xxxxx 1/1 Running 0 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/verify-mcp-server ClusterIP 10.96.xxx.xxx <none> 8000/TCP 30s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/verify-mcp-server 1/1 1 1 30s
NAME DESIRED CURRENT READY AGE
replicaset.apps/verify-mcp-server-xxxxxxxxxx 1 1 1 30s
A.10 Step 8: Test the Deployment
Test the health endpoint:
# Using port-forward
kubectl port-forward -n verify-mcp-server svc/verify-mcp-server 8000:8000
# In another terminal
curl http://localhost:8000/healthExpected Response:
{
"status": "healthy",
"service": "IBM Verify MCP Server"
}A.11 Kubernetes Management Commands
View logs:
# Follow logs
kubectl logs -f -n verify-mcp-server -l app=verify-mcp-server
# View last 100 lines
kubectl logs -n verify-mcp-server -l app=verify-mcp-server --tail=100Scale deployment:
# Scale to 1 replicas - Currently Verify MCP Server runs with single pod until HA is supported
kubectl scale deployment verify-mcp-server -n verify-mcp-server --replicas=1
# Verify scaling
kubectl get pods -n verify-mcp-serverUpdate configuration:
# Re-create configmap with new values
kubectl delete configmap verify-mcp-config -n verify-mcp-server
# Then create it again with updated values
# Re-create secret with new values
kubectl delete secret verify-mcp-credentials -n verify-mcp-server
# Then create it again with updated values
# Restart deployment to pick up changes
kubectl rollout restart deployment verify-mcp-server -n verify-mcp-serverUpdate image:
# Update to new image version
kubectl set image deployment/verify-mcp-server \
verify-mcp-server=icr.io/ibm-verify/verify-mcp-server:latest \
-n verify-mcp-server
# Check rollout status
kubectl rollout status deployment verify-mcp-server -n verify-mcp-serverDelete deployment:
# Delete the entire namespace (removes everything)
kubectl delete namespace verify-mcp-serverOption B: Local Docker Deployment
Run the MCP Server locally by using Docker for development and testing.
B.1 Prerequisites
- Docker installed and running
- Credentials from tenant setup (
setup-env.sh) - Access to IBM Container Registry (
icr.io) for downloading IBM Verify MCP Server image
B.2 Set Environment Variables
Source the environment file generated during tenant setup:
# Navigate to the directory containing setup-env.sh
cd ~/mcp-server-setup
# Source the environment variables
source setup-env.sh
# Verify variables are set
echo $IBM_VERIFY_TENANT_URL
echo $IBM_VERIFY_CLIENT_IDB.3 Run Docker Container
Run the MCP Server container with all required environment variables:
# Ensure environment variables are set
source setup-env.sh
mkdir -p ./logs
# Run the container
# Add --platform linux/amd64 if running on other than linux platform
# Add IBM_VERIFY_ALLOWED_REDIRECT_URIS="http://localhost:*, http://127.0.0.1:*, https://*.mycompany.com/auth/*" where we want to restrict redirect URI from MCP Server
docker run -d \
--name verify-mcp-server \
-p 8000:8000 \
-v "$(pwd)/logs:/app/logs" \
-e MCP_TRANSPORT="streamable-http" \
-e IBM_VERIFY_TENANT_URL="$IBM_VERIFY_TENANT_URL" \
-e IBM_VERIFY_CLIENT_ID="$IBM_VERIFY_CLIENT_ID" \
-e IBM_VERIFY_CLIENT_SECRET="$IBM_VERIFY_CLIENT_SECRET" \
-e IBM_VERIFY_STS_CLIENT_ID="$IBM_VERIFY_STS_CLIENT_ID" \
-e IBM_VERIFY_STS_CLIENT_SECRET="$IBM_VERIFY_STS_CLIENT_SECRET" \
-e IBM_VERIFY_ACTOR_CLIENT_ID="$IBM_VERIFY_ACTOR_CLIENT_ID" \
-e IBM_VERIFY_ACTOR_CLIENT_SECRET="$IBM_VERIFY_ACTOR_CLIENT_SECRET" \
-e IBM_VERIFY_BASE_URL="http://localhost:8000" \
-e IBM_VERIFY_OIDC_CONFIG_URL="{$IBM_VERIFY_TENANT_URL}/oidc/endpoint/default/.well-known/openid-configuration" \
-e IBM_VERIFY_TOKEN_EXCHANGE_URL="{$IBM_VERIFY_TENANT_URL}/v1.0/endpoint/default/token" \
-e IBM_VERIFY_SCOPES="openid profile email" \
-e IBM_VERIFY_MCP_HOST="0.0.0.0" \
-e IBM_VERIFY_MCP_PORT="8000" \
-e IBM_VERIFY_LOG_LEVEL="INFO" \
-e IBM_VERIFY_LOG_FILE="/app/logs/mcp.log" \
-e IBM_VERIFY_LOG_MAX_BYTES="10485760" \
-e IBM_VERIFY_LOG_BACKUP_COUNT="5" \
-e IBM_VERIFY_CACHE_TTL="900" \
-e IBM_VERIFY_CACHE_MAXSIZE="1000" \
-e PORT="8000" \
-e LOG_LEVEL="info" \
--restart unless-stopped \
icr.io/ibm-verify/verify-mcp-server:latest
# Check container status
docker ps | grep verify-mcp-server
# View logs
docker logs -f verify-mcp-serverB.5 Docker Container Management
# View logs
docker logs -f verify-mcp-server
# Stop the container
docker stop verify-mcp-server
# Start the container
docker start verify-mcp-server
# Restart the container
docker restart verify-mcp-server
# Remove the container
docker rm -f verify-mcp-server
# View container details
docker inspect verify-mcp-serverStep 3: Validate Installation
Regardless of deployment method, validate that the MCP Server is running correctly.
3.1 Health Check Endpoint
The MCP Server provides a health check endpoint at /health.
For Kubernetes Deployment:
# Using port-forward
kubectl port-forward -n verify-mcp-server svc/verify-mcp-server 8000:8000
# In another terminal
curl http://localhost:8000/health
# Or using your ingress domain
curl https://verify-mcp-server.example.com/healthFor Local Docker Deployment:
curl http://localhost:8000/healthExpected Response:
{
"status": "healthy",
"service": "IBM Verify MCP Server"
}3.2 Verify Server Logs
Kubernetes:
kubectl logs -n verify-mcp-server -l app=verify-mcp-server --tail=50Docker:
docker logs verify-mcp-server --tail=50Look for:
- ✅ Server started successfully
- ✅ No error messages
- ✅ Listening on port 8000
3.3 Post MCP Server Installation (Nginx for VM / Fyre)
When the MCP Server is deployed on a VM or Fyre system, it runs on plain HTTP (port 8000) by default. Because MCP clients require HTTPS, you must place an nginx reverse proxy in front of it.
What nginx does here:
- Terminates HTTPS on port 443 (or a custom port such as 2443)
- Proxies requests internally to
http://localhost:8000
Once nginx is configured, clients connect to https://<host>/mcp instead of http://localhost:8000/mcp.
Self-signed certificates: If you generate a self-signed TLS certificate for nginx (common in Fyre/lab environments), MCP clients must be configured to trust that certificate. See the Self-Signed Certificates section in the MCP Client Configuration guide for details.
For nginx setup instructions, refer to the nginx reverse proxy guide or the DigitalOcean nginx reverse proxy tutorial.
Configuration Reference
Environment Variables
| Variable | Description | Required | Example |
|---|---|---|---|
IBM_VERIFY_TENANT_URL | IBM Verify tenant URL | Yes | https://tenant.verify.ibm.com |
IBM_VERIFY_CLIENT_ID | Subject app client ID | Yes | abc123... |
IBM_VERIFY_CLIENT_SECRET | Subject app client secret | Yes | secret123... |
IBM_VERIFY_STS_CLIENT_ID | STS client ID | Yes | sts123... |
IBM_VERIFY_STS_CLIENT_SECRET | STS client secret | Yes | stssecret123... |
IBM_VERIFY_ACTOR_CLIENT_ID | Actor app client ID | Yes | actor123... |
IBM_VERIFY_ACTOR_CLIENT_SECRET | Actor app client secret | Yes | actorsecret123... |
PORT | Server port | No | 8000 (default) |
LOG_LEVEL | Logging level | No | info (default) |
Resource Requirements
Minimum:
- CPU: 500m (0.50 cores)
- Memory: 512Mi
Recommended:
- CPU: 1000m (1 cores)
- Memory: 1Gi
Network Requirements
Inbound:
- Port 8000 (HTTP) - MCP Server API
Outbound:
- Port 443 (HTTPS) - IBM Verify tenant communication
Troubleshooting
If you encounter any issues during installation or deployment, refer to the comprehensive Troubleshooting Guide which covers:
- Connection issues
- Authentication problems
- Server not running
- Docker-specific issues
- Kubernetes-specific issues
- Performance problems
- Configuration errors
Quick Debug Commands:
# Docker - Check logs
docker logs verify-mcp-server
# Kubernetes - Check logs
kubectl logs -n verify-mcp-server -l app=verify-mcp-server
# Verify environment variables
docker exec verify-mcp-server env | grep IBM_VERIFY
# or
kubectl exec -n verify-mcp-server <pod-name> -- env | grep IBM_VERIFYFor detailed troubleshooting steps, see the Troubleshooting Guide.
Security Best Practices
Credentials Management
- 🔒 Never commit credentials to version control
- 🔒 Use Kubernetes Secrets for sensitive data
- 🔒 Rotate credentials regularly (every 90 days)
- 🔒 Use RBAC to restrict access to secrets
- 🔒 Enable secret encryption at rest in Kubernetes
Network Security
- 🔒 Use TLS/HTTPS for all external access
- 🔒 Implement network policies in Kubernetes
- 🔒 Restrict ingress to specific IP ranges if possible
- 🔒 Use private container registries
Container Security
- 🔒 Run containers as non-root user (already configured)
- 🔒 Use read-only root filesystem where possible
- 🔒 Scan images for vulnerabilities regularly
- 🔒 Keep images updated with latest security patches
Monitoring and Logging
- 📊 Enable centralized logging
- 📊 Set up health check monitoring
- 📊 Configure alerts for failures
- 📊 Monitor resource usage
- 📊 Audit access logs regularly
Next Steps
After successful installation:
- ✅ Configure MCP Client to connect to your MCP Server
- ✅ Test authentication flow with entitled users
- ✅ Set up monitoring and alerting
- ✅ Configure backup and disaster recovery
- ✅ Review and implement security hardening
Additional Resources
Support
For issues or questions:
- Review this documentation thoroughly
- Check the troubleshooting section
- Consult IBM Verify support documentation
- Contact your IBM Verify administrator
The installation is now complete and the IBM Verify MCP server is ready to use.
Next Steps
Now that your MCP Server is installed and running, configure your MCP client to connect to it:
👉 Configuring MCP Clients - Step-by-step guide to configure Claude Desktop and IBM Bob to connect to your MCP Server.
Key points:
- How to configure Claude Desktop
- How to configure IBM Bob
- How to validate the connection
- Troubleshooting connection issues
Updated about 2 hours ago
