GCP Compute Engine VM Deployment¶
This guide walks you through deploying the Zscaler Integrations MCP Server to a Google Compute Engine VM running Debian 12, with the server installed from PyPI (pip install zscaler-mcp[gcp]) and managed by systemd.
The unified gcp_mcp_operations.py script provisions the VM, opens a firewall rule for the MCP port, runs a startup script that installs the package and registers the service, and (optionally) wires up GCP Secret Manager for credential delivery.
Note
Compute Engine VM has no dedicated video walkthrough yet — see the complete GCP walkthrough on Wistia for full coverage of every GCP target including this one.
When to Pick the VM Target¶
The VM target is useful when:
Your organization enforces
constraints/iam.allowedPolicyMemberDomainsand Cloud Run’sallUsersingress is blocked. The VM avoids Cloud Run’s IAM layer entirely — the MCP server’s own auth (JWT, API Key, Zscaler) is the sole gatekeeper.You need direct OS-level control (custom networking, sidecar processes, package management).
You want a long-lived deployment without containers or Kubernetes.
You’re running a PoC and want the simplest possible “single VM” footprint.
For managed / serverless alternatives see GCP Cloud Run Deployment and GCP GKE Deployment.
Prerequisites¶
gcloud CLI installed and authenticated (
gcloud auth login)A GCP project with billing enabled
Zscaler OneAPI credentials (
ZSCALER_CLIENT_ID,ZSCALER_CLIENT_SECRET,ZSCALER_VANITY_DOMAIN,ZSCALER_CUSTOMER_ID)
Required GCP APIs¶
gcloud services enable \
compute.googleapis.com \
secretmanager.googleapis.com \
--project YOUR_PROJECT_ID
Required IAM Roles¶
If you enable Secret Manager, the VM’s runtime service account (default Compute Engine service account PROJECT_NUMBER-compute@developer.gserviceaccount.com) needs:
Role |
Purpose |
|---|---|
|
Read Zscaler credentials from GCP Secret Manager at startup |
PROJECT_ID="your-project"
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA" --role="roles/secretmanager.secretAccessor"
Quick Start¶
cd integrations/google/gcp
python gcp_mcp_operations.py deploy
When prompted for the deployment target, select Compute Engine VM. The script then asks for:
GCP project ID and zone (defaults pulled from
.envif present; default zoneus-central1-a)VM name — defaults to
zscaler-mcp-serverMachine type — defaults to
e2-mediumMCP port — defaults to
8000MCP auth mode — JWT, API Key, Zscaler, or None
GCP Secret Manager — recommended (
y)
What the Script Does¶
Verifies
gcloudis installed and the user is logged inEnables the Compute Engine API on the target project
Creates a VPC firewall rule (
allow-mcp-<port>) opening the MCP port formcp-server-tagged instances(Secret Manager path) creates Zscaler secrets in Secret Manager and grants IAM access
Generates a startup script that:
Installs Python and
pipRuns
pip install zscaler-mcp[gcp](thegcpextra includes the Secret Manager client)Writes
/opt/zscaler-mcp/envwith the resolved configurationInstalls and starts a
zscaler-mcp.servicesystemdunit
Provisions the VM with the
mcp-servernetwork tag and the embedded startup scriptPolls the instance for its external IP
Updates Claude Desktop and Cursor configs with
http://<EXTERNAL_IP>:<port>/mcp
Operations¶
python gcp_mcp_operations.py status # check VM and service health
python gcp_mcp_operations.py logs # stream systemd journal
python gcp_mcp_operations.py ssh # SSH into the VM
python gcp_mcp_operations.py destroy # delete VM + firewall rule
python gcp_mcp_operations.py destroy -y # non-interactive teardown
VM Service Management¶
Once deployed, you can manage the MCP server directly from the VM:
python gcp_mcp_operations.py ssh
# On the VM:
sudo systemctl status zscaler-mcp # service status
sudo journalctl -u zscaler-mcp -f # stream logs
sudo systemctl restart zscaler-mcp # restart service
# Configuration / credentials:
cat /opt/zscaler-mcp/env
# Re-install / upgrade the package:
sudo /opt/zscaler-mcp/venv/bin/pip install --upgrade 'zscaler-mcp[gcp]'
GCP Secret Manager Integration¶
When you answer Yes to “Use GCP Secret Manager for credentials?”, the script:
Stores each Zscaler credential as a separate secret (canonical names:
zscaler-client-id,zscaler-client-secret,zscaler-vanity-domain,zscaler-customer-id,zscaler-cloud)Grants
roles/secretmanager.secretAccessorto the VM’s runtime service accountConfigures the VM with
ZSCALER_MCP_GCP_SECRET_MANAGER=trueandGCP_PROJECT_ID=<project>
The MCP server’s built-in credential loader fetches each secret at startup before the server initializes — no wrapper scripts required. Without Secret Manager, credentials are written into /opt/zscaler-mcp/env as plain values.
To rotate a credential:
echo -n "new-client-secret" | \
gcloud secrets versions add zscaler-client-secret --data-file=-
# Restart the service so it picks up the new version:
gcloud compute ssh <VM_NAME> --zone <ZONE> \
--command "sudo systemctl restart zscaler-mcp"
Authentication Modes¶
The VM supports four MCP client authentication modes (same set as Cloud Run / GKE):
Mode |
Description |
Client Auth Header |
|---|---|---|
JWT |
Validate JWTs against a JWKS endpoint |
|
API Key |
Shared secret (auto-generated if not provided) |
|
Zscaler |
Validate via OneAPI client credentials (recommended for VM) |
|
None |
No authentication — development only |
No header |
The script generates the appropriate Authorization header for the selected mode and writes it into your Claude Desktop and Cursor configs alongside the VM’s external IP.
Connecting Clients¶
The script updates Claude Desktop and Cursor automatically. If you need to configure a client manually:
Claude Desktop:
{
"mcpServers": {
"zscaler-mcp-server": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"http://<EXTERNAL_IP>:8000/mcp",
"--allow-http",
"--header",
"Authorization: Basic <base64(client_id:client_secret)>"
]
}
}
}
Cursor (``mcp.json``):
{
"mcpServers": {
"zscaler-mcp-server": {
"url": "http://<EXTERNAL_IP>:8000/mcp",
"headers": {
"Authorization": "Basic <base64(client_id:client_secret)>"
}
}
}
}
The --allow-http flag is required by mcp-remote for non-localhost HTTP URLs. Drop it if you front the VM with a load balancer + TLS.
Production Hardening¶
The default deployment exposes plain HTTP on the MCP port via a single firewall rule. For production:
TLS — front the VM with an external HTTPS Load Balancer + Google-managed certificate, or terminate TLS on the VM with NGINX / Caddy + Let’s Encrypt.
Restrict ingress — replace the firewall rule’s default
0.0.0.0/0source range with your corporate CIDRs or VPC ranges (--source-ranges), or move the VM into a private subnet behind an internal LB.Identity-Aware Proxy — for browser-mediated access from
@yourcompany.comusers, place the VM behind an external HTTPS LB with IAP enabled and grantroles/iap.httpsResourceAccessorto the appropriate principals.OS hardening — restrict SSH ingress to IAP / your bastion, and patch the VM regularly (
unattended-upgradesis installed by default on Debian 12).
Troubleshooting¶
``Connection refused`` from clients — confirm the firewall rule exists (gcloud compute firewall-rules describe allow-mcp-8000) and that the VM has the mcp-server network tag (gcloud compute instances describe <VM_NAME> --zone <ZONE>).
Service fails to start with ``permission denied`` on Secret Manager — verify the project’s default Compute Engine service account has roles/secretmanager.secretAccessor. If you ran the destroy/redeploy cycle, the binding may not have been re-applied — gcloud projects add-iam-policy-binding it again.
``systemctl status zscaler-mcp`` shows ``activating (auto-restart)`` — check sudo journalctl -u zscaler-mcp -n 100 for the underlying error. The most common causes are missing env vars in /opt/zscaler-mcp/env or transient network errors reaching ZIdentity at startup.
``mcp-remote`` hangs in Claude Desktop — verify the URL is reachable (curl http://<EXTERNAL_IP>:8000/mcp). If you’re behind a corporate proxy, also try --allow-http on the mcp-remote command.
References¶
integrations/google/ — full integration source, env templates, and per-client configuration examples
GCP Cloud Run Deployment — Cloud Run deployment guide
GCP GKE Deployment — GKE deployment guide