The mysql-mcp server protects your databases. It secures stdio, HTTP, and SSE transports.
MySQL MCP is a production-ready integration engineered for AI agents. It minimizes LLM token consumption by up to 90% via sandboxed Code Mode. It scales reliably through built-in connection pooling. It secures database access using strict OAuth 2.1 validation.
Identifier Sanitization (src/utils/identifiers.ts)
- β Comprehensive coverage β validates and quotes all table, column, schema, and index names across all 28 tool groups.
- β MySQL identifier rules enforced β start with letter/underscore, contain only alphanumerics, underscores, or $ signs
- β 64-character limit enforced (MySQL maximum)
- β
Invalid identifiers throw
InvalidIdentifierError
Key functions:
sanitizeIdentifier(name)β Validates and double-quotes an identifiersanitizeTableName(table, schema?)β Handles schema-qualified table referencessanitizeColumnRef(column, table?)β Handles column references with optional table qualifiersanitizeIdentifiers(names[])β Batch sanitization for column lists
Parameterized Queries
- β
All user-provided values use parameterized queries via
mysql2library - β Identifier sanitization complements parameterized values β defense in depth
Every tool returns structured error responses β never raw exceptions or internal details:
{
"success": false,
"error": "Descriptive message with context",
"code": "MODULE_ERROR_CODE",
"category": "VALIDATION_ERROR",
"suggestion": "Actionable remediation hint",
"recoverable": true
}Error logic leverages the MySQLMcpError hierarchy (9 distinct categories). It returns enriched payloads via formatHandlerError(). Error codes are module-prefixed. Internal stack traces are logged server-side but never exposed to clients.
- β Zod schemas β all tool inputs validated at tool boundaries before database operations
- β Parameterized queries used throughout β never string interpolation
- β Audit filters required β audit log queries must provide at least one filter to prevent mass data extraction
- β Data masking aliases β validated strictly at the MCP boundary to prevent evasion
- β Identifier sanitization β table, column, schema, and index names validated against injection
A dedicated security sandbox strictly confines all file I/O operations exposed by the server. This includes MySQL Shell operations and Audit Subsystem snapshots.
- β
ALLOWED_IO_ROOTSEnforcement β operations must target absolute paths within administrator-configured directories. HTTP transports hard-fail on startup if omitted. - β
Path Traversal Prevention β blocks directory traversal sequences (
..), null bytes, and query parameters in path inputs. - β
Symlink Awareness β resolves and asserts
realpathto prevent escaping the sandbox via symlink targets. - β Hidden Files Protection β rejects dotfiles and hidden directories (unless explicitly authorized by the root config).
- β
Drive Letter Validation β fully cross-platform compatible with strict Windows drive letter (
C:\) and UNC path checking.
Code Mode executes user-provided JavaScript in a hardened isolated-vm sandbox. This includes multiple layers of defense-in-depth and fleet-standard restrictions. These features are detailed prominently in the README.md.
- β Strict V8 Isolate Boundary β executes within a physically separate V8 isolate. It ensures native objects and prototypes cannot cross the boundary.
- β Memory & CPU Constraints β enforced at the C++ level. This includes synchronous timeouts and strict heap limits.
- β
API Bindings via Reference β all MySQL API methods are securely injected into the isolate using
ivm.Referencewrappers.
- β
29 blocked patterns β regex rules block
require(),import(),eval(),process, and__proto__. They also block filesystem/network access and system commands. - β Unicode & Comment Sanitization β performs NFKC normalization and strips all comments before pattern validation to prevent regex evasion.
- β 50KB code input limit β prevents payload-based resource exhaustion.
- β RPC Quotas β strict cap of 100 API calls per execution to prevent unbounded loops.
- β Execution timeout β 30s hard limit (not configurable, enforced by the isolate engine) to prevent resource exhaustion.
- β
Egress boundary enforcement β streaming
JSON.stringifyserialization aborts mid-flight when exceeding size caps (default 100KB). - β
Rate limiting β 60 executions per minute per client. Distributed across deployments via Redis if
REDIS_URLis provided, with graceful in-memory fallback. - β
Readonly enforcement β when
readonly: true, write methods return structured errors instead of executing. - β Audit logging β every execution logged with UUID, client ID, metrics, and redacted code preview.
- β
Admin scope β Code Mode requires
adminscope when OAuth is enabled.
When running in HTTP mode (--transport http), the following security measures apply:
- β
DNS Rebinding Protection β
validateHostHeader()strictly validatesHostheaders - β X-Content-Type-Options: nosniff β prevents MIME sniffing
- β X-Frame-Options: DENY β prevents clickjacking
- β Content-Security-Policy: default-src 'none'; frame-ancestors 'none' β prevents XSS and framing
- β Cache-Control: no-store, no-cache, must-revalidate β prevents caching of sensitive data
- β Referrer-Policy: no-referrer β prevents referrer leakage
- β Permissions-Policy: camera=(), microphone=(), geolocation=() β restricts browser APIs
- β Strict-Transport-Security header for HTTPS deployments
- β
Enable via
--enable-hstsflag orMCP_ENABLE_HSTS=true
- β
Origin whitelist with
Vary: Originheader for caching - β
Optional credentials support (
corsAllowCredentials) - β
MCP-specific headers allowed (
X-Session-ID,mcp-session-id)
- β
Built-in Rate Limiting β 100 requests/minute per IP. Distributed across deployments via Redis if
REDIS_URLis provided, with graceful in-memory fallback. - β
Health Endpoint Bypass β
/healthbypasses limits to ensure reliable load balancer checks - β
Returns 429 Too Many Requests with proper
Retry-Afterheaders when limits are exceeded - β
Slowloris DoS Protection β configurable read timeouts via
MCP_REQUEST_TIMEOUTandMCP_HEADERS_TIMEOUT
Reverse Proxy Note: The server uses
req.socket.remoteAddressfor rate limiting. Behind a reverse proxy (e.g., nginx, Cloudflare Tunnel), all requests may share the same source IP. You must ensure your proxy forwards distinct client IPs. Alternatively, you can apply rate limiting at the proxy layer instead.
- β Memory Exhaustion Protection β Strict request bounds prevent memory exhaustion DoS
Full OAuth 2.1 for production multi-tenant deployments is supported. These enterprise security features are detailed prominently in the README.md.
- β
RFC 9728 Protected Resource Metadata (
/.well-known/oauth-protected-resource) - β RFC 8414 Authorization Server Discovery with caching
- β RFC 7591 OAuth 2.1 Dynamic Client Registration
- β JWT validation with JWKS support (TTL: 1 hour, configurable)
- β
MySQL-specific scopes:
read,write,admin,full,db:{name},schema:{name},table:{schema}:{table} - β
Per-tool scope enforcement via
AsyncLocalStoragecontext threading
β οΈ HTTP without OAuth: When OAuth is not configured, all scope checks are bypassed. If you expose the HTTP transport without enabling OAuth, any client has full unrestricted access. Always enable OAuth for production HTTP deployments.
- β
Dedicated user:
app(UID 1001) with minimal privileges - β
Restricted group:
app(GID 1001) - β
Restricted data directory:
700permissions
- β
Minimal base image:
node:24-alpine - β Multi-stage build: Build dependencies not in production image
- β
Production pruning:
npm prune --omit=devafter build - β
Health check: Built-in
HEALTHCHECKinstruction (transport-aware for HTTP/SSE/stdio) - β Process isolation from host system
The Dockerfile patches npm-bundled transitive dependencies for Docker Scout compliance:
- β
cross-spawnβ CVE-2024-21538 - β
globβ CVE-2025-64756 - β
@isaacs/brace-expansion@5.0.1β CVE-2025-5889 - β
tar@7.5.19β CVE-2026-26960 - β
minimatch@10.2.5β CVE-2026-27904, CVE-2026-27903
# Secure volume mounting
docker run -v ./data:/app/data:rw,noexec,nosuid,nodev writenotenow/mysql-mcp:latest# Apply resource limits
docker run --memory=1g --cpus=1 writenotenow/mysql-mcp:latest- β Full JSONL Audit Trails β comprehensive logging array capturing mutations, Code Mode executions, and system events
- β Session Token Estimates β robust burn-rate tracking appended to log entries
- β Pre-Mutation Snapshots β interceptor captures table states before destructive administration operations
- β
Sensitive fields automatically redacted in logs:
password,secret,token,apikey,issuer,audience,jwksUri,credentials, etc. - β Recursive sanitization for nested objects
- β Control character sanitization (ASCII 0x00-0x1F except tab/newline, 0x7F, C1 characters)
- β Prevents log forging and escape sequence attacks
- β CodeQL analysis β automated static analysis on push/PR
- β pnpm audit β dependency vulnerability checking (audit-level: moderate)
- β Dependabot β automated dependency update PRs (weekly for npm and GitHub Actions)
- β Secrets scanning β dedicated workflow for leaked credential detection
- β E2E transport parity β Playwright suite validates HTTP/SSE security behavior
- Never commit database credentials to version control β use environment variables
- Use OAuth 2.1 authentication for HTTP transport in production β never expose HTTP transport without OAuth
- Restrict database user permissions to minimum required
- Enable SSL for database connections in production (
ssl=truein connection string) - Enable HSTS when running over HTTPS (
--enable-hsts) - Configure CORS origins explicitly β avoid wildcards
- Use resource limits β apply Docker
--memoryand--cpuslimits - Apply rate limiting at the proxy layer when deploying behind a reverse proxy
- Consider SHA-pinning critical GitHub Actions in CI workflows for supply-chain defense-in-depth
- Parameterized queries only β never interpolate user input into SQL strings
- Zod validation β all tool inputs validated via schemas at tool boundaries
- No secrets in code β use environment variables (
.envfiles are gitignored) - Typed error classes β descriptive messages with context; don't expose internals
- Regular updates β keep Node.js and npm dependencies updated
- Security scanning β regularly scan Docker images for vulnerabilities
- Parameterized SQL queries throughout
- Identifier sanitization (table, column, schema, index names)
- Input validation via Zod schemas
- Filesystem boundary sandbox (
ALLOWED_IO_ROOTS) for all file I/O operations - Code Mode sandbox isolation (true separate V8 isolate via isolated-vm)
- Code Mode V8 codeGeneration restrictions (eval/Function disabled at engine level)
- Code Mode native prototype isolation (objects cannot cross isolate boundary)
- Code Mode blocked patterns (29 static regex rules + Unicode/NFKC validation)
- Code Mode RPC quotas (100 calls per execution)
- Code Mode streaming egress boundary (abort serialization on oversized results)
- Code Mode execution timeout (30s hard limit)
- Code Mode rate limiting (60 executions/min, Redis-backed with in-memory fallback)
- Code Mode audit logging
- HTTP bounds limits
- Configurable CORS with origin whitelist
- Rate limiting (100 req/min per IP, Redis-backed with in-memory fallback)
- Slowloris DoS timeouts (
MCP_REQUEST_TIMEOUT,MCP_HEADERS_TIMEOUT) - DNS rebinding protection via Host header validation
- Security headers (CSP, X-Content-Type-Options, X-Frame-Options, Cache-Control, Referrer-Policy, Permissions-Policy)
- HSTS (opt-in)
- OAuth 2.1 with JWT/JWKS validation (RFC 9728, RFC 8414)
- MySQL-specific scope enforcement (
read,write,admin,full,db:*,schema:*,table:*:*) - Per-tool scope enforcement via
AsyncLocalStorage - Credential redaction in logs
- Log injection prevention
- Non-root Docker user
- Multi-stage Docker build with production pruning
- Transitive dependency CVE patching in Dockerfile
- CI/CD security pipeline (CodeQL, pnpm audit, secrets scanning)
- Structured error responses (no internal details leaked)
- Comprehensive security documentation
| Version | Supported |
|---|---|
| 3.x.x | β |
| 2.x.x | β |
| 1.x.x | β |
| < 1.0 | β |
If you discover a security vulnerability:
- Do not open a public GitHub issue
- Email security concerns to: admin@adamic.tech
- Include detailed reproduction steps and potential impact
- Allow reasonable time for a fix before public disclosure
- Initial Response: Within 48 hours
- Status Update: Within 7 days
- Fix Timeline: Depends on severity
We appreciate responsible disclosure and will acknowledge your contribution in our release notes (unless you prefer to remain anonymous).
- Container updates: Rebuild Docker images when base images are updated
- Dependency updates: Keep npm packages updated via
pnpm auditand Dependabot - Database maintenance: Run
OPTIMIZE TABLEandANALYZE TABLEregularly for optimal performance - Security patches: Apply host system security updates
The mysql-mcp server is designed with security-first principles. It protects your databases. It maintains excellent performance and full MySQL capability.