Skip to main content
Glama
redis-switchboard-mcp

redis-switchboard-mcp

by hexiaowu

redis-switchboard-mcp

English | 简体中文

A Redis MCP server that switches logical databases per request instead of relying on Redis's connection-level SELECT.

execute    → run a Redis command against db 2, db 4, ...
read_page  → bounded page of a list / hash / set / zset / stream / string
scan_keys  → cursor-based SCAN with limits
key_info   → type / TTL / memory / encoding / length

redis-switchboard-mcp is designed for the way MCP clients actually work: many independent tool calls, often concurrent, against several environments and several Redis logical databases.

Tool parameters and descriptions are delivered to the MCP client through tools/list; this README covers configuration, safety limits and runtime behavior.

Quick start

  1. Check you are on Node.js 20+ — no global install is needed, the client launches npx -y redis-switchboard-mcp.

  2. Add the server to your MCP client: MCP client configuration.

  3. Restart the client and run PING; a working setup returns PONG.


Related MCP server: database-remote-mcp

Why this exists

Redis's SELECT changes the database of a connection, not of a command. An MCP server that shares one connection and runs SELECT on demand will silently mix databases: a concurrent call, a pooled connection, or an automatic reconnect can leave the client on the wrong DB.

This server treats the database as a per-call argument instead. Every tool accepts db, each (instance, db) gets its own connection selected and verified for that database, and SELECT (plus MOVE, SWAPDB, COPY ... DB) is rejected. So execute in db 2 and db 4 can run concurrently without leaking state, and a reconnect never lands a command on the wrong database.


Features

  • Per-call database selection for every tool (db: 0-255).

  • Multiple Redis instances from a JSON config, selected with the instance argument.

  • Explicit permission mode (readonly / readwrite, default readonly); readonly uses an explicit read-command whitelist.

  • Command blocklist for connection-level, administrative, destructive and blocking commands.

  • Lua scripting disabled by default (EVAL/EVALSHA/FCALL).

  • Bounded output with per-container and global item/character budgets.

  • Paged collection reads via read_page, so large lists/hashes/sets/streams are never fetched in one shot.

  • Fetch guards in execute: unbounded bulk reads are rejected before they materialize, with a pointer to read_page (see Output and fetch bounds).

  • Bounded scans with limit, SCAN iteration cap, and a wall-clock budget.

  • Cluster detection — logical DBs other than 0 are rejected on a Redis Cluster.

  • Connection cache limit per instance (maxConnections, default 32), with a small pool per (instance, db) (poolSize, default 4) and idle connection recycling (idleTimeoutMs, default 5 minutes): a connection that has not run any command for 5 minutes is closed and evicted, so databases you stop using stop holding server resources.

  • Credential redaction in error messages.

  • No stdout logging — stdout is reserved for the MCP stdio transport.


Requirements

  • Node.js 20 or newer

  • Redis 6 or newer (SCAN TYPE); SORT_RO requires Redis 7+

  • A standalone Redis server, or a Redis Cluster used at db 0 only


Installation

From npm

npm install -g redis-switchboard-mcp
rsm --help

Or run it without a global install:

npx -y redis-switchboard-mcp

From source

git clone https://github.com/hexiaowu/redis-switchboard-mcp.git
cd redis-switchboard-mcp
npm ci
npm run build
node dist/index.js

MCP client configuration

Add the block below to your MCP client's server configuration — for example claude_desktop_config.json for Claude Desktop. Other clients (VS Code, for instance) use different files or keys; the mcpServers shape shown here is the common one.

Single instance, environment variables

Use this if you have one Redis; see multiple instances only if you need several.

{
  "mcpServers": {
    "redis": {
      "command": "npx",
      "args": ["-y", "redis-switchboard-mcp"],
      "env": {
        "REDIS_HOST": "127.0.0.1",
        "REDIS_PORT": "6379",
        "REDIS_PASSWORD": "your-password",
        "REDIS_MODE": "readonly"
      }
    }
  }
}

Remove REDIS_PASSWORD if your Redis requires no authentication.

If the package is installed globally, "command": "rsm" with no args also works.

Multiple instances from a JSON file

{
  "mcpServers": {
    "redis": {
      "command": "npx",
      "args": ["-y", "redis-switchboard-mcp"],
      "env": {
        "REDIS_MCP_CONFIG": "/Users/me/.config/redis-switchboard.config.json"
      }
    }
  }
}

Note: diagnostics are written to stderr; stdout is reserved for the MCP stdio transport.

Verify the setup

Restart the MCP client, then ask it to run a command:

{ "command": "PING", "db": 0 }

A working setup returns "reply": "PONG". Use the db argument to target another logical database; it defaults to the instance db. Then ask it for real work, for example “run GET user:42 against db 2”.


  1. Command-line flags (--config, --db, ...)

  2. Environment variables

  3. Defaults

--config selects a JSON config file. --name/--db are rejected when a JSON config is used; edit the JSON file for per-instance values.

Option

Required

Description

--config <path>

🔶 Conditional

JSON config file describing one or more Redis instances

--name <name>

⚪ Optional

Instance name (default: default)

--db <n>

⚪ Optional

Default logical database, 0-255 (default: 0)

--mode <mode>

⚪ Optional

Override permission mode for all instances: readonly or readwrite

-h, --help

⚪ Optional

Show help

-v, --version

⚪ Optional

Show the version

Variable

Required

Default

Description

REDIS_MCP_CONFIG

🔶 Conditional

—

Path to a multi-instance JSON config file

REDIS_NAME

⚪ Optional

default

Instance name for the single-instance form

REDIS_HOST

🔶 Conditional

—

Redis host (required when no JSON config is used)

REDIS_PORT

🔶 Conditional

—

Redis port (required when no JSON config is used)

REDIS_USERNAME

⚪ Optional

—

ACL username

REDIS_PASSWORD

🔶 Conditional

—

Password (required when Redis requires authentication)

REDIS_DB

⚪ Optional

0

Default logical database when db is omitted

REDIS_TLS

⚪ Optional

false

Enable TLS

REDIS_TLS_REJECT_UNAUTHORIZED

⚪ Optional

true

Verify the server certificate

REDIS_MODE

⚪ Optional

readonly

Permission mode: readonly or readwrite (defaults to readonly when omitted)

REDIS_ALLOWED_DBS

⚪ Optional

—

Comma-separated allowlist, e.g. 0,2,4; must include REDIS_DB

REDIS_ALLOW_SCRIPTING

⚪ Optional

false

Allow EVAL/EVALSHA/FCALL (see security caveat)

REDIS_MAX_CONNECTIONS

⚪ Optional

32

Per-instance connection cache limit (1-256)

REDIS_POOL_SIZE

⚪ Optional

4

Connections pooled per (instance, db) (1-16)

REDIS_IDLE_TIMEOUT_MS

⚪ Optional

300000

Close an idle (instance, db) connection after this long without a command; 0 disables

REDIS_CONNECT_TIMEOUT_MS

⚪ Optional

5000

TCP/connect timeout

REDIS_COMMAND_TIMEOUT_MS

⚪ Optional

15000

Per-command timeout; 0 disables it (a 60 s socket timeout still applies)

REDIS_MAX_RESULT_ITEMS

⚪ Optional

200

Per-array/object item cap in replies

REDIS_MAX_RESULT_CHARS

⚪ Optional

4000

Per-string cap in replies

REDIS_MAX_RESULT_DEPTH

⚪ Optional

4

Maximum nested container depth

REDIS_MAX_FETCH_ITEMS

⚪ Optional

1000

Max items one execute bulk read may fetch

REDIS_MAX_FETCH_CHARS

⚪ Optional

1000000

Max bytes one execute string read may fetch

REDIS_SCAN_COUNT

⚪ Optional

500

Default SCAN COUNT hint

REDIS_MAX_SCAN_ITERATIONS

⚪ Optional

200

Maximum SCAN round trips per call

REDIS_SCAN_TIME_BUDGET_MS

⚪ Optional

10000

Wall-clock budget per scan_keys call

Method

Required

How

JSON config

🔶 Conditional

Set REDIS_MCP_CONFIG (or --config); host, port and mode come from the file

Host + port

🔶 Conditional

Set REDIS_HOST and REDIS_PORT (and REDIS_MODE if needed)

For the single-instance environment form, REDIS_HOST and REDIS_PORT are required — there is no built-in host or port default. The JSON config alternative defines host/port for each instance.

JSON config and REDIS_HOST/REDIS_PORT/REDIS_MODE are mutually exclusive: setting them with a JSON config is a configuration error (the process refuses to start and tells you to define host/port/mode per instance in the JSON file). Other single-instance environment variables are not applied when a JSON config is used.

{
  "defaultInstance": "cache-dev",
  "instances": [
    {
      "name": "cache-dev",
      "host": "127.0.0.1",
      "port": 6379,
      "db": 0,
      "mode": "readwrite",
      "allowedDbs": [0, 2, 4],
      "maxConnections": 32
    },
    {
      "name": "cache-prod",
      "host": "redis.prod.internal",
      "port": 6380,
      "username": "app",
      "password": "your-password",
      "tls": true,
      "db": 0,
      "mode": "readonly",
      "allowedDbs": [0],
      "commandTimeoutMs": 10000,
      "maxResultItems": 100,
      "maxResultChars": 2000,
      "maxFetchItems": 500,
      "maxFetchChars": 500000
    }
  ]
}

Field

Required

Default

Description

instances

✅ Required

—

Array with at least one instance

defaultInstance

⚪ Optional

—

Instance used when a tool call omits instance

Field

Required

Default

Description

name

🔶 Conditional

default

Unique instance name; must be unique when several instances are configured

host / port

✅ Required

—

Connection endpoint

username

⚪ Optional

—

ACL username

password

🔶 Conditional

—

Inline password (required when Redis requires authentication)

usernameEnv / passwordEnv

⚪ Optional

—

Read credentials from an environment variable

db

⚪ Optional

0

Default logical database

tls

⚪ Optional

false

Enable TLS

tlsRejectUnauthorized

⚪ Optional

true

Verify the server certificate

mode

⚪ Optional

readonly

Permission mode: readonly or readwrite (defaults to readonly when omitted)

allowScripting

⚪ Optional

false

Allow EVAL/EVALSHA/FCALL

allowedDbs

⚪ Optional

—

Restrict which logical DBs this instance may access; must include db

maxConnections

⚪ Optional

32

Cache limit for (instance, db) connections

poolSize

⚪ Optional

4

Connections pooled per (instance, db) (1-16)

idleTimeoutMs

⚪ Optional

300000

Close an idle (instance, db) connection after this long without a command; 0 disables

connectTimeoutMs

⚪ Optional

5000

TCP/connect timeout

commandTimeoutMs

⚪ Optional

15000

Per-command timeout; 0 disables it (a 60 s socket timeout still applies)

maxResultItems

⚪ Optional

200

Per-container item cap

maxResultChars

⚪ Optional

4000

Per-string character cap

maxResultDepth

⚪ Optional

4

Nested container depth limit

maxFetchItems

⚪ Optional

1000

Max items one execute bulk read may fetch

maxFetchChars

⚪ Optional

1000000

Max bytes one execute string read may fetch

scanCount

⚪ Optional

500

Default SCAN COUNT hint

maxScanIterations

⚪ Optional

200

SCAN round-trip cap

scanTimeBudgetMs

⚪ Optional

10000

scan_keys wall-clock budget

Keep a config file containing passwords at chmod 600. passwordEnv/usernameEnv are supported if you prefer to inject credentials from the environment (password and passwordEnv cannot be combined).

Unknown fields (top-level or per instance) are rejected at startup, so a typo aborts the process.


Security model

Permission modes

The permission mode is an explicit enum with no readOnly boolean, and it defaults to readonly:

Mode

Behavior

readonly

Only an explicit read-command whitelist is accepted; SET, HSET, DEL, RESTORE, ... are rejected. EVAL/FCALL remain rejected even if allowScripting is true.

readwrite

Write commands such as SET, HSET, DEL are allowed; the always-rejected list below still applies, and EVAL/FCALL are allowed only when allowScripting is true.

Set it per instance ("mode"), for the single-instance environment form (REDIS_MODE), or for every instance at once (--mode). A Redis ACL with a read-only user is a second layer of defense — readonly mode is a convenience, not a replacement for server-side ACLs.

Always rejected

Category

Examples

Database / connection state

SELECT, MOVE, SWAPDB, COPY ... DB, MULTI, EXEC, WATCH, RESET, HELLO, AUTH, QUIT

Pub/sub and streaming

SUBSCRIBE, PSUBSCRIBE, MONITOR, SYNC, PSYNC

Administration

CONFIG, DEBUG, CLIENT, ACL, MODULE, SHUTDOWN, SCRIPT, FUNCTION

Topology / replication

CLUSTER, REPLICAOF, SLAVEOF, FAILOVER, MIGRATE, REPLCONF

Destructive / server-wide

FLUSHDB, FLUSHALL, SAVE, BGSAVE, BGREWRITEAOF

Blocking

BLPOP, BRPOP, BLMOVE, BZPOPMIN, WAIT, XREAD, XREADGROUP, ...

Slow key enumeration

KEYS, raw SCAN — use scan_keys

Blocking commands are rejected because they hold a shared per-database connection and can stall every later request on that DB.

Lua scripting

EVAL, EVALSHA, EVAL_RO, EVALSHA_RO, FCALL and FCALL_RO are disabled by default. allowScripting: true / REDIS_ALLOW_SCRIPTING=1 enables them for trusted callers. In readonly mode the read-command whitelist still wins, so scripting stays rejected even with allowScripting enabled.

A Lua script can call commands that the blocklist otherwise rejects, and depending on the Redis version it may be able to reach other logical databases. Treat allowScripting as disabling both the blocklist and the allowedDbs boundary: only enable it for trusted callers and enforce limits with a Redis ACL.

Output and fetch bounds

Replies are truncated: maxResultItems per array/object, maxResultChars per string/buffer, maxResultDepth for nesting, and a global item/character budget derived from them so nested replies cannot multiply into gigabytes.

execute also checks bulk reads before the command runs:

Shape

Guarded commands

Strings

GET, GETDEL, GETEX, GETSET, SET ... GET, GETRANGE/SUBSTR, MGET (≤ 100 keys), HMGET (≤ 100 fields)

Hash / set / zset

HGET, HGETALL, HKEYS, HVALS, SMEMBERS, SINTER/SUNION/SDIFF, ZRANGE/ZREVRANGE/ZRANGEBY*, ZUNION/ZINTER/ZDIFF

Lists

LRANGE, LPOS ... COUNT 0

Streams

XRANGE/XREVRANGE without COUNT, XINFO STREAM ... FULL, XPENDING, XAUTOCLAIM

Aggregates

SORT/SORT_RO without LIMIT, LCS, GEOSEARCH/GEORADIUS*, DUMP

Counts

pop and random-member counts, HSCAN/SSCAN/ZSCAN COUNT, MEMORY USAGE ... SAMPLES 0, COMMAND, SLOWLOG GET

Unbounded forms are rejected with COMMAND_REJECTED and a pointer to read_page; bounded forms still run. The limits are maxFetchItems (default 1000) and maxFetchChars (default 1,000,000).

The check is advisory — metadata is read just before the command, so a concurrent writer can still grow the key afterwards — and not exhaustive: LINDEX and the *STORE variants are not checked, and item-count checks do not bound the byte size of a single field or member.

The guard and read_page issue STRLEN, HSTRLEN, LLEN, HLEN, SCARD, ZCARD, XLEN, TYPE and MEMORY USAGE, so the Redis user must be allowed to run them. A NOPERM on a guard command fails the execute call; read_page treats a failed size probe as unavailable and skips the page-size reduction. Since the byte check uses whole-key memory usage, a very large key can be rejected even when you only read a small page — use read_page for page-sized reads.

Other bounds:

  • read_page: server-side paging; limit is validated at 1,000 and capped by maxFetchItems. Pass nextOffset, nextCursor or nextStart back unchanged until complete is true.

  • scan_keys: limit, maxScanIterations, scanTimeBudgetMs

  • maxConnections: bounds total sockets per instance

Credentials

  • A Redis user must be allowed to run SELECT to use any database other than 0. Without +select, db > 0 fails closed with a DB_ERROR instead of silently using db 0.

  • Prefer passwordEnv / REDIS_PASSWORD over inline JSON passwords.

  • Keep a config file containing secrets at chmod 600.

  • Error messages redact password=..., quoted/JSON password fields, echoed AUTH arguments, and any connection URL that may appear in an error.

  • TLS certificate verification is on by default; tlsRejectUnauthorized: false disables it and should only be used for self-signed development servers.

  • TLS supports tls and tlsRejectUnauthorized only; a custom CA or client certificate (ca/cert/key) cannot be configured.

Transport

This package exposes a stdio MCP server. It does not open an HTTP port and does not implement MCP authentication. The MCP client that launches it is the trust boundary.

Errors

Failed calls return isError: true with a JSON text block {"error": "...", "code": "..."}. Codes: CONFIG_ERROR, COMMAND_REJECTED, COMMAND_SYNTAX, COMMAND_ERROR, INSTANCE_ERROR, DB_ERROR, CONNECTION_ERROR, INTERNAL_ERROR. Redis server errors such as NOPERM or WRONGTYPE map to COMMAND_ERROR.


Behavior and limitations

  • No SELECT: logical DB selection is per call — see Why this exists.

  • Redis Cluster: only db 0 exists. The server detects cluster_enabled:1 and rejects db > 0. It connects to a single node, so keys owned by other slots can return MOVED; it is not a cluster-aware sharding client.

  • No transactions: MULTI/EXEC/WATCH are connection-level and would leak between requests.

  • No pub/sub or MONITOR: they change the connection mode.

  • No blocking commands: they would pin a shared connection. Use non-blocking variants (XRANGE instead of blocking XREAD, etc.).

  • Command timeouts are client-side: the timeout rejects the call but does not cancel the command in Redis, so a timed-out write may still have been applied. Verify state before retrying. commandTimeoutMs: 0 disables the command timeout, but the 60 s socket timeout still applies, so a command that stays silent for 60 s fails anyway.

  • Commands in flight during a disconnect are not resent: a write that was sent when the socket dropped can fail even though Redis may have executed it. Verify state before retrying.

  • Binary values: replies are decoded as UTF-8 strings. DUMP and other binary payloads may not round-trip; buffers are returned as bounded base64 when the client produces them.

  • Large reads: a command the guard does not cover (see Output and fetch bounds) can still be fully materialized before output truncation runs. Prefer key_info for metadata, scan_keys for enumeration, read_page for collections, and a restricted ACL / commandTimeoutMs for very large data.

  • SCAN consistency: SCAN is incremental and not a snapshot; results can be missed or duplicated across calls.

  • Connection cache: each (instance, db) pair keeps up to poolSize (default 4) pooled connections. The per-instance cap is maxConnections (default 32) and is a hard stop. Connections idle for longer than idleTimeoutMs (default 5 minutes) are closed automatically; a connection with a command that timed out is dropped immediately and replaced on the next request. Raise maxConnections if you legitimately use many logical DBs.

  • Cluster + ACL: if INFO cluster is denied by ACL, the explicit SELECT verification still rejects db > 0 on a cluster with a clear error. db 0 does not require SELECT.


Troubleshooting

Symptom

Check

DB_ERROR

allowedDbs must contain the requested db, and the Redis user needs +select for db > 0.

COMMAND_ERROR with NOPERM

The ACL must allow the size/type commands the fetch guard uses (STRLEN, HSTRLEN, LLEN, HLEN, SCARD, ZCARD, XLEN, TYPE, MEMORY USAGE).

CONFIG_ERROR mentioning references missing environment variable

passwordEnv/usernameEnv must be present in the MCP client's env block.

CONFIG_ERROR mentioning unknown field(s)

A JSON field is misspelled; unknown fields abort startup.

MOVED

The key lives on another cluster node; only db 0 of a single node is supported.

CONNECTION_ERROR

Host/port unreachable, TLS handshake failed, or the server closed the connection.


License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables exploring and diagnosing a Redis instance from MCP clients with read-only safety, using SCAN instead of KEYS for safe key enumeration.
    7
    607 npm
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables remote database access (RDBMS and MongoDB) through MCP tools, supporting read/write queries, schema management, and more.
    -
  • A
    license
    B
    quality
    D
    maintenance
    Read-only Redis MCP server with a configurable command allowlist for safe production diagnostics, enabling exact read-only subcommands like CLIENT LIST and SLOWLOG GET.
    5
    MIT