multidb-mcp
Provides guarded, permission-scoped access to MariaDB databases, including listing tables and views, describing table structure and indexes, and executing one bound-parameter SQL statement with limits, masking, and audit logging.
Provides guarded, permission-scoped access to MySQL databases, including listing tables and views, describing table structure and indexes, and executing one bound-parameter SQL statement with limits, masking, and audit logging.
Provides guarded, permission-scoped access to PostgreSQL databases, including listing tables and views, describing table columns, keys, and indexes, and executing one bound-parameter SQL statement with limits, masking, and audit logging.
Provides guarded access to Redis through a single allowlisted command per call, such as HGETALL or SCAN, with command safety limits, masking, and audit logging.
Provides guarded, permission-scoped access to SQLite database files, including listing tables and views, describing table structure and indexes, and executing one bound-parameter SQL statement with limits, masking, and audit logging.
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.
multidb-mcp
A Model Context Protocol server that gives Claude Code guarded access to PostgreSQL, MySQL/MariaDB, IBM Db2 LUW, SQLite, and Redis through one small set of tools.
Every connection declares what it may do (read, insert, update, delete, ddl, call) in a
config file. A SQL guard checks each request before it reaches the database, results are
truncated and masked, and every tool call is written to an audit log.
The guard is the first layer of defense, not the only one. Always connect with a database user that has only the privileges the connection needs. SeeSecurity model.
Contents
Related MCP server: MCP Database Server
Features
One config, many databases. PostgreSQL, MySQL, MariaDB, Db2 LUW, SQLite, and Redis.
Explicit permissions per connection, the same rules for every environment, including production.
A SQL guard built on a dependency-free, dialect-aware lexer: one statement per call, permission checks, a deny-list of dangerous functions and statements, and a schema whitelist.
Redis allowlist of safe commands, with limits on commands that could stall the server.
Limits and masking: a row limit, a timeout, an output size limit, and masking of sensitive columns, keys, and fields.
No credentials in output: passwords and hosts are redacted from errors, logs, and tool results, and checked by a leak test.
Audit log with one JSON line per tool call, rotated daily.
Reconnects after a dropped connection (reads are retried once; writes never are).
Adding a database kind means writing one adapter; tools and the guard do not change.
Tools
The server only registers the tools that the configured connections need.
Tool | Purpose | Registered when |
| List connections: id, driver, env, permissions, limits, status, purpose | always |
| List tables and views, with an optional schema and name search | a SQL connection |
| Columns, primary key, foreign keys, and indexes of one table | a SQL connection |
| Run one SQL statement; parameters are bound, never concatenated | a SQL connection |
| Run one Redis command, e.g. | a Redis connection |
The db parameter of every tool is an enum of the connection ids from your config, so the model
cannot invent a connection name. Table contents are returned labeled as data, not instructions.
Quick start
Requirements: Node.js 24 LTS and a database to connect to. Docker is needed to run Db2 (see Running with Docker) and for the development databases.
git clone https://github.com/hmrnsp/multidb-mcp.git
cd multidb-mcp
npm install
npm run buildCreate databases.json next to your project (see Configuration) and a separate
env file for the credentials, then register the server in the project's .mcp.json:
{
"mcpServers": {
"multidb": {
"command": "node",
"args": [
"/absolute/path/to/multidb-mcp/dist/index.js",
"--config",
"databases.json",
"--dotenv",
".env.multidb"
]
}
}
}Open the project in Claude Code, approve the multidb server, and run /mcp: the server should be
connected. Then ask, for example, "which databases are available?"
To try it without any setup of your own, use the development databases of this repository:
cp .env.example .env
npm run db:up # PostgreSQL, MySQL, MariaDB, Redis in Docker
npm run seed:sqlite # a sample SQLite file in .data/
npm run seed:redis # sample cache/session/queue keys
npm run buildThe .mcp.json of this repository already starts the server with databases.dev.json.
Configuration
A project needs three files:
File | Contents | Commit it? |
| How Claude Code starts the server | yes |
| The list of connections | yes (no secrets) |
| Credentials, referenced from | never |
{
"defaults": { "maxRows": 200, "timeoutSec": 30, "maxChars": 40000 },
"maskColumns": ["salary", "account_no"],
"databases": [
{
"id": "local_mysql",
"driver": "mysql",
"env": "local",
"access": ["read", "insert", "update", "delete", "ddl"],
"description": "Laravel application database for development",
"url": "${LOCAL_MYSQL_URL}"
},
{
"id": "prod_db2",
"driver": "db2",
"env": "production",
"access": ["read"],
"description": "Core transaction data, for reports only",
"url": "${PROD_DB2_CONN}",
"maxRows": 500,
"schemas": ["CORE", "REPORT"]
}
]
}Complete examples live in templates/.
Field | Required | Default | Meaning |
| yes | Unique id (lower-case letters, digits, | |
| yes |
| |
| yes |
| |
| yes | Permissions, see below | |
| yes | What the connection is for; the model uses it to pick a connection | |
| yes | Connection string; secrets must come from | |
| no | from defaults | Limits for this connection |
| no | all | Schema whitelist for list, describe, and queries (not for SQLite or Redis) |
| no |
| Open the connection on first use |
maskColumns adds to the built-in patterns (password, token, secret, nik, card_number,
and others); it never replaces them.
Rules enforced when the server starts (it refuses to start otherwise, naming the problem):
Unknown fields are rejected, so a typo such as
readOnlycannot silently do nothing.A
${VAR}that is missing or empty is an error; every missing variable is reported at once.A literal password in
urlis rejected forstagingandproduction.accessmust be present and containread; unknown or repeated values are rejected.
Command line: --config <file>, --dotenv <file> (not --env-file, which Node.js intercepts),
--log-level, --log-file, --audit-dir, --audit-keep-days, --no-audit. Run with --help.
Passwords inside a URL must be URL-encoded. The simplest approach is to keep the whole connection
string in one variable: "url": "${PROD_PG_URL}".
Permissions (access)
Every connection must list its permissions. They are the same for every environment; there is no hidden default.
{ "id": "reports_db2", "env": "production", "access": ["read"] }
{ "id": "prod_pg", "env": "production", "access": ["read", "update", "delete"] }
{ "id": "local_pg", "env": "local", "access": ["read", "insert", "update", "delete", "ddl", "call"] }Value | Allows |
| SELECT, WITH…SELECT, VALUES, SHOW, DESCRIBE, EXPLAIN. Required |
| INSERT |
| UPDATE, including |
| DELETE |
| CREATE, ALTER, DROP, VACUUM, |
| CALL (stored procedures). Not applicable to SQLite |
The guard looks for write words in the whole statement, so one statement can need several permissions:
Statement | Permissions needed |
|
|
|
|
|
|
|
|
|
|
A
["read"]connection also uses a read-only transaction in the database (PostgreSQL, MySQL, MariaDB, SQLite). Connections that may write use a normal transaction; the guard enforces which statement kinds are allowed, and the database user's privileges remain the last layer.list_databasesshows each connection's permissions, and the server instructions ask Claude to explain a change and get your approval before writing to production.The old
readonlyfield is rejected at startup with a message explaining the replacement.
The SQL guard
Queries rejected by the guard never touch the database.
Rule | Read-only ( | With write permissions |
More than one statement | Rejected | Rejected |
SELECT, WITH…SELECT, VALUES, SHOW, DESCRIBE, EXPLAIN | Allowed | Allowed |
INSERT, UPDATE, DELETE, MERGE, DDL, CALL | Rejected | According to |
Hidden write words (a deleting CTE, | Rejected | According to |
| Rejected | Needs |
| Rejected | Needs |
GRANT, REVOKE, CREATE/ALTER/DROP USER/ROLE, DROP DATABASE/SCHEMA, ALTER SYSTEM | Rejected | Rejected |
BEGIN/COMMIT/ROLLBACK, SET/RESET/USE | Rejected | Rejected |
DO, EXECUTE, PREPARE, HANDLER, COPY, LOAD DATA, | Rejected | Rejected |
Dangerous functions ( | Rejected | Rejected |
MySQL executable comments | Rejected | Rejected |
A schema-qualified table outside | Rejected | Rejected |
SQL that cannot be analyzed (an unterminated string or comment) | Rejected | Allowed with a warning, only for |
How it works:
The guard uses a dependency-free SQL lexer per dialect. A keyword inside a string, a comment, or a quoted identifier is not treated as a command.
Where the lexer could read the text differently from the server, it picks the reading that sees more code: block comments do not nest, the
--rule follows MySQL exactly, and strings with backslashes are checked in two modes.A table name without a schema is limited by the connection's
search_path(PostgreSQL) or default schema, not by the guard.
Column masking
The values of columns whose names match maskColumns are replaced with ***. Matching is per name
segment: no_nik and password_hash are masked, technique is not.
Masking works on the result's column names, so an alias (SELECT password AS x) can get past it. For
data that is truly secret, use a database user without access to that column, or expose a VIEW.
Per-database notes
PostgreSQL
Every query runs in its own transaction:
BEGIN [READ ONLY], thenstatement_timeoutandsearch_path(whenschemasis set), then a cursor that stops atmaxRows + 1, thenROLLBACK(read-only) orCOMMIT(write permissions).A connection with write permissions runs
DISCARD ALLafter each query, so a sessionSETdoes not carry over to the next query.date,timestamp,time, andintervalcome back as text exactly as the database sends them, with no time zone conversion.bigintandnumericare text too, so no precision is lost.
MySQL and MariaDB
One adapter for both (
mysql2). Thedriverin the config must match the server: on connect the adapter checksVERSION()and refuses amysqlconnection that is really MariaDB, or the reverse, because the guard's lexer rules and the timeout mechanism differ.Each query sets a session timeout (
max_execution_timein ms for MySQL,max_statement_timein seconds for MariaDB), startsSTART TRANSACTION [READ ONLY], readsmaxRows + 1rows, then ends withROLLBACKorCOMMIT.MySQL's
max_execution_timeonly covers SELECT, so a watchdog sendsKILL QUERYfrom a separate connection one second after the limit (for example for a slow UPDATE).When a read result exceeds
maxRows, the connection is dropped and the query isKILLed: closing the socket alone does not stop the query on the server. On a connection that may write, the remaining rows are still read (and discarded) so a statement such as MariaDB'sDELETE … RETURNINGcompletes beforeCOMMIT.A connection that may write is reset (
COM_RESET_CONNECTION) after each query, the equivalent of PostgreSQL'sDISCARD ALL.Queries with
paramsrun as prepared statements (values are bound on the server and the statement is closed again afterwards).When
schemasis set, the default database in the connection string must be one of them.Only the
sslandcharsetURL parameters are accepted (so?multipleStatements=trueis refused), andLOAD DATA LOCAL INFILEis disabled at the protocol level.BIGINTandDECIMALcome back as text, and so doDATE,DATETIME, andTIMESTAMP.
IBM Db2 LUW
Db2 for i and Db2 for z/OS need a DB2 Connect license and are not supported (
SQL1598N).The server must run in the Docker image on most modern Linux distributions. IBM's CLI driver needs
libxml2.so.2, which distributions such as Ubuntu 26.04 no longer ship. See Running with Docker.Each query:
prepare,SQL_ATTR_QUERY_TIMEOUT, readmaxRows + 1rows, thenROLLBACKorCOMMIT. Closing the result set closes the server-side cursor.Db2 does not enforce read-only transactions (the CLI read-only access mode is ignored; this was tested). A
["read"]connection is protected by the guard, an always-executedROLLBACK, and a database user that only has SELECT. For a read-only production connection a SELECT-only user is a must; for one with write permissions, grant the database user no more thanaccessallows.When
schemasis set, the adapter appendsCurrentSchema=<first schema>to the connection string.Unquoted names are stored upper-case.
list_tables,describe_table, and theschemaparameter accept lower-case:ordersmeansORDERS.DECIMAL:
ibm_dbalways reads DECIMAL as a double. A value below 10^(15 − scale) is restored exactly as text with the column's scale (1.50), includingSUM()results. Larger values, and all DECFLOAT values, may be inexact; the result then carries a note suggestingCAST(column AS VARCHAR(40)).On a query timeout
ibm_dbdrops the SQL0952N message (an empty error). The adapter recognizes it from the elapsed time and reports a timeout.
SQLite
No extra dependency: it uses Node's built-in
node:sqlite.urllooks likesqlite:<file path>. A relative path is resolved from the folder of the config file, e.g."url": "sqlite:./database/database.sqlite". An absolute path works too.The file must already exist; the adapter never creates a database. A
["read"]connection opens the file read-only, so SQLite itself refuses writes.node:sqliteis synchronous: a running query cannot be stopped from inside, even withworker.terminate()(tested). So each SQLite connection runs in its own child process. A timeout kills that process; the operating system releases the file lock, SQLite rolls back the unfinished transaction, and the connection reopens on the next query.Always rejected:
ATTACH/DETACH,PRAGMA,VACUUM INTO,load_extension,readfile, andwritefile. To inspect a table usedescribe_tableorSELECT * FROM pragma_table_info('orders').schemasis not used (a SQLite file has only themainschema).SQLite is a file, not a server. To reach a file on another machine, run multidb-mcp there over SSH. Do not write to a SQLite file over a network share (SQLite's documentation warns of corruption).
Redis (redis_command)
Redis has no SQL, so a driver: "redis" connection is served by its own tool:
{ "db": "cache_prod", "command": "HGETALL", "args": ["user:42"] }
{ "db": "cache_prod", "command": "SCAN", "args": ["0", "MATCH", "laravel_cache:*", "COUNT", "100"] }url:redis://user:password@host:6379/0(rediss://for TLS). The database number is part of the url; aSELECTfrom the model is rejected.accessfor Redis:read= read commands;insert= create a new key or element (LPUSH, SADD, XADD, SETNX);update= change a value or TTL (EXPIRE, LSET);delete= remove (DEL, HDEL, LPOP, ZREM). A command that can both create and overwrite (SET, HSET, INCR, ZADD) needsinsert+update;SET … NXneeds onlyinsert,SET … XXonlyupdate.ddlandcalldo not apply.Allowlist: only commands the guard knows can run. Always rejected, whatever the permissions:
FLUSHALL,FLUSHDB,KEYS(useSCAN),EVAL/FCALL,CONFIG,ACL,MODULE,SHUTDOWN,SELECT,MULTI/EXEC, blocking commands (BLPOP,SUBSCRIBE,XREAD),MONITOR,PUBLISH,SORT.Heavy commands are limited before they run, because Redis runs commands one at a time and one huge command can stall every application:
HGETALL/HKEYS/HVALS/SMEMBERSare rejected when the key holds more thanmaxRowselements (with a hint to useHSCAN/SSCAN);LRANGE/ZRANGEare narrowed tomaxRows;XRANGEgets aCOUNT; theCOUNTofSCANis capped.Masking: the value of a key whose name contains
session,sess,csrf,otp,token,password,secret(and yourmaskColumns) is replaced with***, and so are hash/stream fields with sensitive names. Sensitive key names are hidden fromSCANresults, because a session id is a credential; such a key can still be deleted when the user names it.A timeout only disconnects the client; Redis cannot cancel a running command, so the limits above are the main protection.
In production use a least-privilege ACL user. Read-only:
ACL SETUSER mcp on >PASSWORD ~* &* +@read +@connection -@dangerous. May only delete cache entries:ACL SETUSER mcp_cache on >PASSWORD ~laravel_cache:* +@read +del +unlink -@dangerous.
Running with Docker
IBM's Db2 CLI driver (used by ibm_db) needs libxml2.so.2, which distributions such as Ubuntu 26.04
no longer provide. The Docker image is based on Debian 12 and removes the problem without installing
anything on the host. A server started directly with node still works for every other database; only
its Db2 connections report a failed status with a message that suggests Docker.
npm run docker:build # runtime image: multidb-mcp:<version> and multidb-mcp:latest
npm run docker:build:dev # dev image for the Db2 tests (rebuild when dependencies change)
# a local Db2 (the first start takes 5-10 minutes and needs about 4 GB of RAM)
npm run db:up:db2
npm run docker:dev -- node scripts/seed-db2.mjs
npm run docker:dev -- npm run check:db2
npm run docker:dev -- npm run test:db2To let Claude Code run the image, use templates/mcp.docker.example.json:
docker run -i --rm --init --pull=never --network host -e TZ=Europe/Berlin \
-v "$PWD/databases.json:/work/databases.json:ro" \
-v "$PWD/.env.multidb:/work/.env.multidb:ro" \
-v "$PWD/.multidb:/work/.multidb" \
multidb-mcp:latest --config /work/databases.json --dotenv /work/.env.multidbThe image never contains an env file; config and credentials are mounted read-only.
--network hostlets the container reach databases on127.0.0.1and on your VPN.--pull=neverprevents Docker from pulling an image of the same name from a registry if yours is not built yet.The container runs in UTC; pass
-e TZ=<your zone>so audit files are split by your local date.For SQLite, mount the folder of the database file (SQLite needs it for its
-wal,-shm, and-journalfiles) at the same relative path under/work.docker:devmounts the source into a dev container; the runtime image needs a rebuild after code changes.The Db2 driver is downloaded from IBM's mirror on GitHub at build time (version pinned in the
Dockerfile), because IBM's own download server is very slow.
Using it in an application project
Copy
templates/databases.example.jsontodatabases.jsonin the project root and adjust it.Keep credentials in a separate file such as
.env.multidb, and add it to.gitignore.Copy
templates/mcp.example.json(plainnode) ortemplates/mcp.docker.example.json(Docker, needed for Db2 on newer distributions) to.mcp.json. The path todist/index.jsmust be absolute.Append
templates/CLAUDE.md.exampleto the project'sCLAUDE.mdand mergetemplates/settings.example.jsoninto.claude/settings.json(it makes Claude Code ask beforeexecute_sqlandredis_command).Add
.multidb/(the audit log) to.gitignore.
Claude Code permissions apply per tool, not per connection, which is why production protection is enforced by the guard and not only by those permissions.
Audit log and reconnecting
Every tool call is appended as one JSON line to .multidb/audit-YYYY-MM-DD.jsonl (next to
databases.json):
{"ts":"2026-11-03T09:12:44+08:00","tool":"execute_sql","db":"prod_db2","env":"production","sql":"SELECT ... FROM CORE.ORDERS WHERE ID = ?","paramCount":1,"statement":"SELECT","rows":1,"truncated":false,"masked":false,"outcome":"ok","durationMs":84}
{"ts":"2026-11-03T09:13:02+08:00","tool":"execute_sql","db":"prod_db2","env":"production","sql":"DELETE FROM CORE.ORDERS","paramCount":0,"outcome":"rejected","reason":"readonly","durationMs":0}
{"ts":"2026-11-03T09:14:10+08:00","tool":"redis_command","db":"prod_redis","env":"production","command":"DEL","keys":["laravel_session:***"],"masked":false,"outcome":"ok","durationMs":2}outcomeisok,rejected(a guard rule;reasonnames it), orerror(reasonis the kind of error).It never stores
paramsvalues, result rows, Redis values, or passwords. SQL text is redacted, and sensitive Redis key names are masked after the last colon.A new file starts every (local) day; files older than 90 days are deleted. Options:
--audit-dir <folder>,--audit-keep-days <n>(0keeps everything),--no-audit.If the folder cannot be written, the server keeps running and logs
audit log disabled: write failedonce. With Docker, create the folder first and mount it without:ro.
When a connection that was already open drops (a database restart, a firewall closing an idle
connection), reads (list_tables, describe_table, SELECT, Redis read commands) are repeated once
on a fresh connection. Writes are never repeated; Claude is told the change may or may not have
been saved and must check first. Failing to open the very first connection is not retried. The Db2
pool closes connections that have been idle for 30 seconds.
Security model
multidb-mcp reduces risk; it does not replace database permissions.
Use a dedicated database user per connection with only the privileges
accessgrants:SELECTonly for["read"], and an ACL user for Redis. Do not use an application or DBA account.Everything the database user can read can end up in the model's context. Prefer VIEWs that leave out secret columns, and grant minimal privileges; masking is an extra layer, not the main control.
Reach production over a VPN or an SSH tunnel; do not expose database ports publicly. SSH tunnels are not built in.
Table contents are data: the server's instructions tell the model to ignore commands found in results.
Credentials are wrapped so they print as
[secret], and errors, logs, and tool results are redacted (host, port, and user names too, for text sent to the model). A protocol test checks that a password planted in the environment appears in no tool result, stderr, log file, or audit log.The development passwords in
docker-compose.ymland.env.exampleare for local containers bound to127.0.0.1only. Never reuse them.
To report a vulnerability, see SECURITY.md.
Development
npm install
npm run typecheck
npm run lint
npm test # unit tests, no database needed
npm run db:up # PostgreSQL, MySQL, MariaDB, Redis in Docker
npm run seed:sqlite # .data/app.sqlite
npm run seed:redis # sample keys in Redis database 0
npm run test:integration # adapters against the real databases
npm run test:protocol # build, then drive the server over stdio with a real MCP client
npm run db:up:db2 # Db2 Community Edition (heavy)
npm run docker:build:dev
npm run docker:dev -- npm run test:db2
npm run check:env # check this machine for development readiness
npm run db:downnpm 11 blocks dependency install scripts by default; ibm_db is approved in the allowScripts field
of package.json, pinned to its version. After upgrading ibm_db, approve it again with
npm install-scripts approve ibm_db.
src/
├─ index.ts, cli.ts, server.ts, instructions.ts # entry point, options, tool registration
├─ config/ # zod schema, ${VAR} interpolation, loader, Secret
├─ registry/ # connection registry (lazy connect, status per connection)
├─ adapters/ # DbAdapter / KeyValueAdapter contract and one folder per database
├─ guard/ # SQL lexer, analyzer, policy, masking, Redis allowlist
├─ tools/ # the MCP tools, their input schemas, and reconnect logic
├─ output/ # compact text tables and result formatting
└─ observability/ # JSON logger, audit log, redaction
test/{unit,integration,db2,protocol}
docker/seed/ # seed SQL for the development databases
scripts/ # seeds, Db2 check, environment check, dev-container runner
templates/ # example .mcp.json, databases.json, CLAUDE.md, settings.jsonThe server speaks MCP over stdio, so stdout is reserved for the protocol: a single console.log
would corrupt the connection. ESLint forbids console.* in src/; diagnostics go to stderr.
Adding a database kind means implementing DbAdapter (or KeyValueAdapter), registering it in
src/adapters/index.ts, and adding a dialect to the guard if it speaks SQL. See CONTRIBUTING.md.
Troubleshooting
Symptom | Likely cause | Fix |
| A newer distribution (Ubuntu 26.04) only ships | Run the server through the Docker image; run Db2 tests with |
| IBM's download server is slow | Set |
| Invalid config or a missing variable | Run |
| Wrong path in | Relative paths start at the config file's folder; with Docker mount the database folder under |
| An application is writing to the same file | Retry; raise |
| Wrong user or password in the url | Check the variable; URL-encode special characters in the password |
| The Redis ACL user lacks the command or key | Expected for a read-only user; to allow writes, extend the ACL and |
| The image is not built ( |
|
| Db2 host, port, or firewall unreachable | Check |
| The server is Db2 for i or z/OS | Not supported (needs a DB2 Connect license) |
Port already in use | Ports 55432/53306/53307/55000/56379 are taken | Change the left-hand port in |
Container | Not enough Docker memory | Give Docker 4 GB of RAM or more |
Seeds did not change | Database seeds only run when the volume is empty |
|
| The audit folder is not writable (common with Docker) | Create |
Contributing
Contributions are welcome. Please read CONTRIBUTING.md first; it explains the workflow, the tests to run, and the rules for changes that touch the guard.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Query Postgres, MySQL, SQL Server, Oracle, BigQuery, ClickHouse and Redshift from your AI client.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides Claude Desktop with secure access to multiple database connections, allowing users to query MySQL, PostgreSQL, SQLite, and SQL Server databases directly through natural language.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to connect to and interact with SQLite, SQL Server, PostgreSQL, and MySQL databases through natural language. Supports executing queries, managing tables, exporting data, and storing business insights with authentication options including AWS IAM.1,108 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude Desktop to interact with MySQL, PostgreSQL, and Redis databases using natural language for data querying and schema analysis. It provides a secure interface with a default read-only mode to prevent unauthorized database modifications.127 npm943MIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude Code to execute read-only queries and DML operations on Oracle and PostgreSQL databases, and to list or describe database tables.9 npm1MIT