Sign inSign up

netscaler/netscaler-mcp-server

By netscaler

•Updated about 1 month ago

A Model Context Protocol (MCP) server for Citrix NetScaler ADC (Application Delivery Controller).

Image
0

100

netscaler/netscaler-mcp-server repository overview

⁠NetScaler MCP Server Deployment Guide

⁠This guide explains how to deploy the NetScaler MCP Server. It bridges the Model Context Protocol (MCP) with a NetScaler (VPX/MPX) appliance directly via the Nitro REST API, allowing AI clients to configure and manage NetScaler resources.

⁠Table of Contents


⁠Prerequisites

  • Container Engine: Docker or Kubernetes cluster (v1.19+).
  • NetScaler Credentials: Nitro API access (nsroot or equivalent credentials).
  • Connectivity: Network access from the container to the Netscaler management IP.
  • Identity Provider (If using OAuth 2.1): An OIDC-compliant provider is required. The MCP server acts as an OAuth 2.1 Resource Server. Reference configuration for Keycloak:
    • Realm: Create a Realm (example: NetScaler_Realm, Access Token Lifetime: configurable; Session Max: <24h>).
    • Client: Create a Public client for MCP clients (VS Code, Claude Desktop, etc.) — example: mcp-client.
    • Flows: Enable "Standard Flow" (Authorization Code with PKCE).
    • PKCE: Required — Code Challenge Method: S256.
    • Redirect URIs: Set to the MCP server external URL.
    • Web Origins: Set to * to allow CORS.
    • User: Ensure users are created, enabled, and have verified email with scopes: openid, profile, email.
    • Required env vars for OAuth:
      • MCP_NS_OAUTH_ISSUER: Full issuer URL
      • MCP_NS_JWKS_URI: JWKS endpoint for public keys
      • MCP_NS_OAUTH_AUTH_ENDPOINT: Auth endpoint (optional)
      • MCP_NS_OAUTH_TOKEN_ENDPOINT: Token endpoint (optional)

⁠Authentication

The server connects to NetScaler using Nitro API credentials supplied via environment variables:

VariableDescriptionDefault
NS_IPNetScaler management IP—
NS_PORTNitro API port443
NS_PROTOCOLhttp or httpshttps
NS_USERNAMEusernamensroot
NS_PASSWORDpassword—

Kubernetes secret: create netscaler-secret with keys NS_USERNAME and NS_PASSWORD (see Kubernetes Deployments⁠).


⁠TLS / HTTPS

The image does not include any TLS certificates. Certificate provisioning is the operator's responsibility.

  • Set MCP_SERVER_PROTOCOL=https and mount your certificate files into the container.
  • If MCP_SERVER_PROTOCOL=https is set but no certificate files are found at the configured paths, the container exits immediately with an error.
  • Use MCP_SERVER_PROTOCOL=http (the k8s default) to skip TLS entirely.

Mount your own certificates:

-v /path/to/server.key:/app/certs/server.key:ro \
-v /path/to/server.crt:/app/certs/server.crt:ro

Or override the expected paths via env:

-e SSL_CERT_PATH=/certs/my.crt \
-e SSL_KEY_PATH=/certs/my.key


Two tools exposed to the AI client:

  • discover_tool — semantic search over the full NITRO API catalogue (700+ resources, 5000+ tools). Returns matching tool names and parameter schemas.
  • execute_tool — executes any NITRO operation by tool name and arguments.

Discovery uses fastembed (BAAI/bge-small-en-v1.5) for hybrid vector+keyword search. The model is baked into the image — no internet access required at runtime.

Configure discovery behaviour:

VariableDescriptionDefault
DISCOVERY_SEARCH_MODEhybridhybrid
DISCOVERY_MAX_TOOLSMax tools returned per query10

⁠Configuration

