PluginBench
MCP Server
Active
MIT

PostgreSQL MCP Server

io.github.antonorlov/mcp-postgres-server

MCP server for PostgreSQL: query and manage local, Docker, RDS, Neon, Supabase, or SSH-tunneled databases.

What is the PostgreSQL MCP server?

The PostgreSQL MCP server enables Claude and other AI agents to query and optionally modify PostgreSQL databases—local, containerized, or cloud-hosted (RDS, Neon, Supabase)—with read-only enforcement by default and optional SSH tunneling. It provides a small, auditable interface with prepared-statement parameters, result size caps, and session timeouts.

Connect Claude to your PostgreSQL database to run queries, explore schemas and tables, and optionally execute writes. Read-only mode is the default; the server enforces it at the database engine level using PostgreSQL's READ ONLY transactions, not client-side parsing. Supports local Postgres, Docker, Amazon RDS, Neon, Supabase, and databases behind SSH bastions.

How to install PostgreSQL

Copy-paste configuration for popular MCP clients.

transport: stdio
Config generated by PluginBench — verify against the source before use.
Environment / auth
  • DATABASE_URL
    secret

    Full connection string (preferred). Supports sslmode in the URL.

  • PG_HOST

    Database host (fallback when DATABASE_URL is not set).

  • PG_PORT

    Database port.

  • PG_USER

    Database user.

  • PG_PASSWORD
    secret

    Database password.

  • PG_DATABASE

    Database name.

  • PG_ALLOW_WRITE

    When true, execute performs writes and reads are sent directly. Off (default) is read-only: execute refuses writes and each read runs in a READ ONLY transaction.

  • PG_SSLMODE

    TLS mode. require/allow/prefer encrypt without verifying the certificate; verify-ca/verify-full verify it (supply a CA via PG_SSL_CA). Unlike libpq, allow/prefer do not fall back to plaintext, so a server without TLS needs disable.

  • PG_SSL_CA

    Path to a CA certificate file. Setting it by itself implies verify-full.

  • PG_ENABLE_RUNTIME_CONNECT

    Register the connect_db tool (runtime credential switching).

  • PG_MAX_RESULT_BYTES

    Byte budget for a query result sent to the model. Whole rows are kept while they fit; over the budget returnedRows < rowCount and truncated is true.

  • PG_STATEMENT_TIMEOUT

    Statement timeout in milliseconds, applied to every session.

  • PG_CONNECT_TIMEOUT

    Timeout in milliseconds for a single connect attempt (raise it for slow links or SSH tunnels).

  • PG_SSH_HOST

    SSH bastion host. Setting it enables tunneling: the server reaches the database only through an SSH tunnel to this host. Needs the ssh2 optional dependency.

  • PG_SSH_PORT

    SSH bastion port.

  • PG_SSH_USER

    SSH username.

  • PG_SSH_PRIVATE_KEY

    Path to a private key file. If unset, auth falls back like ssh: a running agent (SSH_AUTH_SOCK), then a default key (~/.ssh/id_ed25519, id_rsa, id_ecdsa).

  • PG_SSH_PASSPHRASE
    secret

    Passphrase for the private key, if encrypted.

  • PG_SSH_AGENT

    true to use the ambient agent (SSH_AUTH_SOCK), or an explicit socket path / Windows named pipe.

  • PG_SSH_PASSWORD
    secret

    SSH login password. Opt-in; a key or agent takes precedence. Prefer keys, a bastion often disables password auth.

  • PG_SSH_FINGERPRINT

    Pinned host-key fingerprint (SHA256:...). Host-key verification is mandatory and set only this way: without it the tunnel refuses to connect. Get it with ssh-keygen -lF host.

  • PG_SSH_KEEPALIVE_INTERVAL

    SSH keepalive interval in ms; the tunnel drops after 3 unanswered keepalives, and the next call reconnects.

