How to Set Up a Postgres MCP Server With Claude Code
Spencer Pauly
•4 min read
I was elbow-deep in a refactor when a Slack ping landed: "hey can you pull a list of users who signed up last week but never came back?" Not a big ask. But switching contexts, opening a psql terminal, and writing the query by hand felt brutal at that exact moment. I wanted to just ask it in plain English and move on. That's the setup this post walks through.
We'll connect your Postgres database to Claude Code through QueryBear's MCP server. Fifteen minutes tops.
Pasting your DATABASE_URL directly into Claude's environment gives the agent the same permissions as that database user, with no audit trail and no per-column visibility control. QueryBear sits in between: it runs a SQL parser that blocks anything that isn't a SELECT, lets you allowlist exactly which tables are visible, blocks specific columns (think password_hash, ssn_last_4), enforces a row limit, and logs every query. For the full breakdown, see the Postgres MCP Server guide.
Choose Postgres, then paste your connection URL. Format: postgres://user:pass@host:5432/dbname. Point this at a read replica if you have one.
Under "Allowed tables," pick the tables you want the agent to see. Leave anything sensitive off the list.
Under "Blocked columns," add any column you wouldn't want appearing in your terminal: password_hash, totp_secret, stripe_customer_id, whatever applies.
Save. QueryBear will test the connection and confirm it's live.
Install the QueryBear MCP server in Claude Code
Run this in your terminal:
claude mcp add --transport http querybear https://mcp.querybear.com/mcp
That's it. Claude Code will walk you through the OAuth flow. Once it's done, three tools are available in every Claude Code session: list_connections, get_schema, and run_query. All three proxy through QueryBear.
Ask your first question
Start a Claude Code session in any project directory. Ask something in plain English:
I asked: "Which users signed up in the last 7 days but haven't logged in since?"
Claude Code generated this query and ran it through QueryBear:
SELECT id, email, created_atFROM usersWHERE created_at >= now() - interval '7 days' AND last_login_at IS NULL;
Got back 23 rows. The whole round trip took under a second.
Claude first calls get_schema to see what columns are available, then writes the query, then calls run_query. You just see the result. If the query touches a blocked column or a table not on the allowlist, QueryBear returns a clear rejection message before anything reaches the database.
A Claude Code-specific tip
Claude is good at generating queries on the fly, but if you find yourself asking the same question every week, save it. In QueryBear, after running a query you like, hit "Save as tool" and give it a short memorable name, like inactive-new-signups. Next time you're in Claude Code, just say:
Use the inactive-new-signups tool.
Claude calls it directly. Same query, same columns, same format every time. No SQL roulette, no slight variations depending on Claude's mood that day. This is the workflow change that makes QueryBear feel like a real reporting layer, not a novelty.