⁠All Environment Variables
VariableDescriptionDefault
NS_IPNetScaler management IP—
NS_PORTNetscaler API port443
NS_PROTOCOLProtocol to reach Netscaler (http/https)https
NS_USERNAMENetscaler usernamensroot
NS_PASSWORDNetscaler password—
NS_ENABLE_CERT_VALIDATIONValidate Netscaler TLS cert (true/false)false
MCP_SERVER_PROTOCOLMCP server protocol (http/https)https
MCP_SERVER_HOSTMCP server bind address0.0.0.0
MCP_SERVER_PORTMCP server bind port10000
MCP_SERVER_EXTERNAL_HOSTAdvertised external host (OAuth discovery)—
MCP_SERVER_EXTERNAL_PORTAdvertised external port (OAuth discovery)—
MCP_ALLOWED_HOSTSAllowed host header values*
MCP_NS_OAUTH_ISSUEROAuth 2.1 issuer URL (enables OAuth when set with JWKS_URI)—
MCP_NS_JWKS_URIJWKS endpoint for JWT verification—
MCP_NS_OAUTH_AUTH_ENDPOINTOAuth authorization endpoint—
MCP_NS_OAUTH_TOKEN_ENDPOINTOAuth token endpoint—
DISCOVERY_SEARCH_MODEhybridhybrid
DISCOVERY_MAX_TOOLSMax tools returned per discover query10
SSL_CERT_PATHTLS certificate path inside container/app/certs/server.crt
SSL_KEY_PATHTLS key path inside container/app/certs/server.key
LOG_LEVELLog verbosity (DEBUG, INFO, WARNING)INFO

⁠Deployment Steps

⁠Docker Deployments
⁠1. HTTP (No TLS, No OAuth) — Quickest for local testing
docker run -d \
  --name netscaler-mcp-server \
  -p 10000:10000 \
  -e MCP_SERVER_PROTOCOL=http \
  -e NS_IP="<Netscale_IP>" \
  -e NS_USERNAME="<Netscaler_Username>" \
  -e NS_PASSWORD="<Netscaler_PASSWORD>" \
  docker.io/netscaler/netscaler-mcp-server:tech-preview

Verify:

curl http://localhost:10000/health
⁠2. HTTPS with Custom Certificate (No OAuth)

Note: The container runs as a non-root user (uid 1001). Cert files must be world-readable (chmod 644).

chmod 644 /path/to/server.key /path/to/server.crt

docker run -d \
  --name netscaler-mcp-server \
  -p 10000:10000 \
  -v /path/to/server.key:/app/certs/server.key:ro \
  -v /path/to/server.crt:/app/certs/server.crt:ro \
  -e MCP_SERVER_PROTOCOL=https \
  -e NS_IP="<Netscaler_IP>" \
  -e NS_USERNAME="nsroot" \
  -e NS_PASSWORD="<Netscaler_PASSWORD>" \
   docker.io/netscaler/netscaler-mcp-server:tech-preview

Verify:

curl -fk https://localhost:10000/health
⁠3. HTTPS + OAuth 2.1 (Production)
docker run -d \
  --name netscaler-mcp-server \
  -p 10000:10000 \
  -e MCP_SERVER_PROTOCOL=https \
  -e NS_IP="<Netscaler_IP>" \
  -e NS_USERNAME="nsroot" \
  -e NS_PASSWORD="<Netscaler_PASSWORD>" \
  -e MCP_NS_OAUTH_ISSUER="<IDP_ISSUER_URL>" \
  -e MCP_NS_JWKS_URI="<IDP_JWKS_URL>" \
  -e MCP_NS_OAUTH_AUTH_ENDPOINT="<IDP_AUTH_URL>" \
  -e MCP_NS_OAUTH_TOKEN_ENDPOINT="<IDP_TOKEN_URL>" \
  -e MCP_SERVER_EXTERNAL_HOST="<HOST_IP>" \
  -e MCP_SERVER_EXTERNAL_PORT="10000" \
   docker.io/netscaler/netscaler-mcp-server:tech-preview

Verify:

curl -fk https://localhost:10000/health

⁠Kubernetes Deployments
⁠Pre-requisite Secret
kubectl create secret generic netscaler-secret \
  --from-literal=NS_USERNAME='<Netscaler_Username>' \
  --from-literal=NS_PASSWORD='<Netscaler_PASSWORD>'