~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "mcp-postgres-server": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-postgres-server"
      ],
      "env": {
        "DATABASE_URL": "<YOUR_DATABASE_URL>",
        "PG_HOST": "<YOUR_PG_HOST>",
        "PG_PORT": "<YOUR_PG_PORT>",
        "PG_USER": "<YOUR_PG_USER>",
        "PG_PASSWORD": "<YOUR_PG_PASSWORD>",
        "PG_DATABASE": "<YOUR_PG_DATABASE>",
        "PG_ALLOW_WRITE": "<YOUR_PG_ALLOW_WRITE>",
        "PG_SSLMODE": "<YOUR_PG_SSLMODE>",
        "PG_SSL_CA": "<YOUR_PG_SSL_CA>",
        "PG_ENABLE_RUNTIME_CONNECT": "<YOUR_PG_ENABLE_RUNTIME_CONNECT>",
        "PG_MAX_RESULT_BYTES": "<YOUR_PG_MAX_RESULT_BYTES>",
        "PG_STATEMENT_TIMEOUT": "<YOUR_PG_STATEMENT_TIMEOUT>",
        "PG_CONNECT_TIMEOUT": "<YOUR_PG_CONNECT_TIMEOUT>",
        "PG_SSH_HOST": "<YOUR_PG_SSH_HOST>",
        "PG_SSH_PORT": "<YOUR_PG_SSH_PORT>",
        "PG_SSH_USER": "<YOUR_PG_SSH_USER>",
        "PG_SSH_PRIVATE_KEY": "<YOUR_PG_SSH_PRIVATE_KEY>",
        "PG_SSH_PASSPHRASE": "<YOUR_PG_SSH_PASSPHRASE>",
        "PG_SSH_AGENT": "<YOUR_PG_SSH_AGENT>",
        "PG_SSH_PASSWORD": "<YOUR_PG_SSH_PASSWORD>",
        "PG_SSH_FINGERPRINT": "<YOUR_PG_SSH_FINGERPRINT>",
        "PG_SSH_KEEPALIVE_INTERVAL": "<YOUR_PG_SSH_KEEPALIVE_INTERVAL>"
      }
    }
  }
}

Tools & capabilities

Tools this server exposes to the agent.

  • query — Execute read-only SQL statements (SELECT, WITH...SELECT, EXPLAIN, SHOW). Supports $1-style prepared-statement parameters. Returns compact JSON with rows, row count, and a truncated flag if results exceed the byte budget.
  • list_schemas — List all schemas in the connected database.
  • list_tables — List tables in a specified schema (defaults to 'public').
  • describe_table — Get the structure of a table: columns, types, nullability, defaults, and primary keys.
  • execute — Execute INSERT, UPDATE, DELETE, or DDL statements. Requires PG_ALLOW_WRITE=true; refuses writes by default with an error.
  • connect_db — Connect to a different PostgreSQL database at runtime using provided credentials. Only registered when PG_ENABLE_RUNTIME_CONNECT=true.

Use cases

  • Query production or staging databases to retrieve data, analyze schemas, and troubleshoot issues without leaving your IDE.
  • Explore database structure (schemas, tables, columns) to understand data models before writing queries.
  • Automate data migrations, backups, or ETL tasks by executing INSERT, UPDATE, or DELETE statements through Claude.
  • Connect to databases behind SSH bastions or in private networks using SSH tunneling.
  • Maintain read-only safety by default while optionally enabling writes for specific workflows via environment configuration.

PostgreSQL MCP server FAQ

What is the PostgreSQL MCP server?

It's an MCP server that gives Claude and other AI agents the ability to query and optionally modify PostgreSQL databases. It supports local Postgres, Docker, RDS, Neon, Supabase, and databases behind SSH bastions. Read-only mode is the default; writes require explicit opt-in via PG_ALLOW_WRITE=true.

Is it free?

Yes. The server is open-source (available on npm as mcp-postgres-server) and has no licensing fees. You pay only for your database hosting.

How do I install it in Cursor or Claude?

Add it to your MCP configuration (e.g., in Cursor's settings or Claude's config file) with type 'stdio', command 'npx', and args ['-y', 'mcp-postgres-server']. Set DATABASE_URL or individual PG_* environment variables with your database credentials.

Does it require authentication?

Yes. You must provide database credentials via DATABASE_URL or PG_HOST, PG_USER, PG_PASSWORD, and PG_DATABASE environment variables. For SSH tunneling, you also configure PG_SSH_HOST and authentication (private key, passphrase, or password) plus a mandatory host-key fingerprint.

Is it safe to use with production databases?

The server enforces read-only mode by default using PostgreSQL's READ ONLY transactions, not client-side parsing. However, the documentation recommends using a replica, snapshot, or tightly scoped role rather than pointing directly at production. A least-privilege database role is the real security boundary.

Can I use it with databases behind a firewall?

Yes. The server supports SSH tunneling: set PG_SSH_HOST, PG_SSH_USER, PG_SSH_PRIVATE_KEY, and PG_SSH_FINGERPRINT to reach a database only accessible through a bastion host.

