readonly-db-mcp
Provides read-only access to MariaDB databases for schema discovery, running single SELECT queries with row limits and timeouts, and retrieving EXPLAIN query plans.
Provides read-only access to MySQL databases for schema discovery, running single SELECT queries with row limits and timeouts, and retrieving EXPLAIN query plans.
Provides read-only access to PostgreSQL databases for schema discovery (schemas, tables, columns, keys, indexes), running single SELECT queries with row limits and timeouts, and retrieving EXPLAIN plans without executing the query.
Provides read-only access to SQLite database files for schema discovery, running single SELECT queries with row limits and timeouts, and retrieving EXPLAIN query plans.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@readonly-db-mcphow many orders were placed last month?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
readonly-db-mcp
A read-only MCP server for PostgreSQL, MySQL/MariaDB, SQL Server, SQLite, and Oracle. The code is intentionally small, about 400 lines across two files, so you can read and audit it yourself.
File | Contents |
| MCP server: connections, read-only sessions, 6 tools, audit log |
| SQL validation: only one |
| Connection list (no passwords) |
| Connection URLs + passwords (never commit this) |
| 121 tests (validator + end-to-end over the MCP protocol) |
Tools
Tool | Purpose |
| List allowed connections (no credentials) |
| List schemas/databases |
| Tables & views in a schema |
| Columns, types, PK, FK, indexes |
| Run a single |
| Query plan without running the query (not available for Oracle) |
Related MCP server: Database MCP Server
Security layers
A read-only database user (required). This is the only truly strong safeguard. See the scripts below.
Read-only session at the database level:
PostgreSQL:
SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLYMySQL:
SET SESSION TRANSACTION READ ONLYOracle:
SET TRANSACTION READ ONLYper querySQLite: file opened with
mode=ro+PRAGMA query_onlySQL Server has no read-only session, so on SQL Server layer 1 is essential.
SQL validation (sqlglot, fail-closed). Anything that is not a
SELECTis rejected, including multiple statements,SELECT INTO,FOR UPDATE, CTEs containingDELETE, and dangerous functions such aspg_sleep,pg_terminate_backend,dblink,SLEEP,LOAD_FILE,xp_cmdshell,OPENROWSET,WAITFOR,DBMS_*andUTL_*.Always ROLLBACK. There is also a query timeout (30 seconds by default), a row limit (500 by default), and long text values are truncated.
Audit log. Every query, including rejected ones, is logged to
audit.login JSON Lines format.
Note: code comments are currently in Indonesian.
Quick install (Windows)
Double-click setup.bat. It creates .venv, installs dependencies, prepares connections.toml and .env, and registers the server with Claude Desktop. Your existing Claude Desktop config is backed up first to claude_desktop_config.json.bak-<date>. Then edit connections.toml and .env, and restart Claude Desktop.
Manual install
Requires Python 3.11 or newer.
cd readonly-db-mcp
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt # remove drivers you don't need if you like
cp connections.example.toml connections.toml
cp .env.example .env # fill in the URL + password of the read-only userConnection URL format (passwords containing @ : / # % must be URL-encoded, e.g. @ becomes %40):
postgresql+psycopg://user:pass@host:5432/dbname
mysql+pymysql://user:pass@host:3306/dbname
mssql+pymssql://user:pass@host:1433/dbname
oracle+oracledb://user:pass@host:1521/?service_name=ORCLPDB1SQLite needs no URL. Just set path = "..." in connections.toml (on Windows, use forward slashes /).
Register with Claude Desktop
Edit claude_desktop_config.json:
Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"readonly-db": {
"command": "C:\\path\\readonly-db-mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\path\\readonly-db-mcp\\server.py"]
}
}
}On macOS/Linux, set command to /path/readonly-db-mcp/.venv/bin/python. Then restart Claude Desktop.
Creating a read-only user
PostgreSQL
CREATE ROLE claude_ro LOGIN PASSWORD 'change-me';
ALTER ROLE claude_ro SET default_transaction_read_only = on;
GRANT CONNECT ON DATABASE dwh TO claude_ro;
GRANT USAGE ON SCHEMA public TO claude_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO claude_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO claude_ro;
-- PG 14+: quick alternative for all tables -> GRANT pg_read_all_data TO claude_ro;MySQL / MariaDB
CREATE USER 'claude_ro'@'%' IDENTIFIED BY 'change-me';
GRANT SELECT, SHOW VIEW ON app.* TO 'claude_ro'@'%';SQL Server
CREATE LOGIN claude_ro WITH PASSWORD = 'change-me';
USE ERP;
CREATE USER claude_ro FOR LOGIN claude_ro;
ALTER ROLE db_datareader ADD MEMBER claude_ro;
DENY EXECUTE TO claude_ro;Oracle
CREATE USER claude_ro IDENTIFIED BY "change-me";
GRANT CREATE SESSION TO claude_ro;
GRANT SELECT ON schema_name.table_name TO claude_ro; -- repeat for each table/view that may be readOn Oracle, tables owned by another schema are read by setting the schema parameter of the tool.
For sensitive tables (salaries, passwords, personal data), simply don't GRANT access. That way Claude genuinely cannot see them.
Running the tests
pip install pytest
python -m pytest -q tests/
# + end-to-end PostgreSQL:
TEST_PG_URL="postgresql+psycopg://user@host:5432/db" python -m pytest -q tests/Test status
SQLite & PostgreSQL 16 have been tested end-to-end over the MCP protocol: queries, row limits, timeouts, explain, query rejection, and the audit log. There is also a test showing that a PostgreSQL session still rejects
DELETEeven when the validator is bypassed and the user is a superuser.MySQL, SQL Server, Oracle: the SQL validator is tested, but they have not yet been tried against a real server. Try them on a non-production database first.
Compatible with MCP Python SDK 1.x and 2.x.
License
MIT — see 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.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query Postgres, MySQL, SQL Server, Oracle, BigQuery, ClickHouse and Redshift from your AI client.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables read-only SQL database access for AI assistants, allowing schema exploration and safe query execution without risk of data modification.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely query and explore SQL Server and PostgreSQL databases with read-only access, supporting schema discovery, relationship exploration, and query execution.17 npm3MIT
- AlicenseNot gradedqualityCmaintenanceEnables an AI assistant to run guarded, read-only SQL queries against a Postgres database with enforced limits and validation.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI applications to discover MySQL and PostgreSQL database schemas and run validated read-only SELECT queries against a configured database, with result limits and SQL safety controls.10 npm20MIT