The usual way to give an agent Postgres is to paste a connection string, at which point the permissions are the database user's and the audit trail says nothing about who asked. Here the agent is its own principal with its own grants, the tool list it sees is the shape of those grants, and every statement it runs is parsed and checked before execution and then recorded with the tool name and the agent. Two practical notes: results on the MCP route are capped at 1000 rows so a broad `SELECT` cannot flood the context, and a delegated agent can never exceed the person it acts for.
Pgconsole is a web-based PostgreSQL editor — a single binary and a single config file, with no database of its own to run — that gives a team access control and audit logging over shared Postgres connections. Its MCP server exposes those same connections to external agents such as Claude Code, Cursor, VS Code Copilot and CI bots over a Streamable HTTP endpoint at `/mcp`. The point is that the agent never receives database credentials: it presents a token, resolves to a defined principal, and every statement it sends goes through the same permission checks and audit trail as a human clicking Run.
- `list_connections` — the connections this agent can reach, each with the permissions granted on it
- `list_objects` — browse a connection's catalog; without a schema it lists schemas with counts, with one it returns a paginated, filterable list of tables and views including kind, estimated rows, size and comment
- `describe_table` — one table or view in full: columns, primary and foreign keys, indexes, constraints and comments
- `explain_query` — plan a single `SELECT`, with `analyze`, `buffers` and `format` options; unlocked by the `explain` permission
- `query` — read-only statements, unlocked by `read`, capped at 1000 rows with `truncated: true` and the real `rowCount` reported when the cap bites
- `write_data` — `INSERT`, `UPDATE`, `DELETE` and `COPY`, unlocked by `write`
- `run_ddl` — `CREATE`, `ALTER`, `DROP`, `GRANT`, `REVOKE` and the rest, unlocked by `ddl`
- A tool list shaped by permissions: an agent is only shown the tools its grants unlock, so an agent with `read` never sees a way to write
- Statement-level enforcement rather than trust: the SQL is parsed and each statement's required permission must match the tool it arrived through, so a `DROP` sent to `query` — or a mixed batch — is refused before the database is touched
- Two kinds of principal: a pure agent authorised by `agent:<id>` IAM rules, or a delegated agent acting `on_behalf_of` a user, which inherits that user's permissions, can be narrowed further, and loses access when the user does
Node.js 20+, a running pgconsole instance, and the Postgres connections you want reachable defined in `pgconsole.toml`. Each agent is an `[[agents]]` entry with an id and a token; clients send it as `Authorization: Bearer <token>` and requests without a valid one get `401`. One thing to set deliberately: if no `[[iam]]` rules exist at all, IAM is off and agents can reach every connection — define at least one rule to bring least privilege into effect. Install with `npm install -g @pgplex/pgconsole` and run `pgconsole --config pgconsole.toml`, use `npx`, or run the `pgplex/pgconsole` container on port 9876. Starting it without `--config` opens a demo mode with a bundled sample database.
One command plus a key — npm install -g @pgplex/pgconsole, then supply credentials
