# MySQL MCP Server
A lightweight Model Context Protocol (MCP) server for MySQL database operations. Supports multiple named connections and runs in a minimal Docker container.
## Features
- **Multiple Connections**: Manage multiple MySQL connections with unique names
- **Persistent Storage**: Connection configs saved to SQLite (survives restarts)
- **Query Execution**: Execute arbitrary SQL queries with parameterized support
- **Schema Inspection**: List databases, tables, and describe table structures
- **Minimal Footprint**: Alpine-based Docker image (~92MB)
- **Pre-configured Connections**: Optionally load connections from environment variables
## Tools
| Tool | Description |
|------|-------------|
| `add_connection` | Add a new MySQL connection with a unique name |
| `remove_connection` | Remove an existing connection |
| `list_connections` | List all active connections |
| `execute_query` | Execute SQL queries on a named connection |
| `list_databases` | List all databases on a connection |
| `list_tables` | List tables in a database |
| `describe_table` | Get table schema/structure |
## Quick Start
### Build the Docker Image
```bash
docker build -t mysql-mcp .
```
### Run with Docker
```bash
# Run interactively (for MCP stdio communication)
# Mount ./config to persist connection data
docker run -i --rm -v $(pwd)/config:/app/config mysql-mcp
```
### Pre-configure Connections
Set the `MYSQL_CONNECTIONS` environment variable with a JSON array:
```bash
docker run -i --rm \
-v $(pwd)/config:/app/config \
-e MYSQL_CONNECTIONS='[{"name": "prod", "host": "mysql.example.com", "port": 3306, "user": "admin", "password": "secret", "database": "myapp"}]' \
mysql-mcp
```
### Docker Compose
```bash
docker-compose up -d
```
## MCP Configuration
Add to your MCP client configuration (e.g., Claude Desktop):
```json
{
"mcpServers": {
"mysql": {
"command": "docker",
"args": ["run", "-i", "--rm", "-v", "/path/to/config:/app/config", "mysql-mcp"],
"env": {
"MYSQL_CONNECTIONS": "[{\"name\": \"dev\", \"host\": \"host.docker.internal\", \"port\": 3306, \"user\": \"root\", \"password\": \"secret\"}]"
}
}
}
}
```
**Note**: Use `host.docker.internal` to connect to MySQL running on your host machine.
## Usage Examples
### Add a Connection
```json
{
"name": "add_connection",
"arguments": {
"name": "production",
"host": "db.example.com",
"port": 3306,
"user": "app_user",
"password": "secure_password",
"database": "myapp"
}
}
```
### Execute a Query
```json
{
"name": "execute_query",
"arguments": {
"connection": "production",
"query": "SELECT * FROM users WHERE status = %s LIMIT 10",
"params": ["active"]
}
}
```
### List Tables
```json
{
"name": "list_tables",
"arguments": {
"connection": "production",
"database": "myapp"
}
}
```
## Development
### Run Locally (without Docker)
```bash
# Install dependencies
pip install -r requirements.txt
# Run the server
python src/server.py
```
### Test with a Local MySQL
Uncomment the MySQL service in `docker-compose.yml`:
```bash
docker-compose up -d
```
## Persistence
Connection configurations are stored in a SQLite database at `/app/config/connections.db`. Mount a volume to `./config` to persist connections across container restarts:
```bash
docker run -i --rm -v $(pwd)/config:/app/config mysql-mcp
```
The database stores:
- Connection name, host, port, user, password, and default database
## Security Notes
- **Passwords are stored in the SQLite database** - ensure the config directory has appropriate permissions
- Use environment variables for initial seeding; they will be saved to the store
- The container runs as a non-root user (uid 1000)
- Consider using Docker secrets or a vault for sensitive credentials
- Set `MCP_CONFIG_PATH` environment variable to customize the config directory
## License
MIT