Skip to main content
Glama
araxiaonline

MySQL MCP Server

by araxiaonline
README.md
# 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