README (reference)

Source of truth, from the repository.

MCP PostgreSQL Server

npm version CI

A Model Context Protocol (MCP) server for PostgreSQL: local, Docker, RDS, Neon, and Supabase databases.

The server is small and auditable, with four runtime dependencies: the MCP SDK, pg, pg-connection-string, and zod (plus ssh2, an optional dependency used only for SSH tunneling).

Requires Node.js 20 or newer.

Quick start

The preferred way to configure the server is a single DATABASE_URL:

{
  "mcpServers": {
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "mcp-postgres-server"],
      "env": {
        "DATABASE_URL": "postgres://user:password@localhost:5432/mydb",
        "PG_ALLOW_WRITE": "false"
      }
    }
  }
}

With PG_ALLOW_WRITE set to "false" the server has read-only access to the database. This is the default; set it to "true" only if the model must write.

The same JSON works in any MCP client that speaks stdio: VS Code, Cursor, Claude Code, Codex, Windsurf.

Alternatively, set the individual PG_* variables; they are used when DATABASE_URL is not set:

{
  "mcpServers": {
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "mcp-postgres-server"],
      "env": {
        "PG_HOST": "your_host",
        "PG_PORT": "5432",
        "PG_USER": "your_user",
        "PG_PASSWORD": "your_password",
        "PG_DATABASE": "your_database",
        "PG_ALLOW_WRITE": "false"
      }
    }
  }
}

Manual Installation

npm install mcp-postgres-server

Or run directly with:

npx mcp-postgres-server

Connect to your database

Local Postgres:

DATABASE_URL=postgres://mcp_readonly:secret@localhost:5432/mydb

Postgres in Docker: if the database runs in a container with a published port, connect to localhost:<published-port> as usual. If the MCP server itself runs inside a container and the database runs on your host machine, use host.docker.internal instead of localhost:

DATABASE_URL=postgres://mcp_readonly:secret@host.docker.internal:5432/mydb

Amazon RDS:

DATABASE_URL=postgres://mcp_readonly:secret@mydb.xxxxxx.us-east-1.rds.amazonaws.com:5432/mydb?sslmode=require

Neon:

DATABASE_URL=postgres://mcp_readonly:secret@ep-xxx-xxx.us-east-2.aws.neon.tech/mydb?sslmode=require

Supabase:

DATABASE_URL=postgres://postgres.xxxxxxxx:secret@aws-0-us-east-1.pooler.supabase.com:5432/postgres?sslmode=require

Tools

Tool availability depends on configuration:

ToolAvailable
query, list_schemas, list_tables, describe_tableAlways
executeAlways (refuses writes unless PG_ALLOW_WRITE=true)
connect_dbOnly when PG_ENABLE_RUNTIME_CONNECT=true

1. query

Execute a read-only SQL statement. Accepts SELECT, WITH ... SELECT, EXPLAIN, and SHOW. One statement per call - multi-statement input is rejected by the extended query protocol. In read-only mode (the default) the statement runs as BEGIN READ ONLY, the query, and ROLLBACK - three commands, roughly two network round trips with pipelining - so the database itself refuses any write. With PG_ALLOW_WRITE=true the statement is sent directly, without that wrapper, so a write run through query would execute - use execute for writes. Supports PostgreSQL-style $1, $2 prepared-statement parameters; values are bound by the driver and never spliced into the SQL text.

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

Returns compact JSON: {"rows": [...], "rowCount": n, "returnedRows": n, "truncated": false}. When the serialized rows exceed PG_MAX_RESULT_BYTES, only the rows that fit are returned (returnedRows < rowCount), truncated is true, and a hint suggests adding LIMIT/WHERE or selecting fewer columns.

2. list_schemas

List all schemas in the connected database.

use_mcp_tool({
  server_name: "postgres",
  tool_name: "list_schemas",
  arguments: {}
});

3. list_tables

List tables in the connected database. Accepts an optional schema parameter (defaults to 'public').

// List tables in the 'public' schema (default)
use_mcp_tool({
  server_name: "postgres",
  tool_name: "list_tables",
  arguments: {}
});

// List tables in a specific schema
use_mcp_tool({
  server_name: "postgres",
  tool_name: "list_tables",
  arguments: {
    schema: "my_schema"
  }
});

4. describe_table

