A Model Context Protocol (MCP) server for Citrix NetScaler ADC (Application Delivery Controller).
100
NetScaler_Realm, Access Token Lifetime: configurable; Session Max: <24h>).mcp-client.* to allow CORS.openid, profile, email.MCP_NS_OAUTH_ISSUER: Full issuer URLMCP_NS_JWKS_URI: JWKS endpoint for public keysMCP_NS_OAUTH_AUTH_ENDPOINT: Auth endpoint (optional)MCP_NS_OAUTH_TOKEN_ENDPOINT: Token endpoint (optional)The server connects to NetScaler using Nitro API credentials supplied via environment variables:
| Variable | Description | Default |
|---|---|---|
NS_IP | NetScaler management IP | — |
NS_PORT | Nitro API port | 443 |
NS_PROTOCOL | http or https | https |
NS_USERNAME | username | nsroot |
NS_PASSWORD | password | — |
Kubernetes secret: create
netscaler-secretwith keysNS_USERNAMEandNS_PASSWORD(see Kubernetes Deployments).
The image does not include any TLS certificates. Certificate provisioning is the operator's responsibility.
MCP_SERVER_PROTOCOL=https and mount your certificate files into the container.MCP_SERVER_PROTOCOL=https is set but no certificate files are found at the configured paths, the container exits immediately with an error.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
discovery (default — recommended)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:
| Variable | Description | Default |
|---|---|---|
DISCOVERY_SEARCH_MODE | hybrid | hybrid |
DISCOVERY_MAX_TOOLS | Max tools returned per query | 10 |
| Variable | Description | Default |
|---|---|---|
NS_IP | NetScaler management IP | — |
NS_PORT | Netscaler API port | 443 |
NS_PROTOCOL | Protocol to reach Netscaler (http/https) | https |
NS_USERNAME | Netscaler username | nsroot |
NS_PASSWORD | Netscaler password | — |
NS_ENABLE_CERT_VALIDATION | Validate Netscaler TLS cert (true/false) | false |
MCP_SERVER_PROTOCOL | MCP server protocol (http/https) | https |
MCP_SERVER_HOST | MCP server bind address | 0.0.0.0 |
MCP_SERVER_PORT | MCP server bind port | 10000 |
MCP_SERVER_EXTERNAL_HOST | Advertised external host (OAuth discovery) | — |
MCP_SERVER_EXTERNAL_PORT | Advertised external port (OAuth discovery) | — |
MCP_ALLOWED_HOSTS | Allowed host header values | * |
MCP_NS_OAUTH_ISSUER | OAuth 2.1 issuer URL (enables OAuth when set with JWKS_URI) | — |
MCP_NS_JWKS_URI | JWKS endpoint for JWT verification | — |
MCP_NS_OAUTH_AUTH_ENDPOINT | OAuth authorization endpoint | — |
MCP_NS_OAUTH_TOKEN_ENDPOINT | OAuth token endpoint | — |
DISCOVERY_SEARCH_MODE | hybrid | hybrid |
DISCOVERY_MAX_TOOLS | Max tools returned per discover query | 10 |
SSL_CERT_PATH | TLS certificate path inside container | /app/certs/server.crt |
SSL_KEY_PATH | TLS key path inside container | /app/certs/server.key |
LOG_LEVEL | Log verbosity (DEBUG, INFO, WARNING) | INFO |
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
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
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
kubectl create secret generic netscaler-secret \
--from-literal=NS_USERNAME='<Netscaler_Username>' \
--from-literal=NS_PASSWORD='<Netscaler_PASSWORD>'
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
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
10000GET /health (HTTP 200 when running)BAAI/bge-small-en-v1.5) is baked into the image — no internet access needed at runtimeMCP_SERVER_PROTOCOL=httpsContent type
Image
Digest
sha256:51fd2729c…
Size
199.3 MB
Last updated
about 1 month ago
docker pull netscaler/netscaler-mcp-server:tech-preview