It was 2am and our daily order volume chart had gone flat. Not zero, just... suspiciously flat. I needed to know whether orders had actually stopped or whether the reporting query was broken. I didn't want to wake anyone up. I also didn't want to dig through the codebase for the right query, paste my prod URL into something I didn't trust, and go from there. I wanted to ask a question and get a number. This is how I set that up for MySQL.
We'll connect your MySQL database to Claude Code through QueryBear's MCP server. Should take about fifteen minutes.
Giving Claude your raw database URL means the agent inherits whatever permissions that user has, with nothing between it and your data. QueryBear runs a SQL parser that blocks DML and DDL before they reach MySQL, enforces a table allowlist, lets you block specific columns, caps row counts, and logs every query. The MySQL MCP Server guide covers the full security model if you want the details.
Choose MySQL, then paste your connection URL. Format: mysql://user:pass@host:3306/dbname. Use a read replica and a user with SELECT only.
Under "Allowed tables," check off the tables the agent should be able to see. Orders, products, users, sure. Anything with credentials or PII you'd rather not expose, leave it off.
Under "Blocked columns," add the ones you definitely don't want in Claude's context: password_hash, payment_token, anything similar.
Save. QueryBear will verify the connection and confirm it's ready.
Install the QueryBear MCP server in Claude Code
In your terminal:
claude mcp add --transport http querybear https://mcp.querybear.com/mcp
Claude Code walks you through OAuth. After that, every Claude Code session has access to three tools: list_connections, get_schema, and run_query. All three go through QueryBear's gateway, not directly to your database.
Ask your first question
Open a Claude Code session. Ask something in plain English:
I asked: "What was our daily order count for the past 30 days?"
Claude Code generated this query and ran it through QueryBear:
SELECT DATE(created_at) AS order_date, COUNT(*) AS order_countFROM ordersWHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)GROUP BY DATE(created_at)ORDER BY order_date ASC;
Got back 30 rows, one per day. The whole round trip took under a second.
Claude calls get_schema first so it knows what columns exist, then writes the query in MySQL syntax, then calls run_query. If the query touches a blocked column or something not on the allowlist, QueryBear rejects it cleanly before MySQL ever sees it.
A Claude Code-specific tip
If you run the same question every day or every Monday morning, save it once and stop rewriting it. In QueryBear, after running a query you like, click "Save as tool" and give it a name you'll remember, something like daily-order-trend. Back in Claude Code:
Use the daily-order-trend tool.
Claude calls it directly. You get the same query every time, not a slightly different version that happened to group by a different date column. For operational questions you check on a schedule, this is the difference between a tool you trust and one you're always second-guessing.