Get the structure of a specific table (columns, types, nullability, defaults, primary keys). Accepts an optional schema parameter (defaults to 'public').

use_mcp_tool({
  server_name: "postgres",
  tool_name: "describe_table",
  arguments: {
    table: "users",
    schema: "my_schema"  // optional
  }
});

5. execute - requires PG_ALLOW_WRITE=true

Execute an INSERT, UPDATE, DELETE, or DDL statement. Always registered, but in read-only mode (the default) it refuses with an error naming PG_ALLOW_WRITE and changes nothing - the statement never reaches the database. With PG_ALLOW_WRITE=true it runs: same $1, $2 parameter handling as query, one complete statement per call, and the connecting role governs what it may do. Returns {"rowCount": n, "command": "INSERT"}.

use_mcp_tool({
  server_name: "postgres",
  tool_name: "execute",
  arguments: {
    sql: "INSERT INTO users (name, email) VALUES ($1, $2)",
    params: ["John Doe", "john@example.com"]
  }
});

6. connect_db - requires PG_ENABLE_RUNTIME_CONNECT=true

Connect to a different PostgreSQL database at runtime using provided credentials. Not registered by default - prefer configuring credentials through the environment so they never pass through model-visible arguments. Session limits (statement_timeout, idle_in_transaction_session_timeout) are re-applied after every reconnect; read-only reads enforce read-only in their own BEGIN READ ONLY transaction.

use_mcp_tool({
  server_name: "postgres",
  tool_name: "connect_db",
  arguments: {
    host: "localhost",
    port: 5432,
    user: "your_user",
    password: "your_password",
    database: "your_database"
  }
});

Configuration reference

VariableDefaultDescription
DATABASE_URL-Full connection string (preferred). Supports ?sslmode= in the URL.
PG_HOST-Database host (fallback when DATABASE_URL is not set)
PG_PORT5432Database port
PG_USER-Database user
PG_PASSWORD-Database password
PG_DATABASE-Database name
PG_ALLOW_WRITEfalseWhen true, execute performs writes and reads are sent directly. Off (default) is read-only: execute refuses writes and each read runs in a READ ONLY transaction
PG_SSLMODE-disable | allow | prefer | require | verify-ca | verify-full. require/allow/prefer encrypt without verifying the certificate; verify-ca/verify-full verify (supply a CA via PG_SSL_CA). Unrecognized values fail at startup. Limitation: unlike libpq, allow/prefer do not fall back to plaintext (node-postgres has no opportunistic SSL), so a server without TLS needs disable.
PG_SSL_CA-Path to a CA certificate file. Setting it by itself implies verify-full
PG_ENABLE_RUNTIME_CONNECTfalseRegister the connect_db tool (runtime credential switching)
PG_MAX_RESULT_BYTES32768Byte budget for a query result sent to the model. Whole rows are kept while they fit; over the budget returnedRows < rowCount and truncated: true (if not even the first row fits, returnedRows is 0 with a hint). ~32 KiB ≈ 8k tokens; lower it for strict clients, raise it if your client allows more.
PG_STATEMENT_TIMEOUT30000Statement timeout in milliseconds, applied to every session
PG_CONNECT_TIMEOUT10000Timeout in milliseconds for a single connect attempt (raise it for slow links or SSH tunnels)

To reach a database only accessible through a bastion, see SSH tunneling (adds PG_SSH_* variables).

Features

  • Read-only by default; writes are an explicit opt-in (PG_ALLOW_WRITE=true)
  • Read-only enforced by the engine (BEGIN READ ONLY), never by client-side SQL parsing
  • Data access behind a small typed interface; the pg driver never leaks past it
  • DATABASE_URL support with SSL (sslmode=disable|allow|prefer|require|verify-ca|verify-full, custom CA)
  • Prepared-statement parameters: $1-style placeholders, bound by the driver
  • Result size cap (byte budget) with an explicit truncated flag instead of flooding the model's context
  • Session statement timeout plus a client deadline; transaction poolers may not preserve session settings
  • Errors returned as readable tool results with SQLSTATE-based hints, so the model can self-correct
  • Survives dropped connections - reconnects lazily instead of crashing
  • Optional SSH tunneling (PG_SSH_*) with mandatory host-key verification, loaded only when configured
  • MCP tool annotations (read-only / destructive hints) per spec 2025-11-25
  • Multi-schema support for database operations

Security

