MySQL MCP

Servidor MCP para MySQL/MariaDB: inspección de esquemas, consultas y manipulación de datos para asistentes de IA

Documentación

Servidor MySQL MCP

Una implementación de servidor de Protocolo de Contexto de Modelo (MCP) de alta calidad para bases de datos MySQL. Este servidor permite que asistentes de IA como Claude interactúen con bases de datos MySQL a través de un protocolo estandarizado.

Versión: 0.2.0 | Protocolo: MCP 2025-03-26 | Rust: 1.70+ | Estado: Listo para producción

Tabla de Contenidos

Características

  • Inspección de Esquemas: Recupera esquemas de tablas e información de estructura
  • Ejecución de Consultas: Ejecuta consultas SQL (solo lectura por defecto por seguridad)
  • Manipulación de Datos: Operaciones de inserción, actualización y eliminación
  • Contexto de Base de Datos: Especifica qué base de datos usar en cada consulta
  • Controles de Seguridad: Restricciones de consultas configurables para prevenir operaciones peligrosas
  • Gestión de Conexiones: Manejo robusto de conexiones con lógica de reintentos y agrupación
  • Manejo de Errores: Reporte integral de errores con mensajes detallados
  • Protocolo JSON-RPC 2.0: Comunicación estandarizada a través de stdio

Instalación

Requisitos Previos

  • Rust 1.70+
  • MySQL 5.7+ o MariaDB 10.2+
  • Acceso a una base de datos MySQL

Compilación desde el Código Fuente

git clone <repository-url>
cd mcp-server-mysql
cargo build --release

El binario compilado estará disponible en target/release/mcp-server-mysql.

Desde el Paquete de Versión

# Extract the package
tar -xzf mcp-server-mysql-v0.2.0-linux-x86_64.tar.gz

# Move binary to system path (optional)
sudo cp mcp-server-mysql /usr/local/bin/

# Verify installation
mcp-server-mysql --version

Inicio Rápido (5 Minutos)

Paso 1: Compilar el Servidor

cargo build --release

El binario estará en target/release/mcp-server-mysql

Paso 2: Probar la Conexión

./target/release/mcp-server-mysql \
  --host localhost \
  --username root \
  --password yourpassword \
  --database testdb

Deberías ver: "MCP MySQL Server started and ready to accept connections"

Paso 3: Configurar Claude Desktop

Edita tu archivo de configuración de Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Añade esta configuración:

{
  "mcpServers": {
    "mysql": {
      "command": "/absolute/path/to/mcp-server-mysql",
      "args": [
        "--host", "localhost",
        "--port", "3306",
        "--username", "your_username",
        "--password", "your_password",
        "--database", "your_database"
      ]
    }
  }
}

Nota de Seguridad: Para uso en producción, considera usar variables de entorno o una solución segura de gestión de secretos en lugar de codificar contraseñas en el archivo de configuración.

Paso 4: Reiniciar Claude Desktop

Cierra y vuelve a abrir Claude Desktop por completo. Deberías ver un pequeño ícono de martillo indicando que el servidor MCP está conectado.

Paso 5: ¡Pruébalo!

Pregúntale a Claude:

  • "¿Puedes mostrarme el esquema de la tabla users en mi base de datos MySQL?"
  • "Consulta la base de datos y muéstrame las primeras 10 filas de la tabla products"
  • "¿Qué tablas hay en mi base de datos?"

Uso

Argumentos de Línea de Comandos

mcp-server-mysql \
  --host localhost \
  --port 3306 \
  --username your_username \
  --password your_password \
  --database your_database \
  --allow-dangerous-queries false

Referencia de Argumentos

ArgumentoDescripciónValor PredeterminadoRequerido
--hostHostname del servidor MySQLlocalhostNo
--portPuerto del servidor MySQL3306No
--usernameNombre de usuario de MySQL-
--passwordContraseña de MySQL (vacía)No
--databaseNombre de la base de datos a la que conectarse-
--allow-dangerous-queriesPermitir consultas INSERT/UPDATE/DELETEfalseNo

Configuración con Claude Desktop

