postgres-mcp-query-tool
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@postgres-mcp-query-toolquery prod for the latest user join time"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
postgres-mcp-query-tool
An MCP server that gives an AI agent scoped, safe access to your Postgres databases. Configure as many named connections as you like — each with its own access mode, row cap, and timeout — so the same agent can have full read/write on local and strict read-only on prod without ever confusing the two.
Ask "query prod for the latest user join time" and the agent sees that
prodis read-only, routes aSELECTthrough the read tool, and physically cannot write to it.
Inspired by PlanetScale's MCP server query executor, reworked for plain Postgres with per-connection access control.
Features
Multiple named connections — define
local,prod,staging, etc. in one config.Per-connection access mode —
read_onlyorread_write. Read-only connections refuse every write.Defense-in-depth read-only enforcement — two independent layers:
A SQL validator rejects writes up front with a clear message.
Reads run inside a
BEGIN READ ONLYtransaction, so Postgres itself rejects writes even if the validator is ever fooled. (For a third layer, point the connection at a Postgres role with no write grants.)
Hard row caps — per-connection
max_rows. Exceeding it is a clean error, never a silent truncation.Configurable timeouts — per-connection
timeout_seconds(default 30s) enforced viastatement_timeout, plus a client-side backstop that cancels a wedged query. Long queries never hang.Two-phase confirmation for destructive writes — DDL (
CREATE/DROP/ALTER/…) andDELETEare refused until the agent re-issues them withconfirm_destructive: trueafter you approve the exact statement.Dangerous statements blocked outright —
TRUNCATE, andDELETE/UPDATEwith noWHEREor an always-trueWHERE(e.g.WHERE 1=1).Credentials stay secret —
list_connectionsnever reveals URLs; the server never logs SQL or rows.Inline or file config — pass config as a file path or drop the whole JSON straight into the MCP definition. No separate file required.
Related MCP server: MCP Server for Database
Tools
Tool | Purpose |
| Lists each connection's |
| Runs a read-only query ( |
| Runs a write against a |
Install
npm install
npm run buildConfigure
Each connection takes:
Field | Required | Notes |
| one of | A literal Postgres URL, or the name of an env var holding it. Use |
| yes |
|
| no | Hard cap on returned rows. Default |
| no | Per-query timeout. Default |
| no | Schema (or comma-separated list) set as the |
Example (config.example.json):
{
"connections": {
"local": {
"url": "postgres://postgres:postgres@localhost:5432/postgres",
"access": "read_write",
"max_rows": 10000,
"timeout_seconds": 30
},
"prod": {
"url_env": "PROD_DB_URL",
"access": "read_only",
"max_rows": 1000,
"timeout_seconds": 30,
"default_schema": "public"
}
}
}Wire into your MCP client
Add to your MCP client config (e.g. ~/.claude.json under mcpServers). There are two ways to supply the config.
Option A — inline config (no separate file)
Drop the whole config into the POSTGRES_MCP_CONFIG env var. Nothing else on disk:
{
"mcpServers": {
"postgres-query": {
"command": "node",
"args": ["/absolute/path/to/postgres-mcp-query-tool/dist/index.js"],
"env": {
"PROD_DB_URL": "postgres://reader:secret@prod-host:5432/app",
"POSTGRES_MCP_CONFIG": "{\"connections\":{\"local\":{\"url\":\"postgres://postgres:postgres@localhost:5432/postgres\",\"access\":\"read_write\",\"max_rows\":10000},\"prod\":{\"url_env\":\"PROD_DB_URL\",\"access\":\"read_only\",\"max_rows\":1000}}}"
}
}
}
}You can also pass it on the command line with --config-json '<json>'.
Option B — config file
{
"mcpServers": {
"postgres-query": {
"command": "node",
"args": [
"/absolute/path/to/postgres-mcp-query-tool/dist/index.js",
"--config",
"/absolute/path/to/config.json"
],
"env": {
"PROD_DB_URL": "postgres://reader:secret@prod-host:5432/app"
}
}
}
}Config source precedence (first match wins): --config-json → POSTGRES_MCP_CONFIG env var → --config <path> → ./config.json.
Run standalone
node dist/index.js --config /absolute/path/to/config.json
# or
POSTGRES_MCP_CONFIG='{"connections":{...}}' node dist/index.jsError shape
Tool errors come back with isError: true and a JSON body:
{ "error": "row_limit_exceeded", "message": "...", "details": { "max_rows": 1000, "connection": "prod" } }Codes: row_limit_exceeded, query_timeout, validation_failed, needs_confirmation, read_only_connection, unknown_connection, postgres_error.
Security notes
Keep production credentials out of the config file. Use
url_env(or the inlinePOSTGRES_MCP_CONFIGenv var) so secrets live in the client's environment, not in a checked-in file.Read-only enforcement is real defense-in-depth. Even if the validator is bypassed,
BEGIN READ ONLYmakes Postgres reject the write. For the strongest guarantee, also connect with a Postgres role that has no write privileges.The server never logs SQL or returned rows — only startup/shutdown diagnostics on stderr.
Acknowledgements
Inspired by PlanetScale's MCP server and its query executor.
This server cannot be deployed
Maintenance
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
- XataOAuthio.github.xataio
Xata MCP server lets AI agents interact with your Xata projects, and Postgres database branches.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Related MCP Servers
- AlicenseAqualityDmaintenanceA production-grade MCP server that gives AI agents safe, authenticated access to a PostgreSQL database.3MIT
- FlicenseNot gradedqualityFmaintenanceA read-only MCP server that enables AI agents to explore database schemas and execute safe queries on PostgreSQL and MySQL.-
- AlicenseNot gradedqualityAmaintenanceA hardened, read-only Postgres MCP server that enables LLMs to safely query databases without write, DDL, shell, or credential exposure.MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that provides safe, read-only SQL access for AI agents to query databases (PostgreSQL, MySQL, SQLite) with schema awareness and guardrails.5 npmMIT