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:

  1. Kubernetes Deployment - For production environments (Currenly Single pod deployment is supported)
  2. 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.sh file 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-server

Expected 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:

MethodUse CaseComplexityScalability
KubernetesProduction, multi-instanceMediumHigh
Local DockerDevelopment, testing, demosLowLow

Option A: Kubernetes Deployment

Deploy the MCP Server to a Kubernetes cluster for production use.

A.1 Prerequisites

  • Kubernetes cluster (v1.19+)
  • kubectl configured 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-k8s

Deployment Steps Overview:

  1. Create namespace
  2. Create secret with credentials
  3. Create configmap with configuration
  4. Deploy the application
  5. Create service
  6. 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
EOF

Apply the namespace:

# Create namespace
kubectl apply -f 01-namespace.yaml

# Verify namespace creation
kubectl get namespace verify-mcp-server

Expected 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}"
EOF

Apply the secret:

# Create the secret
kubectl apply -f 02-secret.yaml

# Verify secret creation
kubectl get secret verify-mcp-credentials -n verify-mcp-server

Expected 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"
  
EOF

Apply the configmap:

# Create the configmap
kubectl apply -f 03-configmap.yaml

# Verify configmap creation
kubectl get configmap verify-mcp-config -n verify-mcp-server

Expected 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
EOF

Apply the deployment:

# Create the deployment
kubectl apply -f 04-deployment.yaml

# Verify deployment creation
kubectl get deployment verify-mcp-server -n verify-mcp-server

Expected 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
EOF

Apply the service:

# Create the service
kubectl apply -f 05-service.yaml

# Verify service creation
kubectl get service verify-mcp-server -n verify-mcp-server

Expected 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
EOF

Apply the ingress:

kubectl apply -f 06-ingress.yaml

For 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
EOF

Apply the route:

oc apply -f 06-route.yaml

A.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-server

Expected 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/health

Expected 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=100

Scale 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-server

Update 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-server

Update 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-server

Delete deployment:

# Delete the entire namespace (removes everything)
kubectl delete namespace verify-mcp-server

Option 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_ID

B.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-server

B.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-server

Step 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/health

For Local Docker Deployment:

curl http://localhost:8000/health

Expected 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=50

Docker:

docker logs verify-mcp-server --tail=50

Look 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

VariableDescriptionRequiredExample
IBM_VERIFY_TENANT_URLIBM Verify tenant URLYeshttps://tenant.verify.ibm.com
IBM_VERIFY_CLIENT_IDSubject app client IDYesabc123...
IBM_VERIFY_CLIENT_SECRETSubject app client secretYessecret123...
IBM_VERIFY_STS_CLIENT_IDSTS client IDYessts123...
IBM_VERIFY_STS_CLIENT_SECRETSTS client secretYesstssecret123...
IBM_VERIFY_ACTOR_CLIENT_IDActor app client IDYesactor123...
IBM_VERIFY_ACTOR_CLIENT_SECRETActor app client secretYesactorsecret123...
PORTServer portNo8000 (default)
LOG_LEVELLogging levelNoinfo (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_VERIFY

For 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:

  1. Configure MCP Client to connect to your MCP Server
  2. Test authentication flow with entitled users
  3. Set up monitoring and alerting
  4. Configure backup and disaster recovery
  5. 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

Did this page help you?