db-readonly-mcp
db-readonly-mcp
Un servidor MCP que le da a un asistente de IA (Claude Code, Claude Desktop o cualquier otro cliente MCP) acceso protegido y de solo lectura a una base de datos Postgres. Pide algo como "dame todos los comercios creados ayer" y el asistente escribe el SQL y lo ejecuta a través de este servidor, que garantiza que la consulta solo pueda leer datos.
Solo Postgres: no se admiten otras bases de datos.
Por qué existe esto
Dejar que un asistente consulte tu base de datos directamente es realmente útil para depurar, explorar datos y responder preguntas de "cuántos X" sin escribir un script cada vez. El riesgo es obvio: un LLM puede alucinar o ser inducido a escribir una consulta destructiva. Este servidor existe para reducir ese riesgo a casi cero, con varias capas independientes de protección en lugar de depender de una sola.
Related MCP server: Postgres Scout MCP
Modelo de seguridad
En capas, en orden de cuánto se confía realmente en ellas:
Rol de base de datos: la conexión usa un rol de Postgres dedicado con permisos de solo
SELECT. Este es el límite real: incluso si se omitieran todas las demás capas, el rol no puede escribir.Validación de consultas: rechaza cualquier cosa que no sea una sola sentencia
SELECT/WITH ... SELECT(sin sentencias apiladas con punto y coma, sin palabras clave DDL/DML).LIMITforzado: cada consulta se envuelve enSELECT * FROM (...) LIMIT N, con un tope deMAX_LIMITindependientemente de lo que se solicite.statement_timeout: las consultas se cancelan después deSTATEMENT_TIMEOUT_MS.Registro de inicio: registra la base de datos/usuario conectados en stderr al arrancar, para que sea obvio a qué base de datos apuntas antes de que se ejecute cualquier consulta.
Solo apunta este servidor a una base de datos de desarrollo/pruebas/staging, nunca a producción. Las capas 2-5 son defensa en profundidad; la capa 1 (el rol de base de datos) es la única capa en la que deberías confiar realmente, y ni siquiera esa debería usarse con datos de producción.
Requisitos
Node.js >= 20
Una base de datos Postgres en la que puedas crear un rol
Un cliente MCP (por ejemplo, Claude Code, Claude Desktop o cualquier otro cliente que admita servidores MCP sobre stdio)
Configuración
1. Clonar e instalar
git clone https://github.com/david-mogbeyi/db-readonly-mcp.git
cd db-readonly-mcp
npm install2. Crear el rol de solo lectura
Ejecuta esto contra tu base de datos Postgres de destino: reemplaza el nombre del rol, la contraseña,
el nombre de la base de datos y el esquema/propietario si tu aplicación usa algo distinto de public:
CREATE ROLE myapp_readonly WITH LOGIN PASSWORD '<choose-a-password>';
GRANT CONNECT ON DATABASE myapp TO myapp_readonly;
GRANT USAGE ON SCHEMA public TO myapp_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO myapp_readonly;
-- Keeps future tables (new migrations) readable automatically, without
-- re-running this grant every time the schema changes.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO myapp_readonly;Si tu esquema no es public, o tienes varios esquemas, repite las líneas GRANT USAGE/GRANT SELECT/ALTER DEFAULT PRIVILEGES para cada uno. Este servidor
actualmente solo consulta el esquema public para list_tables/describe_table, pero
query_readonly puede referenciar cualquier esquema al que se le haya concedido acceso al rol.
3. Configurar
cp .env.example .envEdita .env y establece DATABASE_URL con la cadena de conexión del rol de solo lectura:
DATABASE_URL=postgresql://myapp_readonly:<password>@localhost:5432/myappConsulta Configuración más abajo para las otras variables.
4. Compilar
npm run buildEsto compila src/ a dist/ mediante tsc. Vuelve a ejecutarlo después de hacer cambios o editar
el código fuente.
Registrar con un cliente MCP
Claude Code
En el proyecto desde el que quieras consultar, añade un .mcp.json (o edita el que ya
tengas):
{
"mcpServers": {
"db-readonly": {
"command": "node",
"args": ["/absolute/path/to/db-readonly-mcp/dist/index.js"],
"env": {
"DATABASE_URL": "postgresql://myapp_readonly:<password>@localhost:5432/myapp"
}
}
}
}Reemplaza /absolute/path/to/db-readonly-mcp con la ubicación donde clonaste este repositorio.
Reinicia Claude Code (o reconecta los servidores MCP) para que lo detecte.
También puedes registrarlo globalmente en lugar de por proyecto: consulta la documentación de MCP de Claude
Code para las opciones de claude mcp add y
de alcance.
Claude Desktop / otros clientes MCP
Cualquier cliente que admita servidores MCP sobre stdio puede usarlo de la misma manera: apúntalo
a node /absolute/path/to/db-readonly-mcp/dist/index.js con DATABASE_URL (y
opcionalmente las demás variables de entorno de abajo) establecidas en su entorno. Consulta la documentación de tu cliente
para saber dónde está su configuración de servidor MCP: para Claude Desktop es
claude_desktop_config.json, usando la misma forma de command/args/env que arriba.
Configuración
Toda la configuración se hace mediante variables de entorno (establecidas en .env para ejecuciones locales, o en
el bloque env de la configuración de tu cliente MCP).
Variable | Requerida | Por defecto | Descripción |
| Sí | — | Cadena de conexión de Postgres para el rol de solo lectura. |
| No | 100 | Límite de filas aplicado cuando una consulta no especifica uno. |
| No | 1000 | Tope máximo de filas devueltas, independientemente de lo solicitado. |
| No | 5000 |
|
Herramientas
El servidor expone tres herramientas al asistente:
list_tables
Lista las tablas del esquema public. Sin argumentos.
→ [
{ "table_name": "merchants" },
{ "table_name": "orders" },
...
]describe_table(table)
Columnas, tipos, nulabilidad y valores por defecto de una tabla del esquema public.
{ "table": "merchants" }
→ [
{ "column_name": "id", "data_type": "uuid", "is_nullable": "NO", "column_default": "gen_random_uuid()" },
{ "column_name": "created_at", "data_type": "timestamp with time zone", "is_nullable": "NO", "column_default": "now()" },
...
]query_readonly(sql, limit?)
Ejecuta una sola sentencia SELECT (o WITH ... SELECT) protegida. limit es opcional
y se limita a MAX_LIMIT incluso si se pasa un valor mayor.
{ "sql": "SELECT id, name, created_at FROM merchants WHERE created_at > now() - interval '1 day'" }
→ { "rowCount": 3, "rows": [ { "id": "...", "name": "...", "created_at": "..." }, ... ] }Cualquier cosa que no sea una sola sentencia SELECT/WITH (múltiples sentencias, DDL,
DML, SET, etc.) se rechaza antes de llegar a la base de datos, con una explicación de
por qué.
Desarrollo local
npm run dev # runs src/index.ts directly via tsx, loads .env via Node's --env-fileEstructura del proyecto
src/
index.ts # MCP server setup and tool definitions
sqlGuard.ts # query validation (layer 2 of the safety model)
db.ts # Postgres pool setup (statement_timeout, pool size)
config.ts # env var loading/validationSolución de problemas
"DATABASE_URL environment variable is required" — falta
.envo no se está cargando; confirma que existe (desdecp .env.example .env) y que tu cliente MCP lo está recogiendo en su bloqueenvo ennpm run dev/npm start.El servidor registra la base de datos/usuario incorrectos al inicio — revisa
DATABASE_URL; el registro de inicio (connected as "..." to database "...") se imprime precisamente para que sea fácil detectarlo antes de que se ejecute cualquier consulta."Query rejected: ..." — la consulta no era una sola sentencia
SELECT/WITHo contenía una palabra clave no permitida. Esto es la capa 2 del modelo de seguridad funcionando como se espera, no un error.La consulta se cuelga y luego da error — probablemente está alcanzando
STATEMENT_TIMEOUT_MS; súbelo en.envsi tu carga de trabajo legítimamente necesita más tiempo, u optimiza la consulta.
Contribuciones
Las incidencias y las solicitudes de extracción son bienvenidas. Esta es intencionalmente una herramienta pequeña y auditable: el objetivo es mantener el modelo de seguridad lo bastante simple como para leerlo completo, no convertirlo en un constructor de consultas general.
Licencia
This server cannot be deployed
Maintenance
Related MCP Connectors
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
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.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI assistants to interact with PostgreSQL databases using natural language queries, providing secure read-only access to database schemas and SQL translation capabilities.68 npm-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely explore, analyze, and maintain PostgreSQL databases with read-only mode by default, SQL injection prevention, query performance analysis, and optional write operations.52 npmApache 2.0
- FlicenseAqualityCmaintenanceEnables read-only exploration of a Postgres database using natural language, with multiple safety layers to prevent any modifications.5-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query PostgreSQL, inspect schemas, and explain queries, designed for local and development databases with read-only safety by default.42 npmMIT