# One FLUSHALL Away From Losing Everything

> The Redis MCP server lets AI agents run SET, DELETE, and FLUSHALL. Here's how to block destructive commands and rate limit writes.

Published: Mon Mar 16

Canonical: https://policylayer.com/blog/secure-redis-mcp-server

Your AI agent just ran `FLUSHALL`. Your session cache, your rate limiter state, your feature flags, your job queue — gone. Every key across every database in the instance, wiped in a single call. The agent was trying to "clean up unused keys" and decided the fastest approach was to start fresh.

This is the kind of failure that doesn't throw an error. Redis returns `OK`. Your application starts returning nulls. By the time anyone notices, the damage is done.

<!--truncate-->

## What the Redis MCP server exposes

The [`@modelcontextprotocol/server-redis`](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/redis) MCP server gives AI agents direct access to four tools:

- **`get`** — retrieve a value by key
- **`list`** — list keys matching a pattern
- **`set`** — write a key-value pair with optional expiration
- **`delete`** — delete one or more keys
- **`flushall`** — wipe every key in every database
- **`flushdb`** — wipe every key in the current database

The read tools are harmless. The write tools need limits. The flush tools should never be called by an agent under any circumstances.

## Block the nuclear options

[PolicyLayer](/mcp-gateway) sits between your agent and the Redis MCP server. Every `tools/call` is evaluated against a YAML policy before it reaches Redis. Start with the most important rules — hard denials on the commands that can destroy everything:

```yaml
version: "1"
description: "Policy for @modelcontextprotocol/server-redis"
default: "allow"
tools:
    flushall:
        rules:
            - name: "block flushall"
              action: deny
              on_deny: "FLUSHALL is blocked by policy. This command would wipe the entire Redis instance."

    flushdb:
        rules:
            - name: "block flushdb"
              action: deny
              on_deny: "FLUSHDB is blocked by policy. This command would wipe the current database."
```

No conditions, no rate limits — just a flat `action: deny`. The agent receives the `on_deny` message as the tool response. It can't retry its way past it. It can't rephrase the request. The block is [deterministic](/blog/deterministic-ai-agent-policies), at the transport layer, outside the model's control.

## Rate limit writes and deletes

Blocking flush commands handles the catastrophic case. But an agent running `SET` in a tight loop can still pollute your keyspace with thousands of junk entries, and an agent running `DELETE` aggressively can quietly remove keys your application depends on.

```yaml
    set:
        rules:
            - name: "rate limit writes"
              rate_limit: 60/hour
              on_deny: "Write rate limit of 60 per hour reached. Wait before setting more keys."

    delete:
        rules:
            - name: "rate limit deletes"
              rate_limit: 10/hour
              on_deny: "Delete rate limit of 10 per hour reached. Wait before deleting more keys."
```

Writes are capped at 60 per hour — enough for legitimate operations, tight enough to stop a runaway loop. Deletes are stricter at 10 per hour, because removing keys is harder to recover from than adding them.

A global rate limit catches anything that slips through the per-tool rules:

```yaml
    "*":
        rules:
            - name: "global rate limit"
              rate_limit: 120/minute
              on_deny: "Global rate limit of 120 calls per minute reached. Wait before making more requests."
```

The `rate_limit` shorthand expands internally to a stateful counter that tracks calls and resets at the start of each window. For a deeper look at how this mechanism works, see [Rate Limiting MCP Tool Calls](/blog/rate-limiting-mcp-tool-calls).

Read tools like `get` and `list` pass through without restriction thanks to `default: "allow"`. If you want tighter control, switch to `default: "deny"` and explicitly allowlist every tool — the approach we walk through in [What Happens When an AI Agent Goes Rogue](/blog/ai-agent-goes-rogue).

## Getting started

Route your Redis MCP server through PolicyLayer — point your MCP client at the gateway URL with a per-person grant token, and the policy above runs on every call before it reaches Redis:

```json
{
  "mcpServers": {
    "redis": {
      "url": "https://proxy.policylayer.com/mcp/<server-uuid>/",
      "headers": { "Authorization": "Bearer <grant-token>" }
    }
  }
}
```

You define and adjust the policy in the [PolicyLayer dashboard](https://app.policylayer.com) — no local proxy to install or run.

Every tool call now passes through the policy engine. `FLUSHALL` gets blocked instantly. Write number 61 in an hour gets blocked. Your data stays where it is.

Adjust the limits to match your workload. A caching layer that expects frequent writes might raise `set` to 200/hour. A production database backing user sessions might drop `delete` to 5. The point is that the limit exists outside the model's reasoning — it cannot be prompt-injected away.

[Full Redis policy →](/policies/redis)
