Write Operations¶
Write tools (create / update / delete / activate / bulk-mutate) are disabled by default. Every Zscaler MCP Server deployment ships as read-only until an operator explicitly opts in. This is the most important security control in the product.
Two-step opt-in¶
Enabling writes requires both a flag and an allowlist:
--enable-write-tools(orZSCALER_MCP_WRITE_ENABLED=true) turns the write subsystem on.--write-tools "pattern1,pattern2,…"(orZSCALER_MCP_WRITE_TOOLS) declares which write tools are registered.
The second flag is intentionally required — there is no “enable all writes” shortcut. The minimum viable enablement:
zscaler-mcp \
--enable-write-tools \
--write-tools "zpa_create_*,zia_update_*"
The patterns use fnmatch glob syntax. Concrete examples:
Pattern |
What it allows |
|---|---|
|
Every ZPA create-* tool (segments, server groups, policies, …) |
|
Every ZIA rule-update tool (firewall, URL filtering, SSL inspection, …) but not create or delete |
|
Every ZPA write tool — broadest pattern, use sparingly |
|
One specific tool — narrowest pattern, audit-friendly |
The patterns intersect with the toolset selection: a write tool that’s outside the loaded toolsets won’t be registered even if it matches a write pattern.
HMAC-confirmed destructive actions¶
For destructive operations — every delete tool and a few bulk-update tools — the server requires a second, cryptographically signed confirmation step. The flow:
The agent calls the destructive tool (e.g.
zpa_delete_application_segment(segment_id="123")).Instead of executing, the server returns:
{ "confirmation_required": true, "token": "<HMAC-SHA256-of-tool-name-id-action-timestamp>", "expires_at": "2026-05-27T23:14:32Z", "message": "This action will delete application segment '123'. Pass the token back to confirm." }
The agent surfaces the message to the human operator.
The operator approves, the agent calls the same tool again with the token included as a parameter, and only then does the delete execute.
The token is:
Bound to four facts: tool name, target resource ID, action (“delete”), and creation timestamp. Tampering with any of them invalidates the signature.
Single-use: the server tracks consumed tokens for the TTL window.
Time-bounded: default TTL is 300 seconds (configurable via
ZSCALER_MCP_CONFIRMATION_TTL).HMAC-signed with a server-side secret: prompt-injection attacks can’t forge or replay tokens because the attacker can’t compute the HMAC.
Implementation: zscaler_mcp/common/elicitation.py — generate_confirmation_token() and verify_confirmation_token().
Disabling confirmations¶
For automation pipelines where the operator approval is upstream (CI, a separate workflow engine), confirmations can be skipped:
ZSCALER_MCP_SKIP_CONFIRMATIONS=true zscaler-mcp \
--enable-write-tools \
--write-tools "zpa_delete_*"
This is production-disabling for agent-driven flows — the whole point of the confirmation step is to make the AI agent’s intent visible to a human before the API call executes. Only set ZSCALER_MCP_SKIP_CONFIRMATIONS=true when the calling system already has its own approval gate.
ZIA activation is its own gate¶
Every ZIA write tool stages changes in the pending bucket. Until zia_activate_configuration is called, the change is not live. The activation tool is itself a write tool — it must be in the --write-tools allowlist to be available.
In practice you want both, so a typical ZIA write deployment looks like:
zscaler-mcp \
--enable-write-tools \
--write-tools "zia_create_*,zia_update_*,zia_delete_*,zia_activate_configuration"
If the agent forgets to call zia_activate_configuration after a batch of changes, nothing happens at the API level — the tenant view stays as it was. That’s the safest failure mode.
What’s considered a write tool¶
The registry is explicit. Every tool function is declared as either a read tool or a write tool in zscaler_mcp/services.py via the service class’s read_tools / write_tools lists. The categorization is conservative:
Read: list, get, search, count, lookup, validate, dry-run-style operations.
Write: create, update, delete, activate, bulk-update, enroll, deauthorize, reset.
A read tool can never mutate tenant state — that’s enforced at the service-class level, not by convention.
Audit¶
To audit the write surface of a running server:
# List every registered write tool
zscaler-mcp --list-tools | grep -E "(create|update|delete|activate)"
# Same, but limited to one service
zscaler-mcp --list-tools | grep "zia_" | grep -E "(create|update|delete)"
When tool-call audit logging is enabled (--log-tool-calls), every write tool invocation produces a [TOOL CALL] / [TOOL OK] / [TOOL ERR] log line including the (redacted) arguments and result summary. See Tool-Call Audit Logging.
Environment summary¶
Setting |
Default |
Purpose |
|---|---|---|
|
|
Master switch for the write subsystem. |
|
(unset) |
Comma-separated |
|
|
Bypass HMAC confirmations for destructive tools. Use only when an upstream approval gate exists. |
|
|
HMAC token expiry window. |
See also¶
MCP Client Authentication — controlling who can connect in the first place.
Tool-Call Audit Logging — observability for every tool invocation.
Output Sanitization — defense against prompt-injection embedded in tool responses.