Atlas / MCP servers / betterdb-inc / BetterDB Monitor

BetterDB MonitorBLOCK

mcp/betterdb-inc/betterdb-monitor

Real-time monitoring, slowlog analysis, and audit trails for Valkey and Redis

Verdict
BLOCK
Grade
F
Trust score
36 /100
Exposed tools
78 69r · 8w · 1d
Transport
stdio
License
NOASSERTION
Stars
1,301
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://hub.docker.com/r/betterdb/monitor) [](https://hub.docker.com/r/betterdb/monitor/tags) [](https://artifacthub.io/packages/search?repo=betterdb-monitor) [](https://www.npmjs.com/package/@betterdb/monitor) [](https://www.npmjs.com/package/@betterdb/monitor) [](https://github.com/betterdb-inc/monitor/actions/workflows/api-tests.yml) [](LICENSE) [](https://valkey.io) [](https://redis.io)

The monitoring layer that Valkey deserves.

BetterDB persists what Valkey throws away - slowlogs, command patterns, client activity, anomaly signals - so you can debug what happened at 3am, not just what's happening now. Built for Valkey 8.x with native support for COMMANDLOG, CLUSTER SLOT-STATS, and per-thread I/O metrics. Redis 6+ compatible for everything else.

Website | Docker Hub | npm | Documentation | Blog

BetterDB is built by BetterDB Inc., a public benefit company operating under the OCV Open Charter.