Añade esta configuración a tu archivo de configuración de Claude Desktop:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "mysql": {
      "command": "/path/to/mcp-server-mysql",
      "args": [
        "--host", "localhost",
        "--port", "3306",
        "--username", "your_username",
        "--password", "your_password",
        "--database", "your_database"
      ]
    }
  }
}

Herramientas Disponibles

1. mysql (Inspección de Esquemas)

Recupera información del esquema de la base de datos para tablas.

Parámetros:

  • table_name (cadena): Nombre de la tabla a inspeccionar, o "all-tables" para obtener todos los esquemas de tablas

Ejemplo:

{
  "table_name": "users"
}

Devuelve:

  • Información de columnas (nombre, tipo, nullable, valores predeterminados, claves)
  • Información de índices
  • Restricciones de tablas

2. query (Ejecución de SQL)

Ejecuta consultas SQL en la base de datos.

Parámetros:

  • query (cadena): Consulta SQL a ejecutar
  • database (cadena, opcional): Nombre de la base de datos a usar para esta consulta específica

Ejemplo:

{
  "query": "SELECT * FROM users WHERE active = 1 LIMIT 10",
  "database": "my_database"
}

Seguridad:

  • Por defecto, solo se permiten consultas SELECT
  • Usa la bandera --allow-dangerous-queries para habilitar INSERT/UPDATE/DELETE
  • Las palabras clave peligrosas están bloqueadas a menos que se habiliten explícitamente

3. insert (Insertar Datos)

Inserta datos en una tabla especificada.

Parámetros:

  • table_name (cadena): Nombre de la tabla
  • data (objeto): Pares clave-valor de nombres de columnas y valores

Ejemplo:

{
  "table_name": "users",
  "data": {
    "username": "john_doe",
    "email": "john@example.com",
    "active": true
  }
}

Devuelve: ID de la última inserción

4. update (Actualizar Datos)

Actualiza datos en una tabla especificada según condiciones.

Parámetros:

  • table_name (cadena): Nombre de la tabla
  • data (objeto): Pares clave-valor de columnas a actualizar
  • conditions (objeto): Pares clave-valor para la cláusula WHERE

Ejemplo:

{
  "table_name": "users",
  "data": {
    "email": "newemail@example.com",
    "updated_at": "2024-01-15 10:30:00"
  },
  "conditions": {
    "id": 123
  }
}

Devuelve: Número de filas afectadas

5. delete (Eliminar Datos)

Elimina datos de una tabla especificada según condiciones.

Parámetros:

  • table_name (cadena): Nombre de la tabla
  • conditions (objeto): Pares clave-valor para la cláusula WHERE

Ejemplo:

{
  "table_name": "users",
  "conditions": {
    "id": 123
  }
}

Devuelve: Número de filas afectadas

Advertencia: ¡Siempre especifica condiciones para evitar eliminar todas las filas!

Función de Contexto de Base de Datos

El Problema

Anteriormente, el contexto de la base de datos no se mantenía entre consultas:

-- Query 1
USE dev_database;  -- Succeeds

-- Query 2 (new connection from pool)
SELECT * FROM my_table;  -- ❌ Fails: context was lost

La Solución

Usa el parámetro opcional database en cada consulta:

{
  "query": "SELECT * FROM my_table",
  "database": "dev_database"
}

Beneficios

  1. Explícito y Claro: Sabes exactamente qué base de datos usa cada consulta
  2. Sin Estado Oculto: Cada consulta es independiente
  3. Compatibilidad Retroactiva: Las consultas existentes sin el parámetro siguen funcionando
  4. Sin Condiciones de Carrera: Cada consulta obtiene su propia conexión
  5. Fácil de Usar: Solo añade "database": "name" a los argumentos de la consulta

Ejemplos de Uso

Consulta Básica con Parámetro de Base de Datos

{
  "query": "SELECT * FROM crm_sites LIMIT 10",
  "database": "dev_smartConnect_za"
}

Consulta Sin Parámetro de Base de Datos (Usa la Predeterminada)

{
  "query": "SELECT * FROM users WHERE active = 1"
}

