Skip to main content

MySQL · MCP ServerOn MySQL, a “read-only” MCP server isn't a boundary.

Hand it your DSN and the guard is thinner than it looks — a multi-statement connection slips a DROP past the SELECT filter, and MySQL DDL commits on contact, with nothing to roll back. Bytebase moves the MCP server in front of the governance layer: the agent connects to Bytebase, Bytebase connects to MySQL.

A raw MySQL MCP server is a wrapper around a connection string: the agent runs SQL straight through a pass-through server to MySQL with full access, skipping identity, masking, write review, and audit.

Strip away the protocol and a typical MySQL MCP server is a thin wrapper around a connection string. Several things fall out of that, none of them good:

Over-privileged credential

Nobody writes a column-scoped GRANT for 'agent'@'%' before a five-minute setup. They paste the DSN they already have — and a MySQL GRANT is table- or schema-wide, so that login reads and drops far more than the one table the agent needed.

One principal, and barely a trail

MySQL Community ships no audit plugin — Enterprise Audit, Percona's audit_log, and MariaDB's server_audit are each edition- or fork-specific. The one built-in everywhere, the general query log, is a debug firehose that records 'agent'@'%' and nothing about which agent, which user, or which prompt.

“Read-only” doesn't hold on MySQL

Two MySQL facts break the usual guard. A connection with multi-statements enabled runs SELECT 1; DROP TABLE orders in a single round trip, and MySQL DDL implicitly commits — a DROP or TRUNCATE can't be rolled back, so wrapping the agent in a read-only transaction sandboxes nothing.

The prompt is an attack surface

The agent reads data, ingests untrusted content, and sends it back out — the lethal trifecta in one shot. A scoped credential can't stop an injection that asks for data it's allowed to read.

Governed MCP in Bytebase

The agent connects to Bytebase, never to MySQL directly.

The agent badges in under its own identity — OAuth and a service account, not a shared DSN — and inherits exactly the permissions that identity carries. Because the policy lives in Bytebase rather than a server plugin, one identity, masking, and audit model covers Community, Enterprise, Percona, MariaDB, and every managed flavor alike — no per-edition audit plugin to standardize on first.

Routed through Bytebase, the agent runs SQL through the Bytebase MCP server, which enforces policy before reaching MySQL with scoped access — per-agent identity, masking on the read path, writes reviewed, every action audited.
01

Per-agent identity

The agent authenticates as itself, not as a DSN. Scope follows the identity — only the projects, databases, and tables its role allows.

02

Masking on the read path

Sensitive values are masked before they reach the model. A restricted SSN comes back as ******, so it can't leak what it never saw.

03

Writes become proposals

A change doesn't run on send. It opens a Bytebase issue, where SQL review and approval apply just as for a human-authored migration.

Run the support-ticket injection against this and it fizzles — the SELECT runs, masking returns ******, scope caps the reach, and the audit log names the identity that tried.

What the agent sees

Same query through MCP. Masked by identity.

The agent calls the query tool over MCP; the result comes back masked for the agent's role, with no change to the table:

// Agent calls the Bytebase MCP "query" tool
{ "sql": "SELECT id, email, ssn FROM customers LIMIT 2" }

// Result returned to the model — masked for this identity
+----+---------------------+-------------+
| id | email               | ssn         |
+----+---------------------+-------------+
|  1 | a******@example.com | ***-**-4801 |
|  2 | m******@example.com | ***-**-2210 |
+----+---------------------+-------------+

An exempted human running the same query in the SQL Editor sees cleartext. Both reads land in the audit log — under the agent identity and the user it acted for.

Audit with two identities

Every action traces from result to prompt to principal.

Because the agent badges in under its own identity, every query and proposed change is logged twice — under the agent and under the person it acted for. A result traces back to the prompt that triggered it and the principal that ran it.

On MySQL Community there's no audit plugin to switch on, and the general query log can't tell two agents apart. The trail lives in Bytebase instead — the same record whether the instance is Community, Percona, or Aurora. When the regulator asks which agent saw which customer record, “we pasted a DSN” is not an answer.

MySQL MCP server questions

Common questions.

What is a MySQL MCP server?
An MCP (Model Context Protocol) server exposes MySQL to an AI agent as tools — typically a query tool the model can call. A raw one wraps a connection string and runs whatever SQL the model asks. A governed one, like Bytebase, sits in front of the governance layer so identity, masking, review, and audit apply to every call.
How is this different from a community MySQL MCP server?
A community server connects directly with a DSN — convenient on a throwaway local database, wide open against production. Bytebase connects the agent through itself: per-agent identity, masking on the read path, writes routed to review, and audit under two identities. Same database, same agent; the difference is where the MCP server sits.
Our MySQL MCP server is read-only — isn't that enough?
Read-only on MySQL is leakier than it looks. A keyword check that allows SELECT is bypassed by a multi-statement connection (SELECT 1; DROP TABLE …), and because MySQL DDL implicitly commits, a read-only transaction can't roll the damage back. Read-only also does nothing about the real risk — masked columns flowing into the model. Bytebase scopes by identity, masks on the read path, and routes any write to review, so “can it write” stops being the only line of defense.
Does it mask sensitive data before the model sees it?
Yes. Masking runs on the read path at the MCP boundary, so restricted values are transformed before they reach the model. A masked SSN returns as ******. The model cannot leak what it never received.
Can the agent write to the database?
Not directly. A schema or data change opens a Bytebase change issue instead of executing on send, where SQL review and approval apply just as for a human-authored migration. The agent proposes; the pipeline governs.
Which MySQL flavors are supported?
Any MySQL or MariaDB Bytebase can connect to — Community, Enterprise, Percona, MariaDB, RDS, Aurora, Cloud SQL, managed forks. Governance runs in Bytebase, in front of the database, so there's no plugin or component requirement on the server.

Explore the standard for database development