PostgreSQL MCP Server
Provides 36 tools for interacting with PostgreSQL databases, including schema introspection, query execution, data exploration, performance monitoring, security auditing, and maintenance.
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., "@PostgreSQL MCP Serverdescribe the users table"
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.
postgresql-mcp-server – MCP Server for PostgreSQL
Full-featured MCP (Model Context Protocol) server that exposes 36 tools for interacting with PostgreSQL databases. Covers schema introspection, query execution, data exploration, performance monitoring, security auditing, and maintenance — all accessible from Claude Code, Claude Desktop, Cursor, and any MCP-compatible client.
Table of Contents
Related MCP server: postgres-mcp
Features
36 tools across 6 domains: schema, queries, data, monitoring, security, maintenance
Dual transport: HTTP (Docker/remote) and stdio (local subprocess)
Read-only enforcement:
pg_queryrejects non-SELECT statements at the application levelDestructive-op guards: DROP, TRUNCATE, DELETE-without-WHERE require explicit
confirm_destructive: truePagination + truncation: all list tools respect
limit/offset; responses capped at 25,000 charsDual output formats: every tool supports
response_format: markdown(default) orjsonDemo schema: first-run seed with users, products, orders, triggers, views, and indexes
Requirements
Docker + Docker Compose (recommended) — or Node.js 20+ for local run
PostgreSQL 13+ (16 included in Docker setup)
An MCP-compatible client (Claude Code, Claude Desktop, Cursor…)
Quick Start (Docker)
# 1. Clone / enter project
cd mcp-postgresql
# 2. Start PostgreSQL + MCP server
docker compose up -d
# 3. Verify both containers are healthy
docker compose psDefault ports:
Service | Port | Description |
PostgreSQL |
| Exposed to host for direct psql access |
MCP HTTP server |
| MCP endpoint at |
Default credentials
Host: localhost:5432
Database: mcpdb
User: mcpuser
Password: mcppasswordOverride via .env:
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mysecret
POSTGRES_DB=mydb
PG_PORT=5432
MCP_PORT=3002Demo schema
On first start, init/01_demo_schema.sql is executed automatically, creating:
Tables:
users,products,orders,order_items,audit_logViews:
active_users,order_summaryFunction + triggers:
update_updated_at()7 indexes, seed data (5 users, 5 products)
Extensions:
uuid-ossp,pg_stat_statements
Configuration
Environment variables
Variable | Default | Description |
| — | Full connection string (overrides all PG_* vars) |
|
| PostgreSQL host |
|
| PostgreSQL port |
|
| Database name |
|
| PostgreSQL user |
| — | PostgreSQL password |
|
|
|
|
| HTTP server port (when |
|
| HTTP bind address ( |
Tools Reference
Schema Introspection
Tool | Description |
| All databases with encoding and size |
| Schemas with owner, table/view counts |
| Tables in schema with size and estimated row count |
| Full table description: columns, FK, indexes, check constraints |
| Views and materialized views with optional SQL definitions |
| Functions, procedures, aggregates, window functions |
| Indexes by schema/table with size and definition |
| Installed PostgreSQL extensions |
| Sequences with range, increment, and current value |
| Triggers per table with timing and event |
| Enums, composite types, domains, range types |
| Partitioned tables and their child partitions |
| Search all DB objects by LIKE pattern across all types |
| CREATE statement (DDL) for table, view, function, or index |
Query Execution
Tool | Description |
| Execute a SELECT query (rejects any non-read-only statement) |
| EXPLAIN or EXPLAIN ANALYZE with text or JSON output |
| Execute DML/DDL: INSERT, UPDATE, DELETE, CREATE, ALTER, DROP |
| Execute multiple statements atomically in a single transaction |
Data Exploration
Tool | Description |
| Sample rows from a table with optional WHERE, ORDER BY, column filter |
| Exact COUNT(*) with optional WHERE clause |
| Export query results as CSV with header row |
| Size, live/dead rows, vacuum dates, scan counts per table |
Monitoring & Performance
Tool | Description |
| Currently running queries with duration and wait events |
| Slow query analysis from |
| Index scan counts — identify unused or underused indexes |
| Tables with high dead-tuple ratios needing VACUUM |
| Active locks with blocking pair detection |
| Streaming replica status and replay lag |
| Connection summary grouped by database, user, app, or state |
Security & Access Control
Tool | Description |
| All roles with attributes: superuser, login, replication, bypassRLS, memberships |
| Privileges on tables, views, sequences, functions |
| Row Level Security policies and RLS-enabled tables |
| Cancel (SIGINT) or terminate (SIGTERM) a backend by PID |
Maintenance & Configuration
Tool | Description |
| Server version, uptime, connection counts, key settings |
|
|
| Run VACUUM, VACUUM ANALYZE, or VACUUM FULL on a table |
Client Setup
Claude Code
# Register via HTTP (Docker must be running)
claude mcp add --transport http postgresql-mcp-server http://localhost:3002/mcpClaude Desktop
Claude Desktop requires stdio transport. Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"postgresql": {
"command": "node",
"args": ["/absolute/path/to/mcp-postgresql/dist/index.js"],
"env": {
"DATABASE_URL": "postgres://mcpuser:mcppassword@localhost:5432/mcpdb"
}
}
}
}Restart Claude Desktop after editing.
Cursor
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (project-level):
{
"mcpServers": {
"postgresql": {
"url": "http://localhost:3002/mcp"
}
}
}Transport Modes
Mode | When to use | How to run |
HTTP | Docker, remote servers, multiple clients |
|
stdio | Claude Desktop, local subprocess, single client |
|
DNS rebinding note: when running HTTP locally (outside Docker), the server binds to 127.0.0.1 by default. In Docker, set HOST=0.0.0.0 (already set in docker-compose.yml).
Development
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run locally (stdio, connects to DATABASE_URL)
DATABASE_URL=postgres://user:pass@localhost:5432/mydb npm start
# Run as HTTP server
TRANSPORT=http PORT=3000 DATABASE_URL=... npm start
# Watch mode (dev)
DATABASE_URL=... npm run devDocker commands
# Start
docker compose up -d
# Stop (keep volumes)
docker compose down
# Stop and wipe database
docker compose down -v
# Rebuild after code changes
docker compose up --build -d
# Follow logs
docker compose logs -f mcp-serverAdding tools
Create or edit a file in
src/tools/Export a
register*Tools(server: McpServer)functionImport and call it in
src/index.tsnpm run build— TypeScript strict mode catches issues at compile timedocker compose up --build -dto deploy
Project Structure
mcp-postgresql/
├── src/
│ ├── index.ts # Entry point — registers all tools, starts transport
│ ├── constants.ts # CHARACTER_LIMIT, defaults, ResponseFormat enum
│ ├── types.ts # TypeScript interfaces for all DB result rows
│ ├── db.ts # pg.Pool, dbQuery, quoteIdentifier, validateIdentifier
│ ├── tools/
│ │ ├── schema.ts # pg_list_databases/schemas/tables/views/functions/indexes/extensions/sequences/triggers/types/partitions/search/ddl/describe
│ │ ├── query.ts # pg_query, pg_explain, pg_execute, pg_transaction
│ │ ├── data.ts # pg_sample_rows, pg_count_rows, pg_table_stats, pg_copy_csv
│ │ ├── advanced.ts # pg_server_info, pg_list_locks, pg_get_ddl
│ │ ├── monitoring.ts # pg_active_queries, pg_slow_queries, pg_index_usage, pg_bloat_report, pg_replication_status
│ │ ├── security.ts # pg_list_types/grants/policies/partitions, pg_copy_csv, pg_kill_query
│ │ └── maintenance.ts # pg_list_roles, pg_list_settings, pg_vacuum, pg_connection_stats
│ └── utils/
│ ├── errors.ts # PostgreSQL error formatting, isPgError type guard
│ └── format.ts # formatMarkdownTable, truncateIfNeeded, formatBytes
├── init/
│ └── 01_demo_schema.sql # Auto-loaded on first container start
├── dist/ # Compiled JavaScript (gitignored)
├── Dockerfile # Multi-stage: builder → runtime (node:20-alpine)
├── docker-compose.yml # postgres:16-alpine + mcp-server
├── .env # Local overrides (not committed)
├── .dockerignore
├── package.json
└── tsconfig.jsonSafety Model
Operation | Protection |
SELECT via | Rejects INSERT/UPDATE/DELETE/DDL at app level |
DROP / TRUNCATE | Requires |
DELETE without WHERE | Requires |
VACUUM FULL | Requires |
| Shows target query before acting; requires explicit mode |
Identifier injection |
|
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/foxter-io/mcp-postgresql'
If you have feedback or need assistance with the MCP directory API, please join our Discord server