@infoinlet/mcp-postgres-nl-query
v0.1.1
Published
RLS/tenant-aware Postgres access for AI agents — list/describe schema, run read-only SQL, and NL→SQL with safety rails. MCP server.
Readme
postgres-nl-query
RLS/tenant-aware Postgres access for AI agents, as an MCP server. Five tools:
list_tables, describe_table, query_sql, query_nl (NL→SQL via OpenRouter), explain_query.
Design doc: ../../docs/06-POSTGRES-NL-QUERY-MCP.md.
Safety model (defense in depth)
- Connect with a least-privilege role. RLS policies on your DB apply to it automatically — that's the real guard.
- Read-only by default (
PG_WRITE_ALLOWED=false):query_sqlrejects anything that isn't a singleSELECT/WITH/EXPLAIN(static guard insql-guard.ts), and runs it inside aBEGIN READ ONLYtransaction. - Row cap + timeout: every read is wrapped in an outer
LIMIT(PG_MAX_ROWS) and astatement_timeout(PG_STATEMENT_TIMEOUT_MS). - Tenant guard: set
PG_TENANT_COLUMN/PG_TENANT_VALUEand NL→SQL is instructed to filter every tenant-scoped table (RLS still backs it). - Human-in-the-loop:
PG_NL_REQUIRE_APPROVAL=truemakesquery_nlreturn the generated SQL without executing — the agent (or a human) then runs it viaquery_sql.
Run
cp .env.example .env # set PG_URL (+ OPENROUTER_API_KEY for query_nl)
npm install
npm run build
node dist/server.js # stdio MCP serverMCP client config (e.g. Claude Desktop / Code):
{
"mcpServers": {
"postgres-nl-query": {
"command": "node",
"args": ["/opt/postgres-nl-query/dist/server.js"],
"env": { "PG_URL": "postgres://agent_readonly:...@host:5432/appdb", "OPENROUTER_API_KEY": "sk-or-..." }
}
}
}Why it's differentiated
Generic Postgres MCP servers exist; this one is multi-tenant aware (per-tenant filtering), read-only-by-default with a real static guard + READ ONLY tx, and supports an approval gate for NL→SQL — the things enterprises need before letting an agent near production data.
