
corporatepiyush/mcp-pg-rust
Developer toolsPostgresql MCP server written in Rust
Overview
is a high-performance MCP server that brings PostgreSQL into Claude Desktop and any MCP-compatible AI tool. 133 PostgreSQL tools, lock-free connection pooling, sub-10ms latency. No tools are exposed by default. You enable them one category at a time with --enable- flags (or --enable-all). A server started with no enable flags advertises an tool list and rejects every tools/call. See Tool Exposure. One of four high-performance MCP servers written in Rust — mcp-postgres · mcp-filesystem · mcp-memory · mcp-web-search. All implement MCP protocol revision . Tools are opt-in — pass one or more --enable- flags (or --enable-all). Without them the server exposes no tools. The HTTP/2 transport can be served over TLS (rustls, ring provider — the same provider used for sslmode-gated PostgreSQL connections, no OpenSSL/aws-lc).
README
mcp-postgres
mcp-postgres is a high-performance MCP server that brings PostgreSQL into Claude Desktop and any MCP-compatible AI tool. 133 PostgreSQL tools, lock-free connection pooling, sub-10ms latency.
Tools are opt-in (5.2.0+). No tools are exposed by default. You enable them one category at a time with
--enable-flags (or--enable-all). A server started with no enable flags advertises an empty tool list and rejects everytools/call. See Tool Exposure.
MCP suite. One of four high-performance MCP servers written in Rust — mcp-postgres · mcp-filesystem · mcp-memory · mcp-web-search. All implement MCP protocol revision
2025-11-25.
Quick Start
Install
# From crates.io
cargo install mcp-postgres
# Or from Homebrew (macOS)
brew tap corporatepiyush/mcp-postgres
brew install mcp-postgres
Run
Tools are opt-in — pass one or more --enable- flags (or
--enable-all). Without them the server exposes no tools.
# Stdio mode (for Claude Desktop) — expose read-only query + schema tools
mcp-postgres --database-url "postgres://user:pass@localhost:5432/mydb" --stdio \
--enable-query --enable-schema
# TCP server (port 3000) — expose everything
mcp-postgres --database-url "postgres://user:pass@localhost:5432/mydb" --enable-all
# HTTP/2 server (port 3001) — query + monitoring only
mcp-postgres --database-url "postgres://user:pass@localhost:5432/mydb" --http-port 3001 \
--enable-query --enable-monitoring
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"postgres": {
"command": "mcp-postgres",
"args": ["--database-url", "postgres://user:pass@localhost:5432/mydb", "--stdio", "--enable-all"]
}
}
}
Why mcp-postgres?
| Feature | mcp-postgres | DIY / psql |
|---|---|---|
| 133 purpose-built tools | Schema inspection, DDL, monitoring, replication, batch ops, security audit, text search, extensions, maintenance, and more | You build every query from scratch |
| Lock-free connection pool | Zero-mutex crossbeam::ArrayQueue — pure CAS loops, no kernel overhead |
Deadpool or manual Mutex |
| Dual-protocol | TCP (3000) + HTTP/2 (3001) + stdio — one binary, three transports | Multiple servers to wire up |
| Sub-10ms latency | Allocated for AI interactivity — hot path is allocation-free | Unpredictable |
| SQL injection prevention | Every identifier validated, quote_ident sanitization, structured predicates |
Manual parameterization |
| PG version-aware | Queries verified against PG 16–18 docs, graceful fallbacks for version differences | Version-specific failures |
Command-Line Options
Usage: mcp-postgres [OPTIONS]
Options:
-d, --database-url PostgreSQL connection string
-H, --host TCP server host [127.0.0.1]
-p, --port TCP server port [3000]
--http-port HTTP/2 server port [3001]
--min-connections Min pool connections [5]
--max-connections Max pool connections [20]
--log-level Log level [info]
--enable-metrics Prometheus /metrics endpoint
--metrics-port Metrics port [9090]
--stdio Stdio mode (Claude Desktop)
--access-mode unrestricted, restricted [unrestricted]
--tls-cert PEM cert chain to serve HTTP over TLS (HTTPS)
--tls-key PEM private key matching --tls-cert
Tool exposure (none enabled by default — see "Tool Exposure"):
--enable-all Expose every category (overrides the flags below)
--enable-query Query: execute/explain/async-execute + sampling
--enable-batch Batch: bulk insert/update/delete + COPY
--enable-schema Schema: read-only inspection + DDL generation
--enable-ddl DDL: create/drop/alter/rename objects
--enable-admin Admin: vacuum/reindex/analyze/truncate + sessions
--enable-monitoring Monitoring: stats, conns, txns, replication, config
--enable-security Security: roles, users, privileges, audits
--enable-data-io Data I/O: CSV export + URL/file import
--enable-extensions Extensions: pgvector, TimescaleDB, BM25, ext mgmt
-h, --help Print help
-V, --version Print version
TLS (HTTPS)
The HTTP/2 transport can be served over TLS (rustls, ring provider — the same
provider used for sslmode-gated PostgreSQL connections, no OpenSSL/aws-lc).
Provide a PEM certificate chain and private key via --tls-cert/--tls-key or
the MCP_TLS_CERT/MCP_TLS_KEY environment variables and the HTTP server speaks
HTTPS instead of plaintext. The two must be supplied together or startup is
refused; when neither is set the HTTP transport stays plaintext (the default).
The raw TCP transport is unaffected.
mcp-postgres --http-port 3001 --tls-cert ./cert.pem --tls-key ./key.pem
MCP Compliance
Implements the Model Context Protocol revision 2025-11-25 over JSON-RPC 2.0, via TCP, HTTP/2, or stdio.
| Area | Support |
|---|---|
| Transports | stdio, TCP (3000), HTTP/2 (3001) |
| Protocol version | 2025-11-25, negotiates down to 2025-06-18 / 2025-03-26 / 2024-11-05 |
initialize |
✅ version negotiation + instructions |
tools/list, tools/call |
✅ (133 tools) |
CallToolResult |
✅ content[] + structuredContent + isError |
| Capabilities advertised | tools only — nothing is advertised that isn’t implemented |
resources · prompts · logging · completion |
❌ roadmap — see MIGRATION.md |
Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "list_tables", "arguments": {} },
"id": 1
}
Result — a spec-compliant CallToolResult. The payload is available as a
machine-readable structuredContent object and as serialized text; tool
failures come back with isError: true (not as JSON-RPC protocol errors) so the
model can self-correct:
{
"content": [{ "type": "text", "text": "{\"tables\":[\"users\",\"orders\"]}" }],
"structuredContent": { "tables": ["users", "orders"] },
"isError": false
}
Upgrading from 4.x? The result shape changed — see MIGRATION.md.
Tool Exposure (opt-in by category)
Every tool belongs to exactly one of 9 categories. Nothing is exposed
until you enable its category at startup — disabled tools are hidden from
tools/list and rejected from tools/call as if they did not exist. This lets
you hand an agent precisely the surface area it needs (e.g. read-only query +
monitoring) and nothing more.
| Flag | Category | What it exposes |
|---|---|---|
--enable-query |
Query | execute_query, execute_insert/update/delete, async_execute_*, explain_query, sample_data |
--enable-batch |
Batch | async_batch_insert/update/delete, async_batch_insert_copy |
--enable-schema |
Schema (read) | list_tables, describe_table, list_indexes/schemas/triggers/partitions, show_constraints, get_object_details, list_databases, table_dependencies, generate_create_*_ddl |
--enable-ddl |
DDL (write) | create/drop/alter table·view·schema·sequence·index·partition, backup_table, add/drop/rename_column, alter_column_type, rename_table/index/schema, FK & constraint ops, clone_table_schema, create_database |
--enable-admin |
Admin | vacuum, vacuum_full, vacuum_analyze, analyze_table, reindex_table/database, reset_statistics, truncate_table, cancel_query, terminate_connection |
--enable-monitoring |
Monitoring (read) | table/index stats, sizes, cache ratio, pg_stat_statements, connections, running/blocked queries, transactions, locks, deadlocks, replication, WAL, settings, health checks, suggest_indexes, bloat |
--enable-security |
Security | list/create/alter/drop_user, role ops, grant/revoke_privileges, privilege listings |
--enable-data-io |
Data I/O | export_csv, import_from_url (also gated behind --allow-url-import) |
--enable-extensions |
Extensions | pgvector (vector_search, create_vector_index, list_vector_columns), TimescaleDB (create_hypertable, show_chunks, retention/compression policies, continuous aggregates), BM25 full-text, and generic create/drop/list_extension |
--enable-all |
(all of the above) | Every category. Overrides the individual flags. |
# Read-only analyst: inspect schema and run SELECTs, nothing else
mcp-postgres -d "$DATABASE_URL" --stdio --enable-query --enable-schema --enable-monitoring
# Full access
mcp-postgres -d "$DATABASE_URL" --stdio --enable-all
Category gating composes with the existing --access-mode restricted (which
additionally blocks all write tools) and --allow-url-import controls.
Tools (133 Total)
The headings below are the human-readable groupings. To map each one to the
--enable- flag that exposes it, see the
Tool Exposure table above.
Performance
Lock-Free Connection Pool (v4.0.0)
No mutexes. No semaphores. Just CAS loops.
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Task 1 │ │ crossbeam:: │ │ Task 2 │
│ (acquire) │────▶│ ArrayQueue │◀────│ (release) │
└─────────────┘ │ CachePadded │ └─────────────┘
│ Head/Tail │
│ (CAS only) │
└──────────────────┘
| Metric | Deadpool (v3.x) | LockFreePool (v4.0.0) |
|---|---|---|
| Lock acquisitions per acquire+release | 3+ (Mutex + Semaphore) | 0 |
| Allocation on hot path | Yes (VecDeque growth) | Zero (pre-allocated) |
| False sharing | Likely (adjacent fields) | Cache-padded atomics |
| Inlining | Cross-crate, opaque | Monomorphic, LTO-friendly |
| Dependencies | 2 (deadpool + deadpool-postgres) | 0 external (crossbeam already in tree) |
Sub-10ms latency is guaranteed by design: zero allocation on the hot path, monomorphic dispatch, cache-line-isolated atomics, and a single-pointer CAS for connection handoff.
Architecture
┌─────────────────┐ ┌─────────────────┐
│ TCP Client │ │ HTTP Client │
│ (port 3000) │ │ (port 3001) │
└────────┬────────┘ └────────┬────────┘
└─────────────┬─────────────┘
│
┌────────┴────────┐
│ JSON-RPC 2.0 │
│ (MCP Protocol) │
└────────┬────────┘
│
┌────────────┴────────────┐
│ Tool Dispatcher │
│ (133 tools) │
└────────────┬────────────┘
│
┌────────────┴────────────┐
│ Connection Pool │
│ (lock-free, CAS-only) │
│ Min: 5, Max: 20 │
└────────────┬────────────┘
│
┌────────┴────────┐
│ PostgreSQL DB │
└─────────────────┘
Key Design Principles
- Stateless HTTP — Each request is independent. Transaction state isolated per-connection.
- Lock-free pooling —
crossbeam::ArrayQueuewithCachePaddedatomics. Zero mutex acquisitions. - Input validation at the boundary — SQL capped at 10K chars, identifiers at 255, batch rows at 1K. SQL injection prevention via
quote_ident. - PG version-aware queries — Verified against PG 16–18. Graceful fallbacks when views/columns differ across versions.
Versioning & Compatibility
Follows Semantic Versioning. The current line is 5.x,
which targets MCP revision 2025-11-25. The 5.0.0 release changed the
tools/call result shape to be spec-compliant — see MIGRATION.md
and the CHANGELOG.
| mcp-postgres | MCP revision (default) | Negotiates |
|---|---|---|
| 5.x | 2025-11-25 |
2025-06-18, 2025-03-26, 2024-11-05 |
| ≤ 4.x | 2024-11-05 |
— |
License
Apache-2.0
Support
Install
This server does not publish a one-line install command.
Open the repository installation guide New to MCP? Start with the mcpskill.org guide →Configuration
{
"mcpServers": {
"postgres": {
"command": "mcp-postgres",
"args": ["--database-url", "postgres://user:pass@localhost:5432/mydb", "--stdio", "--enable-all"]
}
}
}