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
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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