Usa la base de datos especificada en el argumento de inicio --database.

Múltiples Bases de Datos en la Misma Sesión

// Query database 1
{
  "query": "SELECT COUNT(*) FROM customers",
  "database": "production_db"
}

// Query database 2
{
  "query": "SELECT COUNT(*) FROM test_data",
  "database": "test_db"
}

Antes vs Después

Antes (Se requerían nombres completamente calificados):

SELECT * FROM dev_smartConnect_za.crm_sites
  JOIN dev_smartConnect_za.crm_orgs ON ...
WHERE dev_smartConnect_za.crm_sites.active = 1;

Después (Limpio y simple):

{
  "query": "SELECT * FROM crm_sites JOIN crm_orgs ON ... WHERE active = 1",
  "database": "dev_smartConnect_za"
}

Escenarios Comunes

Escenario 1: Proyecto de Una Sola Base de Datos

Establece la base de datos predeterminada y omite el parámetro:

# Startup
--database my_project_db

# Query (no database parameter needed)
{
  "query": "SELECT * FROM users"
}

Escenario 2: Proyecto de Múltiples Bases de Datos

Especifica la base de datos para cada consulta:

// Customer database
{ "query": "...", "database": "customers_db" }

// Orders database
{ "query": "...", "database": "orders_db" }

// Analytics database
{ "query": "...", "database": "analytics_db" }

Manejo de Errores

Código de Error -32005: Fallo en la Adquisición de Conexión

Cause: Connection pool exhausted
Solution: Retry after a moment

Código de Error -32006: Fallo en el Cambio de Contexto de Base de Datos

Cause: Database doesn't exist or user lacks permissions
Solution: Verify database exists and user has access

Mejores Prácticas

HACER

  • Especifica la base de datos explícitamente para consultas de producción
  • Usa nombres descriptivos de bases de datos en tus consultas
  • Prueba con SELECT DATABASE() para verificar el contexto
  • Agrupa las consultas por base de datos para mayor claridad

NO HACER

  • Mezclar nombres calificados y no calificados en la misma consulta
  • Asumir persistencia: especifica la base de datos en cada consulta
  • Usar caracteres especiales en los nombres de bases de datos si es posible
  • Olvidar verificar los permisos de usuario para todas las bases de datos

Consideraciones de Seguridad

Modo de Solo Lectura (Predeterminado)

Por defecto, el servidor opera en modo de solo lectura, permitiendo únicamente consultas SELECT. Esto evita la modificación o eliminación accidental de datos.

Modo de Consultas Peligrosas

Habilita operaciones de escritura con --allow-dangerous-queries:

mcp-server-mysql --username user --password pass --database mydb --allow-dangerous-queries true

¡Úsalo con precaución! Esto habilita:

  • Sentencias INSERT
  • Sentencias UPDATE
  • Sentencias DELETE
  • Otras operaciones potencialmente destructivas

Protección contra Inyección SQL

  • Los nombres de tablas se validan para contener solo caracteres alfanuméricos y guiones bajos
  • Todos los valores de datos se parametrizan usando sentencias preparadas
  • Los nombres de bases de datos se escapan reemplazando los acentos graves con acentos graves dobles
  • No se realiza concatenación de SQL sin procesar

Seguridad de la Conexión

  • Soporta conexiones SSL/TLS estándar de MySQL
  • Las cadenas de conexión se pueden configurar de forma segura
  • Las contraseñas se pueden proporcionar mediante variables de entorno
  • Considera usar usuarios de base de datos dedicados con permisos limitados

Seguridad en la Implementación de Producción

  1. Usa un usuario de base de datos dedicado:

    CREATE USER 'mcp_user'@'localhost' IDENTIFIED BY 'secure_password';
    GRANT SELECT ON your_database.* TO 'mcp_user'@'localhost';
    FLUSH PRIVILEGES;
    
  2. Habilita el acceso de escritura solo cuando sea necesario:

    --allow-dangerous-queries true  # Use with caution!
    
  3. Usa variables de entorno (mejora futura): Considera envolver el binario en un script de shell que lea las variables de entorno.

Arquitectura

