Databases: Natural Language Queries
- Connect a PostgreSQL or MySQL database to Claude Code using the @bytebase/dbhub stdio server and a DSN connection string
- Create a read-only database user and configure safe credential handling using environment variable expansion
- Use Claude to explore schema, run analytic queries, and answer data questions without writing SQL manually
Answering a data question that requires three SQL joins
Data questions arise constantly during development: how many users completed onboarding this week, what is the average session length by plan tier, which customers have not logged in for 90 days. The standard workflow is to open a database client, recall or look up the schema, write the SQL, run it, read the output, and then bring the answer back to whatever you were working on.
With a database MCP server connected, you ask Claude the question in plain English. Claude queries the database, reads the result, and answers — or it can explain what the data suggests and propose a code change based on what it found.
The @bytebase/dbhub server
The official Claude Code documentation uses @bytebase/dbhub as the database MCP server. It supports PostgreSQL, MySQL, and several other databases through a connection string (DSN) and runs as a local stdio process — meaning it runs on your machine and connects to whatever database host your connection string points at.
You do not need a separate database running locally. The DSN can point at your development database, a staging database, or a read replica of production — wherever the data you want to query lives.
Creating a read-only database user
Before connecting, create a dedicated read-only user for Claude to use. This is a simple but important safety step: even if Claude is directed to run a destructive query by an injected instruction, a read-only credential cannot execute it.
For PostgreSQL:
CREATE USER readonly_claude WITH PASSWORD 'your-password'; GRANT CONNECT ON DATABASE your_database TO readonly_claude; GRANT USAGE ON SCHEMA public TO readonly_claude; GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_claude; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_claude;
For MySQL:
CREATE USER 'readonly_claude'@'%' IDENTIFIED BY 'your-password'; GRANT SELECT ON your_database.* TO 'readonly_claude'@'%'; FLUSH PRIVILEGES;
Use these credentials — not your application's read-write credentials — when building the DSN for Claude.
Adding the server
The DSN format for PostgreSQL is postgresql://user:password@host:port/database. For MySQL it is mysql://user:password@host:port/database.
Add the server with the DSN as an environment variable:
claude mcp add --env POSTGRES_DSN="postgresql://readonly_claude:password@db.example.com:5432/mydb" --transport stdio db -- npx -y @bytebase/dbhub --dsn ${POSTGRES_DSN}
A cleaner approach is to keep the DSN in your shell environment and reference it in your project .mcp.json:
{
"mcpServers": {
"db": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${POSTGRES_DSN}"],
"env": { "POSTGRES_DSN": "${POSTGRES_DSN}" }
}
}
}
This file is safe to commit — the actual DSN comes from your environment at startup. Set export POSTGRES_DSN="postgresql://..." in your shell profile and Claude Code expands it when it launches the server.
Exploring schema and running queries
Once connected, Claude has full read access to your database schema and can answer data questions:
What tables do we have and what does each one store?
Claude discovers the schema through the MCP server and describes each table's purpose based on column names and relationships.
How many users signed up in the last 30 days, broken down by plan?
Claude writes the SQL, executes it through the MCP server, and returns the result in a readable format. You did not need to remember the table or column names.
Find customers who have not logged in for 90 days and have an active paid subscription.
Claude joins the relevant tables, applies the conditions, and returns the result. The query runs against real data and returns real numbers.
The safety discipline for production databases
There is a strong argument for pointing Claude at a read replica or staging database rather than production, especially when you are first exploring. A read-only credential prevents writes, but queries against a large production table can still put load on your database. A replica carries the same data with no impact on production traffic.
If you must connect to production, keep your Claude sessions focused: ask specific questions rather than open-ended exploration queries that might scan large tables. The read-only user ensures no data is modified, but query load is still real.
- The @bytebase/dbhub stdio server connects Claude to PostgreSQL, MySQL, and other databases through a standard DSN connection string — no separate local database required.
- Create a dedicated read-only database user before connecting — a SELECT-only credential prevents writes even if Claude is misdirected by a prompt injection attempt.
- Store your DSN in a shell environment variable and reference it with <code>${VAR}</code> in .mcp.json — the config file stays safe to commit and the credential never appears in version control.
- Claude can discover schema, answer analytic questions, and run joins in plain English — you specify what you want to know, not how to write the SQL to find it.
- Point Claude at a read replica or staging database when possible — a read-only credential prevents writes but does not prevent query load on production.