mysql-db-mcp
v0.1.0
Published
A secure MySQL MCP server with read-only defaults, structured inserts, and guarded DDL tools.
Maintainers
Readme
mysql-db-mcp
A secure MySQL database MCP Server for reading schemas, tables, columns, running SELECT queries, running EXPLAIN, and optionally performing structured inserts and controlled table DDL.
The default mode is read-only:
MYSQL_ENABLE_WRITE=false
MYSQL_ENABLE_DDL=falseNo arbitrary execute_sql, execute_write, or execute_ddl tool is provided. Write and DDL operations are only available through structured tool parameters, so identifiers can be validated, values can use MySQL parameter binding, and high-risk operations can require explicit confirmation.
Tools
Read-only tools enabled by default:
list_schemaslist_tablesdescribe_tablequery_selectexplain_select
Write tools disabled by default:
insert_rowinsert_rows
DDL tools disabled by default:
alter_table_add_columnalter_table_modify_columnalter_table_drop_columnalter_table_rename_columnalter_table_add_indexalter_table_drop_index
Environment Variables
| Variable | Default | Description |
| --- | --- | --- |
| MYSQL_HOST | 127.0.0.1 | MySQL host |
| MYSQL_PORT | 3306 | MySQL port |
| MYSQL_USER | root | MySQL user |
| MYSQL_PASSWORD | empty | MySQL password |
| MYSQL_DATABASE | unset | Default schema |
| MYSQL_SSL | false | Enable mysql2 SSL option |
| MYSQL_CONNECTION_LIMIT | 10 | Pool connection limit |
| MYSQL_MAX_ROWS | 200 | Maximum returned SELECT rows |
| MYSQL_ENABLE_WRITE | false | Enables insert_row and insert_rows |
| MYSQL_ENABLE_DDL | false | Enables controlled ALTER TABLE tools |
| MYSQL_WRITE_ALLOWED_SCHEMAS | unset | Comma-separated schemas allowed for writes |
| MYSQL_WRITE_ALLOWED_TABLES | unset | Comma-separated tables allowed for writes |
| MYSQL_DDL_ALLOWED_SCHEMAS | unset | Comma-separated schemas allowed for DDL |
| MYSQL_DDL_ALLOWED_TABLES | unset | Comma-separated tables allowed for DDL |
| MYSQL_BLOCKED_TABLES | unset | Extra comma-separated blocked tables |
| MYSQL_MAX_INSERT_ROWS | 100 | Max rows for insert_rows |
| MYSQL_REQUIRE_CONFIRMATION | true | Requires confirm: true for write and DDL tools |
System schemas are always blocked: mysql, information_schema, performance_schema, and sys.
Install And Run
mkdir mysql-db-mcp
cd mysql-db-mcp
npm install
npm run build
npm link
mysql-db-mcpFor local development:
npm run devAfter publishing to npm, users can start it with:
npx mysql-db-mcpMCP Client Config
Read-only mode:
{
"mcpServers": {
"mysql-db": {
"command": "npx",
"args": ["-y", "mysql-db-mcp"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "readonly_user",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_database",
"MYSQL_MAX_ROWS": "200"
}
}
}
}Allow inserts:
{
"mcpServers": {
"mysql-db": {
"command": "npx",
"args": ["-y", "mysql-db-mcp"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "writer_user",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_database",
"MYSQL_ENABLE_WRITE": "true",
"MYSQL_WRITE_ALLOWED_SCHEMAS": "your_database",
"MYSQL_WRITE_ALLOWED_TABLES": "users,orders",
"MYSQL_REQUIRE_CONFIRMATION": "true",
"MYSQL_MAX_INSERT_ROWS": "100"
}
}
}
}Allow DDL:
{
"mcpServers": {
"mysql-db": {
"command": "npx",
"args": ["-y", "mysql-db-mcp"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "ddl_user",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_database",
"MYSQL_ENABLE_DDL": "true",
"MYSQL_DDL_ALLOWED_SCHEMAS": "your_database",
"MYSQL_DDL_ALLOWED_TABLES": "users,orders",
"MYSQL_REQUIRE_CONFIRMATION": "true"
}
}
}
}Allow inserts and DDL:
{
"mcpServers": {
"mysql-db": {
"command": "npx",
"args": ["-y", "mysql-db-mcp"],
"env": {
"MYSQL_HOST": "127.0.0.1",
"MYSQL_PORT": "3306",
"MYSQL_USER": "admin_limited_user",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_database",
"MYSQL_ENABLE_WRITE": "true",
"MYSQL_ENABLE_DDL": "true",
"MYSQL_WRITE_ALLOWED_SCHEMAS": "your_database",
"MYSQL_WRITE_ALLOWED_TABLES": "users,orders",
"MYSQL_DDL_ALLOWED_SCHEMAS": "your_database",
"MYSQL_DDL_ALLOWED_TABLES": "users,orders",
"MYSQL_REQUIRE_CONFIRMATION": "true"
}
}
}
}Tool Examples
SELECT:
{
"sql": "SELECT id, email FROM users WHERE status = ? LIMIT 10",
"params": ["active"]
}EXPLAIN:
{
"sql": "SELECT id, email FROM users WHERE status = ? LIMIT 10",
"params": ["active"]
}Insert one row:
{
"schema": "your_database",
"table": "users",
"data": {
"email": "[email protected]",
"status": "active"
},
"confirm": true
}Insert multiple rows:
{
"schema": "your_database",
"table": "users",
"rows": [
{ "email": "[email protected]", "status": "active" },
{ "email": "[email protected]", "status": "pending" }
],
"confirm": true
}Add a column:
{
"schema": "your_database",
"table": "users",
"columnName": "nickname",
"columnType": "VARCHAR(255)",
"nullable": true,
"comment": "Display name",
"afterColumn": "email",
"confirm": true
}Modify a column:
{
"schema": "your_database",
"table": "users",
"columnName": "nickname",
"columnType": "VARCHAR(128)",
"nullable": true,
"comment": "Short display name",
"confirm": true
}Drop a column:
{
"schema": "your_database",
"table": "users",
"columnName": "nickname",
"confirm": true
}Rename a column:
{
"schema": "your_database",
"table": "users",
"oldColumnName": "nickname",
"newColumnName": "display_name",
"confirm": true
}Add an index:
{
"schema": "your_database",
"table": "users",
"indexName": "idx_users_status",
"columns": ["status"],
"unique": false,
"confirm": true
}Drop an index:
{
"schema": "your_database",
"table": "users",
"indexName": "idx_users_status",
"confirm": true
}MCP Inspector
Build first, then run the MCP Inspector:
npm run build
npx @modelcontextprotocol/inspector node dist/index.jsSet MySQL environment variables in the Inspector process before testing tools.
MySQL Account Recommendations
Do not use root in production.
Read-only user:
CREATE USER 'mcp_readonly'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT ON your_database.* TO 'mcp_readonly'@'%';
FLUSH PRIVILEGES;Insert user:
CREATE USER 'mcp_writer'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT, INSERT ON your_database.* TO 'mcp_writer'@'%';
FLUSH PRIVILEGES;DDL user:
CREATE USER 'mcp_ddl'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT, ALTER, INDEX ON your_database.* TO 'mcp_ddl'@'%';
FLUSH PRIVILEGES;Development user:
CREATE USER 'mcp_dev'@'%' IDENTIFIED BY 'your_password';
GRANT SELECT, INSERT, ALTER, INDEX ON your_database.* TO 'mcp_dev'@'%';
FLUSH PRIVILEGES;The MCP Server does not execute authorization SQL. A DBA or developer should run those SQL statements manually.
Safety Notes
- Keep the default read-only mode for production unless there is a clear operational need.
- Prefer separate database accounts for read-only, insert, and DDL use cases.
- Use
MYSQL_WRITE_ALLOWED_SCHEMASandMYSQL_WRITE_ALLOWED_TABLESto narrow write scope. - Use
MYSQL_DDL_ALLOWED_SCHEMASandMYSQL_DDL_ALLOWED_TABLESto narrow DDL scope. - DDL should be enabled only in development or tightly controlled environments.
- MySQL DDL commonly causes implicit commits and cannot be treated as safely rollbackable.
confirm: trueexists to make write and DDL calls explicit at the tool boundary.- Passwords and full connection strings are never written to logs by this server.
Publish To npm
npm login
npm run build
npm publish --access public