a2db
Acceso a múltiples bases de datos (PostgreSQL, SQLite, MySQL, Oracle, SQL Server) con consultas por lotes, conexiones preconfiguradas y seguridad de solo lectura impuesta por SQLGlot
Documentación
🗄️ a2db
Agente a Base de Datos
Dale a los agentes de IA acceso seguro y de solo lectura a tus bases de datos. Una llamada, múltiples consultas, resultados limpios.
5 bases de datos · consultas por lotes · conexiones preconfiguradas · SQLGlot de solo lectura
Inicio Rápido · Herramientas MCP · Seguridad · Comparación · Configuración
Agent: "Show me active users and their recent orders"
↓
a2db execute → 2 queries, 1 call, structured results
↓
Agent: "Got it — 847 active users, avg order $42.50"
¿Por qué a2db?
La mayoría de los servidores MCP de bases de datos te obligan a ejecutar una consulta a la vez, repetir los detalles de conexión en cada llamada y devolver resultados doblemente codificados dentro de cadenas JSON. a2db soluciona todo eso:
- Conexiones preconfiguradas — define bases de datos en
.mcp.jsoncon--register, el agente consulta inmediatamente - Consultas por lotes — ejecuta múltiples consultas nombradas en una sola llamada de herramienta
- Conexión predeterminada — configura la conexión una vez, úsala en todas las consultas de un lote
- Salida limpia — envoltorio JSON estructurado con datos TSV compactos y tiempos por consulta (ver ¿por qué TSV?)
- Solo lectura garantizada — el análisis AST de SQLGlot bloquea todas las operaciones de escritura
- Todos los controladores incluidos —
pip install a2dby listo - Los secretos permanecen en el entorno —
${DB_PASSWORD}en los DSN, expandidos solo al momento de la conexión
Bases de Datos Soportadas
| Base de datos | Controlador | Async |
|---|---|---|
| PostgreSQL | asyncpg | nativo |
| SQLite | aiosqlite | nativo |
| MySQL / MariaDB | mysql-connector-python | envuelto |
| Oracle | oracledb | envuelto |
| SQL Server | pymssql | envuelto |
Inicio Rápido
pip install a2db
Como Servidor MCP (recomendado)
Claude Code (con conexión preconfigurada):
claude mcp add -s user a2db -- a2db-mcp \
--register myapp/prod/main 'postgresql://user:${DB_PASSWORD}@host/mydb'
Claude Code (mínimo — el agente llama a login bajo demanda):
claude mcp add -s user a2db -- a2db-mcp
Claude Desktop / Cursor / cualquier cliente MCP (.mcp.json):
{
"mcpServers": {
"a2db": {
"command": "uvx",
"args": [
"a2db-mcp",
"--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/mydb"
],
"env": {
"DB_PASSWORD": "your-password-here"
}
}
}
}
Múltiples bases de datos:
{
"args": [
"a2db-mcp",
"--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/maindb",
"--register", "myapp/prod/analytics", "postgresql://user:${DB_PASSWORD}@host/analytics"
]
}
--register pre-registra conexiones al iniciar el servidor — el agente puede consultar de inmediato. Las contraseñas usan la sintaxis ${ENV_VAR} y se expanden al momento de la conexión, nunca se almacenan en texto plano.
Como CLI
# Save a connection (validates immediately)
a2db login -p myapp -e prod -d main 'postgresql://user:${DB_PASSWORD}@localhost/mydb'
# Query
a2db query -p myapp -e prod -d main "SELECT * FROM users LIMIT 10"
# JSON output
a2db query -p myapp -e prod -d main -f json "SELECT * FROM users LIMIT 10"
# Explore schema
a2db schema -p myapp -e prod -d main tables
a2db schema -p myapp -e prod -d main columns -t users
# List / remove connections
a2db connections
a2db logout -p myapp -e prod -d main
Herramientas MCP
| Herramienta | Descripción |
|---|---|
login | Guarda una conexión — valida conectándose primero |
logout | Elimina una conexión guardada |
list_connections | Lista conexiones (sin exponer secretos) |
execute | Ejecuta consultas por lotes nombradas con paginación |
search_objects | Explora el esquema — tablas, columnas, con niveles de detalle |
execute — la herramienta principal
Diccionario nombrado con conexión predeterminada (preferido):
{
"connection": {"project": "myapp", "env": "prod", "db": "main"},
"queries": {
"active_users": {"sql": "SELECT id, name FROM users WHERE active = true"},
"recent_orders": {"sql": "SELECT id, total FROM orders ORDER BY created_at DESC LIMIT 5"}
}
}
Formato de lista (auto-nombrado q1, q2, ...):
{
"connection": {"project": "myapp", "env": "prod", "db": "main"},
"queries": [
{"sql": "SELECT COUNT(*) AS cnt FROM users"},
{"sql": "SELECT AVG(total) AS avg_order FROM orders"}
]
}
Respuesta (formato TSV — predeterminado):
{
"active_users": {
"data": "id\tname\n1\tAlice\n2\tBob\n3\tCharlie",
"rows": 3,
"truncated": false,
"time_ms": 12
},
"recent_orders": {
"data": "id\ttotal\n501\t129.00\n500\t49.99",
"rows": 2,
"truncated": false,
"time_ms": 8
}
}
No se necesitan conversiones ::text — enteros, flotantes, marcas de tiempo, arreglos, NULL funcionan de forma nativa.
Contexto de errores
Cuando una consulta falla con un error de columna, a2db enriquece el mensaje:
column "nme" does not exist
Did you mean: name?
Available columns: id (integer), name (text), email (text), active (integer)
¿Por qué TSV?
Las ventanas de contexto de los LLM son costosas. Los datos de filas en JSON son verbosos — cada fila repite cada nombre de columna, agrega llaves, comas y comillas. TSV es una cuadrícula plana: una fila de encabezado, luego solo valores separados por tabulaciones.
Para un conjunto de resultados de 100 filas y 5 columnas, TSV típicamente usa 40-60% menos tokens que el formato JSON de filas. El envoltorio JSON estructurado aún te da metadatos (conteo de filas, estado de truncamiento) — solo la carga útil de filas es TSV.
Configura format="json" si necesitas salida estructurada completa con nombres de columna en cada fila.
Seguridad
Cumplimiento de Solo Lectura
Cada consulta es analizada por SQLGlot antes de la ejecución:
- Bloqueado: INSERT, UPDATE, DELETE, DROP, TRUNCATE, ALTER, CREATE, GRANT, REVOKE
- Resistente a evasión: ataques de múltiples declaraciones y escrituras envueltas en comentarios se detectan a nivel de AST, no solo por coincidencia de palabras clave
- Permitido: SELECT, UNION, EXPLAIN, SHOW, DESCRIBE, PRAGMA
Esto es defensa en profundidad — también deberías usar un usuario de base de datos de solo lectura, pero a2db no permitirá escrituras incluso si el usuario tiene permisos de escritura.
Soporte de escritura está implementado en el núcleo pero aún no expuesto vía MCP. Planificado: permisos de escritura por conexión, habilitados explícitamente por el operador humano — no por el agente. Ver TODO.md.
Almacenamiento de Credenciales
Las conexiones se guardan en ~/.config/a2db/connections/ como archivos TOML.
- Sintaxis
${DB_PASSWORD}— las referencias a variables de entorno se almacenan literalmente y se expanden solo al momento de la conexión. Los secretos permanecen en tu entorno, no en el disco. - Sin secretos en la salida de lista —
list_connectionsmuestra proyecto/entorno/BD y tipo de base de datos, nunca DSN o contraseñas - Los archivos de conexión son locales a tu máquina y fuera de cualquier repositorio
Alcance de Implementación
a2db actualmente se ejecuta como un servidor MCP stdio local. Hereda variables de entorno del proceso que lo lanza (tu shell, Claude Code, Docker). Este es el modelo estándar para servidores MCP locales — el mismo enfoque usado por DBHub, Google Toolbox y otros.
Planificado: transporte HTTP remoto con OAuth 2.1 según la especificación MCP. Por ahora, si se ejecuta en Docker, inyecta secretos vía variables de entorno en el tiempo de ejecución del contenedor.
Comparación
| Característica | a2db | DBHub | Google Toolbox | PGMCP | Supabase MCP |
|---|---|---|---|---|---|
| Bases de datos | 5 (PG, SQLite, MySQL, Oracle, MSSQL) | 5 (PG, MySQL, MSSQL, MariaDB, SQLite) | 40+ (nube + OSS) | Solo PG | PG (Supabase) |
| Consultas por lotes | Diccionario nombrado + lista | Separadas por punto y coma | No | No | No |
| Conexión predeterminada | Configura una vez, usa para todas | Por consulta | N/A | BD única | Proyecto único |
| Solo lectura | SQLGlot AST (garantizado) | Verificación de palabras clave (config) | Sugerencia/anotación | Transacción de solo lectura + regex | Bandera de configuración |
| Soporte de escritura | Planificado (por conexión) | Bandera de configuración | Vía definición de herramienta | No | Bandera de configuración |
| Salida | JSON + datos TSV | Texto estructurado | Protocolo MCP | Tabla / JSON / CSV | JSON |
| Descubrimiento de esquema | 3 niveles de detalle | Herramienta dedicada | Herramientas preconstruidas | Vía NL-a-SQL | Herramientas dedicadas |
| Preconfigurado | --register en configuración MCP | Archivo de configuración | Configuración YAML | Variable de entorno | Gestionado en la nube |
| Credenciales | ${ENV_VAR} en DSN | Cadenas DSN | Variables de entorno + IAM de GCP | Variable de entorno | OAuth 2.1 |
| Controladores incluidos | Todos incluidos | Todos incluidos | Varía | Integrados | Gestionados |
| CLI | Sí | No | Sí | Sí | No |
| Contexto de errores | Sugerencias de columna + tipos | No | No | No | No |
| Licencia | Apache 2.0 | MIT | Apache 2.0 | Apache 2.0 | Apache 2.0 |
Cuándo usar qué:
- a2db — consultas por lotes multi-BD con salida limpia, diseño primero para agentes, configuración rápida
- DBHub — herramientas personalizadas vía configuración TOML, interfaz web de trabajo
- Google Toolbox — ecosistema GCP, integración IAM, 40+ fuentes
- PGMCP — lenguaje natural a SQL para PostgreSQL (requiere clave de OpenAI)
- Supabase MCP — gestión completa de la plataforma Supabase (funciones edge, ramificaciones, almacenamiento)
Configuración por Entorno
Local (macOS / Linux)
pip install a2db
# CLI
a2db login -p myapp -e dev -d main 'postgresql://user:pass@localhost/mydb'
# Or add as MCP server (see Quick Start)
Docker
FROM python:3.12-slim
RUN pip install a2db
CMD ["a2db-mcp", "--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/mydb"]
docker run -e DB_PASSWORD=secret -i my-a2db-image
Los secretos se inyectan como variables de entorno en tiempo de ejecución — nunca se hornean en la imagen.
CI / Automatización
pip install a2db
# Pre-configured — no login needed
a2db-mcp --register myapp/ci/main "postgresql://ci_user:${CI_DB_PASSWORD}@db-host/mydb"
# Or use CLI directly
a2db login -p myapp -e ci -d main "postgresql://ci_user:${CI_DB_PASSWORD}@db-host/mydb"
a2db query -p myapp -e ci -d main "SELECT COUNT(*) FROM migrations"
Desarrollo
make bootstrap # Install deps + hooks
make check # Lint + test + security (full gate)
make test # Tests with coverage (90% minimum)
make lint # Lint only (never modifies files)
make fix # Auto-fix + lint
Licencia
Apache 2.0
🗄️ Acceso a bases de datos primero para agentes desde 2025.
Construido por Denis Tomilin