Open source · MIT · v0.1.0

A Postgres MCP server that stays read-only

A drop-in replacement for the archived reference server. Other Postgres MCP servers give Claude your schema; this one also gives it your business definitions, and the agent adds what it learns.

$ npx @contextflo/postgres-mcp postgresql://localhost/mydb

Setup

Add it to your MCP client. Node.js 20 or later.

Loading code sample...
  • Claude Code: run
    Loading code sample...
  • Cursor: .cursor/mcp.json, same shape.
  • Claude Desktop: claude_desktop_config.json in ~/Library/Application Support/Claude/ (macOS) or %APPDATA%\Claude\ (Windows).
  • VS Code: .vscode/mcp.json, with servers in place of mcpServers.

Then generate a context file:

Loading code sample...

That writes .contextflo/context.md, seeded from your COMMENT ON values, and prints the CREATE ROLE snippet for a read-only role.

Tools

ToolWhat it does
queryRuns one read-only statement: SELECT, WITH ... SELECT, EXPLAIN, or SHOW.
list_tablesLists readable tables with descriptions. pattern matches anywhere in the name or description.
get_table_contextColumns, types, keys, foreign key targets, enum values, curated descriptions.
add_table_contextLets the agent note a gotcha it found (amount is in cents) in the context file.

Read-only, four layers

Each layer stops the archived server's exploit on its own.

  1. Extended query protocol. Postgres itself rejects multi-statement input.
  2. Read-only connection. Every statement runs in BEGIN READ ONLY and always ends in ROLLBACK.
  3. The real Postgres parser. The whole parse tree is walked, so a write hidden in a CTE is caught.
  4. A read-only role. Enforced by Postgres regardless of the code above.

The known exploit, sent to this server:

Loading code sample...

Not covered: a user-defined function called from a SELECT can do whatever its body does, which is why the read-only role is the recommended setup. And read-only is not confidentiality: the model can read anything the role can.

Migrating from @modelcontextprotocol/server-postgres

The reference server was archived in May 2025 and deprecated on npm on July 10, 2025, yet it was still downloaded about 105,000 times in the week of September 19 to 25, 2026. Swap the package name. The tool is still query, still takes sql. Deliberate differences:

  • Multi-statement SQL and SET/RESET are rejected with a clear error.
  • Results are capped at 1000 rows and 50,000 characters by default. Truncation is always stated.
  • Schema discovery is a tool, not just a resource.
  • All non-system schemas are visible, not only public.

The context file

Seeded from your existing COMMENT ON values, edited by you, and appended to by the agent when it finds a gotcha. Keep it in git and review the diff.

Loading code sample...

Everything above ## Tables is handed to the model. Your text wins over COMMENT ON, and edits apply on the next tool call with no restart.

Options

Loading code sample...

DATABASE_URL supplies the connection string if you do not pass one.

Using it with a team? Contextflo adds shared definitions, per-person access control and an audit trail. Try Contextflo