MariaDB / MySQL MCP server (Model Context Protocol), packaged for the Docker MCP gateway and for direct use by MCP clients (Claude Code, Claude Desktop, Codex, …).
Speaks stdio by default. SSE on port 9001 stays available behind an argument.
0.2.6 (also 0.2.6-arm64 / 0.2.6-x86 single-arch builds)linux/amd64, linux/arm64python:3.11-slimMariaDB/mcp v0.2.6, repackaged. src/
is unmodified upstream code.docker run --rm -i \
-e DB_HOST=db.example.net \
-e DB_PORT=3306 \
-e DB_USER=myuser \
-e DB_PASSWORD=mypassword \
-e DB_NAME=mydb \
kampn/mariadb-mcp:0.2.6
-i is required: the server talks MCP over stdin/stdout. Nothing is printed on
stdout except JSON-RPC; logs go to stderr and to a file.
DB_USER and DB_PASSWORD are mandatory. The server raises ConnectionError
at startup without them, before any tool is registered.
Writes are refused by default. MCP_READ_ONLY defaults to true, and
execute_sql then raises PermissionError on any write. Set
-e MCP_READ_ONLY=false if the client must write.
{
"mcpServers": {
"mariadb": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "DB_HOST=db.example.net",
"-e", "DB_PORT=3306",
"-e", "DB_USER=myuser",
"-e", "DB_PASSWORD=mypassword",
"-e", "DB_NAME=mydb",
"-e", "MCP_READ_ONLY=true",
"kampn/mariadb-mcp:0.2.6"
]
}
}
}
~/.codex/config.toml)[mcp_servers.mariadb]
command = "docker"
args = ["run", "-i", "--rm",
"-e", "DB_HOST", "-e", "DB_PORT", "-e", "DB_USER",
"-e", "DB_PASSWORD", "-e", "DB_NAME", "-e", "MCP_READ_ONLY",
"kampn/mariadb-mcp:0.2.6"]
[mcp_servers.mariadb.env]
DB_HOST = "db.example.net"
DB_PORT = "3306"
DB_USER = "myuser"
DB_PASSWORD = "mypassword"
DB_NAME = "mydb"
MCP_READ_ONLY = "true"
The image carries ENTRYPOINT ["python", "src/server.py"] with
CMD ["--transport", "stdio"], so a catalog entry passes flags only:
registry:
mariadb:
title: MariaDB
type: server
image: kampn/mariadb-mcp:0.2.6
command:
- --transport
- stdio
secrets:
- name: mariadb.password
env: DB_PASSWORD
env:
- name: DB_HOST
value: '{{mariadb.host}}'
- name: DB_PORT
value: '{{mariadb.port}}'
- name: DB_USER
value: '{{mariadb.user}}'
- name: DB_NAME
value: '{{mariadb.database}}'
Six SQL tools, always registered:
| Tool | Purpose |
|---|---|
list_databases | Lists accessible databases. |
list_tables | Lists tables in a database. |
get_table_schema | Schema of one table. |
get_table_schema_with_relations | Schema plus foreign-key relations. |
execute_sql | Runs a query. Writes need MCP_READ_ONLY=false. |
create_database | Creates a database if absent. |
Five more (create_vector_store, list_vector_stores, delete_vector_store,
insert_docs_vector_store, search_vector_store) register only when
EMBEDDING_PROVIDER is set.
Configuration is environment-only. Everything is optional except DB_USER and
DB_PASSWORD.
| Variable | Default | Note |
|---|---|---|
DB_HOST | localhost | Unset aims the pool at the container itself. |
DB_PORT | 3306 | |
DB_USER | (none) | Required. |
DB_PASSWORD | (none) | Required. |
DB_NAME | (none) | No default; not checked before pool creation. |
DB_CHARSET | (none) | |
MCP_MAX_POOL_SIZE | 10 |
| Variable | Default |
|---|---|
DB_SSL | false |
DB_SSL_CA | (none) |
DB_SSL_CERT | (none) |
DB_SSL_KEY | (none) |
DB_SSL_VERIFY_CERT | true |
DB_SSL_VERIFY_IDENTITY | false |
| Variable | Default | Note |
|---|---|---|
MCP_READ_ONLY | true | execute_sql raises PermissionError on writes until set to false. |
MCP_BLOCK_SENSITIVE_SHOW | true | Independent of MCP_READ_ONLY. Blocks SHOW PROCESSLIST, SHOW [GLOBAL|SESSION] VARIABLES, SHOW GRANTS, SHOW CREATE USER, SHOW PRIVILEGES, SHOW ENGINE STATUS and the replication/binlog variants. |
EMBEDDING_PROVIDER | Result |
|---|---|
| unset | 6 SQL tools |
openai | 6 SQL + 5 vector tools. Needs OPENAI_API_KEY. |
gemini | 6 SQL + 5 vector tools. Needs GEMINI_API_KEY. |
huggingface | Unsupported in this image — fails at startup. The sentence-transformers dependency is removed (it pulled 2.7 GB of CUDA wheels). |
| anything else | Silently reset to unset, logged at INFO. 6 SQL tools, no error. |
| Variable | Default | Note |
|---|---|---|
LOG_LEVEL | INFO | First thing to raise when the container misbehaves. |
LOG_FILE | logs/mcp_server.log | Relative to /app. |
LOG_MAX_BYTES | 10485760 | 10 MiB per rotated file. |
LOG_BACKUP_COUNT | 5 |
| Variable | Default | Note |
|---|---|---|
ALLOWED_HOSTS | localhost, 127.0.0.1 | Passed to Starlette's TrustedHostMiddleware. Any other Host header gets 400 Invalid host header. Set it to the hostname clients really use. |
ALLOWED_ORIGINS | http://localhost, http://127.0.0.1, http://*, https://localhost, https://127.0.0.1, vscode-file://vscode-app | CORS. |
docker run --rm -p 9001:9001 \
-e DB_HOST=db.example.net -e DB_USER=myuser \
-e DB_PASSWORD=mypassword -e DB_NAME=mydb \
-e ALLOWED_HOSTS=myhost.example.net \
kampn/mariadb-mcp:0.2.6 --transport sse --host 0.0.0.0
The MCP endpoint is /sse — e.g. http://<host>:9001/sse. /mcp returns
404 in SSE mode.
CLI arguments: --transport {stdio,sse,http} (default stdio), --host
(default 127.0.0.1), --port (default 9001), --path (default /mcp,
applies to the http transport only).
0.2.6 was republished with the stdio
default. Before that date the same tag started in SSE with no argument. Run
docker pull kampn/mariadb-mcp:0.2.6 on hosts that cached the old image; a
stale one fails under the Docker MCP gateway with
exec: "--transport": executable file not found in $PATH./app is required. The server opens
/app/logs/mcp_server.log at import time. The image runs as root, so this
works by default, but startup fails under --read-only or a non-root
--user. Set LOG_FILE to a writable path, or mount a volume on
/app/logs.AttributeError: 'NoneType' object has no attribute 'GoogleAPIError',
masking the real error, because google.api_core is not a declared
dependency upstream. Affects the openai and gemini error paths only;
happy paths are unaffected. Present identically in upstream v0.2.6 and
deliberately not patched here, to keep src/ byte-identical to upstream.Content type
Image
Digest
sha256:5938e019d…
Size
88.5 MB
Last updated
about 1 month ago
docker pull kampn/mariadb-mcp:0.2.6