![BetterDB Monitor - Key Analytics with per-type key size distribution h

Read from source at commit cffef10ac693OBSERVED · 2026-09-24
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (npm)
claude mcp add mcp --env BETTERDB_TOKEN=${BETTERDB_TOKEN} -- npx -y @betterdb/[email protected]
03

Exposed tools (78)

69 read · 8 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
add_connectionwriteAdd a new Valkey/Redis connection to BetterDB. Optionally set it as the active default.
ai_instance_historyreadGet the stored metrics time-series for one AI component instance (hits, misses, hit rate, cost saved, evictions, item count, index size, threshold). Use ai_list_instances first to find the instance field identifier. Use this to see trends: hit-rate degradation, growth, threshold drift.
ai_list_instancesread
cache_approve_proposalreadApprove a pending proposal. Synchronously applies the change to Valkey and returns the terminal status (applied|failed). Idempotent: a second call on an already-applied proposal returns the cached result.
cache_edit_and_approve_proposalwriteEdit an existing pending proposal and approve it in one step. Provide exactly one edit field matching the proposal type: new_threshold for threshold_adjust, new_ttl_seconds for tool_ttl_adjust. Invalidate proposals are not editable.
cache_get_proposalreadFetch a single cache proposal by id, including its audit trail.
cache_healthreadDetailed health for a single cache. Response branches by type: semantic_cache reports category_breakdown + uncertain_hit_rate; agent_cache reports tool_breakdown.
cache_listreadList all caches (semantic_cache and agent_cache) registered for the active instance, with hit rate and total ops.
cache_list_pending_proposalsreadList pending cache proposals for the active instance, newest first. Optionally filter by cache_name.
cache_propose_invalidatereadPropose a cache invalidation for review. Filter shape depends on cache type: semantic_cache requires filter_kind=valkey_search + filter_expression; agent_cache requires filter_kind in (tool|key_prefix|session) + filter_value. Warns when estimated_affected exceeds 10000.
cache_propose_threshold_adjustreadPropose a semantic-cache similarity-threshold change for review. Creates a pending proposal that requires human approval before any change is applied. Reasoning must be at least 20 characters.
cache_propose_tool_ttl_adjustreadPropose an agent-cache per-tool TTL change for review. Creates a pending proposal that requires human approval. Reasoning must be at least 20 characters.
cache_recent_changesreadRecent proposals for a single cache (any status), so agents can avoid re-proposing pending or recently-applied changes. Newest first.
cache_reject_proposalreadReject a pending proposal. Optionally records a reason in the audit trail.
cache_similarity_distributionreadHistogram of recent similarity scores (20 buckets, width 0.1) for a semantic_cache. Errors on agent_cache.
cache_threshold_recommendationreadThreshold-tuning recommendation for a semantic_cache, based on the rolling similarity-score window. Errors with INVALID_CACHE_TYPE on agent_cache.
cache_tool_effectivenessreadPer-tool hit rate, cost saved, and TTL recommendation for an agent_cache. Errors with INVALID_CACHE_TYPE on semantic_cache.
calculatereadMath helper
capabilityreadRuntime capability key (e.g. canSlowLog, canCommandLog, canLatency)
correlate_ai_traceread
deliveryIdreadDelivery ID
eventNamereadName of the latency event
get_acl_auditreadGet persisted ACL audit log entries from storage. Filter by username, reason (auth, command, key, channel), or time range. Use this to investigate why a connection is failing or audit access patterns.
get_acl_failuresreadGet ACL/authentication failures from audit log
get_ai_tracereadGet the full span waterfall for one AI trace: every span with timing, parent relationships, and attributes (model, cache hit/miss, similarity scores). Use list_ai_traces to find trace IDs.
get_anomaliesreadGet anomaly detection events from persisted storage. BetterDB continuously runs Z-score analysis on memory, hit rate, CPU, and other metrics — this returns the detected anomalies. Use to investigate what triggered an alert or correlate with an incident.
get_client_activityreadGet time-bucketed client activity from persisted snapshots. Shows connection counts, command distribution, and buffer usage over time. Use startTime/endTime to focus on a specific incident window.
get_client_analyticsreadGet client connection analytics and trends
get_client_listreadGet list of connected clients grouped by name
get_clientsreadGet the active client list with connection details.
get_cluster_node_statsreadGet per-node performance stats: memory usage, ops/sec, connected clients, replication offset, and CPU. Use this to identify hot nodes, lagging replicas, or uneven load distribution.
get_cluster_nodesreadDiscover all nodes in the Valkey cluster — role (master/replica), address, health status, and slot ranges. Returns an error message if this instance is not running in cluster mode.
get_cluster_slowlogreadGet the aggregated slowlog across ALL nodes in the cluster. This is the primary tool for finding slow commands in cluster mode — per-node slowlogs are incomplete. Returns an error message if not in cluster mode.
get_commandlogreadGet the most recent entries from COMMANDLOG (Valkey 8+ only, superset of slowlog).
get_commandlog_historyreadGet persisted COMMANDLOG entries from storage (Valkey 8+ only). Supports time range filtering to investigate specific incidents. Returns empty with a note if COMMANDLOG is not supported on this instance.
get_commandlog_patternsreadGet analyzed COMMANDLOG patterns from persisted storage (Valkey 8+ only). Like get_slowlog_patterns but includes large-request and large-reply patterns in addition to slow commands.
get_connected_clientsreadGet number of connected and blocked clients
get_forecastreadGet a capacity forecast for one metric: current trajectory and projected time until the resource ceiling is hit. Metric kinds: opsPerSec, usedMemory, cpuTotal, memFragmentation. Use for capacity planning (
get_healthread
get_hot_keysread
get_inference_latencyread
get_inforeadGet INFO stats for the active instance. Contains all health data: memory, clients, replication, keyspace, stats (hit rate, ops/sec), and server info. Optionally filter to a section: server|clients|memory|stats|replication|keyspace.
get_key_countreadGet total number of keys in the database
get_largest_keysread
get_latencyreadGet latency event history for the active instance.
get_latency_historyreadGet the full latency history for a named event (e.g.
get_latency_regressionsreadGet detected latency regressions (sustained p99 command-latency degradations vs baseline) from persisted storage. Companion to get_anomalies: same event store, pre-filtered to latency regressions. Use when investigating
get_memoryreadGet memory diagnostics: MEMORY DOCTOR assessment and MEMORY STATS breakdown.
get_memory_usagereadGet memory usage statistics
get_server_statusreadGet current server status: connected clients, memory usage, ops/sec, total keys, uptime
get_slot_statsreadGet per-slot key counts and CPU usage (Valkey 8.0+ only). Use orderBy=
get_slowlogreadGet the most recent slow commands from the slowlog.
get_slowlog_patternsreadGet analyzed slowlog patterns from persisted storage. Groups slow commands by normalized pattern, showing frequency, average duration, and example commands. Survives slowlog buffer rotation — data goes back as far as BetterDB has been running.
get_vector_indexesreadGet health details for every vector search index on the instance: document count, memory usage, indexing failures, and percent indexed. Requires the Search module (valkey-search / RediSearch) on the connection — errors clearly if absent. Use to diagnose incomplete indexing or index memory growth.
get_weatherreadGet current weather for a city
idwriteConnection ID to set as default
list_ai_tracesreadList recent AI application traces ingested via OpenTelemetry (LLM calls, cache lookups, memory recalls, retrieval spans). Not tied to a Valkey instance — traces come from instrumented AI apps. Use get_ai_trace for a full span waterfall and correlate_ai_trace to join a trace with live Valkey state.
list_instancesreadList all Valkey/Redis instances registered in BetterDB. Shows connection status and capabilities.
memory_approve_forgetreadApprove a pending forget proposal, applying the deletion against the live store.
memory_forgetreadPropose forgetting memories (by id, or by scope/tags). Creates a pending proposal that a human must approve before anything is deleted.
memory_getreadFetch a single memory by ID from a store.
memory_listreadList memories in a store, newest first, with optional scope and tag filters.
memory_list_pending_forgetsreadList pending forget proposals awaiting approval on an instance.
memory_recallreadRecall memories from a store by a precomputed query vector (the caller supplies the embedding).
memory_reject_forgetreadReject a pending forget proposal without deleting anything.
memory_statsreadGet item count, eviction count, and live config for a memory store.
memory_storesreadList agent-memory stores discovered on an instance (name, capabilities, stats key).
nodeIdreadNode ID
parameterreadConfiguration parameter name
remove_connectiondestructiveRemove a connection from BetterDB.
run_latency_diagnosiswriteRun latency diagnostic analysis
run_memory_diagnosiswriteRun memory diagnostic analysis
searchreadSearch web
select_instancereadSelect which instance subsequent tool calls operate on.
set_default_connectionwriteSet a connection as the active default for BetterDB.
start_monitorwriteStart the BetterDB monitor as a persistent background process. If already running, returns the existing URL. The monitor persists across MCP sessions and must be stopped explicitly with stop_monitor.
stop_monitorwriteStop a persistent BetterDB monitor process that was previously started with start_monitor or --autostart --persist.
test_connectionreadTest a Valkey/Redis connection without persisting it. Use before add_connection to validate credentials.
04

Trust audit

BLOCKgrade F · trust 36/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryFAIL
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (11 observation(s))
Network
declared (8 observation(s))
Shell
declared (5 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

CRITICALHard-coded secrets · secret.private_key · CWE-798, CWE-321
proprietary/entitlement/.env.example:22
LICENSE_SIGNING_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
CRITICALHard-coded secrets · secret.private_key · CWE-798, CWE-321
proprietary/entitlement/.env.example:29
BROKER_SIGNING_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
HIGHInventory / provenance · inv.suspicious_name · CWE-1104
apps/api/src/webhooks/webhook-payload-formatter.ts
webhook-payload-formatter.ts
Why it matters. member named after an attack tool
Fix. remove or justify
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
apps/api/src/auth/better-auth-esm.ts:25
return new Function('specifier', 'return import(specifier)') as EsmImport;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/cli/scripts/build.mjs:74
exec(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/cli/scripts/build.mjs:101
exec(`npx esbuild src/index.ts --bundle --platform=node --target=node20 --outfile=dist/index.js --external:@inquirer/prompts --external:commander --external:picocolors --define:__CLI_VERSION__='"${cli
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHFilesystem / path · fs.credential_store · CWE-22, CWE-59
apps/web/src/components/ConnectionSelector.tsx:722
placeholder="id_ed25519"
Why it matters. touches a credential store
MEDIUMInventory / provenance · inv.symlink · CWE-1104
proprietary/node_modules
proprietary/node_modules
Why it matters. link not followed
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
apps/api/src/workspace/personal-token.service.ts:141
this.logger.warn(`Failed to update lastUsedAt for token ${token.id}: ${String(error)}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/agent/src/agent.ts:128
console.log(`[Agent] Rebuilding Valkey client with fresh IAM token (attempt ${this.reconnectAttempt}, delay ${delayMs}ms)`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
proprietary/entitlement/src/entitlement/entitlement.service.ts:198
this.logger.error(`Failed to sign entitlement token for ${license.id}: ${(error as Error).message}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
proprietary/entitlement/src/provisioning/provisioning.service.ts:552
this.logger.warn(`Error deleting secret ${params.secretName}: ${error.message}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
proprietary/entitlement/src/provisioning/provisioning.service.ts:637
this.logger.warn(`Secret ${secretName} already exists in ${namespace}, continuing...`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
Dockerfile:233
CMD wget -T 2 -q --spider "http://127.0.0.1:${PORT:-3001}/api/health" || exit 1
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
Dockerfile.aiven:210
CMD wget -T 2 -q --spider "http://127.0.0.1:${PORT:-3001}/api/health" || exit 1
MEDIUMObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
apps/web/src/components/cluster/ClusterSlowlog.tsx:50
if (microseconds < MICROSECONDS_TO_MS) return `${microseconds}μs`;
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
README.md:193
-e STORAGE_URL=postgresql://dev:devpass@localhost:5432/postgres \
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
apps/api/src/storage/adapters/__tests__/invitation-storage.spec.ts:18
'postgres://betterdb:devpassword@localhost:5433/betterdb';
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
apps/api/test/agent-token-storage-postgres.e2e-spec.ts:9
'postgres://betterdb:devpassword@localhost:5433/betterdb';
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
docs/configuration.md:478
-e STORAGE_URL=postgresql://dev:devpass@localhost:5432/postgres \
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/api/scripts/seed-demo-data.ts:999
secret: 'slack-secret-key-123',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
proprietary/cloud-auth/cloud-actor-resolver.spec.ts:5
const SECRET = 'cloud-session-secret';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
proprietary/cloud-auth/cloud-auth.guard.spec.ts:5
const SECRET = 'cloud-session-secret';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
proprietary/cloud-auth/cloud-upgrade.spec.ts:13
const SECRET = 'cloud-session-secret';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
proprietary/entitlement/src/entitlement/__tests__/offline-license.service.spec.ts:51
token: 'signed.offline.token',

Gates applied: critical_finding, no_behavioural_pass.

Audited 2026-09-24 · audit v0.4.1 · source sha cffef10ac693full audit observations/trust-audit/mcp-server/betterdb-inc__betterdb-monitor.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-09-24cffef10ac693BLOCKF36first audit
06

Questions

What is the BetterDB Monitor MCP server?

Real-time monitoring, slowlog analysis, and audit trails for Valkey and Redis

What tools does BetterDB Monitor expose?

78 in total: 69 read-only, 8 that write, and 1 that can delete or overwrite (remove_connection). Every one is listed on this page with its risk.

Is BetterDB Monitor safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (36/100) and found 7 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does BetterDB Monitor need?

It reads ADMIN_API_TOKEN, AGENT_AUTH_MODE, AGENT_TOKEN_POSTGRES_TEST_DSN, AUTH_BROKER_KEY_ID, AUTH_BROKER_PUBLIC_KEY, AUTH_PRIVATE_KEY, AUTH_PUBLIC_KEY, AUTH_PUBLIC_URL, AUTH_SECRET, BETTERDB_LICENSE_KEY, BETTERDB_TOKEN and BROKER_API_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does BetterDB Monitor run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as @app/entitlement at 1.12.0.

How current is this page?

The grade is for one exact copy of the source (cffef10ac693), read on 2026-09-24. The repository is watched and re-audited when it changes.

Advertisement