Skip to content

HTTP Transport

Chris edited this page Jul 6, 2026 · 159 revisions

HTTP TransportToolsResourcesPrompts
OAuth 2.1Code Mode## 🚀 Value PropositionEnterprise-Grade & Zero-Trust Architecture: mysql-mcp delivers unparalleled transport security by running full OAuth 2.1 authentication natively over HTTP, ensuring every tool execution is deeply verified against JSON Web Key Sets (JWKS) before touching your database. Expose mysql-mcp remotely with confidence, knowing you have strict rate limits, robust TLS termination, and granular scope enforcement protecting your data.This page explains how to run mysql-mcp as an HTTP server supporting two MCP transport protocols simultaneously — Streamable HTTP for modern clients and legacy SSE for backward compatibility.---## Decide When to Use HTTP ModeUse HTTP mode when:- Deploying the server to a remote location (cloud, Docker container)- Multiple AI clients need to connect to the same database- You need OAuth 2.1 authentication for enterprise security- Running the server as a standalone network service- Serverless/stateless deployments (--stateless)Use stdio mode (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 mode. HTTP mode is for advanced deployments.---## Accelerate Your Deployment (Quick Start)> Important: HTTP transport mode requires --allowed-io-roots to be set to explicitly authorize filesystem access boundaries. The server will fail to start without it.### Local Installationbash# Build the project firstpnpm run build# Start HTTP server on port 3001npx @neverinfamous/mysql-mcp --transport http --port 3001 --server-host 0.0.0.0 --allowed-io-roots /data --mysql mysql://user:password@localhost:3306/database### Dockerbash# Run with port mappingdocker run -p 3001:3001 writenotenow/mysql-mcp:latest \ --transport http \ --port 3001 \ --server-host 0.0.0.0 \ --allowed-io-roots /data \ --mysql mysql://user:password@host.docker.internal:3306/database### With Simple Bearer Authbashnpx @neverinfamous/mysql-mcp --transport http --port 3001 --allowed-io-roots /data --auth-token my-secret --mysql mysql://user:password@localhost:3306/database### Stateless Modebashnpx @neverinfamous/mysql-mcp --transport http --port 3001 --stateless --allowed-io-roots /data --mysql mysql://user:password@localhost:3306/database---## Understand Transport ProtocolsThe HTTP transport supports two MCP protocol versions simultaneously, allowing both modern and legacy clients to connect to the same server.### Streamable HTTP (Recommended)Modern protocol (MCP 2025-03-26) — single endpoint, session-based:| Method | Endpoint | Purpose || -------- | -------- | ------------------------------------------------ || POST | /mcp | JSON-RPC requests (initialize, tools/list, etc.) || GET | /mcp | SSE stream for server notifications || DELETE | /mcp | Session termination |In stateless mode (--stateless): GET /mcp returns 405, DELETE /mcp returns 204, /sse and /messages return 404. Each POST /mcp creates a fresh transport with no session persistence, relying exclusively on synchronous HTTP request-response cycles.Sessions are managed via the Mcp-Session-Id header. The server returns a session ID in the response to initialize, and clients must include it in subsequent requests.Example — Initialize a session:bashcurl -X POST http://localhost:3001/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-client","version":"1.0.0"}}}'Example — List tools (with session):bashcurl -X POST http://localhost:3001/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: Streamable HTTP requests must include Accept: application/json, text/event-stream — the server may respond with either format.### Legacy SSE (Backward Compatibility)Legacy protocol (MCP 2024-11-05) — for older MCP clients:| Method | Endpoint | Purpose || ------ | -------------------------- | ------------------------------------------------------------- || GET | /sse | Opens SSE stream, returns /messages?sessionId=<id> endpoint || POST | /messages?sessionId=<id> | Send JSON-RPC messages to the session |Example:bash# Establish SSE connection (will stream events)curl -N http://localhost:3001/sse# Send a message (in another terminal, using the sessionId from the SSE stream)curl -X POST "http://localhost:3001/messages?sessionId=<id>" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-client","version":"1.0.0"}}}'### Security HeadersAll HTTP responses include the following headers (6 base, 7 with HSTS):| 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 enableHSTS (for HTTPS) |### Server Timeouts (Slowloris Protection)The HTTP server applies three timeout layers to prevent slow-connection DoS attacks:| Timeout | Value | Purpose || ------------------ | ------- | --------------------------------------------- || requestTimeout | 120,000 ms | Maximum time for the entire request lifecycle || keepAliveTimeout | 65,000 ms | Idle time before closing keep-alive connections || headersTimeout | 66,000 ms | Maximum time to receive complete headers |### Session TimeoutsThe HTTP transport enforces strict session lifecycle management to prevent memory leaks from disconnected clients:- Idle TTL: 30 minutes. If a session receives no requests, it is terminated.- Absolute TTL: 24 hours. Hard limit for any session duration.- Reaper Interval: 1 minute. A background sweep cleans up orphaned sessions. Sessions with in-flight requests are protected from early termination.### CORSCORS is currently hardcoded to allow all origins (*) to facilitate easy connections from web-based clients and inspectors. Restricting origins via CLI flags is not yet supported.### Trust ProxyWhen running behind a reverse proxy (nginx, ALB, Cloudflare, etc.), enable trustProxy to read the client IP from X-Forwarded-For instead of the socket address. This ensures rate limiting and logging use the real client IP.### Rate LimitingPer-IP request throttling is enabled by default to prevent abuse. The Transport Rate limiter (100 HTTP requests/min default) uses a sliding window approach with deterministic cleanup. Rate limiting is distributed across deployments via Redis if REDIS_URL is provided, with a graceful in-memory fallback. (Note: This is distinct from the 60 V8 Code Mode executions/min Execution Rate limit).- /health bypass — Health check requests are served before rate limiting is checked, ensuring monitoring probes always succeed regardless of per-IP quotas- Retry-After header — Rate-limited responses (429 Too Many Requests) include a Retry-After header indicating seconds until the window resets- Environment override — Set MCP_RATE_LIMIT_MAX to customize the per-IP request limit (default: 100 requests/minute)### Body Size EnforcementRequest body size is enforced with two layers:1. Content-Length header check — fast rejection for well-behaved clients2. Streaming byte tracking — catches missing/spoofed headers and chunked encodingDefault maximum body size: 1 MB (1,048,576 bytes).---## Optimize Configuration Options### Environment VariablesFor production deployments, use a structured .env file following fleet groupings:bash# ServerMCP_TRANSPORT=httpMYSQLMCP_PORT=3001MCP_HOST=0.0.0.0TRUST_PROXY=falseMCP_RATE_LIMIT_MAX=100# DatabaseMYSQL_HOST=localhostMYSQL_PORT=3306MYSQL_USER=app_userMYSQL_PASSWORD=secure_passwordMYSQL_DATABASE=production### CLI Arguments| Argument | Environment Variable | Default | Description || -------------------- | -------------------- | ----------- | ------------------------------------------ || --transport, -t | MCP_TRANSPORT | stdio | Transport type (stdio, http, or sse) || --port | MYSQLMCP_PORT | 3001 | HTTP server port || --server-host | MCP_HOST | localhost | Host to bind HTTP transport to || --auth-token | MCP_AUTH_TOKEN | — | Simple bearer token for HTTP auth || --stateless | — | false | Stateless HTTP mode (no sessions, no SSE) || --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 | false | Enable prometheus metrics endpoint /metrics|| --allowed-io-roots | ALLOWED_IO_ROOTS | — | Explicitly authorize filesystem boundaries || --oauth-enabled, -o | OAUTH_ENABLED | false | Enable OAuth 2.1 authentication || --oauth-issuer | OAUTH_ISSUER | — | OAuth 2.1 issuer URL || --oauth-audience | OAUTH_AUDIENCE | — | OAuth 2.1 audience || --oauth-jwks-uri | OAUTH_JWKS_URI | — | JWKS URI (auto-discovered) || --oauth-clock-tolerance | OAUTH_CLOCK_TOLERANCE | — | Clock tolerance in seconds || --audit-log | — | — | Enable JSONL forensic logging and tokens || --audit-backup | — | false | Enable audit backups || --audit-reads | — | false | Include read-scope tool calls in audit log || --audit-redact | — | false | Redact sensitive arguments in audit log || --audit-log-max-size | — | — | Max file size before rotation (bytes) || --audit-backup-data | — | false | Include sample data in pre-mutation snaps || --audit-backup-max-size | — | — | Max table size in bytes for data capture || --code-mode-max-result-size | CODE_MODE_MAX_RESULT_SIZE | 102400 | Max Code Mode result payload in bytes |---## Secure Your Access: Using with OAuth 2.1HTTP mode supports OAuth 2.1 authentication for enterprise deployments:bashnpx @neverinfamous/mysql-mcp \ --transport http \ --port 3001 \ --allowed-io-roots /data \ --mysql mysql://user:password@localhost:3306/database \ --oauth-enabled \ --oauth-issuer https://your-keycloak.com/realms/mysql-mcp \ --oauth-audience mysql-mcpSee the OAuth page for complete setup instructions.---## Connect Your MCP Clients### Using MCP InspectorTest your HTTP server with MCP Inspector:bash# Start the servernpx @neverinfamous/mysql-mcp --transport http --port 3001 --allowed-io-roots /data --mysql mysql://...# In another terminal, connect Inspectornpx @modelcontextprotocol/inspector http://localhost:3001/sse### Health Checkbashcurl http://localhost:3001/health# {"status":"healthy","timestamp":"2026-03-05T..."}---## Launch Your Docker Deployment### Basic Deploymentbash# Build imagedocker build -t mysql-mcp .# Run container with port mappingdocker run -d \ --name mysql-mcp-server \ -p 3001:3001 \ mysql-mcp \ --transport http \ --port 3001 \ --server-host 0.0.0.0 \ --allowed-io-roots /data \ --mysql mysql://user:password@host.docker.internal:3306/database### Docker Composeyamlservices: mysql-mcp: image: writenotenow/mysql-mcp:latest ports: - "3001:3001" command: - --transport - http - --port - "3001" - --allowed-io-roots - /data - --mysql - mysql://user:password@mysql:3306/database environment: - MYSQL_POOL_SIZE=20 depends_on: - mysql mysql: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: database volumes: - mysql-data:/var/lib/mysqlvolumes: mysql-data:---## Scale with Cloud Deployment### AWS ECS / Fargate1. Push Docker image to ECR2. Create ECS task definition with port 3001 exposed3. Configure ALB to route traffic to the container4. Set environment variables for MySQL connection### Google Cloud Runbash# Build and push to GCRgcloud builds submit --tag gcr.io/PROJECT_ID/mysql-mcp# Deploy to Cloud Rungcloud run deploy mysql-mcp \ --image gcr.io/PROJECT_ID/mysql-mcp \ --port 3001 \ --set-env-vars MYSQL_HOST=...,MYSQL_USER=...,MYSQL_PASSWORD=... \ --command "--transport,http,--port,3001,--allowed-io-roots,/data"### Azure Container Instancesbashaz container create \ --resource-group myResourceGroup \ --name mysql-mcp \ --image writenotenow/mysql-mcp:latest \ --ports 3001 \ --environment-variables \ MYSQL_HOST=... \ MYSQL_USER=... \ MYSQL_PASSWORD=... \ --command-line "--transport http --port 3001 --allowed-io-roots /data"---## Resolve Issues Fast (Troubleshooting)### Connection RefusedProblem: Client cannot connect to the serverSolutions:- Verify server is running: curl http://localhost:3001/health- Check firewall rules allow port 3001- Ensure --server-host 0.0.0.0 if connecting from another machine- Check Docker port mapping: -p 3001:3001### 406 Not Acceptable (Streamable HTTP)Problem: POST /mcp returns 406Solution: Include the required Accept header:Accept: application/json, text/event-streamThe StreamableHTTPServerTransport requires clients to accept both JSON and SSE response formats.### Session Not FoundProblem: Requests return 400 Bad Request or 404 Not Found with session-related errorsSolutions:- Ensure you're sending the Mcp-Session-Id header from the initialize response- SSE sessions cannot be used on /mcp and vice versa (cross-protocol guard)- Sessions expire when the client disconnects### OAuth Authentication FailuresProblem: Requests return 401 UnauthorizedSolutions:- Verify OAuth issuer URL is correct- Check token audience matches --oauth-audience- Ensure JWKS URI is accessible from the server- See OAuth troubleshooting section---## Expand Your Knowledge (See Also)- Configuration - General configuration options- OAuth - OAuth 2.1 authentication setup- MCP-Inspector - Testing with MCP Inspector- MCP Protocol Specification - Official MCP docs

MySQL MCP Documentation

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.

🏠 Home


Launch Your Setup


Connect Ecosystem Tools


Enforce Security & Compliance


Scale Your Operations


Explore External Links

Clone this wiki locally