A secure MCP server for PostgreSQL.
Connect Claude, Cursor, or any MCP client to your database with read-only access, column filtering, and query limits. Open source, self-hostable, one small TypeScript server.
Works with Claude Desktop, Cursor, Windsurf, Zed, and any MCP-compatible client.
Tools
Four tools for reading a database.
query{ sql, schema? }Run a read-only SELECT. Returns rows, column names, and a row count. Anything that isn't a SELECT is rejected before it reaches the database.
list_tables{ schema? }List every table in a schema (default: public) so the assistant can learn the shape of your database.
describe_table{ table, schema? }Return column names, data types, nullability, and defaults for a table.
list_schemas( )List all non-system schemas — useful for multi-tenant or large databases.
Security
Read-only by default. No unsafe opt-in.
Every query runs through a security pipeline before it touches your database. The controls below are always on.
INSERT, UPDATE, DELETE, DROP, TRUNCATE, and all DDL are rejected before execution.
Statement stacking (;), line and block comments, and EXEC-style calls are blocked at the parser level.
Sensitive columns — passwords, tokens, secrets — are stripped from every result. Configurable via BLOCKED_COLUMNS.
Results are capped at MAX_ROWS with a truncation flag, so an assistant can't dump an entire table by accident.
A statement_timeout from QUERY_TIMEOUT_MS kills runaway queries and protects the database under load.
Quick start
Add it to your MCP client.
Point it at a connection string and you're done. For Claude Desktop, add this to claude_desktop_config.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["@querybear/postgres-mcp-server"],
"env": {
"DATABASE_URL": "postgresql://user:pass@host:5432/db"
}
}
}
}Optional environment variables:
DATABASE_URL postgresql://… # required MAX_ROWS 500 # default 1000 QUERY_TIMEOUT_MS 15000 # default 30000 BLOCKED_COLUMNS password,token # comma-separated
Full configuration and adapters for other clients are in the README.
For teams
Works perfectly for one. Outgrows it fast.
The OSS server is one connection, one user, one set of rules. When any of these come up, you need something more:
There's no per-user configuration. Everyone shares the same connection and the same rules — or you spin up separate servers per person.
Every query passes through, but nothing is recorded. No user attribution, no history, nothing to show a security audit.
Marketing, engineering, and execs all need different table access. There's no per-user allow-list or column-level policy.
QueryBear handles all of this.
The managed version of this server — same security model, plus per-user RBAC, column-level access control, table allow-lists, audit logs, and SSO. Nothing to host, nothing to manage.
Try QueryBear