postgres-mcp-js
Provides safe, structured access to a PostgreSQL database, enabling health checks, index tuning, lock analysis, bloat detection, schema inspection, and SQL execution with read-only enforcement.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@postgres-mcp-jsRun a full health check on the primary database"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
postgres-mcp-js
A Model Context Protocol (MCP) server for PostgreSQL — written in TypeScript.
Connect it to Claude, Cursor, Windsurf, or any MCP-compatible AI and give it safe, structured access to your Postgres database: health checks, index tuning, lock analysis, bloat detection, and more.
Install
npm install -g postgres-mcp-jsOr use without installing:
npx postgres-mcp-jsRelated MCP server: PostgreSQL MCP Server
Local setup
1. Clone and install
git clone https://github.com/YOUR_USERNAME/postgres-mcp-js.git
cd postgres-mcp-js
npm install2. Configure credentials
cp .env.example .envOpen .env and fill in your values:
# Required
DB_PRIMARY_URL=postgresql://user:password@localhost:5432/mydb
DB_PRIMARY_NAME=primary
# Optional — second database (replica, staging, etc.)
# DB_REPLICA_URL=postgresql://user:password@replica:5432/mydb
# DB_REPLICA_NAME=replica
# restricted = read-only + 30s timeout ← use this for production
# unrestricted = full read/write ← dev/local only
ACCESS_MODE=restricted3. Build and run
npm run build
node dist/index.jsOr skip the build step in dev mode:
npm run devConnect to your AI client
All clients need three things: command, args, and env (your DB credentials).
No
.envfile needed. Theenvblock in your MCP client config is passed directly to the server process — credentials never need to touch a file on disk. The.envfile is only useful if you run the server manually in a terminal.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["postgres-mcp-js"],
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@localhost:5432/mydb",
"DB_PRIMARY_NAME": "primary",
"ACCESS_MODE": "restricted"
}
}
}
}If you cloned locally and built it, point directly at the file instead:
{
"mcpServers": {
"postgres": {
"command": "node",
"args": ["/Users/yourname/postgres-mcp-js/dist/index.js"],
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@localhost:5432/mydb",
"ACCESS_MODE": "restricted"
}
}
}
}Claude Code (CLI)
Edit ~/.claude/settings.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["postgres-mcp-js"],
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@localhost:5432/mydb",
"ACCESS_MODE": "restricted"
}
}
}
}Cursor
Go to Settings → MCP → Add new MCP server and paste:
{
"command": "npx",
"args": ["postgres-mcp-js"],
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@localhost:5432/mydb",
"ACCESS_MODE": "restricted"
}
}Windsurf
Edit ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["postgres-mcp-js"],
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@localhost:5432/mydb",
"ACCESS_MODE": "restricted"
}
}
}
}Two databases at once
Add both URLs — the AI can then query either one by name:
{
"env": {
"DB_PRIMARY_URL": "postgresql://user:pass@primary:5432/mydb",
"DB_PRIMARY_NAME": "primary",
"DB_REPLICA_URL": "postgresql://user:pass@replica:5432/mydb",
"DB_REPLICA_NAME": "replica",
"ACCESS_MODE": "restricted"
}
}Then ask the AI: "Compare buffer cache hit ratio between primary and replica" — it will call the same tool twice with database: "primary" and database: "replica".
Tools
Every tool accepts an optional database parameter (defaults to primary).
Schema
Tool | Description |
| Show configured DB aliases — credentials never exposed |
| All schemas in the database |
| Tables / views / sequences / extensions in a schema |
| Columns, constraints, indexes for a table or view |
SQL & query plans
Tool | Description |
| Run SQL. Read-only in restricted mode; full access in unrestricted |
| EXPLAIN plan. Pass |
| Slowest/heaviest queries from |
Index analysis
Tool | Description |
| Index recommendations from the full query workload |
| Index recommendations for up to 10 specific queries |
| Tables with seq-scan dominance, FK columns without indexes |
Health checks
Run any subset or pass all to run everything:
health_type: "index" | "connection" | "vacuum" | "sequence" | "replication" | "buffer" | "constraint" | "all"Check | What it looks for |
| Unused, invalid, duplicate indexes; FK columns with no index |
| State breakdown, max_connections, long-running queries |
| Dead tuple bloat, transaction ID wraparound risk |
| Sequences > 75% exhausted |
| Replica lag, dangling replication slots |
| Shared buffer cache hit ratio globally and per table |
| Invalid / not-yet-validated constraints |
Advanced diagnostics
Tool | Description |
| Blocking chains, idle-in-transaction sessions, lock waits by table |
| Dead-tuple bloat, index bloat, TOAST sizes, VACUUM commands |
Optional Postgres extensions
Not required, but unlock more features:
-- Enables get_top_queries and analyze_workload_indexes
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Enables hypothetical index simulation in explain_query
CREATE EXTENSION IF NOT EXISTS hypopg;For pg_stat_statements, also add to postgresql.conf:
shared_preload_libraries = 'pg_stat_statements'Security
Credentials never reach the AI. DB URLs are read from env at startup; tool arguments and results never contain them.
Alias only. The AI sees
"primary"/"replica", never a connection string.Read-only enforcement. In restricted mode every query runs inside
BEGIN; SET TRANSACTION READ ONLY; ... ROLLBACK— PostgreSQL itself blocks any writes.Statement validation. First keyword is checked (SELECT / EXPLAIN / SHOW / WITH only) before the query hits the DB.
30-second timeout.
SET LOCAL statement_timeout = 30000kills runaway queries.
Publishing to npm
Before publishing, update package.json:
{
"name": "your-package-name",
"author": "Your Name <you@example.com>",
"homepage": "https://github.com/you/your-repo#readme",
"repository": { "url": "git+https://github.com/you/your-repo.git" }
}Then:
npm login # one-time login to npmjs.com
npm publish --access publicUsers can now install it:
npm install -g your-package-name
# or
npx your-package-nameTo release a new version:
npm version patch # 1.0.0 → 1.0.1 (bug fix)
npm version minor # 1.0.0 → 1.1.0 (new feature)
npm version major # 1.0.0 → 2.0.0 (breaking change)
npm publishDocker (local only)
Build and run locally without npm:
docker build -t postgres-mcp-js .
docker run --rm -i \
-e DB_PRIMARY_URL="postgresql://user:pass@host:5432/mydb" \
-e ACCESS_MODE=restricted \
postgres-mcp-jsOr with docker-compose (includes a bundled Postgres for testing):
cp .env.example .env # fill in your DB details
docker compose upLicense
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/shubham4038/postgres-mcp-js'
If you have feedback or need assistance with the MCP directory API, please join our Discord server