How MCP Server Kubernetes Implements Tool Filtering for Non-Destructive and Read-Only Modes
The MCP server filters available tools at runtime by checking three environment variables—ALLOW_ONLY_READONLY_TOOLS, ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS, and ALLOWED_TOOLS—to restrict the tool catalog to safe, read-only operations or specific whitelisted commands.
The flux159/mcp-server-kubernetes repository implements a declarative security model that controls which Kubernetes management tools are exposed to clients. By evaluating environment-driven flags during the ListTools request handling, the server dynamically builds the available tool catalog to prevent accidental cluster modifications or to comply with strict operational policies.
Environment Variables That Control Tool Access
The filtering mechanism relies on three mutually exclusive configuration options parsed in src/index.ts (lines 79–94). When multiple variables are set, the whitelist takes precedence, followed by the read-only flag, then the non-destructive flag.
ALLOW_ONLY_READONLY_TOOLS
Setting ALLOW_ONLY_READONLY_TOOLS="true" restricts the server to observability operations only. The readonlyTools array (lines 85–94) includes schemas for kubectl get, kubectl describe, kubectl logs, kubectl context, explainResource, listApiResources, and ping. No mutating commands are exposed to the client.
ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS
Setting ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS="true" enables a broader set of operations while explicitly excluding destructive capabilities. The server filters the full allTools catalog by removing any tool present in the destructiveTools array defined at lines 96–104. This removes kubectlDeleteSchema, uninstallHelmChartSchema, cleanupSchema, kubectlGenericSchema, and nodeManagementSchema, preventing resource deletion, Helm uninstalls, node drains, and generic destructive kubectl commands.
ALLOWED_TOOLS Whitelist
The ALLOWED_TOOLS variable accepts a comma-separated list of tool names (e.g., kubectlGet,kubectlDescribe). When present, the server bypasses all other logic and returns only the schemas matching the specified names (lines 79–83). This provides explicit, granular control over the exposed surface area.
Implementation Details in src/index.ts
The filtering logic executes during the ListTools request handler, constructing the response array based on the active environment configuration.
The Filtering Logic Flow
At lines 106–147, the server first assembles the complete allTools array containing every available tool schema. It then applies the decision tree:
- Whitelist check: If
ALLOWED_TOOLSis defined, parse the comma-separated values and return only matching schemas. - Read-only check: If
ALLOW_ONLY_READONLY_TOOLSequals"true", return the predefinedreadonlyToolsarray. - Non-destructive check: If
ALLOW_ONLY_NON_DESTRUCTIVE_TOOLSequals"true", filterallToolsto exclude any tool present indestructiveTools. - Default: Return the unfiltered
allToolsarray.
Defining Destructive and Read-Only Tool Sets
The classification of tools is hardcoded in src/index.ts based on operational impact:
- Read-only tools (lines 85–94): Query operations that cannot modify cluster state.
- Destructive tools (lines 96–104): Operations that delete resources, uninstall Helm releases, drain nodes, or execute arbitrary destructive commands.
The test suite in tests/non_destructive_tools.test.ts (lines 11–70) validates this behavior, confirming that enabling ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS removes the destructive schemas from the response and that disabling it restores the full catalog.
Practical Code Examples
Enabling Read-Only Mode
To restrict the server to observability commands only, set the environment variable before starting the server:
export ALLOW_ONLY_READONLY_TOOLS="true"
npx mcp-server-kubernetes
When a client sends a ListTools request, the server returns only the readonlyTools subset:
// Returned schemas include:
// - kubectlGetSchema
// - kubectlDescribeSchema
// - kubectlLogsSchema
// - kubectlContextSchema
// - explainResourceSchema
// - listApiResourcesSchema
// - pingSchema
Enabling Non-Destructive Mode
To allow resource creation and updates while blocking deletion operations:
export ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS="true"
npx mcp-server-kubernetes
The server filters the allTools array by excluding the destructiveTools set defined at lines 96–104 of src/index.ts. This removes tools such as kubectlDeleteSchema, uninstallHelmChartSchema, and nodeManagementSchema from the available catalog.
Using Tool Whitelisting
For granular control, specify exact tool names via the whitelist variable:
export ALLOWED_TOOLS="kubectlGet,kubectlDescribe,kubectlLogs"
npx mcp-server-kubernetes
This configuration bypasses both the read-only and non-destructive flags, returning only the three specified tool schemas regardless of their operational classification.
Summary
- Environment-driven filtering: The server evaluates
ALLOW_ONLY_READONLY_TOOLS,ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS, andALLOWED_TOOLSat runtime to determine the exposed tool catalog. - Hierarchical precedence: The whitelist (
ALLOWED_TOOLS) overrides all other flags, followed by read-only mode, then non-destructive filtering. - Explicit classification: Destructive tools are explicitly enumerated in
src/index.ts(lines 96–104) and include deletion, Helm uninstall, node drain, and generic destructive kubectl operations. - Validation: The test suite
tests/non_destructive_tools.test.tsconfirms that filtering correctly removes dangerous operations while preserving safe, observational commands.
Frequently Asked Questions
What is the difference between read-only and non-destructive modes?
Read-only mode (ALLOW_ONLY_READONLY_TOOLS="true") exposes only observability tools such as kubectl get, describe, logs, and context that cannot modify cluster state. Non-destructive mode (ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS="true") allows a broader range of operations including resource creation and updates, but explicitly filters out tools that delete resources, uninstall Helm charts, drain nodes, or execute arbitrary destructive commands.
Can I combine multiple filtering flags?
While you can set multiple environment variables simultaneously, the server applies a strict precedence order: ALLOWED_TOOLS takes priority over all other settings, followed by ALLOW_ONLY_READONLY_TOOLS, and finally ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS. If you set both read-only and non-destructive flags without a whitelist, the read-only restriction will apply because it is evaluated first in the decision tree at lines 79–94 of src/index.ts.
How do I verify which tools are available after filtering?
Send a ListTools request to the server via your MCP client or inspect the response programmatically. The server returns only the JSON schemas for tools that pass the active filters. You can also check the server logs at startup to confirm which environment variables are active, or review the test file tests/non_destructive_tools.test.ts to see the expected tool sets for each configuration.
Where are the destructive tools defined in the source code?
The destructive tool set is explicitly enumerated in src/index.ts at lines 96–104. This array includes kubectlDeleteSchema, uninstallHelmChartSchema, cleanupSchema, kubectlGenericSchema, and nodeManagementSchema. These schemas represent operations that remove resources, uninstall Helm releases, perform node maintenance, or execute arbitrary kubectl commands that could damage cluster state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →