redis-switchboard-mcp
Provides tools for interacting with Redis instances, including executing Redis commands against a per-request logical database, reading bounded pages from lists/hashes/sets/zsets/streams/strings, cursor-based key scanning, and inspecting key type, TTL, memory usage, encoding, and length. Supports multiple configured Redis instances, readonly/readwrite modes, command restrictions, and safe connection handling per database.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
redis-switchboard-mcp
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 / lengthredis-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
Check you are on Node.js 20+ — no global install is needed, the client launches
npx -y redis-switchboard-mcp.Add the server to your MCP client: MCP client configuration.
Restart the client and run
PING; a working setup returnsPONG.
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
instanceargument.Explicit permission mode (
readonly/readwrite, defaultreadonly);readonlyuses 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 toread_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_ROrequires 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 --helpOr run it without a global install:
npx -y redis-switchboard-mcpFrom source
git clone https://github.com/hexiaowu/redis-switchboard-mcp.git
cd redis-switchboard-mcp
npm ci
npm run build
node dist/index.jsMCP 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”.
Command-line flags (
--config,--db, ...)Environment variables
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 |
| 🔶 Conditional | JSON config file describing one or more Redis instances |
| ⚪ Optional | Instance name (default: |
| ⚪ Optional | Default logical database, 0-255 (default: 0) |
| ⚪ Optional | Override permission mode for all instances: |
| ⚪ Optional | Show help |
| ⚪ Optional | Show the version |
Variable | Required | Default | Description |
| 🔶 Conditional | — | Path to a multi-instance JSON config file |
| ⚪ Optional |
| Instance name for the single-instance form |
| 🔶 Conditional | — | Redis host (required when no JSON config is used) |
| 🔶 Conditional | — | Redis port (required when no JSON config is used) |
| ⚪ Optional | — | ACL username |
| 🔶 Conditional | — | Password (required when Redis requires authentication) |
| ⚪ Optional |
| Default logical database when |
| ⚪ Optional |
| Enable TLS |
| ⚪ Optional |
| Verify the server certificate |
| ⚪ Optional |
| Permission mode: |
| ⚪ Optional | — | Comma-separated allowlist, e.g. |
| ⚪ Optional |
| Allow |
| ⚪ Optional |
| Per-instance connection cache limit (1-256) |
| ⚪ Optional |
| Connections pooled per |
| ⚪ Optional |
| Close an idle |
| ⚪ Optional |
| TCP/connect timeout |
| ⚪ Optional |
| Per-command timeout; |
| ⚪ Optional |
| Per-array/object item cap in replies |
| ⚪ Optional |
| Per-string cap in replies |
| ⚪ Optional |
| Maximum nested container depth |
| ⚪ Optional |
| Max items one |
| ⚪ Optional |
| Max bytes one |
| ⚪ Optional |
| Default SCAN |
| ⚪ Optional |
| Maximum SCAN round trips per call |
| ⚪ Optional |
| Wall-clock budget per |
Method | Required | How |
JSON config | 🔶 Conditional | Set |
Host + port | 🔶 Conditional | Set |
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 |
| ✅ Required | — | Array with at least one instance |
| ⚪ Optional | — | Instance used when a tool call omits |
Field | Required | Default | Description |
| 🔶 Conditional |
| Unique instance name; must be unique when several instances are configured |
| ✅ Required | — | Connection endpoint |
| ⚪ Optional | — | ACL username |
| 🔶 Conditional | — | Inline password (required when Redis requires authentication) |
| ⚪ Optional | — | Read credentials from an environment variable |
| ⚪ Optional |
| Default logical database |
| ⚪ Optional |
| Enable TLS |
| ⚪ Optional |
| Verify the server certificate |
| ⚪ Optional |
| Permission mode: |
| ⚪ Optional |
| Allow |
| ⚪ Optional | — | Restrict which logical DBs this instance may access; must include |
| ⚪ Optional |
| Cache limit for |
| ⚪ Optional |
| Connections pooled per |
| ⚪ Optional |
| Close an idle |
| ⚪ Optional |
| TCP/connect timeout |
| ⚪ Optional |
| Per-command timeout; |
| ⚪ Optional |
| Per-container item cap |
| ⚪ Optional |
| Per-string character cap |
| ⚪ Optional |
| Nested container depth limit |
| ⚪ Optional |
| Max items one |
| ⚪ Optional |
| Max bytes one |
| ⚪ Optional |
| Default SCAN |
| ⚪ Optional |
| SCAN round-trip cap |
| ⚪ Optional |
|
|
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 |
| Only an explicit read-command whitelist is accepted; |
| Write commands such as |
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 |
|
Pub/sub and streaming |
|
Administration |
|
Topology / replication |
|
Destructive / server-wide |
|
Blocking |
|
Slow key enumeration |
|
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
allowScriptingas disabling both the blocklist and theallowedDbsboundary: 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 |
|
Hash / set / zset |
|
Lists |
|
Streams |
|
Aggregates |
|
Counts | pop and random-member counts, |
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;limitis validated at 1,000 and capped bymaxFetchItems. PassnextOffset,nextCursorornextStartback unchanged untilcompleteistrue.scan_keys:limit,maxScanIterations,scanTimeBudgetMsmaxConnections: bounds total sockets per instance
Credentials
A Redis user must be allowed to run
SELECTto use any database other than 0. Without+select,db > 0fails closed with aDB_ERRORinstead of silently using db 0.Prefer
passwordEnv/REDIS_PASSWORDover inline JSON passwords.Keep a config file containing secrets at
chmod 600.Error messages redact
password=..., quoted/JSON password fields, echoedAUTHarguments, and any connection URL that may appear in an error.TLS certificate verification is on by default;
tlsRejectUnauthorized: falsedisables it and should only be used for self-signed development servers.TLS supports
tlsandtlsRejectUnauthorizedonly; 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:1and rejects db > 0. It connects to a single node, so keys owned by other slots can returnMOVED; it is not a cluster-aware sharding client.No transactions:
MULTI/EXEC/WATCHare 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 (
XRANGEinstead of blockingXREAD, 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: 0disables 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.
DUMPand 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_infofor metadata,scan_keysfor enumeration,read_pagefor collections, and a restricted ACL /commandTimeoutMsfor 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 topoolSize(default 4) pooled connections. The per-instance cap ismaxConnections(default 32) and is a hard stop. Connections idle for longer thanidleTimeoutMs(default 5 minutes) are closed automatically; a connection with a command that timed out is dropped immediately and replaced on the next request. RaisemaxConnectionsif you legitimately use many logical DBs.Cluster + ACL: if
INFO clusteris denied by ACL, the explicitSELECTverification still rejects db > 0 on a cluster with a clear error. db 0 does not requireSELECT.
Troubleshooting
Symptom | Check |
|
|
| The ACL must allow the size/type commands the fetch guard uses ( |
|
|
| A JSON field is misspelled; unknown fields abort startup. |
| The key lives on another cluster node; only db 0 of a single node is supported. |
| Host/port unreachable, TLS handshake failed, or the server closed the connection. |
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Governed data discovery, exact queries, decisions, simulations, and runtime utilities over MCP.
Read authorized Loam tables and supported external databases through a bounded MCP connection.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Build multi-tenant apps over MCP. Schemas, CRUD, deploys — access control enforced server-side.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables exploring and diagnosing a Redis instance from MCP clients with read-only safety, using SCAN instead of KEYS for safe key enumeration.7607 npm2MIT
- FlicenseNot gradedqualityDmaintenanceEnables remote database access (RDBMS and MongoDB) through MCP tools, supporting read/write queries, schema management, and more.-
- FlicenseNot gradedqualityDmaintenanceMCP server for Redis interaction with dynamic connection setup and management.-
- AlicenseBqualityDmaintenanceRead-only Redis MCP server with a configurable command allowlist for safe production diagnostics, enabling exact read-only subcommands like CLIENT LIST and SLOWLOG GET.5MIT