Labsco
pugltd logo

mcp-postgres-secure

from pugltd

A Model Context Protocol server for PostgreSQL with permission-based access modes.

๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅโœ“ VerifiedAccount requiredNeeds API keys

MCP PostgreSQL Secure

A Model Context Protocol server for PostgreSQL with permission-based access modes. Choose how much database power the AI gets at install time.

Access modes

ModePG_ACCESS_MODEToolsSQL allowed
Read-onlyreadonly (default)query, schema introspectionSELECT, WITH, EXPLAIN, SHOW, etc.
Read + DMLdmlabove + executeDML: INSERT, UPDATE, DELETE, MERGE
Full accessfullabove + execute (DDL)DML + DDL: CREATE, ALTER, DROP, TRUNCATE, etc.

Defense in depth:

  • Application-level SQL classification (blocks multi-statement queries and disallowed statement types)
  • PostgreSQL session default_transaction_read_only = on in readonly mode
  • Connection lock via PG_LOCK_CONNECTION so credentials cannot be swapped at runtime when using env config

Pair each mode with a PostgreSQL role that has matching grants. The server enforces intent; the database user is the final authority.

Available tools

query

Read-only SQL. Supports PostgreSQL ($1, $2) and MySQL-style (?) placeholders.

use_mcp_tool({
  server_name: "postgres-readonly",
  tool_name: "query",
  arguments: {
    sql: "SELECT * FROM users WHERE id = $1",
    params: [1]
  }
});

execute (dml and full modes only)

Mutating SQL. In dml mode: INSERT, UPDATE, DELETE, MERGE only. In full mode: DML and DDL.

use_mcp_tool({
  server_name: "postgres-dml",
  tool_name: "execute",
  arguments: {
    sql: "UPDATE users SET active = $1 WHERE id = $2",
    params: [true, 1]
  }
});

list_schemas, list_tables, describe_table

Schema introspection (all modes).

connect_db

Optional runtime connection when PG_LOCK_CONNECTION=false and env vars are not set. Disabled by default when using env-based config.

PostgreSQL role examples

Read-only user:

CREATE ROLE mcp_readonly LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE your_database TO mcp_readonly;
GRANT USAGE ON SCHEMA public TO mcp_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;

DML user (add write grants, no DDL):

CREATE ROLE mcp_dml LOGIN PASSWORD '...';
-- same as above, plus:
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO mcp_dml;

Admin user (migrations / DDL): grant only on schemas the AI should manage.

Security

  • Parameterized queries for user-supplied values
  • Single-statement enforcement (no ;-chained batches)
  • Statement-type validation per access mode
  • Read-only PostgreSQL transactions in readonly mode
  • Runtime connect_db disabled when connection is env-locked
  • Credentials via environment variables (not chat arguments)

Limitations: validation is keyword-based, not a full SQL parser. Use least-privilege DB roles and non-production databases when possible.

Error handling

The server returns clear errors for:

  • Invalid or disallowed SQL for the current access mode
  • Multiple statements in one request
  • Connection failures
  • Missing parameters
  • Disabled tools (execute in readonly, connect_db when locked)

License

MIT

Upstream

Forked from antonorlov/mcp-postgres-server.