Generated by /repo-architecture skill v2.0.0

MySQL MCP Architecture

MySQL MCP is a lightweight HTTP-based MCP server that provides read-only database access to MariaDB/MySQL instances. It exposes 9 tools for schema inspection, query execution, and server diagnostics through both a simple REST API and the MCP JSON-RPC protocol.

The server acts as a safe database gateway for AI agents, enforcing read-only query restrictions (SELECT, SHOW, DESCRIBE, EXPLAIN only) and identifier sanitization to prevent SQL injection. It integrates with the rod-server MCP Proxy, allowing Claude Code and other MCP clients to query MariaDB databases without direct database credentials.

Key design decision: This server uses HTTP transport (not stdio) so it can run as a long-lived Docker container behind the MCP Proxy, which aggregates multiple MCP backends under a single authenticated endpoint.
MCP Tools
9
Transport
HTTP
Runtime
Node.js 20
Port
3201
Security
Read-only
Source Files
1

2. Runtime Architecture

Diagram A: Runtime Request Flow

stdio / HTTP HTTP :3201 SQL :3306 HTTP direct Claude Code MCP client / stdio AI-powered queries Direct Callers curl / scripts REST API access MCP Proxy Node.js / mcp.home Aggregates MCP backends MySQL MCP Node.js / Express :3201 9 tools, read-only MariaDB mysql2 / :3306 6 databases Legend Primary path Direct access External Services Data

Request Flow

  1. Claude Code sends an MCP tool call (e.g., db_query) via stdio to the MCP Proxy.
  2. The MCP Proxy (mcp.home) routes the call to the mysql-mcp container over HTTP on port 3201, using the POST /call endpoint.
  3. MySQL MCP validates the request (read-only check, identifier sanitization), acquires a connection from the pool, and executes the query against MariaDB.
  4. Results are returned as MCP-formatted JSON content (array of {type: "text", text: ...}).

Direct HTTP access (dashed line) is also supported for scripts and debugging via curl http://mysql-mcp:3201/call from within the Docker network.

5. Public Interfaces

HTTP Endpoints

MethodPathDescription
GET/healthHealth check with DB connectivity status
GET/toolsList all available MCP tools with schemas
GET/docsAPI documentation with examples
POST/callCall a tool: {"tool": "name", "params": {}}
POST/tools/listMCP JSON-RPC tool listing
POST/tools/callMCP JSON-RPC tool call

MCP Tools (9 total)

ToolDescriptionRequired ParamsOptional Params
db_list_databases List all databases on the MariaDB server -- --
db_list_tables List all tables in a specific database database --
db_describe_table Describe column structure, types, and keys of a table; includes CREATE TABLE statement database, table --
db_query Execute a read-only SQL query (SELECT, SHOW, DESCRIBE, EXPLAIN only) database, query limit (default 100, max 1000)
db_table_stats Row counts and size statistics for all tables in a database database --
db_foreign_keys List foreign key relationships for a table or entire database database table
db_indexes List indexes on a table database, table --
db_server_status Server status: version, uptime, connections, total queries -- --
db_process_list Show currently running queries and processes -- --

Example Usage

# List databases
curl -s http://mysql-mcp:3201/call \
  -H "Content-Type: application/json" \
  -d '{"tool":"db_list_databases","params":{}}'

# Query a table
curl -s http://mysql-mcp:3201/call \
  -H "Content-Type: application/json" \
  -d '{"tool":"db_query","params":{"database":"nextcloud","query":"SELECT COUNT(*) FROM oc_users"}}'

# Via MCP Proxy (authenticated)
curl -sk https://mcp.home/mcp/database/call \
  -H "X-API-Key: $MCP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"db_server_status","params":{}}'

6. Repository Structure

docker/mysql-mcp/
  Dockerfile          # Node.js 20 Alpine, production build
  package.json        # Dependencies: express, mysql2
  src/
    index.js          # Entire server (595 lines): tools, handlers, HTTP endpoints

Component Classification

ComponentClassificationRole
src/index.js Primary Single-file server containing: tool definitions (9 tools), SQL handler logic with read-only validation and identifier sanitization, connection pool management, Express HTTP server with 6 endpoints, and graceful shutdown handling.
Dockerfile Secondary Alpine-based Node.js 20 image. Production-only npm install, runs as non-root node user, healthcheck on /health.
package.json Auxiliary Declares two runtime dependencies and the npm start script.

7. Deployment & Operations

Container Details

PropertyValue
Container namemysql-mcp
Base imagenode:20-alpine
Exposed port3201
Networkhosting_web + hosting_backend
Usernode (non-root)
HealthcheckGET /health every 30s, 3s timeout, 3 retries
Restart policyunless-stopped

Environment Variables

VariableDefaultPurpose
PORT3201HTTP listen port
MYSQL_HOSTmariadbMariaDB hostname (Docker service name)
MYSQL_PORT3306MariaDB port
MYSQL_USERrodchemistDatabase user
MYSQL_PASSWORD(from .env)Database password

Health Monitoring

# Check container health
docker inspect mysql-mcp --format='{{.State.Health.Status}}'

# Check health endpoint
curl -s http://mysql-mcp:3201/health | jq .

# View logs
docker logs -f mysql-mcp

Connection Pool Configuration

SettingValue
Connection limit5
Queue limit10
Connect timeout10,000 ms
Keep-aliveEnabled (10s initial delay)
Wait for connectionsYes

8. Dependencies

Runtime Dependencies

PackageVersionPurpose
express ^4.18.0 HTTP server framework for REST and MCP JSON-RPC endpoints
mysql2 ^3.14.0 MariaDB/MySQL client with Promise API and connection pooling

Infrastructure Dependencies

ServiceRelationshipRequired
MariaDB (mariadb:3306) Database backend -- all tools query this server Required
MCP Proxy (mcp-proxy) Upstream aggregator -- routes MCP calls to this backend Optional
Docker network (hosting_backend) Must share network with MariaDB container Required
Minimal dependency footprint: Only 2 npm packages. No build tools, no TypeScript, no bundler. The entire server is a single 595-line JavaScript file.

9. Constraints & Risks

ItemSeverityDetails
Read-only enforcement Mitigated Query validation checks for SELECT/SHOW/DESCRIBE/EXPLAIN prefixes. However, this is a string-prefix check, not a SQL parser. Edge cases with CTEs (WITH) are allowed, which could theoretically be abused. The database user should also have read-only grants as a defense-in-depth measure.
Hardcoded credentials Warning Default credentials (rodchemist / password) are hardcoded as fallbacks in the source. These are overridden by environment variables in production, but the defaults should be removed.
No authentication Warning The HTTP server has no authentication. It relies on Docker network isolation and the MCP Proxy's API key authentication for access control. Direct HTTP access is possible from any container on the same Docker network.
Single-file architecture Acceptable All logic is in one 595-line file. This is appropriate for the server's limited scope (9 tools, 6 endpoints) but would need refactoring if significantly more tools are added.
Connection pool size Acceptable Pool limit of 5 connections is sufficient for the expected low-concurrency MCP usage pattern. Queue limit of 10 provides backpressure.