⁠Scenario A: HTTPS, No OAuth (discovery mode)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netscaler-mcp-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: netscaler-mcp-server
  template:
    metadata:
      labels:
        app: netscaler-mcp-server
    spec:
      containers:
        - name: netscaler-mcp-server
          image:  docker.io/netscaler/netscaler-mcp-server:tech-preview
          imagePullPolicy: Always
          ports:
            - containerPort: 10000
          env:
            - name: NS_IP
              value: "<Netscaler_IP>"
            - name: NS_PORT
              value: "443"
            - name: NS_PROTOCOL
              value: "https"
            - name: NS_USERNAME
              valueFrom:
                secretKeyRef:
                  name: netscaler-secret
                  key: NS_USERNAME
            - name: NS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: netscaler-secret
                  key: NS_PASSWORD
            - name: NS_ENABLE_CERT_VALIDATION
              value: "false"
            - name: MCP_SERVER_PROTOCOL
              value: "https"
            - name: MCP_SERVER_HOST
              value: "0.0.0.0"
            - name: MCP_SERVER_PORT
              value: "10000"
            - name: DISCOVERY_SEARCH_MODE
              value: "hybrid"
            - name: DISCOVERY_MAX_TOOLS
              value: "10"
            - name: LOG_LEVEL
              value: "INFO"
            - name: FASTEMBED_CACHE_PATH
              value: "/app/.cache_fastembed"
---
apiVersion: v1
kind: Service
metadata:
  name: netscaler-mcp-server
spec:
  type: NodePort
  selector:
    app: netscaler-mcp-server
  ports:
    - protocol: TCP
      port: 10000
      targetPort: 10000
      nodePort: 30800
⁠Scenario B: HTTPS + OAuth 2.1 (production)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netscaler-mcp-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: netscaler-mcp-server
  template:
    metadata:
      labels:
        app: netscaler-mcp-server
    spec:
      containers:
        - name: netscaler-mcp-server
          image: docker.io/netscaler/netscaler-mcp-server:tech-preview
          imagePullPolicy: Always
          ports:
            - containerPort: 10000
          env:
            - name: NS_IP
              value: "<Netscaler_IP>"
            - name: NS_PORT
              value: "443"
            - name: NS_PROTOCOL
              value: "https"
            - name: NS_USERNAME
              valueFrom:
                secretKeyRef:
                  name: netscaler-secret
                  key: NS_USERNAME
            - name: NS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: netscaler-secret
                  key: NS_PASSWORD
            - name: NS_ENABLE_CERT_VALIDATION
              value: "false"
            - name: MCP_SERVER_PROTOCOL
              value: "https"
            - name: MCP_SERVER_HOST
              value: "0.0.0.0"
            - name: MCP_SERVER_PORT
              value: "10000"
            - name: MCP_SERVER_EXTERNAL_HOST
              value: "<NODE_IP>"
            - name: MCP_SERVER_EXTERNAL_PORT
              value: "<NODE_PORT>"
            - name: MCP_NS_OAUTH_ISSUER
              value: "<IDP_ISSUER_URL>"
            - name: MCP_NS_JWKS_URI
              value: "<IDP_JWKS_URL>"
            - name: MCP_NS_OAUTH_AUTH_ENDPOINT
              value: "<IDP_AUTH_URL>"
            - name: MCP_NS_OAUTH_TOKEN_ENDPOINT
              value: "<IDP_TOKEN_URL>"
            - name: DISCOVERY_SEARCH_MODE
              value: "hybrid"
            - name: DISCOVERY_MAX_TOOLS
              value: "10"
            - name: LOG_LEVEL
              value: "INFO"
            - name: FASTEMBED_CACHE_PATH
              value: "/app/.cache_fastembed"
---
apiVersion: v1
kind: Service
metadata:
  name: netscaler-mcp-server
spec:
  type: NodePort
  selector:
    app: netscaler-mcp-server
  ports:
    - protocol: TCP
      port: 10000
      targetPort: 10000
      nodePort: 30800

Apply:

kubectl apply -f <deployment yaml file>
kubectl rollout status deployment/netscaler-mcp-server
kubectl logs -l app=netscaler-mcp-server --tail=30

⁠Notes

  • Default server port: 10000
  • Health endpoint: GET /health (HTTP 200 when running)
  • The fastembed model (BAAI/bge-small-en-v1.5) is baked into the image — no internet access needed at runtime
  • No TLS certificates are included in the image — mount your own certs when using MCP_SERVER_PROTOCOL=https

Tag summary

Content type

Image

Digest

sha256:51fd2729c…

Size

199.3 MB

Last updated

about 1 month ago

docker pull netscaler/netscaler-mcp-server:tech-preview