Postgres MCP Server: What It Is & How To Set It Up In 2026
A Postgres MCP server gives an AI client such as Claude, Cursor or VS Code tools to list your tables and run SQL against PostgreSQL. The original reference server is archived and its npm package deprecated; as of October 2026 the maintained options are Google's MCP Toolbox for Databases, the AWS Labs Postgres MCP server and the hosted Neon and Supabase MCP servers, while Postgres MCP Pro still works but hasn't shipped a release since May 2025. Whichever you pick, the safeguard that holds is the Postgres role it logs in as: a read-only role with column-level grants and a statement timeout, not the server's own read-only switch.
Postgres MCP servers compared (October 2026)
Server | Status | How its read-only mode works | Good for |
|---|---|---|---|
Reference server ( | Archived; npm package deprecated; last release 0.6.2, December 2024 | Wraps each query in | Reading old tutorials; don't deploy it |
Postgres MCP Pro ( | Last PyPI release 0.3.0, May 16, 2025 |
| Index tuning, EXPLAIN plans and health checks |
MCP Toolbox for Databases (Google) | Active: 1.15.0 on npm, October 23, 2026 | Rests on the database role; Google calls tool annotations and client confirmations "not a database security boundary" | Prebuilt tools for exploring; fixed, parameterized tools for agents in production |
Active: 1.2.3 on PyPI, October 30, 2026 | Parses each query and allows only read statements unless you pass | Aurora PostgreSQL and RDS for PostgreSQL | |
Hosted at |
| Neon projects in development; Neon advises against production use | |
Hosted at |
| Supabase projects in development |
Release dates come from each package registry, checked on November 1, 2026.
What a Postgres MCP server does
MCP (Model Context Protocol) is an open standard for how AI clients call outside tools. A Postgres MCP server turns your database into a handful of those tools, usually "list schemas", "describe table" and "execute SQL". The client's model reads your question, looks at the schema, writes SQL, calls the execute tool and reads the rows that come back. It starts every conversation knowing only what the schema says. ClickHouse acquired LibreChat and built its agent stack around its own MCP server (ClickHouse's AgentHouse), and Microsoft's Power BI servers raise the same questions as Postgres (Power BI MCP server guide).
Which PostgreSQL MCP servers are still maintained
The reference server: archived
The original reference server now lives in the servers-archived repository, and its npm package is marked "no longer supported". It sends the model's SQL as one string inside BEGIN TRANSACTION READ ONLY, which the risks section below shows how to escape.
Postgres MCP Pro: the DBA's option
Postgres MCP Pro from Crystal DBA also checks database health, reviews EXPLAIN plans, simulates hypothetical indexes and recommends indexes for your workload (with the pg_stat_statements and hypopg extensions). Its restricted mode parses SQL to reject COMMIT and ROLLBACK, though its README says "unsafe stored procedure languages" could still get around that.
MCP Toolbox for Databases: Google's general-purpose server
MCP Toolbox for Databases (renamed from Gen AI Toolbox) supports PostgreSQL alongside AlloyDB, Cloud SQL and many other databases. Start it with a prebuilt toolset (--prebuilt=postgres/data loads only the SQL and schema tools), or define your own tools as fixed SQL statements with parameters. Google's docs say the prebuilt configs "are not secure enough for 'run time' use cases", and that for dynamic SQL tools you should "run these tools with a dedicated database identity" and "not rely on regex keyword blacklists".
AWS Labs Postgres MCP server: for Aurora and RDS
The AWS Labs server connects to Aurora PostgreSQL (through the RDS Data API or directly) and to RDS for PostgreSQL, with TLS enforced (sslmode=verify-full) on direct connections. Its parser, PostgreSQL's own, also rejects functions that change state (nextval(), statistics resets, WAL management) inside a SELECT. AWS still calls the read-only parsing "best effort" and recommends a least-privilege role on top.
Neon MCP server
Neon's MCP server is hosted only and manages projects, branches and migrations as well as running SQL. Besides readonly=true, use projectId to limit it to one project and roleName so SQL logs in as your role instead of the database owner. Neon says the server "is intended for local development and IDE integrations only".
Supabase MCP server
Supabase's MCP server covers tables, migrations, logs, edge functions and branching as well as SQL. Besides project_ref and read_only=true, add features=database,docs to drop the tool groups you don't need. Supabase also says not to give the server to your customers, because it acts with your developer permissions.
Step by step: connect Postgres to Claude through a read-only role
This works with any server above. I use MCP Toolbox for Databases in Claude Desktop as the example because it's maintained and works with any PostgreSQL host.
Step 1: pick the database the agent will see
Point the agent at a read replica if you have one, so a slow query doesn't land on the database your app writes to, and start with an analytics or reporting schema rather than your whole application database.
Step 2: create a read-only role
Run this as an admin, replacing analytics, app, app_owner and the column list with your own names. Part 4 is the one people skip: it keeps email addresses and names out of the agent's reach while it can still count customers by country.
-- 1. A login role that can read and nothing else
CREATE ROLE mcp_reader WITH LOGIN PASSWORD 'change-me-to-a-long-random-secret'
NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS
CONNECTION LIMIT 3;
-- 2. Defaults for every session it opens
ALTER ROLE mcp_reader SET default_transaction_read_only = on;
ALTER ROLE mcp_reader SET statement_timeout = '30s';
ALTER ROLE mcp_reader SET idle_in_transaction_session_timeout = '60s';
-- 3. Read access to one schema, including tables created later
GRANT CONNECT ON DATABASE analytics TO mcp_reader;
GRANT USAGE ON SCHEMA app TO mcp_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA app TO mcp_reader;
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA app
GRANT SELECT ON TABLES TO mcp_reader;
-- 4. Tables with personal data: grant columns, not the whole table
REVOKE SELECT ON app.customers FROM mcp_reader;
GRANT SELECT (id, country, plan, created_at) ON app.customers TO mcp_reader;
- The
GRANTstatements are the real boundary: Postgres enforces them however the SQL is written. default_transaction_read_onlyandstatement_timeoutare defaults, not locks: we confirmed thatmcp_readercan runSET statement_timeout = 0. They catch the common case; the grants catch the rest.CONNECTION LIMITkeeps a looping agent from exhausting connections.- On PostgreSQL 14 and older, every role can create objects in the
publicschema by default. RunREVOKE CREATE ON SCHEMA public FROM PUBLIC;there. - Check what
mcp_readercan reach throughPUBLIC: functions declaredSECURITY DEFINERrun with their owner's rights.
Step 3: check that it holds
We ran the role script on a local PostgreSQL 16 with a small test schema, then connected as mcp_reader:
-- Connected as mcp_reader:
SHOW default_transaction_read_only; -- on
SHOW statement_timeout; -- 30s
SELECT id, country, plan FROM app.customers; -- works
SELECT * FROM app.customers; -- ERROR: permission denied for table customers
INSERT INTO app.orders VALUES (3, 1, 5, '2026-04-01');
-- ERROR: cannot execute INSERT in a read-only transaction
SET default_transaction_read_only = off;
DELETE FROM app.orders; -- ERROR: permission denied for table orders
CREATE TABLE public.x (id int); -- ERROR: permission denied for schema public
A query past the timeout fails with ERROR: canceling statement due to statement timeout. Run the same checks on your own database before you hand the credentials to anything.
Step 4: point the MCP server at the role
In Claude Desktop, open claude_desktop_config.json (on macOS in ~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\) and add the server under mcpServers with the mcp_reader credentials:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@toolbox-sdk/server", "--prebuilt=postgres/data", "--stdio"],
"env": {
"POSTGRES_HOST": "replica.db.internal",
"POSTGRES_PORT": "5432",
"POSTGRES_DATABASE": "analytics",
"POSTGRES_USER": "mcp_reader",
"POSTGRES_PASSWORD": "the-secret-from-step-2"
}
}
}
}
The postgres/data toolset loads only the SQL and schema tools (execute_sql, list_tables, list_views, list_schemas and a few more). Restart Claude Desktop and start with a question that only needs the schema: "Which tables in the app schema hold orders, and how are they related?"
On Neon or Supabase, use the hosted URL with the same principle: one project, read-only, and (on Neon) your own role:
Neon: https://mcp.neon.tech/mcp?readonly=true&projectId=<project-id>&roleName=mcp_reader
Supabase: https://mcp.supabase.com/mcp?project_ref=<project-ref>&read_only=true&features=database,docs
On Neon, the role must be able to log in and exist on each branch you query, and Neon's README says not to add it to neon_superuser.
Step 5: keep a person in the loop
Leave tool-call approval on in your client until you've seen how the agent behaves on your schema. For unattended routines, Supabase suggests pre-approving only project-scoped, read-only tools. Approvals and tool hints such as "read-only" are, in Google's words, "useful UX guardrails, but they are not a database security boundary": a second line behind the role.
The risks, and what each control actually stops
Write access through a "read-only" server
A read-only transaction stops a single DELETE, not a string that ends the transaction and keeps going (Postgres MCP Pro's README cites ROLLBACK; DROP TABLE users;). We reproduced it on PostgreSQL 16 with a role that had write rights: after BEGIN TRANSACTION READ ONLY, which is all the archived reference server does, sending COMMIT; DELETE FROM app.orders WHERE id = 2; in one message committed the empty transaction and deleted the row. As mcp_reader, the same string fails twice over: read-only by default, and no DELETE privilege when the session turns that off.
Prompt injection through your own data
Supabase's example: a support ticket whose text tells the agent to select * from a sensitive table and post the result as a reply. When a developer asks their MCP client to summarize the ticket, the model runs that query with the developer's permissions (Supabase: security risks). Supabase wraps SQL results with extra instructions against this and says it "is not foolproof". What holds is a role that can't read the sensitive table, read-only mode, and a person approving tool calls.
Personal data leaving the database
Every row the agent reads goes to your client's model provider. Column grants (part 4 of the role script) or views without personal fields keep it out at the source. With row-level security on the base tables, note that a plain view runs with its owner's rights; on PostgreSQL 15 and later, create it WITH (security_invoker = true) so the policies apply to the agent's role (which then needs SELECT on the columns the view reads).
Runaway queries
A model that writes a cross join on two large tables doesn't know it did. The role's statement_timeout and connection limit, plus a read replica, contain it, whichever server you use.
When GetDot is a better fit than a Postgres MCP server
A Postgres MCP server suits one engineer working on their own database from an editor. It fits worse when the people asking are in sales, finance or support: they don't run an MCP client, the model has to guess what "active customer" means every time, and the schema owner never sees the queries. An AI analyst with a semantic layer fits there. What GetDot does with PostgreSQL (including Neon and Supabase):
- One read-only statement, checked before it runs. Dot refuses anything but one read-only query, so
COMMIT; DROP TABLE users;(two statements) never reaches Postgres. - Columns you turn off stay off. Once an admin switches a column off on Dot's Model page, no query may read it, for anyone,
SELECT *included. - Row-level rules per user (Team plan). Before the SQL runs, Dot applies each table's row-level rule for the person asking, including on the lookups it makes to match filter values.
- It tells you which grants are missing. Each sync log lists the tables and views Dot's SELECT-only role can't read, with the
GRANT SELECTto run for each.
The bigger difference is context. Dot keeps notes, relationships and table docs between questions, uses your dbt models and metrics, and can be tested against answers you trust. People ask in Slack, Teams, email or the web app and get the answer with the SQL shown, which is what conversational analytics should mean. All LLM providers run with zero data retention, and Dot is SOC 2 Type II. Start free with 300 one-time credits and full Pro features.
Does GetDot have its own MCP server?
Yes, at https://app.getdot.ai/ai/mcp (https://eu.getdot.ai/ai/mcp for the EU instance), for Claude, Cursor, Codex, GitHub Copilot in VS Code or Copilot Studio, with OAuth or a personal MCP token. Instead of a raw SQL tool, the client gets tools such as ask_dot, get_result and get_catalog: Dot writes and runs the SQL under your Dot permissions, with every check above, and nothing in that toolset writes to your database. Setup is on the MCP integration page.
FAQ
A small program that exposes a PostgreSQL database to AI clients through the Model Context Protocol, usually as tools to list schemas, describe tables and execute SQL. Its safety depends on the database role it connects with.
No. @modelcontextprotocol/server-postgres is archived, and its npm package (last release 0.6.2 in December 2024) is marked as no longer supported.
Only with a dedicated read-only role, column grants that leave out personal data, a statement timeout, ideally a read replica, and tool-call approval on. Neon says its MCP server is not meant for production.
Yes, if the role it logs in as can write: a transaction-based read-only mode can be escaped with a string such as COMMIT; DELETE ... unless the server parses and rejects it.
Both are hosted, manage their platform as well as running SQL, and can be scoped to one project. Neon lets you pin a Postgres role with roleName; Supabase's read_only mode runs queries as a read-only Postgres user.
Sven Rudolph
Sven is a co-founder of Dot. He writes about the technical side of AI analytics: MCP servers, BI integrations, and how Dot connects to the data stack.