MCP with Databases
Learning Objectives
- Set up the PostgreSQL MCP server
- Query databases directly from Claude Code
- Use Claude for schema analysis and query optimization
- Understand safety considerations for database MCP
Claude Meets Your Database
Reading code gives Claude one perspective on your data. Reading the actual database gives it another — the complete picture.
With a database MCP server, Claude can:
- See the real schema (columns, types, constraints, indexes)
- Query actual data to understand patterns
- Suggest optimizations based on real cardinality
- Validate data integrity
- Help debug data-related issues
This is transformative for database work. Instead of describing your schema to Claude, it reads it directly.
Setting Up PostgreSQL MCP
Installation
claude mcp add postgres \
-e DATABASE_URL=postgresql://user:password@localhost:5432/mydb \
--transport stdio \
npx -y @modelcontextprotocol/server-postgres
Using a Connection String from Environment
If your DATABASE_URL is already in your shell environment:
claude mcp add postgres \
-e DATABASE_URL=$DATABASE_URL \
--transport stdio \
npx -y @modelcontextprotocol/server-postgres
Verify Connection
/mcp
# Should show: postgres stdio connected [tools: query, schema, ...]
What You Can Do
Explore Schema
"Show me the complete database schema — all tables, columns, types,
and relationships"
Claude runs schema inspection queries and returns a comprehensive view of your database structure.
"What indexes exist on the orders table? Are there any missing indexes
based on the query patterns in our codebase?"
Query Data
"How many orders were placed in the last 7 days? Break down by status."
Claude writes and executes the SQL:
SELECT status, COUNT(*) as count
FROM orders
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY status
ORDER BY count DESC;
Debug Data Issues
"We're seeing duplicate entries in the order_items table. Find all
orders that have duplicate items and show me the pattern."
Claude queries the database, finds the duplicates, and identifies the pattern causing them — maybe a race condition or a missing unique constraint.
Suggest Optimizations
"Analyze the orders table. Given its size and the queries we run
(check src/repos/order-repo.ts for the query patterns), suggest
index improvements."
Claude reads your repository code to understand query patterns, then checks the database for existing indexes, and suggests new ones based on the actual data distribution.
Safety Considerations
Database access is powerful — and dangerous. Here's how to use it safely.
Use a Read-Only User
This is non-negotiable. Create a read-only database user for MCP:
-- Create a read-only user
CREATE ROLE claude_reader WITH LOGIN PASSWORD 'secure_password';
-- Grant read-only access
GRANT CONNECT ON DATABASE mydb TO claude_reader;
GRANT USAGE ON SCHEMA public TO claude_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO claude_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO claude_reader;
Use this user in your connection string:
claude mcp add postgres \
-e DATABASE_URL=postgresql://claude_reader:secure_password@localhost:5432/mydb \
--transport stdio \
npx -y @modelcontextprotocol/server-postgres
Now Claude can SELECT but never INSERT, UPDATE, DELETE, or DROP.
Environment-Specific Rules
| Environment | Should You Connect? | How? |
|---|---|---|
| Local dev | Yes | Full access or read-only |
| Staging | Carefully | Read-only user only |
| Production | Read-only replica only | Read-only user on read-only replica |
| CI/CD | No | Use test database only |
Permission Scoping
Restrict MCP database tools in settings.json:
{
"permissions": {
"allow": [
"mcp__postgres__query"
],
"deny": [
"mcp__postgres__execute"
]
}
}
Allow query (read) but deny execute (write) for an additional layer of protection.
What Not to Do
- Never connect to production primary with a read-write user
- Never put database credentials in CLAUDE.md (use env vars)
- Never let Claude run EXPLAIN ANALYZE on production without understanding the query first
- Never connect to databases containing PII without appropriate data handling policies
Real-World Database Workflows
Data Model Review
"Review our database schema. Check for:
1. Missing foreign key constraints
2. Columns that should have NOT NULL but don't
3. Tables missing created_at/updated_at timestamps
4. Potential N+1 query risks based on the relationships"
Migration Preparation
"I want to add a 'canceled_at' column to the orders table.
Check the current table structure, estimate the number of rows
that would be affected, and write a safe Prisma migration that
won't lock the table for too long."
Data Integrity Audit
"Audit the data integrity:
1. Are there orphaned records (order_items without orders)?
2. Are all foreign keys consistent?
3. Are there any NULL values in required fields?
4. How's the index health?"
Performance Debugging
"The /api/orders endpoint is slow. Read the query in
src/repos/order-repo.ts, then check the database for:
1. Missing indexes on the columns we filter/sort by
2. Table sizes and row counts
3. The actual query plan (EXPLAIN on the query)
Give me specific index recommendations."
Other Database Servers
PostgreSQL is the most common, but MCP servers exist for other databases:
MySQL
claude mcp add mysql \
-e MYSQL_URL=mysql://user:pass@localhost:3306/mydb \
--transport stdio \
npx -y @modelcontextprotocol/server-mysql
SQLite
claude mcp add sqlite \
-e DB_PATH=./data/app.db \
--transport stdio \
npx -y @modelcontextprotocol/server-sqlite
The workflow is the same regardless of the database engine — Claude queries through the MCP server and gets structured results.
Key Takeaway
Database MCP servers give Claude direct access to your data — schema inspection, data queries, index analysis, and integrity checks. Always use a read-only database user (non-negotiable for anything beyond local dev). Connect to staging/production only through read-only replicas. The combination of code context (from file access) plus data context (from database MCP) gives Claude a complete picture of your application that neither provides alone.