postgres_list_schemasLABSCO SUMMARY
Defence in depth, and it still tells you to use a read-only role.
That last line is the honest one. The server enforces read-only at the transaction level, rejects internal semicolons, blocks write keywords by regex and caps rows — and the README still says to give it a PostgreSQL role that cannot write anyway. That is the correct posture for a tool an assistant drives. The four prompts are the underrated part: a table audit or a slow-query profile is a slash command rather than a sequence of calls you have to assemble.
What it is
A PostgreSQL MCP server built to feed a model context without any risk of writing. Read-only is not a convention here but a stack of enforcement: SET TRANSACTION READ ONLY, a statement timeout, a row cap, single-statement rejection and a write-keyword check by regex.
What you get
- Introspection across the allowed schemas: schemas, tables with column counts, a table's columns, constraints and indexes, functions with signature and language, triggers with table and timing, views regular and materialised, and a column search by name pattern —
postgres_list_schemas,postgres_list_tables,postgres_describe_table,postgres_list_functions,postgres_list_triggers,postgres_list_views,postgres_search_columns - Definitions read in full — a function's source, with overload support, and a trigger's complete definition —
postgres_get_function_definition,postgres_get_trigger_definition - Querying two ways: a structured single-table SELECT that uses SQL parameters and never concatenates strings, and an advanced SELECT or WITH for joins, CTEs and aggregations —
postgres_query_table,postgres_execute_query - Plan analysis and storage stats: EXPLAIN and EXPLAIN ANALYZE before you run something expensive, plus total, table, index and toast sizes, vacuum and analyze timings, and indexes sitting at zero scans —
postgres_explain_query,postgres_get_table_stats - Two browsable resources —
postgres://schema/{schema}andpostgres://table/{schema}/{table}— and 4 slash-command prompts:audit-table,find-tables,explain-foreign-keys,profile-slow-query - Pagination that tells you there is more: the list tools take limit and offset and return
has_moreandnext_offset
Requirements
A PostgreSQL database and Node >= 18 with pnpm. Build from a clone with pnpm run build, then register with claude mcp add passing the connection variables, or point a JSON config at dist/index.js. Connection settings are DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, with DB_SSL for managed hosts and DB_SSL_REJECT_UNAUTHORIZED kept true in production. DB_SCHEMAS is the allow-list — empty means every non-system schema. DEFAULT_LIMIT sets the default row limit; the hard cap is 100 rows per query, with 10 s to connect and 30 s per statement. The README recommends a read-only PostgreSQL role on top of all this. It also packages as an MCPB bundle for Claude Desktop, where the password field is marked sensitive in the install form. The README is written in Spanish.
Setup effort
Build from source — git clone https://github.com/cuevacelis/mcp_postgres.git
USE CASES
Getting oriented in a database you did not build
List the schemas and tables, then describe the ones that matter with their constraints and indexes.
Finding the column you half-remember
Search columns by pattern across every allowed schema instead of opening tables one at a time.
Making a slow query faster
Run the profile prompt, which produces an EXPLAIN ANALYZE with prioritised recommendations — missing indexes, scans, expensive sorts.
Reading what a function or trigger actually does
Pull the full source rather than the signature, including the right overload.
Letting an assistant query production
Point it at a read-only role with the schema allow-list set, so the enforcement in the server and the enforcement in the database agree.
Finding storage you are wasting
Read table, index and toast sizes together with the indexes that have never been scanned.
13 tools
Listed in project docs. Your client may show a different list.
postgres_list_tablespostgres_describe_tablepostgres_list_functionspostgres_list_triggerspostgres_get_function_definitionpostgres_get_trigger_definitionpostgres_list_viewspostgres_search_columnspostgres_query_tablepostgres_execute_querypostgres_explain_querypostgres_get_table_statsBEFORE YOU INSTALL
What to know first
Tools you get
13 tools named in the project's documentation.
Requires
- node on PATH
- DB_PASSWORD in your environment
- DB_USER in your environment
INSTALLATION
Connect your client
You clone and build this one yourself.
Server setup
Clone the repository, then install and build it (Node 18 or newer and pnpm)
git clone https://github.com/cuevacelis/mcp_postgres.git
cd mcp_postgres
pnpm install
pnpm run buildMCP Clients
Claude Code — credentials as flags
claude mcp add \
--transport stdio \
--env DB_HOST=localhost \
--env DB_PORT=5432 \
--env DB_NAME=<YOUR_DB_NAME> \
--env DB_USER=<YOUR_DB_USER> \
--env DB_PASSWORD=<YOUR_DB_PASSWORD> \
--env DB_SCHEMAS=public \
postgres \
-- node <YOUR_PATH_TO_MCP_POSTGRES>/dist/index.jsClaude Code — credentials in .env
In the mcp_postgres folder, copy .env.example to .env and put your connection settings in it.
Register the server; add --scope user to make it available in every project:
claude mcp add --transport stdio postgres \
-- node <YOUR_PATH_TO_MCP_POSTGRES>/dist/index.jsAny MCP client
{
"mcpServers": {
"postgres": {
"command": "node",
"args": [
"<YOUR_PATH_TO_MCP_POSTGRES>/dist/index.js"
],
"env": {
"DB_HOST": "<YOUR_DB_HOST>",
"DB_NAME": "<YOUR_DB_NAME>",
"DB_USER": "<YOUR_DB_USER>",
"DB_PASSWORD": "<YOUR_DB_PASSWORD>",
"DB_SCHEMAS": "public"
}
}
}
}