PostgreSQL MCP · for coding agents
Database context for coding agents.
Your coding agent knows your code. QueryIO lets it inspect the real PostgreSQL records behind it — including the rows connected to them — and use SQL when it needs to go deeper.
npm i queryioRead-only · bounded · redacted · audited
See it work
Start from a real record. See the context around it before the agent decides what to query next.
How it works
- 01
Connect PostgreSQL
bash# Set the connection export QUERYIO_DATABASE_URL="postgres://…" # Check the role npx -y queryio check
Connect QueryIO to PostgreSQL with controlled read-oriented access. The preflight prints SQL for a read-only role if you need one.
- 02
Start from the record
inspect_row{ "table": "public.users", "key": { "id": 4821 } } # ← the row, plus rows # linked by foreign keysQueryIO gives the agent the record and relevant linked rows instead of making it guess which table matters next.
- 03
Dig deeper with SQL
querySELECT count(*) FROM users WHERE email_verified_at IS NOT NULL AND activated_at IS NULL; # ← bounded, read-onlyFor questions across many records, the agent can use ordinary SQL through the same controlled interface.
Why QueryIO
Typical database MCP
SQL accessThe agent works out the path through the data one query at a time.
- The agent decides which tables to query.
- Each result can lead to another query.
- Anything it does not think to check can be missed.
think → SQL → result → think → SQL → resultQueryIO
record context + SQLThe agent starts with the record and what is connected to it.
- Start from a customer, user, job, order, project, or another record.
- QueryIO exposes useful connected data first.
- Then the agent uses SQL when deeper investigation is useful.
record → record + linked rows → SQL if neededDatabase MCPs differ, and many offer read-only SQL, schema tools and safety controls. QueryIO runs SQL too; the difference is where the agent starts. Linked rows are rows one declared foreign key away.
What it does
Inspect a record
inspect_row fetches one row by its primary key, plus everything one foreign key away, in a single call.
Follow linked rows
Rows it references and rows referencing it, up to 5 per relation, with has_more when there are more.
Run read-only SQL
query runs one SELECT, WITH, VALUES, TABLE or SHOW statement per call. No chaining.
Understand the schema
list_tables and describe_tables return columns, keys, indexes and planner stats without scanning tables.
Bounded results
SQL results stop at 100 rows or 32 KB. Values longer than 200 characters are cut with a size marker.
Redact sensitive values
Columns named like password, token or api_key come back as [redacted].
Read-only execution
Every call runs in a READ ONLY transaction that is always rolled back.
Server-side timeouts
Postgres cancels statements after 5 seconds and lock waits after 1 second.
Audit operations
One JSON line per call records the tool, tables and sizes. Row values are never logged.
All limits are defaults you can change.
Quick start
- 01Set QUERYIO_DATABASE_URL
export QUERYIO_DATABASE_URL="postgres://user:password@localhost:5432/my_database" - 02Check the connection
npx -y queryio check - 03Add it to Claude Code
claude mcp add queryio -e QUERYIO_DATABASE_URL="postgres://user:password@localhost:5432/my_database" -- npx -y queryio - 04Ask a database-backed question“Why is this customer still on the Free plan?”
Using Codex or another MCP client?
Add the same server to the client's config file. QueryIO runs as a local stdio server through npx, so there is no install step.
{
"mcpServers": {
"queryio": {
"command": "npx",
"args": ["-y", "queryio"],
"env": {
"QUERYIO_DATABASE_URL": "postgres://user:password@localhost:5432/my_database"
}
}
}
}Node 20+ · PostgreSQL · any MCP client that runs local stdio servers · configuration options on npm
Benchmark
A coding agent ran five tasks against a seeded SaaS database with raw psql or QueryIO, with DBHub as a reference: 25 runs, every answer graded by hand. Three tasks were about specific records; two counted across many rows.
- Database calls
- 16 → 13
- Median, record-level tasks, psql → QueryIO
- Database output
- 25 KB → 16 KB
- Median, record-level tasks, psql → QueryIO
- Correct answers
- 100%
- Every arm, graded by hand
In each record-level task, a record lookup in at least one run surfaced the fact that explained the problem: a missing membership, a duplicate invoice, and an API key that was never revoked.
What it didn't show
- We set a target in advance: about 30% fewer calls or less output. Averages missed it: 17% fewer calls and 21% less output on record-level tasks.
- On the counting tasks, QueryIO used more output on average, not less.
- It is a small study: two runs per task, one model.
- We measured bytes of database output, not model tokens.
- The QueryIO runs used a command-line wrapper, not the MCP server.
Get started
Give your coding agent the database context it is missing.
Connect PostgreSQL and start investigating real records from your coding agent.
npm i queryio