Descripción General del Sistema

┌─────────────────────────────────────────────────────┐
│           MCP Client (e.g., Claude)                 │
│  Sends: {query, database}                           │
└────────────────────────┬────────────────────────────┘
                         │ JSON-RPC 2.0 (stdio)
                         ▼
┌─────────────────────────────────────────────────────┐
│      MCP MySQL Server (Rust)                        │
│                                                      │
│  execute_query(query, database, pool)               │
│  ├─ If database param:                              │
│  │  ├─ Acquire connection from pool                 │
│  │  ├─ Execute: USE `database`                      │
│  │  └─ Execute: [user's query]                      │
│  └─ Else:                                           │
│     └─ Execute query on pool (default database)     │
└────────────────────────┬────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────┐
│      MySQL Connection Pool (5 connections)          │
└────────────────────────┬────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────┐
│      MySQL/MariaDB Server                           │
└─────────────────────────────────────────────────────┘

Secuencia: Consulta con Parámetro de Base de Datos

Client          MCP Server       Connection Pool      MySQL Server
  │                 │                    │                  │
  │  query +        │                    │                  │
  │  database       │                    │                  │
  ├────────────────>│                    │                  │
  │                 │                    │                  │
  │                 │ acquire()          │                  │
  │                 ├───────────────────>│                  │
  │                 │ <connection>       │                  │
  │                 │<───────────────────┤                  │
  │                 │                    │                  │
  │                 │ USE database       │                  │
  │                 ├────────────────────┼─────────────────>│
  │                 │ OK                 │                  │
  │                 │<────────────────────┼──────────────────┤
  │                 │                    │                  │
  │                 │ SELECT query       │                  │
  │                 ├────────────────────┼─────────────────>│
  │                 │ Results            │                  │
  │                 │<────────────────────┼──────────────────┤
  │                 │                    │                  │
  │                 │ release()          │                  │
  │                 ├───────────────────>│                  │
  │  Results        │                    │                  │
  │<────────────────┤                    │                  │

Gestión del Pool de Conexiones

Pool (5 connections)
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
│ C1 │ │ C2 │ │ C3 │ │ C4 │ │ C5 │
└────┘ └────┘ └────┘ └────┘ └────┘

Key Properties:
• Each query gets its own connection instance
• Database context is set per connection, per query
• No state persists between queries
• Fully thread-safe and concurrent

Detalles Técnicos

  • Versión del Protocolo: MCP 2025-03-26
  • Transporte: stdio (JSON-RPC 2.0)
  • Agrupación de Conexiones: Máximo 5 conexiones
  • Lógica de Reintentos: Reconexión automática en fallos transitorios
  • Sobrecarga de Rendimiento: ~50-200 microsegundos por consulta con parámetro de base de datos

Solución de Problemas

Fallos de Conexión

Si encuentras errores de conexión:

  1. Verifica que MySQL esté en ejecución:

    mysql -h localhost -u your_username -p
    
  2. Verifica las credenciales:

    • Asegúrate de que el nombre de usuario y la contraseña sean correctos
    • Confirma que el usuario tenga acceso a la base de datos especificada
  3. Verifica el acceso a la red:

    • Verifica que el host y el puerto sean correctos
    • Asegúrate de que ningún firewall esté bloqueando la conexión
  4. Revisa los registros del servidor:

    • El servidor registra en stderr
    • Busca mensajes de error detallados

Errores Comunes

"Database connection failed"

  • El servidor MySQL puede no estar en ejecución
  • Configuración incorrecta de host/puerto
  • Problemas de conectividad de red

"Only SELECT queries are allowed"

  • Estás intentando ejecutar una consulta de escritura en modo de solo lectura
  • Añade --allow-dangerous-queries true si se necesita acceso de escritura

"No database selected"

  • La base de datos especificada no existe
  • El usuario no tiene acceso a la base de datos
  • Verifica con SHOW DATABASES; para ver las bases de datos disponibles

"Table doesn't exist"

  • Verifica que estás consultando la base de datos correcta
  • Añade el parámetro database si usas múltiples bases de datos
  • Usa SELECT DATABASE() para verificar el contexto actual

"Failed to acquire connection"

  • El pool de conexiones está agotado
  • Espera un momento y reintenta

La herramienta no aparece en Claude Desktop

  1. Verifica que la ruta al binario sea absoluta (no relativa)
  2. Revisa los registros de Claude Desktop para ver errores
  3. Reinicia Claude Desktop por completo (no solo recargar)
  4. Asegúrate de que el proceso del servidor se inicie sin errores cuando se ejecuta manualmente

Desarrollo

Estructura del Proyecto

mcp-server-mysql/
├── src/
│   ├── main.rs          # Main server implementation
│   ├── config.rs        # Configuration handling
│   ├── db.rs            # Database operations
│   ├── rpc.rs           # RPC protocol handling
│   └── server.rs        # Server initialization
├── tests/               # Test files
├── Cargo.toml           # Rust dependencies
├── Cargo.lock          # Locked dependency versions
└── README.md           # This file

Compilación para Desarrollo

cargo build
cargo run -- --help

Ejecución de Pruebas

cargo test

Calidad del Código

# Format code
cargo fmt

# Run linter
cargo clippy

# Check for issues
cargo check

Convenciones de Desarrollo

El proyecto sigue las mejores prácticas estándar de Rust:

  • Formato de código: cargo fmt
  • Linting: cargo clippy
  • Pruebas: cargo test

Guía de Implementación

Implementación Rápida

1. Probar la Conexión

./mcp-server-mysql \
  --username your_user \
  --password your_pass \
  --database your_db

Presiona Ctrl+C para salir después de ver "MCP MySQL Server started".

2. Configurar Claude Desktop

Edita tu archivo de configuración de Claude y añade la configuración del servidor (consulta la sección de Inicio Rápido).

3. Reiniciar Claude Desktop

Cierra y vuelve a abrir Claude Desktop por completo.

Consejos para Implementación en Producción

Rendimiento

  • El binario está optimizado con la bandera --release
  • La agrupación de conexiones está configurada (máximo 5 conexiones)
  • Lógica de reintento automático para fallos transitorios

Monitoreo

Los registros del servidor van a stderr. Captúralos con:

./mcp-server-mysql --username user --password pass --database db 2>> server.log

Niveles de registro:

  • INFO: Eventos de conexión, llamadas a herramientas
  • DEBUG: Información detallada de consultas
  • WARN: Problemas no fatales
  • ERROR: Fallos y errores

Servicio Systemd (Opcional)

Para implementaciones de larga duración, crea /etc/systemd/system/mcp-mysql.service:

[Unit]
Description=MySQL MCP Server
After=network.target mysql.service

[Service]
Type=simple
User=mcp-user
ExecStart=/usr/local/bin/mcp-server-mysql --username mcp_user --password secret --database production
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Habilita e inicia:

sudo systemctl enable mcp-mysql
sudo systemctl start mcp-mysql
sudo systemctl status mcp-mysql

Actualización

# Backup current version
cp /usr/local/bin/mcp-server-mysql /usr/local/bin/mcp-server-mysql.backup

# Replace with new version
cp mcp-server-mysql /usr/local/bin/

# Restart services
sudo systemctl restart mcp-mysql  # If using systemd
# Or restart Claude Desktop

Reversión

# Restore previous version
cp /usr/local/bin/mcp-server-mysql.backup /usr/local/bin/mcp-server-mysql

# Or checkout previous git tag
git checkout v0.1.0
cargo build --release

Contribuciones

¡Las contribuciones son bienvenidas! Por favor asegúrate de:

  • Que el código siga las mejores prácticas de Rust
  • Que todas las pruebas pasen
  • Que la documentación esté actualizada
  • Que los mensajes de commit sean claros y descriptivos

Licencia

Apache-2.0

Soporte

Para problemas, preguntas o contribuciones, abre un issue en el repositorio del proyecto.


Versión: 0.2.0 | Fecha de Lanzamiento: 2025-01-XX | Protocolo: MCP 2025-03-26 | Plataforma: Linux x86_64 | Estado: Listo para Producción ✅