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 queryio

Read-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

  1. 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.

  2. 02

    Start from the record

    inspect_row
    {
      "table": "public.users",
      "key": { "id": 4821 }
    }
    
    # ← the row, plus rows
    #   linked by foreign keys

    QueryIO gives the agent the record and relevant linked rows instead of making it guess which table matters next.

  3. 03

    Dig deeper with SQL

    query
    SELECT count(*)
    FROM users
    WHERE email_verified_at IS NOT NULL
      AND activated_at IS NULL;
    
    # ← bounded, read-only

    For questions across many records, the agent can use ordinary SQL through the same controlled interface.

Why QueryIO

Typical database MCP

SQL access

The 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 → result

QueryIO

record context + SQL

The 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 needed

Database 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.

scopewhat that means
enforcedNothing the agent runs can commit a write, with a non-superuser role.
enforcedCredentials come only from QUERYIO_DATABASE_URL. Never from arguments or .env files.
not guaranteedQueryIO is not a sandbox. An agent with shell access can run psql on its own.
not guaranteedRedaction matches column names. A hand-written query can alias a column past it.
not guaranteedA superuser role, dblink or foreign data wrappers break the read-only guarantee.

All limits are defaults you can change.

Quick start

  1. 01Set QUERYIO_DATABASE_URL
    export QUERYIO_DATABASE_URL="postgres://user:password@localhost:5432/my_database"
  2. 02Check the connection
    npx -y queryio check
  3. 03Add it to Claude Code
    claude mcp add queryio -e QUERYIO_DATABASE_URL="postgres://user:password@localhost:5432/my_database" -- npx -y queryio
  4. 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

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
View on npm