Full details, including the threat model and disclosure process, are in SECURITY.md. The short version:

  1. A least-privilege database role is the real boundary. The MCP works with existing credentials; creating or changing roles is not required. A dedicated role is what actually guarantees writes are impossible. On PostgreSQL 14+, the following is a starting point:

    CREATE ROLE mcp_readonly LOGIN PASSWORD 'change-me';
    GRANT CONNECT ON DATABASE your_database TO mcp_readonly;
    GRANT pg_read_all_data TO mcp_readonly;                          -- adds read privileges
    ALTER ROLE mcp_readonly SET default_transaction_read_only = on;  -- read-only by default
    

    (On PostgreSQL 13 or older, grant SELECT explicitly instead of pg_read_all_data - see SECURITY.md.) The server warns on stderr if you connect as a superuser. Read grants do not revoke existing privileges, and defaults remain mutable; available functions, ownership and inherited privileges also matter.

  2. The engine enforces read-only. There is no client-side SQL parsing. In read-only mode every read runs in a rolled-back BEGIN READ ONLY transaction, so PostgreSQL itself - which alone knows what a function, view, or rule does - refuses any write with SQLSTATE 25006 and reverts any session change the statement made. The extended protocol rejects multi-command strings.

Honest framing: the read-only transaction is defense-in-depth on top of the role, not a replacement for it. Read-only mode stops a confused or prompt-injected model from writing to your database; it does not stop prompt injection carried in the row data a query returns. Don't point this server at production - use a replica, a snapshot, or a tightly scoped role. See SECURITY.md.

SSH tunneling

Set PG_SSH_HOST (plus auth and host-key verification) to reach a database that is only accessible through a bastion (an SSH jump host). The connection string / PG_* fields then describe the database as seen from the bastion:

