
MCP server for exploring WordPress MySQL/MariaDB databases.
概览
MCP server for exploring WordPress MySQL/MariaDB databases — schema inspection, relationship mapping, and raw SQL querying. It is read-only when you point it at a SELECT-only database user, which is how it is meant to be run; see Security for why that grant, rather than anything in this process, is what makes it read-only. - Auto-detects WordPress table prefix - Full schema generation (JSON / CSV) - WordPress relationship mapping (posts, terms, meta, users, comments) - Raw SQL querying with SELECT-only validation as a guardrail (see Security) - Automatic redaction of credential-shaped values (passwords, keys, tokens, secrets) - Multisite support, including correct resolution of network-shared tables - Query timeout (MySQL and MariaDB syntax both handled) and a configurable row cap - Post search by title/content, with sane content-type/status defaults - Startup audit of the database account's grants - Extensible to plugin tables (WooCommerce, ACF, etc.
README
以下为原文 README 节选,完整内容请查看原文。
WP Database MCP
MCP server for exploring WordPress MySQL/MariaDB databases — schema inspection, relationship
mapping, and raw SQL querying. It is read-only when you point it at a SELECT-only database
user, which is how it is meant to be run; see Security for why that grant, rather
than anything in this process, is what makes it read-only.
Features
- Auto-detects WordPress table prefix
- Full schema generation (JSON / CSV)
- WordPress relationship mapping (posts, terms, meta, users, comments)
- Raw SQL querying with SELECT-only validation as a guardrail (see Security)
- Automatic redaction of credential-shaped values (passwords, keys, tokens, secrets)
- Multisite support, including correct resolution of network-shared tables
- Query timeout (MySQL and MariaDB syntax both handled) and a configurable row cap
- Post search by title/content, with sane content-type/status defaults
- Startup audit of the database account’s grants
- Extensible to plugin tables (WooCommerce, ACF, etc.)
Security
Read-only is enforced by the database grant, not by this server. Create a MySQL/MariaDB
user that only has SELECT, and use that user’s credentials. That grant is the actual
security boundary; everything else below is defence in depth on top of it.
The SQL validator is a guardrail, not a boundary
wp_query runs every statement through validate_select_only() before execution. It rejects
non-SELECT/SHOW/DESCRIBE/EXPLAIN statements, DDL/DML keywords, filesystem/locking/timing
functions, SHOW GRANTS/SHOW VARIABLES, MySQL “executable comments” (/*! ... */), and access
to the mysql, performance_schema, and sys schemas. It is lexical analysis of a
language with a real grammar, and it exists to stop a confused model from firing off a
destructive statement by accident and to explain clearly why it was rejected. It is not a
sandbox a determined or malicious caller cannot escape.
Concretely: aiomysql unconditionally ORs in the CLIENT.MULTI_STATEMENTS protocol flag with
no way to opt out, so a stacked statement (SELECT 1; DROP TABLE wp_posts) is always
transportable to the server at the wire level, regardless of what the validator rejects in
Python first. If the account connecting has write privileges, a bypass of the validator is a
bypass of everything. The only thing that actually stops a write is the grant.
information_schema is deliberately not blocked. It exposes metadata rather than data, and
MySQL scopes its rows to the connecting account’s privileges — a SELECT-only grant on one
database sees only that database’s objects. Blocking it also achieved nothing while SHOW TABLES
and DESCRIBE remained allowed and return the same information; it only rejected the SQL
spelling of a question the caller could already ask another way. mysql is the schema that
actually holds credentials, and stays blocked.
安装
uvx --from wp-db-mcp wp-db-mcp配置
{
"mcpServers": {
"wp-db": {
"command": "uvx",
"args": [
"--from",
"wp-db-mcp",
"wp-db-mcp"
],
"env": {
"WP_DB_HOST": "127.0.0.1",
"WP_DB_PORT": "3306",
"WP_DB_USER": "wp_mcp_reader",
"WP_DB_PASSWORD": "your_password",
"WP_DB_NAME": "your_wordpress_db"
}
}
}
}