MySQL MCP Server

Ask Claude or Cursor about your MySQL data and slow queries, with the database protected: read-only transactions, time limits, row caps and a statement checker.

MySQL MCP Server product illustration

What it does

Let Claude Code, Claude Desktop, Cursor or any MCP client explore and query a MySQL database, and review its performance, without being able to change it.

  • Read-only by design. Every query runs inside START TRANSACTION READ ONLY with max_execution_time, innodb_lock_wait_timeout and a row cap, then rolls back. A statement checker refuses writes, multiple statements, SELECT ... INTO OUTFILE, LOAD DATA, LOAD_FILE(), SLEEP(), locking reads, SET, executable comments (/*! */) and optimizer hints that could switch the limits off, before anything reaches the server.
  • Knows your schema. Tables with engine, estimated rows and sizes; columns with types, defaults and comments; primary and foreign keys in both directions; check constraints; indexes with their usage counts; view SQL; sample rows.
  • Finds slow spots. explain_query turns EXPLAIN FORMAT=JSON into findings (full scans, unused indexes, filesort, temporary tables) and, with analyze, adds real timings from EXPLAIN ANALYZE. db_health runs 11 checks. top_queries reads the performance_schema statement digests.
  • Tested on MySQL 8.0.46 and 8.4.9. Works with any MySQL 8.0+ that accepts a normal connection, including hosted MySQL (RDS, Aurora MySQL, Cloud SQL, Azure, PlanetScale) where your login has the grants below. MariaDB 10.6+ is supported in the code (it uses max_statement_time and ANALYZE FORMAT=JSON) but was not part of the test run.

What you get

The screenshot is real output from the kit’s own commands. Tested from a fresh download of this exact zip: ./run_tests.sh ran 23 tests OK on Python 3.13 and 3.10.

Real terminal output from MySQL MCP Server: demo and passing tests

Tools

ToolWhat it returns
list_connectionsconfigured connections (password hidden), server version, default database, whether the login can change data
list_databasesdatabases with table counts, sizes and character sets
list_tablestables and views: engine, estimated rows, size, comment
describe_tablecolumns, keys both ways, check constraints, indexes + usage, engine, collation, view SQL, sample rows
read_queryone read statement with ? params; capped rows, truncated flag, timing
explain_queryplan + plain-English findings; analyze: true adds real timings (runs the query, read-only)
search_schematables and columns whose name contains a word
db_healthunused and redundant indexes, tables without a primary key, non-InnoDB tables, utf8mb3 columns, auto_increment near its limit, fragmentation, queries without an index, buffer pool hit ratio, connections, long-running statements
top_queriesslowest / most frequent query patterns from performance_schema
export_csvup to 100,000 rows of a read query into a new .csv (never overwrites)
write_queryonly with --allow-writes: one INSERT/UPDATE/DELETE/REPLACE/DDL, committed

Install

Python 3.9+ and PyMySQL (pure Python, no client libraries needed):

python3 -m pip install PyMySQL      # or: python3 -m pip install -r requirements.txt

Create a read-only user (recommended; see examples/read_only_user.sql):

CREATE USER 'mcp_reader'@'%' IDENTIFIED BY 'change-me';
GRANT SELECT, SHOW VIEW ON mydb.* TO 'mcp_reader'@'%';
GRANT SELECT ON performance_schema.* TO 'mcp_reader'@'%';   -- optional: db_health, top_queries, index usage
GRANT PROCESS ON *.* TO 'mcp_reader'@'%';                   -- optional: other sessions in long_running

Claude Code

claude mcp add mysql -- python3 /path/to/mysql-mcp-server/server.py --dsn mysql://mcp_reader:PASSWORD@localhost:3306/mydb

Or install the folder as a plugin (.claude-plugin/plugin.json, .mcp.json, skill mysql-analyst) and set MYMCP_DSN in your environment.