{
  "mcpServers": {
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "mcp-postgres-server"],
      "env": {
        "DATABASE_URL": "postgres://mcp_readonly:secret@db.internal:5432/mydb?sslmode=verify-full",
        "PG_SSH_HOST": "bastion.example.com",
        "PG_SSH_USER": "jump",
        "PG_SSH_PRIVATE_KEY": "/home/me/.ssh/id_ed25519",
        "PG_SSH_FINGERPRINT": "SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}
VariableDefaultDescription
PG_SSH_HOST-SSH bastion host. Setting it enables tunneling: the server reaches the database only through an SSH tunnel to this host (see below). Optional feature; needs the ssh2 optional dependency.
PG_SSH_PORT22SSH bastion port
PG_SSH_USER-SSH username
PG_SSH_PRIVATE_KEY-Path to a private key file. If unset, auth falls back like ssh: a running agent (SSH_AUTH_SOCK), then a default key (~/.ssh/id_ed25519, id_rsa, id_ecdsa)
PG_SSH_PASSPHRASE-Passphrase for the private key, if encrypted
PG_SSH_AGENT-true to use the ambient agent (SSH_AUTH_SOCK), or an explicit socket path / Windows named pipe (\\.\pipe\openssh-ssh-agent)
PG_SSH_PASSWORD-SSH login password. Opt-in; a key or agent takes precedence. Prefer keys - a bastion often disables password auth.
PG_SSH_FINGERPRINT-Pinned host-key fingerprint (SHA256:...). Host-key verification is mandatory and set only this way: without it the tunnel refuses to connect (fail-closed). Get it with ssh-keygen -lF host (reads your known_hosts) or ssh-keyscan host | ssh-keygen -lf - (see the trust note below)
PG_SSH_KEEPALIVE_INTERVAL15000SSH keepalive interval in ms; the tunnel drops after 3 unanswered keepalives, and the next call reconnects
  • SSH changes only the transport. Read-only enforcement, the result size cap, timeouts, and connect_db behave exactly as on a direct connection, and no extra SQL is sent per query.
  • Host-key verification is mandatory via a pinned PG_SSH_FINGERPRINT - the tunnel will not connect without it, so a man-in-the-middle bastion is refused. Get the fingerprint over a channel you trust, most trustworthy first:
    • on the bastion itself, or from its admin: ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub (no network involved);
    • from your existing ~/.ssh/known_hosts, if you already reach the host over ssh: ssh-keygen -lF bastion.example.com;
    • fetched from the host: ssh-keyscan bastion.example.com | ssh-keygen -lf - (trust this only when run from a network position you trust - it accepts whatever the host returns).
  • TLS validates the real database hostname. With verify-full, the certificate is checked against the database's own hostname (e.g. db.internal), not the loopback the tunnel binds locally, and rejectUnauthorized is pinned on so an inherited NODE_TLS_REJECT_UNAUTHORIZED=0 cannot disable it.
  • ssh2 is an optional dependency, loaded only when PG_SSH_HOST is set, so a direct connection never initializes it. npm installs optional dependencies by default; run npm install --omit=optional to skip it entirely (a direct connection does not need it).

A tunneled connection that fails reports a stable SSH_* code - see Error Handling.

Error Handling

SQL and connection failures are returned as tool results (isError: true) with a message, the SQLSTATE code, and a hint. PostgreSQL's own server hint is used when present; otherwise these fallbacks apply:

codemeaningfirst thing to check
28P01authentication failedPG_USER / PG_PASSWORD
3D000database does not existPG_DATABASE
42P01relation not foundcall list_tables
42703column not foundcall describe_table
57014the query was canceled (a timeout or a cancel request)if timing out, add a LIMIT / simplify it, or raise PG_STATEMENT_TIMEOUT
25006the transaction is read-onlysource may be a read-only role, a replica, a server default, or (for query) the read-only wrapper; execute writes need PG_ALLOW_WRITE=true
ECONNREFUSED / ENOTFOUNDcannot reach or resolve the database hostPG_HOST / PG_PORT / DATABASE_URL

Over an SSH tunnel, a failure carries a stable code (and, where the cause is determinate, a hint naming the setting to fix), so the failing phase is unambiguous:

codemeaningfirst thing to check
SSH_CONFIG_INVALIDinvalid SSH config, incl. a malformed PG_SSH_FINGERPRINTthe PG_SSH_* values
SSH_KEY_INVALIDkey unreadable, unparseable, a public key, or encrypted without the right passphrase (an encrypted key with the correct PG_SSH_PASSPHRASE works)PG_SSH_PRIVATE_KEY, PG_SSH_PASSPHRASE
SSH_CONNECT_FAILEDthe bastion is unreachable, or SSH setup failed for an unclassified reasonPG_SSH_HOST, PG_SSH_PORT, reachability
SSH_TIMEOUTthe bastion did not respond in timenetwork/firewall, PG_CONNECT_TIMEOUT
SSH_AUTH_FAILEDthe bastion rejected authenticationPG_SSH_USER and the key/agent/password in use
SSH_HOST_KEY_MISMATCHhost key does not match PG_SSH_FINGERPRINT (stale value or MITM)re-fetch the fingerprint
SSH_FORWARD_FAILEDtunnel is up, but the bastion could not reach the databasethe DB host and port as seen from the bastion
SSH_CONNECTION_LOSTan established tunnel dropped mid-sessiontransient; the next call reconnects

A genuine PostgreSQL error through a healthy tunnel keeps its own code (e.g. 28P01 for wrong database credentials), not an SSH code.

Migrating from 0.1.x

Not needed for new installs. Two behavior changes since 0.1.x:

  1. Read-only by default. The execute tool is always visible but refuses writes (with an error naming the flag) unless PG_ALLOW_WRITE=true, and every read runs inside an engine-enforced READ ONLY transaction. If your workflow writes to the database, set "PG_ALLOW_WRITE": "true" to restore 0.1.x behavior.
  2. connect_db is disabled by default. Runtime connection switching (passing credentials through tool arguments) requires PG_ENABLE_RUNTIME_CONNECT=true; otherwise connection details come only from the environment.

Tool names, parameter names, and PG_* variables are unchanged. Result payloads are now structured compact JSON for every tool (e.g. query returns {rows, rowCount, returnedRows, truncated} instead of a bare row array) - see CHANGELOG.md for the exact shapes before updating anything that parses tool output.

License

MIT

Related MCP servers

241 RF & electronics calculators + 13 simulation tools for AI agents.

2
TypeScript
MIT
View repository →

A simple MCP server for getting weather information.

Generate 26+ chart types and diagrams for AI agents via AntV's MCP server.

4.2k
TypeScript
MIT
View repository →

Local-first multi-agent coordination for messages, leases, shared plans, status, and resources.

4
Python
AGPL-3.0
View repository →

Local-first Garmin data warehouse: sync once to SQLite, analyze trends and correlations offline.

3
Python
MIT
View repository →

Search Meta, Google Ads, LinkedIn, and TikTok ad libraries plus creative analysis via MCP.

0
MIT
View repository →