A secure MySQL MCP (Model Context Protocol) Server that allows AI tools like Claude Code to safely operate databases in development and testing environments.
- MCP Protocol Support: Full MCP protocol implementation with HTTP transport
- JWT Authentication: Secure token-based authentication
- SQL Security:
- SQL parsing and validation
- Fine-grained DML/DDL control
- Auto LIMIT for dangerous operations
- Query timeout and row limits
- Audit Logging: Complete audit trail with JSON format and log rotation
- Hot Configuration Reload: Update settings without restart
- Prometheus Metrics: Comprehensive observability support
- Docker Support: Production-ready containerization
- CI/CD: GitHub Actions pipeline with automated testing and security scans
# Start with docker-compose (includes MySQL)
docker-compose up -d
# Generate a token
docker exec safemysql-app /app/token -user admin -email admin@example.com -secret your-jwt-secret
# Check health
curl http://localhost:8080/healthmake buildCopy and edit configuration files:
cp config/config.yaml.example config/config.yaml
cp config/security.yaml.example config/security.yamlSet environment variables:
export JWT_SECRET=your-secret-key-min-32-characters
export DEV_DB_USER=your-db-user
export DEV_DB_PASSWORD=your-db-password./bin/mysql-mcp-token --user zhangsan --email zhangsan@company.com --expire 365d./bin/safe-mysql-mcp -config config/config.yaml| Endpoint | Description |
|---|---|
POST /mcp |
MCP JSON-RPC endpoint (requires auth) |
GET /health |
Health check endpoint |
GET /metrics |
Prometheus metrics endpoint |
| Tool | Description |
|---|---|
query |
Execute SQL query on specified database |
list_databases |
List all available databases |
list_tables |
List tables in specified database |
describe_table |
Get table structure |
show_create_table |
Get CREATE TABLE statement |
explain |
Get SQL execution plan |
search_tables |
Search tables by name across databases |
server:
host: 0.0.0.0
port: 8080
jwt_secret: ${JWT_SECRET}
clusters:
dev-cluster-1:
host: mysql.example.com
port: 3306
username: ${DEV_DB_USER}
password: ${DEV_DB_PASSWORD}
databases:
user_db:
cluster: dev-cluster-1
audit:
enabled: true
log_file: logs/audit.log
max_sql_length: 2000
max_size_mb: 100
max_backups: 10
max_age_days: 30
compress: truesecurity:
allowed_dml:
- SELECT
- INSERT
- UPDATE
- DELETE
allowed_ddl:
- CREATE_TABLE
- CREATE_INDEX
- ALTER_TABLE
blocked:
- DROP
- TRUNCATE
auto_limit: 1000
max_limit: 10000
query_timeout: 30s
max_rows: 10000- All SQL statements are parsed and validated
- Dangerous operations (DROP, TRUNCATE, etc.) are blocked
- UPDATE/DELETE without WHERE clause get auto LIMIT
All operations are logged with:
- User identity (from JWT)
- SQL statement (truncated if too long)
- Execution status
- Rows affected
- Duration
Configuration changes are automatically applied:
- Database connections
- Security rules
- Audit settings
Access metrics at /metrics endpoint. Available metrics:
safemysql_http_requests_total- Total HTTP requestssafemysql_http_request_duration_seconds- Request duration histogramsafemysql_http_requests_active- Active requests gauge
safemysql_db_queries_total- Total database queriessafemysql_db_query_duration_seconds- Query duration histogramsafemysql_db_query_rows- Rows returned histogramsafemysql_db_connections_active- Active connectionssafemysql_db_connections_idle- Idle connections
safemysql_security_violations_total- Security violationssafemysql_security_blocked_queries_total- Blocked queriessafemysql_security_sql_injection_attempts_total- SQL injection attempts
safemysql_rate_limit_exceeded_total- Rate limit exceededsafemysql_auth_attempts_total- Authentication attemptssafemysql_auth_failures_total- Authentication failures
safemysql_mcp_calls_total- MCP tool callssafemysql_mcp_call_duration_seconds- MCP call durationsafemysql_mcp_errors_total- MCP errors
- Go 1.22+
- MySQL 5.7+ (or use Docker)
- Docker (optional, for containerized development)
# Run all tests with coverage
make test
# Run with race detection
go test ./... -race -cover
# Run specific package tests
go test ./internal/security/... -vmake lint
# or
golangci-lint run# Build and run with MySQL
docker-compose up -d
# View logs
docker-compose logs -f app
# Stop services
docker-compose downThe project includes GitHub Actions workflows for:
- Build & Test: Runs on Go 1.22, 1.23, 1.24
- Lint: golangci-lint with 25+ linters
- Security Scan: Gosec vulnerability scanner
See docs/openapi.yaml for the complete OpenAPI specification.
SafeMySQLMcpServer provides secure MySQL access through MCP protocol with SQL injection prevention and audit logging.
┌─────────────────────────────────────────────────────────────────────────────┐
│ AI Client (Claude Code) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ HTTP Server (:8080) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ JWT Auth │→ │ Rate Limit │→ │ Metrics │→ │ MCP Handler │ │
│ │ Middleware │ │ Middleware │ │ Middleware │ │ (7 MCP Tools) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ Endpoints: │ │
│ • POST /mcp MCP JSON-RPC │ │
│ • GET /health Health check │ │
│ • GET /metrics Prometheus metrics │ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Security Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ SQL Parser │→ │ Security │→ │ SQL Rewriter│→ │ Input Validator │ │
│ │ (vitess) │ │ Checker │ │ (auto-LIMIT)│ │ (identifier regex) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ Security Rules: │ │
│ • DML/DDL allowlist │ │
│ • Blocked operations (DROP, TRUNCATE) │ │
│ • Query timeout & row limits │ │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ Database Router │ │ Audit Logger │ │ Prometheus Metrics │
│ ┌─────────────────┐ │ │ ┌─────────────────┐ │ │ ┌─────────────────┐ │
│ │ Connection Pool │ │ │ │ JSON Logs │ │ │ │ HTTP Metrics │ │
│ │ (per cluster) │ │ │ │ Rotation │ │ │ │ DB Metrics │ │
│ └─────────────────┘ │ │ │ Compression │ │ │ │ Security Stats │ │
│ │ │ └─────────────────┘ │ │ └─────────────────┘ │
│ Clusters: │ │ │ │ │
│ • dev-cluster-1 │ │ Logs: │ │ Exposed: │
│ • dev-cluster-2 │ │ • User identity │ │ • /metrics endpoint │
│ • ... │ │ • SQL statement │ │ • scrape interval │
└───────────────────────┘ │ • Status/Duration │ └───────────────────────┘
│ └───────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ MySQL Clusters │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ dev-cluster-1 │ │ dev-cluster-2 │ │ ... │ │
│ │ :3306 │ │ :3306 │ │ │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │───▶│ JWT Auth │───▶│ Rate │───▶│ MCP │───▶│ Security │
│ Request │ │ (verify) │ │ Limit │ │ Handler │ │ Check │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
│ ▼
│ ┌──────────┐
│ │ Blocked? │
│ └──────────┘
│ │
│ ┌─────┴─────┐
│ │ │
│ ▼ ▼
│ ┌─────────┐ ┌─────────┐
│ │ Allow │ │ Reject │
│ └─────────┘ └─────────┘
│ │
▼ ▼
┌──────────────────────┐
│ Database Router │
│ (execute query) │
└──────────────────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ MySQL │ │ Audit │ │ Metrics │
│ Cluster │ │ Logger │ │ Recorder │
└─────────────┘ └─────────────┘ └─────────────┘
1. Client sends: { "tool": "query", "database": "mydb", "sql": "SELECT * FROM users" }
│
▼
2. JWT Middleware: Extract user_id, user_email from token → add to context
│
▼
3. Rate Limiter: Check IP-based rate limit (default: 100 req/min)
│
▼
4. MCP Handler:
a. Validate database name: "mydb" → regex check
b. Validate SQL: "SELECT * FROM users" → length check
c. Parse SQL: vitess parser → AST
d. Security check: SELECT is allowed? → Yes
e. Get database connection from router
f. Execute query with timeout
g. Collect results (max 10000 rows)
│
▼
5. Audit Logger: Log { user_id, database, sql, status, duration_ms, rows_affected }
│
▼
6. Response: { "columns": [...], "rows": [...], "rows_affected": N }
| Module | Description | Doc |
|---|---|---|
| cmd/server | Application entry point | README |
| internal/auth | JWT authentication and token generation | README |
| internal/config | Configuration loading and hot reload | README |
| internal/database | MySQL connection pool and routing | README |
| internal/mcp | MCP protocol implementation and tools | README |
| internal/metrics | Prometheus metrics collection | README |
| internal/security | SQL parsing, validation, and rewriting | README |
| internal/server | HTTP server with middleware | README |
| internal/audit | Audit logging with rotation | README |
| internal/validation | Input validation utilities | README |
| internal/constants | Shared constants | README |
| pkg/token | CLI tool for generating JWT tokens | README |