-
Notifications
You must be signed in to change notification settings - Fork 2
HTTP Transport
Value Proposition Scale your enterprise deployments securely with the streamable HTTP transport. Purpose-built for cloud-native environments, it delivers OAuth 2.1 security, robust connection pooling, and resilient concurrent agent access for data-intensive AI workflows. Gain continuous insights with robust metrics and real-time observability. Read the full value proposition.
Note
The http transport utilizes a streamable HTTP architecture by default. It exposes a unified POST endpoint at /mcp for JSON-RPC communication and an SSE stream for continuous updates. An optional strictly stateless mode (--stateless) is available for serverless scaling.
Use HTTP Transport to unlock enterprise-scale capabilities when:
- Deploying globally to remote or cloud environments
- Facilitating concurrent multi-agent access to a centralized server instance
- Enforcing strict enterprise security via native OAuth 2.1
- Running the server as a standalone network service
- Serverless/stateless deployments (
--stateless) - Horizontally scalable, stateless execution
Use stdio Transport (default) when:
- Running locally with Claude Desktop or Cursor IDE
- Single-user development environment
- Simplest setup with no network configuration needed
Tip
Most users should use stdio Transport. HTTP Transport is for advanced deployments.
Important
You must set --allowed-io-roots to explicitly authorize filesystem access for backup/export tools, not codemode. It is strictly required for HTTP transport (will fail to start), but only emits a warning for stdio (filesystem tools will be blocked, but the server will start).
# Local installation
npx -y @neverinfamous/mysql-mcp --transport http --server-host 0.0.0.0 --port 3000 --allowed-io-roots /data --mysql mysql://user:password@localhost:3306/database# Run with port mapping (include Redis and rate limiting env vars for production/enterprise)
docker run -p 3000:3000 \
-e MYSQL_HOST=host.docker.internal \
-e MYSQL_USER=user \
-e MYSQL_PASSWORD=password \
-e MYSQL_DATABASE=database \
-e REDIS_URL=redis://host.docker.internal:6379 \
-e MCP_RATE_LIMIT_MAX=100 \
-e CODEMODE_RATE_LIMIT_MAX=60 \
-e ALLOWED_IO_ROOTS=/data \
--label tags.datadoghq.com/env=production \
--label tags.datadoghq.com/service=mysql-mcp \
--label tags.datadoghq.com/version=latest \
-v ./logs:/var/log/mysql-mcp \
neverinfamous/mysql-mcp:latest \
--transport http \
--server-host 0.0.0.0 \
--port 3000 \
--audit-log /var/log/mysql-mcp/mcp-audit.jsonlnpx -y @neverinfamous/mysql-mcp --transport http --server-host 0.0.0.0 --port 3000 --allowed-io-roots /data --auth-token my-secret --mysql mysql://user:password@localhost:3306/databasenpx -y @neverinfamous/mysql-mcp --transport http --server-host 0.0.0.0 --port 3000 --stateless --allowed-io-roots /data --mysql mysql://user:password@localhost:3306/databaseThe unified HTTP transport layer delivers a bulletproof, infinitely scalable foundation for mission-critical enterprise network architectures. It utilizes a streamable architecture by default for standard JSON-RPC requests and Server-Sent Events.
The modern protocol utilizes SSE (stateful streaming) by default:
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/mcp |
JSON-RPC requests (initialize, tools/list, etc.) |
GET |
/sse |
Server-Sent Events (SSE) connection stream |
POST |
/messages |
JSON-RPC requests for active SSE sessions |
GET |
/metrics |
Prometheus metrics export (when enabled) |
GET |
/health |
Health check bypass endpoint |
In stateless mode (--stateless), all continuous streaming endpoints (e.g. /sse, GET /mcp) are explicitly disabled to guarantee strict stateless execution via POST /mcp. GET /mcp returns 405 (Method Not Allowed). DELETE /mcp returns 204. /sse and /messages return 404. Each POST /mcp creates a fresh transport. It relies solely on synchronous request-response cycles. The --stateless flag is explicitly required to enforce this strictly stateless architecture.
Warning
Stateless Limitations: --stateless disables resource subscriptions and progress notifications. It entirely disables Server-Sent Events. Do not use this mode if your AI needs long-running task updates.
The Mcp-Session-Id header manages sessions. The server returns a session ID during initialize. Clients must include it in subsequent requests. (Note: Strict MCP clients might structurally require the Mcp-Session-Id header. The --stateless mode ignores it internally.)
Example — Initialize a session:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"<protocol-version>","capabilities":{},"clientInfo":{"name":"my-client","version":"<client-version>"}}}'Example — List tools (with session):
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <session-id-from-initialize>" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'Important
SSE HTTP requests must include Accept: application/json, text/event-stream. Stateless mode only requires Accept: application/json.
All HTTP responses include the following headers:
| Header | Value |
|---|---|
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
Cache-Control |
no-store, no-cache, must-revalidate |
Content-Security-Policy |
default-src 'none'; frame-ancestors 'none' |
Permissions-Policy |
camera=(), microphone=(), geolocation=() |
Referrer-Policy |
no-referrer |
Strict-Transport-Security |
Opt-in via the --enable-hsts CLI flag or MCP_ENABLE_HSTS environment variable |
Warning
Load Balancer Trap: Set your proxy's idle timeout lower than the server's keepAliveTimeout (65000 ms). Otherwise, the proxy might close active connections, which causes 502 Bad Gateway errors.
The HTTP server applies three layered timeouts to mitigate slow-connection DoS attacks (e.g., Slowloris). These robust, hardcoded defaults are designed to protect enterprise infrastructure:
| Timeout | Value | Purpose |
|---|---|---|
requestTimeout |
120s | Maximum time for the entire request lifecycle |
keepAliveTimeout |
65s | Idle time before closing keep-alive connections |
headersTimeout |
66s | Maximum time to receive complete headers |
The HTTP transport enforces strict session lifecycle management to prevent memory leaks:
- Idle TTL: Defaults to 30 minutes (30min idle). The server terminates idle sessions.
- Absolute TTL: Defaults to 24 hours (24hr absolute). Hard limit for any session duration.
- Reaper Interval: Hardcoded 1-minute sweep. A background sweep cleans up orphaned sessions. In-flight requests protect active sessions from early termination.
CORS is hardcoded to allow all origins (["*"]) in mcp-server.ts. This permissiveness defaults to internal routing for seamless orchestrator integration. Secure CORS at the reverse proxy in production. (Note: Restricting origins via JSON config files is an advanced preview feature).
Enable trustProxy behind reverse proxies. This reads the client IP from X-Forwarded-For. Rate limiting and logging use the real IP.
Default per-IP request throttling prevents abuse. The Transport Rate limiter uses a fixed window algorithm implemented as an atomic Lua script. Redis distributes rate limiting across deployments via REDIS_URL. An in-memory fallback exists for all rate limits.
-
/healthbypass — The server processes health checks before rate limiting. This ensures monitoring probes always succeed. -
Retry-Afterheader — Rate-limited responses include aRetry-Afterheader. It indicates the seconds remaining until the window resets. -
Environment override — Set
MCP_RATE_LIMIT_MAXto customize the HTTP request limit. SetCODEMODE_RATE_LIMIT_MAXto customize the Code Mode execution limit.
The HTTP transport enforces strict body size limits through a single-layer Content-Length validation mechanism, rejecting oversized requests immediately.
For production deployments, use a structured .env file following fleet groupings:
# Server
MYSQLMCP_PORT=3000
MCP_HOST=0.0.0.0
TRUST_PROXY=false
REDIS_URL=redis://localhost:6379
MCP_RATE_LIMIT_MAX=100
CODEMODE_RATE_LIMIT_MAX=60
# Database
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=app_user
MYSQL_PASSWORD=secure_password
MYSQL_DATABASE=productionNote
This table highlights HTTP-relevant arguments and general server configurations. See Configuration for the complete list of CLI arguments.
| Argument | Environment Variable | Default | Description |
|---|---|---|---|
--transport, -t
|
- |
stdio |
Transport type (stdio or http) |
--port, -p
|
MYSQLMCP_PORT, PORT
|
3000 |
HTTP server port |
--server-host |
MCP_HOST |
localhost |
Host to bind HTTP transport to (Alias: HOST) |
--mysql, -m
|
- |
- |
MySQL connection string |
--auth-token |
MCP_AUTH_TOKEN |
- |
Simple bearer token for HTTP auth |
--stateless |
- |
false |
Enable strictly stateless HTTP transport (disables sessions to support serverless scaling). Note: CLI-only flag, no direct env var equivalent. |
--trust-proxy |
TRUST_PROXY |
false |
Trust X-Forwarded-For for client IP |
--enable-hsts |
MCP_ENABLE_HSTS |
false |
Enable HTTP Strict Transport Security |
--metrics-export |
MCP_METRICS_EXPORT |
disabled |
Enable Prometheus metrics endpoint /metrics (requires a string provider, e.g., prometheus) |
--allowed-io-roots |
ALLOWED_IO_ROOTS |
- |
Explicitly authorize filesystem boundaries (Required for HTTP Transport; emits warning for stdio) |
--oauth-enabled, -o
|
OAUTH_ENABLED |
false |
Enabling OAuth 2.1 authentication (Enterprise Identity Providers like Okta, Auth0, etc.) |
--oauth-issuer |
OAUTH_ISSUER |
- |
OAuth issuer URL |
--oauth-audience |
OAUTH_AUDIENCE |
mysql-mcp-client |
OAuth audience |
--oauth-jwks-uri |
OAUTH_JWKS_URI |
- |
JWKS URI (auto-discovered) |
--oauth-clock-tolerance |
OAUTH_CLOCK_TOLERANCE |
60 |
Clock tolerance in seconds |
--audit-log |
- |
- |
Path to the audit log file (enables forensic logging) |
[ENV Only] |
AUDIT_LOG_PATH |
- |
Read-only path to audit JSONL used by Prometheus metrics exporter / fallback reader |
--audit-backup |
- |
false |
Enable pre-mutation snapshots for destructive DDL and schema maintenance operations |
--audit-reads |
- |
false |
Include read-scope tool calls in audit log |
--audit-redact |
- |
false |
Redact sensitive arguments in audit log |
--audit-log-max-size |
- |
10485760 |
Max file size before rotation (bytes) |
--audit-backup-data |
- |
false |
Include sample data in pre-mutation snaps |
--audit-backup-max-size |
- |
52428800 |
Max table size in bytes for data capture |
--pool-size |
MYSQL_POOL_SIZE |
10 |
Maximum connection pool size |
--pool-timeout |
- |
30000 |
Connection pool timeout in ms |
--pool-queue-limit |
- |
0 |
Connection pool queue limit |
[ENV Only] |
CODEMODE_MAX_RESULT_SIZE |
102400 |
Max Code Mode result payload in bytes (default 100KB, up to 100MB limit) |
[ENV Only] |
CODEMODE_ISOLATION |
isolate |
Sandbox mode (only native isolate is supported) |
[ENV Only] |
REDIS_URL |
- |
Redis connection URL (used for rate limiting) |
[ENV Only] |
MCP_RATE_LIMIT_MAX |
100 |
Custom HTTP request rate limit |
[ENV Only] |
CODEMODE_RATE_LIMIT_MAX |
60 |
Custom Code Mode execution rate limit |
[ENV Only] |
METADATA_CACHE_TTL_MS |
30000 |
Cache TTL for schema metadata in ms |
Note
The --stateless configuration lacks an environment variable equivalent. Standard MYSQL_* environment variables are natively parsed. Note that the --mysql CLI flag only overrides connection-specific variables (Host, Port, User, Password, DB), not all MYSQL_* variables.
HTTP Transport supports OAuth 2.1 authentication for enterprise deployments:
npx -y @neverinfamous/mysql-mcp \
--transport http \
--port 3000 \
--allowed-io-roots /data \
--mysql mysql://user:password@localhost:3306/database \
--oauth-enabled \
--oauth-issuer http://localhost:8080/realms/mysql-mcp \
--oauth-audience mysql-mcp-clientSee the OAuth page for complete setup instructions.
Test your HTTP server with MCP Inspector:
# Start the server
npx -y @neverinfamous/mysql-mcp --transport http --server-host 0.0.0.0 --port 3000 --allowed-io-roots /data --mysql mysql://...
# In another terminal, connect Inspector
npx -y @modelcontextprotocol/inspector http://localhost:3000/mcpwget --spider -q http://127.0.0.1:3000/health || exit 1
# {"status":"healthy","timestamp":"<ISO-8601-Timestamp>"}Tip
Exporter Healthcheck: You can verify the exporter is running using wget --spider -q http://127.0.0.1:3000/metrics.
# Run container with port mapping
docker run -d \
--name mysql-mcp-server \
-p 3000:3000 \
-e MYSQL_HOST=host.docker.internal \
-e MYSQL_USER=user \
-e MYSQL_PASSWORD=password \
-e MYSQL_DATABASE=database \
-e REDIS_URL=redis://host.docker.internal:6379 \
-e MCP_RATE_LIMIT_MAX=100 \
-e CODEMODE_RATE_LIMIT_MAX=60 \
-e ALLOWED_IO_ROOTS=/data \
--label tags.datadoghq.com/env=production \
--label tags.datadoghq.com/service=mysql-mcp \
--label tags.datadoghq.com/version=latest \
-v mcp-data:/data \
-v ./logs:/var/log/mysql-mcp \
neverinfamous/mysql-mcp:latest \
--transport http \
--server-host 0.0.0.0 \
--port 3000 \
--audit-log /var/log/mysql-mcp/mcp-audit.jsonlThe following is a minimal excerpt for deploying the HTTP transport via docker-compose.yml. See the Observability & Telemetry page for the full Datadog test ecosystem. examples/ contains Docker Compose templates, while test-server/infrastructure/ contains the core test ecosystem. Metrics can be seamlessly ingested into Datadog or OpenTelemetry-compatible observability pipelines via standard Prometheus scraping.
# Note: Always include a healthcheck when deploying HTTP transport
services:
mysql-mcp:
image: neverinfamous/mysql-mcp:latest
ports:
- "3000:3000"
command:
- --transport
- http
- --server-host
- "0.0.0.0"
- --port
- "3000"
- --allowed-io-roots
- /data
- --mysql
- mysql://user:password@mysql:3306/database
environment:
- MYSQL_POOL_SIZE=20
- REDIS_URL=redis://redis:6379
- MCP_RATE_LIMIT_MAX=100
- CODEMODE_RATE_LIMIT_MAX=60
depends_on:
- mysql
- redis
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:3000/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
- mcp-data:/data
mysql:
image: mysql:lts
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: database
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
mysql-data:
mcp-data:- Push Docker image to ECR
- Create ECS task definition with port 3000 exposed
- Configure ALB to route traffic to the container
- Set environment variables for MySQL connection
# Build and push to GCR
gcloud builds submit --tag gcr.io/PROJECT_ID/mysql-mcp
# Deploy to Cloud Run
gcloud run deploy mysql-mcp \
--image gcr.io/PROJECT_ID/mysql-mcp \
--port 3000 \
--set-env-vars MYSQL_HOST=...,MYSQL_USER=...,MYSQL_PASSWORD=... \
--args="--transport","http","--server-host","0.0.0.0","--port","3000","--allowed-io-roots","/data","--stateless"az container create \
--resource-group myResourceGroup \
--name mysql-mcp \
--image neverinfamous/mysql-mcp:latest \
--ports 3000 \
--environment-variables \
MYSQL_HOST=... \
MYSQL_USER=... \
MYSQL_PASSWORD=... \
--command-line "--transport http --server-host 0.0.0.0 --port 3000 --allowed-io-roots /data --stateless"Problem: Client cannot connect to the server
Solutions:
- Verify server is running:
wget --spider -q http://127.0.0.1:3000/health || exit 1 - Check firewall rules allow port 3000
- Ensure
--server-host 0.0.0.0if connecting from another machine - Check Docker port mapping:
-p 3000:3000
Problem: POST /mcp returns 406
Solution: Include the required Accept header:
Accept: application/json, text/event-stream
The server requires clients to accept JSON and SSE formats.
Problem: Requests return 400 Bad Request or 404 Not Found with session errors
Solutions:
-
Send the
Mcp-Session-Idheader from theinitializeresponse -
Sessions expire when clients disconnect
Problem: Requests return 401 Unauthorized
Solutions:
- Verify OAuth issuer URL is correct
- Check token audience matches
--oauth-audience - Ensure JWKS URI is accessible from the server
- See OAuth troubleshooting section
Engineered for high-throughput operations, the server delivers microsecond-level latency across schema parsing, rate limiting, and Code Mode sandbox initialization. For comprehensive benchmark data, refer to Performance Tuning.
- Configuration - General configuration options
- OAuth - OAuth 2.1 authentication setup
- MCP Inspector - Testing with MCP Inspector
- MCP Protocol Specification - Official MCP docs
Unlock autonomous database orchestration with an enterprise-grade MySQL MCP server. Featuring blazing-fast sandboxed Code Mode, uncompromising schema enforcement, and seamless ecosystem integrations to power secure, intelligent AI workflows.
- Installation
- Configuration
- Architecture
- HTTP Transport
- Tool Filtering
- Code Mode
- Tools
- Prompts
- Resources
- Observability & Telemetry