# Read-Only vs Non-Destructive Mode in the MCP Server: Understanding the Distinction

> Understand the difference between read-only and non-destructive modes in MCP Server. Learn how to observe resources or modify them while preventing deletions.

- Repository: [Suyog Sonwalkar/mcp-server-kubernetes](https://github.com/flux159/mcp-server-kubernetes)
- Tags: deep-dive
- Published: 2026-03-02

---

**Read-only mode exposes only observation tools like `kubectl_get` and `kubectl_describe`, while non-destructive mode permits resource modifications but blocks deletions by filtering out destructive operations.**

The `flux159/mcp-server-kubernetes` repository implements two independent safety mechanisms to control which Kubernetes operations are available through the Model Context Protocol (MCP). These modes allow administrators to restrict the server's capabilities based on operational requirements, distinguishing between pure observation and protected modification workflows.

## Environment Variables That Control Tool Access

The MCP server evaluates two environment flags at startup in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) to determine which tools to register. These flags operate independently and create distinct security boundaries.

### Read-Only Mode (ALLOW_ONLY_READONLY_TOOLS)

When `ALLOW_ONLY_READONLY_TOOLS` is set to `"true"`, the server exposes **only the explicitly marked read-only tools**. These tools can retrieve information from a cluster but cannot create, modify, or delete any resources.

In [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts), the `readonlyTools` array defines this whitelist:

- `kubectl_get`
- `kubectl_describe`
- `kubectl_logs`
- `kubectl_context`
- `explainResource`
- `listApiResources`
- `ping`

This mode strictly limits the API to pure observation, making it impossible for users to affect cluster state regardless of their intent.

### Non-Destructive Mode (ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS)

When `ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS` is set to `"true"`, the server **filters out the destructive tools** while preserving the rest of the toolset. This permits actions that modify resources—such as `kubectl_apply`, `kubectl_create`, and `kubectl_scale`—while protecting against irreversible deletions.

The implementation in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) reads this flag at startup and subtracts the `destructiveTools` blacklist from the `allTools` collection. Destructive operations removed in this mode include delete operations, Helm uninstall commands, cleanup utilities, generic destructive `kubectl` commands, and node-drain functions.

## Key Distinctions Between the Two Modes

Understanding the practical differences between these modes helps you select the appropriate restriction level for your environment.

### Scope of Allowed Actions

**Read-only mode** limits the API to pure observation. Users cannot create, patch, scale, or delete resources. This represents the most restrictive operational stance.

**Non-destructive mode** still allows creation, updates, and scaling. It only blocks operations that delete or otherwise remove resources from the cluster. This provides a middle ground between full access and complete restriction.

### Implementation Differences

The two modes use fundamentally different filtering strategies in the source code:

- **Read-only** selects a **pre-defined whitelist** (`readonlyTools`) containing only the seven observation tools.
- **Non-destructive** builds the allowed list by **subtracting** the `destructiveTools` blacklist from the complete `allTools` collection, leaving all non-destructive operations intact.

### When to Use Each Mode

Select **read-only mode** for environments where users must never affect the cluster, such as audit dashboards, monitoring interfaces, or production observation consoles where accidental modifications could cause outages.

Select **non-destructive mode** when you want to let users manage configuration and scale resources but safeguard against accidental deletions or infrastructure teardown. This suits development environments, CI/CD pipelines, or scenarios requiring configuration management without destruction risk.

## Practical Configuration Examples

Enable read-only mode before starting the server to restrict operations to observation only:

```bash
export ALLOW_ONLY_READONLY_TOOLS=true
bun run start

```

The server will now return only the seven read-only tools when clients call `listTools`.

Enable non-destructive mode to allow modifications while blocking deletions:

```bash
export ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS=true
bun run start

```

In this configuration, destructive tools including delete operations, Helm uninstall, and node-drain commands are omitted from the available set, but `apply`, `create`, and `scale` remain accessible.

Verify the active tool set programmatically:

```javascript
const tools = await client.request({ method: "listTools" });
console.log(tools);
// Read-only mode: returns only readonlyTools array items
// Non-destructive mode: returns allTools minus destructiveTools

```

## How Tool Filtering Works in the Source Code

The filtering logic resides in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) and determines tool visibility at server initialization.

For read-only mode, the code explicitly exports the `readonlyTools` array (lines 85-94), containing tool schemas that only retrieve data. When the environment variable is detected, the server limits the toolset to this specific collection.

For non-destructive mode, the code checks `ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS` (lines 82-84) and applies a filter function that removes any tool listed in the `destructiveTools` array (lines 96-104) from the complete `allTools` collection. This subtractive approach ensures that any new non-destructive tools added to the codebase automatically become available in this mode without explicit whitelisting.

The test suite validates these behaviors in [`tests/non_destructive_tools.test.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/tests/non_destructive_tools.test.ts), confirming that the environment flag correctly filters out destructive operations while preserving modification capabilities.

## Summary

- **Read-only mode** uses a whitelist approach via `ALLOW_ONLY_READONLY_TOOLS`, exposing only seven observation tools and preventing any cluster modifications.
- **Non-destructive mode** uses a blacklist approach via `ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS`, allowing resource creation and modification while blocking deletions and uninstalls.
- **Implementation location** for both modes is [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts), which defines the `readonlyTools` whitelist and `destructiveTools` blacklist.
- **Default behavior** exposes all tools when neither environment variable is set, including both destructive and non-destructive operations.

## Frequently Asked Questions

### Can I enable both read-only and non-destructive modes simultaneously?

While both flags can technically be set in the environment, [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) processes `ALLOW_ONLY_READONLY_TOOLS` first. If set to true, the server exposes only the `readonlyTools` whitelist, effectively overriding the non-destructive filter. Read-only mode represents the more restrictive constraint, so it takes precedence when both are active.

### Does non-destructive mode prevent all resource modifications?

No. Non-destructive mode specifically removes tools defined in the `destructiveTools` array—primarily delete operations, Helm uninstalls, and node drains. It explicitly permits modifying operations such as `kubectl_apply`, `kubectl_create`, `kubectl_scale`, and `kubectl_patch`. This distinction protects against irreversible deletions while allowing legitimate configuration management.

### Where are the destructive tools defined in the codebase?

The `destructiveTools` array is defined in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) alongside the filtering logic. This array contains references to tool schemas located in the `src/tools/` directory, including files like [`kubectl_delete.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/kubectl_delete.ts) and Helm uninstall utilities. The test file [`tests/non_destructive_tools.test.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/tests/non_destructive_tools.test.ts) provides the definitive list of which specific tools are filtered when non-destructive mode is active.

### Which mode should I use for production environments?

For production environments where the MCP server provides observability without operational risk, **read-only mode** is the safer choice. It guarantees that connected clients cannot accidentally or maliciously modify cluster state. Use non-destructive mode only in production if you have specific operational workflows requiring safe configuration updates with strict protection against resource deletion.