Claude Desktop / Cursor: copy examples/configs/claude_desktop_config.json or examples/configs/cursor-mcp.json and fill in the path and connection string.

Connection string: mysql://user:password@host:3306/database. Options after ?: ssl_ca=/path/ca.pem (verified TLS; add ssl_verify=true to check the host name), ssl=true (encrypted, certificate not verified), unix_socket=/path/mysqld.sock, charset=utf8mb4. URL-encode special characters in the password (@ is %40). Several servers: repeat --dsn name=mysql://... (or separate them with spaces in MYMCP_DSN). With no DSN, MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE are used.

Options: --max-rows 200 (cap per query), --timeout 10 (seconds per query), --allow-writes (adds write_query; the skill asks before every write).

Try it

./run_tests.sh                                                   # unit tests, no database needed
MYMCP_TEST_DSN=mysql://root:pw@127.0.0.1:3306/ ./run_tests.sh     # + integration tests on a real server
MYMCP_DEMO_DSN=mysql://root:pw@127.0.0.1:3306/ ./demo.sh          # MCP session on a fictional shop

The integration tests and the demo recreate database demo_shop (the tests also create user mcp_test_reader). Use a scratch server.

Honest limits

  • The model writes the SQL. Check the query it shows you before acting on a number.
  • Read-only means *this server* won't change data. Use a read-only user as well; the server warns when the login has write or FILE privileges.
  • max_execution_time applies to SELECT statements; SHOW and DESCRIBE are not time-limited by MySQL.
  • explain_query with analyze: true really runs the query (inside a read-only transaction, with the time limit).
  • Row counts in list_tables are InnoDB estimates, and index usage and statement statistics reset when the server restarts; check replicas separately before dropping an "unused" index.
  • top_queries and parts of db_health need performance_schema (on by default in MySQL 8).
  • Not a migration tool, an ORM or a backup tool.

Format and license

Zip, 38 KB, v1.0, 26 files. You may use and modify this kit for your own work and for clients you serve, including paid client work. Not affiliated with or endorsed by MySQL (Oracle), Anthropic or Cursor (Anysphere).

FAQ

Can the model change my data?
Not by default: every query runs in START TRANSACTION READ ONLY with max_execution_time, and writes, INTO OUTFILE, LOAD_FILE(), SLEEP() and executable comments are refused before they reach the server. Writes need --allow-writes, and the skill asks you first.
Which versions?
Tested on MySQL 8.0.46 and 8.4.9; hosted MySQL (RDS, Aurora, Cloud SQL, PlanetScale) connects the same way. MariaDB is supported in the code but was not tested.
What do I need?
Python 3.9+ and PyMySQL (pip install PyMySQL); no MySQL client libraries.
How do I get the files?
Pay by card right here on youraitools.co: your download links appear on this page the moment the payment goes through (claim window: 72 hours, up to 5 downloads per 7 days). Need the files re-sent later? Email hello@youraitools.co.
Refunds?
Email hello@youraitools.co within 14 days if it doesn’t work and we can’t fix it.
Can I pay with crypto?
Yes. Pay the same price in USDC or USDT on Base, Ethereum, Arbitrum, Optimism, Polygon or Solana from the "Pay with crypto" button, with no account or KYC. We check the payment on-chain and show your download links as soon as it confirms.

Get MySQL MCP Server

MySQL MCP server for Claude Code, Claude Desktop and Cursor: read-only transactions, schema, EXPLAIN findings, 11 health checks, slow queries. Python. $29.

Save with a bundle

Pairs well with

Download$29

Postgres MCP Server

PostgreSQL MCP server for Claude Code, Claude Desktop and Cursor: read-only transactions, schema, EXPLAIN findings, health checks, slow queries. Python. $29.

View Postgres MCP Server

Related

1 email a week: new x402 + MCP tools and free kits.

Short weekly digest of new x402 + MCP tools and free kits, including the MCP OAuth Checker. No spam, unsubscribe any time.