mcp-database-server
Servidor de Protocolo de Contexto de Modelo (MCP) de grado de producción para acceso unificado a bases de datos SQL. Conecta múltiples bases de datos a través de un solo servidor MCP con descubrimiento de esquemas, mapeo de relaciones, almacenamiento en caché y controles de seguridad.
Documentación
@adevguide/mcp-database-server
Servidor MCP (Model Context Protocol) de nivel de producción para acceso unificado a bases de datos SQL. Conecta múltiples bases de datos a través de un único servidor MCP con descubrimiento de esquemas, mapeo de relaciones, caché y controles de seguridad.
- npm: https://www.npmjs.com/package/@adevguide/mcp-database-server
- GitHub: https://github.com/iPraBhu/mcp-database-server
Contenido
Características
- Soporte multi-base de datos: PostgreSQL, MySQL/MariaDB, SQLite, SQL Server, Oracle
- Descubrimiento automático de esquemas: tablas, columnas, índices, claves foráneas, relaciones
- Caché persistente de esquemas: TTL + versionado, actualización manual, estadísticas de caché
- Inferencia de relaciones: claves foráneas + heurísticas
- Inteligencia de consultas: seguimiento, estadísticas, tiempos de espera
- Asistencia de joins: rutas de join sugeridas basadas en grafos de relaciones
- Controles de seguridad: modo solo lectura, permitir/denegar operaciones de escritura, redacción de secretos
- Optimización de consultas: recomendaciones de índices, perfilado de rendimiento, detección de consultas lentas
- Monitoreo de rendimiento: análisis de ejecución detallado, identificación de cuellos de botella
- Reescritura de consultas: sugerencias de optimización automatizadas con estimaciones de impacto en el rendimiento
Por qué existe esto
Este proyecto fue originalmente creado con vibe-coding para resolver problemas reales que enfrentaba al conectar herramientas LLM a múltiples bases de datos SQL (conectividad consistente, descubrimiento de esquemas y ejecución segura de consultas). Desde entonces se ha endurecido hasta convertirse en un servidor MCP reutilizable con caché y valores de seguridad predeterminados.
Arquitectura
┌─────────────────────────────────────────────────────────┐
│ MCP Client │
│ (Claude Desktop, IDEs, etc.) │
└────────────────┬────────────────────────────────────────┘
│ JSON-RPC over stdio
┌────────────────▼────────────────────────────────────────┐
│ MCP Database Server │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Schema Cache (TTL + Versioning) │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Query Tracker (History + Statistics) │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Security Layer (Read-only, Operation Controls) │ │
│ └──────────────────────────────────────────────────┘ │
└────┬─────────┬─────────┬──────────┬──────────┬─────────┘
│ │ │ │ │
┌────▼───┐ ┌──▼────┐ ┌──▼─────┐ ┌──▼──────┐ ┌▼────────┐
│Postgres│ │ MySQL │ │ SQLite │ │ MSSQL │ │ Oracle │
└────────┘ └───────┘ └────────┘ └─────────┘ └─────────┘
Bases de datos compatibles
| Base de datos | Driver | Estado | Notas |
|---|---|---|---|
| PostgreSQL | pg | ✅ Soporte completo | Incluye compatibilidad con CockroachDB |
| MySQL/MariaDB | mysql2 | ✅ Soporte completo | Incluye compatibilidad con Amazon Aurora MySQL |
| SQLite | sql.js | ✅ Soporte completo | SQLite respaldado por WASM con persistencia de archivos |
| SQL Server | tedious | ✅ Soporte completo | Microsoft SQL Server / Azure SQL |
| Oracle | oracledb | ⚠️ Stub | Requiere Oracle Instant Client |
Instalación
Instalación global (recomendada)
npm install -g @adevguide/mcp-database-server
Ejecuta:
mcp-database-server --config /absolute/path/to/.mcp-database-server.config
Ejecutar vía npx (sin instalación global)
npx -y @adevguide/mcp-database-server --config /absolute/path/to/.mcp-database-server.config
Instalar desde el código fuente
git clone https://github.com/iPraBhu/mcp-database-server.git
cd mcp-database-server
npm install
npm run build
node dist/index.js --config ./.mcp-database-server.config
Configuración
Crea un archivo .mcp-database-server.config en la raíz de tu proyecto:
Nota: El archivo de configuración se descubre automáticamente dentro del árbol del proyecto actual. Si no especificas
--config, la herramienta busca hacia arriba desde el directorio actual hasta que alcanza la raíz del proyecto detectada (por ejemplo, un directorio que contengapackage.jsono.git). No continúa más allá de la raíz del proyecto. Si usascredentialCommand, pasa--configexplícitamente.
{
"databases": [
{
"id": "postgres-main",
"type": "postgres",
"secretRef": "DB_URL_POSTGRES",
"readOnly": true,
"pool": {
"min": 2,
"max": 10,
"idleTimeoutMillis": 30000
},
"introspection": {
"includeViews": true,
"excludeSchemas": ["pg_catalog"]
}
},
{
"id": "mariadb-reporting",
"type": "mysql",
"secretRef": "DB_URL_MARIADB",
"readOnly": true,
"pool": {
"min": 1,
"max": 5
}
},
{
"id": "sqlite-local",
"type": "sqlite",
"path": "./data/app.db"
}
],
"cache": {
"directory": ".sql-mcp-cache",
"ttlMinutes": 10
},
"security": {
"allowWrite": false,
"allowedWriteOperations": ["INSERT", "UPDATE"],
"disableDangerousOperations": true,
"redactSecrets": true
},
"logging": {
"level": "info",
"pretty": false
}
}
Referencia de configuración
Configuración de base de datos
Cada base de datos en el arreglo databases representa una conexión a una base de datos SQL.
Propiedades principales
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
id | string | ✅ Sí | - | Identificador único para esta conexión de base de datos. Se usa en todas las llamadas de herramientas MCP. Debe ser único entre todas las bases de datos. |
type | enum | ✅ Sí | - | Tipo de sistema de base de datos. Valores válidos: postgres, mysql, sqlite, mssql, oracle |
url | string | Condicional* | - | Cadena de conexión explícita a la base de datos. Soporta interpolación de variables de entorno con ${DB_URL}, pero no es la ruta recomendada para el manejo de secretos. |
secretRef | string | Condicional* | - | Nombre de una variable de entorno que contiene la cadena de conexión completa. Se resuelve desde el entorno del proceso o desde un archivo .env junto al archivo de configuración. |
credentialCommand | string | Condicional* | - | Comando de shell que imprime la cadena de conexión completa en stdout al iniciar. Útil para 1Password, Vault, utilidades de AWS o herramientas de secretos personalizadas. Requiere iniciar el servidor con una ruta --config explícita. |
path | string | Condicional** | - | Ruta del sistema de archivos al archivo de base de datos SQLite. Requerido solo para type: sqlite. Puede ser relativa o absoluta. |
readOnly | boolean | No | true | Cuando es true, bloquea todas las operaciones de escritura (INSERT, UPDATE, DELETE, etc.). Recomendado para seguridad en producción. |
eagerConnect | boolean | No | false | Cuando es true, se conecta a la base de datos inmediatamente al iniciar (fail-fast). Cuando es false, se conecta en la primera consulta (carga diferida). |
* Requerido para postgres, mysql, mssql, oracle
** Requerido solo para sqlite
Formatos de cadena de conexión:
PostgreSQL: postgresql://username:password@host:5432/database
MySQL: mysql://username:password@host:3306/database
SQL Server: Server=host,1433;Database=dbname;User Id=user;Password=pass
SQLite: (use path property instead)
Oracle: username/password@host:1521/servicename
Configuración del pool de conexiones
El objeto pool controla el comportamiento del pool de conexiones. Mejora el rendimiento al reutilizar las conexiones de base de datos.
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
min | number | No | 2 | Número mínimo de conexiones a mantener en el pool. Se mantienen activas incluso cuando están inactivas. |
max | number | No | 10 | Número máximo de conexiones concurrentes. No excedas el límite de conexiones de tu base de datos. |
idleTimeoutMillis | number | No | 30000 | Tiempo (ms) para mantener conexiones inactivas antes de cerrarlas. Ejemplo: 60000 = 1 minuto. |
connectionTimeoutMillis | number | No | 10000 | Tiempo (ms) de espera al establecer una conexión antes de agotar el tiempo. Fail-fast si la base de datos es inalcanzable. |
Recomendaciones:
- Desarrollo:
min: 1,max: 5 - Producción (tráfico bajo):
min: 2,max: 10 - Producción (tráfico alto):
min: 5,max: 20
Configuración de introspección
El objeto introspection controla el comportamiento del descubrimiento de esquemas. Determina qué objetos de base de datos se analizan.
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
includeViews | boolean | No | true | Incluir vistas de base de datos en el descubrimiento de esquemas. Establece a false si las vistas causan problemas de rendimiento. |
includeRoutines | boolean | No | false | Incluir procedimientos almacenados y funciones. (No implementado por completo: funcionalidad planificada) |
maxTables | number | No | ilimitado | Limitar la introspección a las primeras N tablas. Útil para bases de datos con más de 1000 tablas. Puede resultar en un descubrimiento de relaciones incompleto. |
includeSchemas | string[] | No | todos | Lista blanca de esquemas a inspeccionar. Solo aplicable a PostgreSQL y SQL Server. Ejemplo: ["public", "app"] |
excludeSchemas | string[] | No | ninguno | Lista negra de esquemas a omitir. Valores comunes: ["pg_catalog", "information_schema", "sys"] |
Esquema vs. base de datos:
- PostgreSQL/SQL Server: Admite múltiples esquemas por base de datos. Usa
includeSchemas/excludeSchemas. - MySQL/MariaDB: Esquema = base de datos. Usa el nombre de la base de datos en la cadena de conexión.
- SQLite: Base de datos de archivo único, sin concepto de esquema.
Configuración de caché
Controla el almacenamiento en caché de metadatos de esquema para mejorar el rendimiento de inicio y reducir la carga de la base de datos.
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
directory | string | No | .sql-mcp-cache | Ruta del directorio donde se almacenan los archivos de esquema en caché. Un archivo JSON por base de datos. |
ttlMinutes | number | No | 10 | Tiempo de vida (TTL) en minutos. Cuánto tiempo se considera válido el esquema en caché antes de una actualización automática. |
Comportamiento de la caché:
- Al iniciar: Carga el esquema desde la caché si está disponible y no ha expirado
- Después de la expiración del TTL: La siguiente consulta activa una nueva introspección automática
- Actualización manual: Usa la herramienta
clear_cacheointrospect_schemaconforceRefresh: true - Archivos de caché: Se almacenan como
{database-id}.json(p. ej.,postgres-main.json)
Valores TTL recomendados:
- Desarrollo:
5minutos (el esquema cambia con frecuencia) - Staging:
30-60minutos - Producción (estática):
1440minutos (24 horas) - Producción (activa):
60-240minutos (1-4 horas)
Configuración de seguridad
Controles de seguridad integrales para proteger tus bases de datos de operaciones no autorizadas o peligrosas.
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
allowWrite | boolean | No | false | Interruptor maestro para operaciones de escritura. Cuando es false, todas las escrituras se bloquean en todas las bases de datos. |
allowedWriteOperations | string[] | No | todas | Lista blanca de operaciones SQL permitidas cuando allowWrite: true. Valores válidos: INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, TRUNCATE, REPLACE, MERGE |
disableDangerousOperations | boolean | No | true | Capa de seguridad adicional. Cuando es true, bloquea las operaciones DELETE, TRUNCATE y DROP incluso si las escrituras están permitidas. Evita la pérdida accidental de datos. |
redactSecrets | boolean | No | true | Redacta cadenas de conexión, contraseñas y credenciales similares en registros y mensajes de error devueltos. |
Capas de seguridad (evaluadas en orden):
readOnlya nivel de base de datos → Bloquea todas las escrituras para una base de datos específicaallowWriteglobal → Interruptor maestro para todas las bases de datosdisableDangerousOperations→ Bloquea específicamente DELETE/TRUNCATE/DROPallowedWriteOperations→ Lista blanca de operaciones permitidas
Ejemplos de configuración:
// Read-only access (default - safest)
{
"allowWrite": false
}
// Allow INSERT and UPDATE only (no deletes)
{
"allowWrite": true,
"allowedWriteOperations": ["INSERT", "UPDATE"],
"disableDangerousOperations": true
}
// Full write access (development only - dangerous!)
{
"allowWrite": true,
"disableDangerousOperations": false
}
Configuración de registro (logging)
Controla la verbosidad y el formato de salida de los registros.
| Propiedad | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
level | enum | No | info | Nivel de registro. Valores válidos: trace, debug, info, warn, error. Los niveles inferiores incluyen los niveles superiores. |
pretty | boolean | No | false | Cuando es true, formatea los registros como texto legible. Cuando es false, genera JSON estructurado (mejor para la agregación de registros en producción). |
Niveles de registro:
trace: Todo (extremadamente verboso: úsalo solo para depuración)debug: Información de diagnóstico detalladainfo: Mensajes informativos generales (recomendado para producción)warn: Mensajes de advertencia que no impiden la operaciónerror: Solo mensajes de error
Recomendaciones:
- Desarrollo:
level: "debug",pretty: true - Producción:
level: "info",pretty: false - Solución de problemas:
level: "trace",pretty: true
Ejemplo de configuración completa
{
"databases": [
{
"id": "postgres-production",
"type": "postgres",
"url": "${DATABASE_URL}",
"readOnly": true,
"pool": {
"min": 5,
"max": 20,
"idleTimeoutMillis": 60000,
"connectionTimeoutMillis": 5000
},
"introspection": {
"includeViews": true,
"includeRoutines": false,
"excludeSchemas": ["pg_catalog", "information_schema"]
},
"eagerConnect": true
},
{
"id": "mysql-analytics",
"type": "mysql",
"url": "${MYSQL_URL}",
"readOnly": true,
"pool": {
"min": 2,
"max": 10
},
"introspection": {
"includeViews": true,
"maxTables": 100
}
},
{
"id": "sqlite-local",
"type": "sqlite",
"path": "./data/app.db",
"readOnly": true
}
],
"cache": {
"directory": ".sql-mcp-cache",
"ttlMinutes": 60
},
"security": {
"allowWrite": false,
"allowedWriteOperations": ["INSERT", "UPDATE"],
"disableDangerousOperations": true,
"redactSecrets": true
},
"logging": {
"level": "info",
"pretty": false
}
}
Resolución de secretos
Enfoque recomendado: secretRef
Mantén los secretos fuera de la configuración del cliente MCP y fuera de los valores de configuración del servidor.
Ejemplo de configuración:
{
"databases": [
{
"id": "production-db",
"type": "postgres",
"secretRef": "DATABASE_URL"
}
]
}
El servidor resuelve secretRef desde el entorno del proceso primero, y luego desde un archivo .env junto a .mcp-database-server.config.
Archivo de entorno (.env):
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
DB_URL_MYSQL=mysql://user:password@localhost:3306/dbname
DB_URL_MARIADB=mysql://report_user:password@mariadb.local:3306/reporting
DB_URL_MSSQL=Server=host,1433;Database=db;User Id=sa;Password=pass
Alternativa: credentialCommand
{
"databases": [
{
"id": "analytics-db",
"type": "mysql",
"credentialCommand": "op read op://analytics/mysql/url"
}
]
}
El comando debe imprimir solo la cadena de conexión en stdout.
Por seguridad, credentialCommand solo se permite cuando el servidor se inicia con una ruta --config explícita. Las configuraciones auto-descubiertas no pueden ejecutar comandos de credenciales.
Aún compatible: interpolación directa de entorno
Todavía puedes escribir "url": "${DATABASE_URL}", pero secretRef es la opción más limpia porque hace explícita la fuente del secreto.
Mejores prácticas:
- ✅ Almacena el archivo
.envfuera del control de versiones (agrégalo a.gitignore) - ✅ Usa archivos
.envdiferentes para cada entorno (dev, staging, prod) - ✅ Nunca subas credenciales a repositorios de git
- ✅ Usa servicios de gestión de secretos (AWS Secrets Manager, HashiCorp Vault) en producción
Referencia de cadenas de conexión
| Base de datos | Formato | Ejemplo |
|---|---|---|
| PostgreSQL | postgresql://user:pass@host:port/db | postgresql://admin:secret@localhost:5432/myapp |
| MySQL | mysql://user:pass@host:port/db | mysql://root:password@localhost:3306/myapp |
| MariaDB | mysql://user:pass@host:port/db | mysql://report_user:password@mariadb.local:3306/reporting |
| SQL Server | Server=host,port;Database=db;User Id=user;Password=pass | Server=localhost,1433;Database=myapp;User Id=sa;Password=secret |
| SQLite | Usa la propiedad path | "path": "./data/app.db" o "path": "/var/db/app.sqlite" |
Parámetros adicionales:
PostgreSQL:
postgresql://user:pass@host:5432/db?sslmode=require&connect_timeout=10
MySQL:
mysql://user:pass@host:3306/db?charset=utf8mb4&timezone=Z
MariaDB:
mysql://user:pass@host:3306/db?charset=utf8mb4
SQL Server:
Server=host;Database=db;User Id=user;Password=pass;Encrypt=true;TrustServerCertificate=false
Integración con clientes MCP
Ubicaciones de archivos de configuración
| Cliente MCP | Ruta del archivo de configuración |
|---|---|
| Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json |
| Cline (VS Code) | Configuración de VS Code → Servidores MCP |
| Otros clientes | Consulta la documentación específica del cliente |
Métodos de configuración
Método 1: Instalación global con npm
Configuración:
{
"mcpServers": {
"database": {
"command": "mcp-database-server",
"args": ["--config", "/absolute/path/to/.mcp-database-server.config"]
}
}
}
Método 2: Instalación desde el código fuente
Configuración:
{
"mcpServers": {
"database": {
"command": "node",
"args": [
"/absolute/path/to/mcp-database-server/dist/index.js",
"--config",
"/absolute/path/to/.mcp-database-server.config"
]
}
}
}
Propiedades de configuración
| Propiedad | Descripción | Ejemplo |
|---|---|---|
command | Ejecutable a utilizar. Usa mcp-database-server para instalación con npm, node para instalación desde el código fuente. | "mcp-database-server" |
args | Matriz de argumentos de línea de comandos. El primer argumento suele ser --config seguido de la ruta del archivo de configuración. | ["--config", "/path/to/config"] |
env | Variables de entorno opcionales que se pasan al servidor. Prefiere secretRef con un archivo .env local o herramientas externas de secretos para las credenciales de la base de datos. | {"APP_ENV": "production"} |
Cómo encontrar rutas absolutas:
# macOS/Linux
cd /path/to/mcp-database-server
pwd # prints: /Users/username/projects/mcp-database-server
# Windows (PowerShell)
cd C:\path\to\mcp-database-server
$PWD.Path # prints: C:\Users\username\projects\mcp-database-server
Herramientas MCP disponibles
Este servidor proporciona 15 herramientas para la interacción y optimización integral de bases de datos.
Referencia de herramientas
| Herramienta | Propósito | Acceso de escritura | Datos en caché |
|---|---|---|---|
list_databases | Lista todas las bases de datos configuradas con su estado | No | Usa caché |
introspect_schema | Descubre y almacena en caché el esquema de la base de datos | No | Escribe en caché |
get_schema | Recupera metadatos de esquema almacenados en caché | No | Lee de caché |
run_query | Ejecuta consultas SQL con controles de seguridad | Condicional* | Actualiza estadísticas |
export_query | Exporta resultados de consultas grandes de solo lectura a un archivo local | No | Sin caché |
explain_query | Analiza planes de ejecución de consultas | No | Sin caché |
suggest_joins | Obtiene recomendaciones inteligentes de rutas de unión | No | Usa caché |
clear_cache | Limpia la caché de esquema y las estadísticas | No | Limpia caché |
cache_status | Muestra el estado y las estadísticas de la caché | No | Lee de caché |
health_check | Prueba la conectividad de la base de datos | No | Sin caché |
analyze_performance | Obtiene análisis detallados de rendimiento | No | Usa estadísticas |
suggest_indexes | Analiza consultas y recomienda índices | No | Usa estadísticas |
detect_slow_queries | Identifica y alerta sobre consultas lentas | No | Usa estadísticas |
rewrite_query | Sugiere versiones optimizadas de consultas | No | Usa caché |
profile_query | Perfila el rendimiento de consultas con cuellos de botella | No | Sin caché |
* Requiere allowWrite: true y respeta la configuración de seguridad
1. list_databases
Lista todas las bases de datos configuradas con su estado de conexión e información de caché.
Parámetros de entrada:
No se requiere ninguno.
Respuesta:
[
{
"id": "postgres-main",
"type": "postgres",
"connected": true,
"cached": true,
"cacheAge": 45000,
"version": "abc123"
}
]
Campos de la respuesta:
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador de la base de datos según la configuración |
type | string | Tipo de base de datos (postgres, mysql, sqlite, mssql, oracle) |
connected | boolean | Indica si la conexión a la base de datos está activa |
cached | boolean | Indica si el esquema está actualmente en caché |
cacheAge | number | Antigüedad del esquema en caché en milisegundos (si está en caché) |
version | string | Hash de versión de la caché (si está en caché) |
2. introspect_schema
Descubre y almacena en caché el esquema completo de la base de datos, incluyendo tablas, columnas, índices, claves foráneas y relaciones.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos a inspeccionar |
forceRefresh | boolean | No | Fuerza una nueva inspección incluso si la caché es válida (predeterminado: false) |
schemaFilter | object | No | Filtra qué objetos inspeccionar |
schemaFilter.includeSchemas | string[] | No | Inspeccionar solo estos esquemas (PostgreSQL/SQL Server) |
schemaFilter.excludeSchemas | string[] | No | Omitir estos esquemas durante la inspección |
schemaFilter.includeViews | boolean | No | Incluir vistas de la base de datos (predeterminado: true) |
schemaFilter.maxTables | number | No | Limitar a las primeras N tablas |
Ejemplo de solicitud:
{
"dbId": "postgres-main",
"forceRefresh": false,
"schemaFilter": {
"includeSchemas": ["public"],
"excludeSchemas": ["temp"],
"includeViews": true,
"maxTables": 100
}
}
Respuesta:
{
"dbId": "postgres-main",
"version": "a1b2c3d4",
"introspectedAt": "2026-01-26T10:00:00.000Z",
"schemas": [
{
"name": "public",
"tableCount": 15,
"viewCount": 3
}
],
"totalTables": 15,
"totalRelationships": 12
}
3. get_schema
Recupera metadatos detallados del esquema desde la caché sin consultar la base de datos.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos |
schema | string | No | Filtrar por un nombre de esquema específico |
table | string | No | Filtrar por un nombre de tabla específico |
Ejemplo de solicitud:
{
"dbId": "postgres-main",
"schema": "public",
"table": "users"
}
Respuesta: Metadatos completos del esquema, incluyendo tablas, columnas, tipos de datos, índices, claves foráneas y relaciones inferidas.
4. run_query
Ejecuta consultas SQL con almacenamiento automático en caché del esquema, anotación de relaciones y controles de seguridad integrales.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos a consultar |
sql | string | Sí | Consulta SQL a ejecutar |
params | array | No | Valores de consulta parametrizados (previene la inyección SQL) |
limit | number | No | Número máximo de filas a devolver |
offset | number | No | Desplazamiento de filas para lecturas paginadas. Requiere limit. |
maxBytes | number | No | Máximo aproximado de bytes serializados para las filas devueltas. |
includeMetadata | boolean | No | Incluir metadatos de relaciones y estadísticas de consulta en la respuesta. Predeterminado: true. |
trackQuery | boolean | No | Registrar esta consulta en el historial y los análisis de rendimiento. Predeterminado: true. |
timeoutMs | number | No | Tiempo de espera de la consulta en milisegundos |
Ejemplo de solicitud:
{
"dbId": "postgres-main",
"sql": "SELECT * FROM users WHERE active = $1 ORDER BY id",
"params": [true],
"limit": 10,
"offset": 0,
"maxBytes": 32768,
"includeMetadata": false,
"trackQuery": false,
"timeoutMs": 5000
}
Respuesta:
{
"rows": [
{"id": 1, "name": "Alice", "email": "alice@example.com", "active": true},
{"id": 2, "name": "Bob", "email": "bob@example.com", "active": true}
],
"columns": ["id", "name", "email", "active"],
"rowCount": 2,
"executionTimeMs": 15,
"metadata": {
"relationships": [...],
"queryStats": {
"totalQueries": 10,
"avgExecutionTime": 20,
"errorCount": 0
},
"pagination": {
"limit": 10,
"offset": 0,
"hasMore": true,
"nextOffset": 10
},
"responseSize": {
"maxBytes": 32768,
"rowsBytes": 1842,
"rowsTrimmed": false,
"omittedRowCount": 0
}
}
}
Para la ruta de lectura más rápida en MariaDB/MySQL, establece "includeMetadata": false y "trackQuery": false cuando solo necesites las filas de resultados y no requieras anotaciones de relaciones, historial de consultas ni análisis de rendimiento para esa solicitud.
Controles de seguridad:
- ✅ Las operaciones de escritura están bloqueadas por defecto (
allowWrite: false) - ✅ Las operaciones peligrosas (DELETE, TRUNCATE, DROP) están deshabilitadas por defecto
- ✅ Se pueden permitir operaciones específicas mediante la lista blanca
allowedWriteOperations - ✅ Modo
readOnlypor base de datos
5. explain_query
Recupera el plan de ejecución de la consulta sin ejecutarla.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos |
sql | string | Sí | Consulta SQL a analizar |
params | array | No | Parámetros de la consulta (para consultas parametrizadas) |
Ejemplo de solicitud:
{
"dbId": "postgres-main",
"sql": "SELECT * FROM users JOIN orders ON users.id = orders.user_id WHERE users.active = $1",
"params": [true]
}
Respuesta: Plan de ejecución nativo de la base de datos (el formato varía según el tipo de base de datos).
5a. export_query
Exporta los resultados de consultas grandes de solo lectura a un archivo local en .sql-mcp-cache/exports.
Estrategia de ejecución:
- MySQL/MariaDB utiliza transmisión de filas a nivel de adaptador para evitar cargar el conjunto completo de resultados en memoria.
- PostgreSQL y SQLite utilizan exportación paginada reescribiendo las ventanas
LIMIT/OFFSETde nivel superior. - La exportación en SQL Server requiere una ruta de transmisión específica del adaptador en el futuro y actualmente fallará a menos que se admita la reescritura de paginación.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos |
sql | string | Sí | Consulta SQL de solo lectura a exportar |
params | array | No | Parámetros de la consulta |
format | string | No | Formato de salida: jsonl o csv (predeterminado: jsonl) |
pageSize | number | No | Tamaño de página para adaptadores sin transmisión (predeterminado: 1000) |
fileName | string | No | Nombre opcional del archivo de salida escrito dentro del directorio de exportación |
timeoutMs | number | No | Tiempo de espera de la consulta en milisegundos |
Ejemplo de solicitud:
{
"dbId": "mariadb-reporting",
"sql": "SELECT id, email, created_at FROM users ORDER BY id",
"format": "jsonl",
"fileName": "users-export.jsonl",
"timeoutMs": 10000
}
Respuesta:
{
"dbId": "mariadb-reporting",
"outputPath": "/absolute/path/to/.sql-mcp-cache/exports/users-export.jsonl",
"format": "jsonl",
"strategy": "stream",
"rowsExported": 250000,
"columns": ["id", "email", "created_at"],
"fileSizeBytes": 18342011,
"executionTimeMs": 8421
}
6. suggest_joins
Analiza el grafo de relaciones para recomendar rutas de unión óptimas entre múltiples tablas.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Identificador de la base de datos |
tables | string[] | Sí | Matriz de nombres de tablas a unir (2-10 tablas) |
Ejemplo de solicitud:
{
"dbId": "postgres-main",
"tables": ["users", "orders", "products"]
}
Respuesta:
[
{
"tables": ["users", "orders", "products"],
"joins": [
{
"fromTable": "users",
"toTable": "orders",
"relationship": {
"type": "one-to-many",
"confidence": 1.0
},
"joinCondition": "users.id = orders.user_id"
},
{
"fromTable": "orders",
"toTable": "products",
"relationship": {
"type": "many-to-one",
"confidence": 1.0
},
"joinCondition": "orders.product_id = products.id"
}
],
"sql": "FROM users JOIN orders ON users.id = orders.user_id JOIN products ON orders.product_id = products.id"
}
]
7. clear_cache
Limpia la caché de esquema y las estadísticas de consultas para una o todas las bases de datos.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | No | Base de datos a limpiar (omite para limpiar todas) |
Ejemplo de solicitud:
{
"dbId": "postgres-main"
}
Respuesta: Mensaje de confirmación.
8. cache_status
Recupera estadísticas detalladas de la caché e información de estado.
Parámetros de entrada:
No se requiere ninguno.
Respuesta:
{
"directory": ".sql-mcp-cache",
"ttlMinutes": 10,
"databases": [
{
"dbId": "postgres-main",
"cached": true,
"version": "abc123",
"age": 120000,
"expired": false,
"tableCount": 15,
"sizeBytes": 45678
}
]
}
9. health_check
Prueba la conectividad de la base de datos y devuelve información de estado.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | No | Base de datos a verificar (omite para verificar todas) |
Respuesta:
{
"databases": [
{
"dbId": "postgres-main",
"healthy": true,
"connected": true,
"version": "PostgreSQL 15.3",
"responseTimeMs": 12
}
]
}
10. analyze_performance
Obtén análisis completos de rendimiento en todas las consultas de una base de datos.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Base de datos a analizar |
Respuesta:
{
"totalQueries": 1250,
"slowQueries": 23,
"avgExecutionTime": 45.67,
"p95ExecutionTime": 234.5,
"errorRate": 1.2,
"mostFrequentTables": [
{ "table": "users", "count": 456 },
{ "table": "orders", "count": 234 }
],
"performanceTrend": "improving"
}
11. suggest_indexes
Analiza patrones de consulta y recomienda índices óptimos para la base de datos.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Base de datos a analizar |
Respuesta:
[
{
"table": "orders",
"columns": ["customer_id", "order_date"],
"type": "composite",
"reason": "Frequently used in WHERE and JOIN conditions",
"impact": "high"
},
{
"table": "products",
"columns": ["category_id"],
"type": "single",
"reason": "Column category_id is frequently queried",
"impact": "medium"
}
]
12. detect_slow_queries
Identifica consultas que superan los umbrales de rendimiento y proporciona alertas.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | Base de datos a analizar |
Respuesta:
[
{
"dbId": "postgres-main",
"queryId": "a1b2c3",
"sql": "SELECT * FROM large_table WHERE slow_column = ?",
"executionTimeMs": 2500,
"thresholdMs": 1000,
"timestamp": "2024-01-27T10:30:00Z",
"frequency": 5,
"recommendations": [
{
"type": "add_index",
"description": "Add index on slow_column for better performance",
"impact": "high",
"effort": "medium"
}
]
}
]
13. rewrite_query
Sugiere versiones optimizadas de consultas SQL con mejoras de rendimiento.
Parámetros de entrada:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dbId | string | Sí | ID de la base de datos |
sql | string | Sí | Consulta SQL a optimizar |
Respuesta:
{
"originalQuery": "SELECT * FROM users WHERE active = 1",
"optimizedQuery": "SELECT id, name, email FROM users WHERE active = 1 LIMIT 1000",
"improvements": [
"Removed unnecessary SELECT *",
"Added LIMIT clause to prevent large result sets"
],
"performanceGain": 35,
"confidence": "high"
}
14. profile_query
Perfila el rendimiento de una consulta específica con análisis detallado de cuellos de botella.
Parámetros de entrada:
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
dbId | string | Sí | ID de base de datos |
sql | string | Sí | Consulta SQL para perfilar |
params | array | No | Parámetros de consulta |
Respuesta:
{
"queryId": "def456",
"sql": "SELECT u.name, COUNT(o.id) FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.id",
"executionTimeMs": 1250,
"rowCount": 5000,
"bottlenecks": [
{
"type": "join",
"severity": "high",
"description": "Nested loop join on large tables",
"estimatedCost": 150
}
],
"recommendations": [
{
"type": "add_index",
"description": "Add index on orders.user_id",
"impact": "high",
"effort": "low"
}
],
"overallScore": 65
}
Recursos
El servidor expone esquemas en caché como recursos MCP:
- URI:
schema://{dbId} - Tipo MIME:
application/json - Contenido: Metadatos completos del esquema en caché
Introspección de Esquema
Descubrimiento Automático
El servidor descubre automáticamente:
- Tablas y Vistas: Todas las tablas de usuario y opcionalmente vistas
- Columnas: Nombre, tipo de datos, nulabilidad, valores predeterminados, auto-incremento
- Índices: Incluyendo claves primarias y restricciones únicas
- Claves Foráneas: Metadatos explícitos de relaciones
- Relaciones: Tanto explícitas como inferidas
Inferencia de Relaciones
Cuando las claves foráneas no están definidas, el servidor infiere relaciones mediante heurísticas:
- Nombres de columnas que coinciden con
{table}_ido{table}Id - Compatibilidad del tipo de datos con la clave primaria objetivo
- Puntuación de confianza para relaciones inferidas
Estrategia de Caché
- Memoria + Disco: Caché de doble capa para rendimiento
- Basado en TTL: Tiempo de vida configurable
- Seguimiento de Versiones: Versionado basado en contenido (hash)
- Seguro para Concurrencia: Previene introspección duplicada
- Actualización Bajo Demanda: Actualización manual o automática
Seguimiento de Consultas
El servidor mantiene un historial de consultas por base de datos:
- Marca de tiempo y texto SQL
- Tiempo de ejecución y número de filas
- Tablas referenciadas (extracción de mejor esfuerzo)
- Seguimiento de errores
- Estadísticas agregadas
Utilice estos datos para:
- Monitorear el rendimiento de consultas
- Identificar tablas de acceso frecuente
- Detectar patrones de consulta
- Depurar problemas
Desarrollo
# Install dependencies
npm install
# Run in development mode
npm run dev
# Build
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint
npm run lint
# Format code
npm run format
# Type check
npm run typecheck
Estructura del Proyecto
src/
├── adapters/ # Database adapters
│ ├── base.ts # Base adapter class
│ ├── postgres.ts # PostgreSQL adapter
│ ├── mysql.ts # MySQL adapter
│ ├── sqlite.ts # SQLite adapter
│ ├── mssql.ts # SQL Server adapter
│ ├── oracle.ts # Oracle adapter (stub)
│ └── index.ts # Adapter factory
├── cache.ts # Schema caching
├── config.ts # Configuration loader
├── database-manager.ts # Database orchestration
├── logger.ts # Logging setup
├── mcp-server.ts # MCP server implementation
├── query-tracker.ts # Query history tracking
├── types.ts # TypeScript types
├── utils.ts # Utility functions
└── index.ts # Entry point
Agregar Nuevos Adaptadores de Base de Datos
- Implemente la interfaz
DatabaseAdapterensrc/adapters/ - Siga el patrón de los adaptadores existentes
- Agregue a la fábrica de adaptadores en
src/adapters/index.ts - Actualice las definiciones de tipos si es necesario
- Agregue pruebas
Ejemplo:
import { BaseAdapter } from './base.js';
export class CustomAdapter extends BaseAdapter {
async connect(): Promise<void> { /* ... */ }
async disconnect(): Promise<void> { /* ... */ }
async introspect(): Promise<DatabaseSchema> { /* ... */ }
async query(): Promise<QueryResult> { /* ... */ }
async explain(): Promise<ExplainResult> { /* ... */ }
async testConnection(): Promise<boolean> { /* ... */ }
async getVersion(): Promise<string> { /* ... */ }
}
Solución de Problemas
Problemas de Conexión
- Verifique las cadenas de conexión y las credenciales
- Compruebe la conectividad de red y las reglas de firewall
- Habilite el registro de depuración:
"logging": { "level": "debug" } - Utilice la herramienta
health_checkpara probar la conectividad
Problemas de Caché
- Limpiar caché: Utilice la herramienta
clear_cache - Verifique los permisos del directorio de caché
- Verifique la configuración de TTL
- Revise el estado de la caché con la herramienta
cache_status
Rendimiento
- Ajuste la configuración del grupo de conexiones
- Utilice
maxTablespara limitar el alcance de la introspección - Establezca un TTL de caché apropiado
- Habilite el modo de solo lectura cuando sea posible
Configuración de Oracle
El adaptador de Oracle requiere configuración adicional:
- Instale Oracle Instant Client
- Establezca las variables de entorno (
LD_LIBRARY_PATHoPATH) - Instale el paquete
oracledb - Implemente métodos stub en
src/adapters/oracle.ts
Consideraciones de Seguridad
- Utilice siempre el modo de solo lectura en producción a menos que se requiera acceso de escritura
- Utilice variables de entorno para las credenciales, nunca las codifique
- Habilite la redacción de secretos en los registros
- Restrinja las operaciones de escritura con
allowedWriteOperations - Utilice cifrado de cadenas de conexión donde sea compatible
- Auditorías de seguridad periódicas de las configuraciones
Licencia
MIT
Contribuciones
¡Las contribuciones son bienvenidas! Por favor:
- Haga un fork del repositorio
- Cree una rama de funcionalidad
- Agregue pruebas para la nueva funcionalidad
- Asegúrese de que todas las pruebas pasen
- Envíe un pull request
Soporte
Para problemas, preguntas o solicitudes de funciones, abra un issue en GitHub.