Postgres MCP Server
๐ Postgres MCP Server
An AI Database Assistant, built on the Model Context Protocol
Connects an AI client to a real PostgreSQL database โ schema exploration, safe querying, and LLM-powered reasoning, all through MCP tools.
Docker Hub ยท Architecture ยท Installation ยท Example Tool Calls
What is this?
A production-grade Model Context Protocol (MCP) server that connects an AI client (like Claude) to a real PostgreSQL database, combining direct schema/data access with LLM-powered reasoning (via Groq) for SQL generation, query explanation, optimization, and business insight generation.
Built on a fictional company database ("Orbitals Inc.") โ a software consultancy with employees, departments, clients, projects, orders, invoices, support tickets, and meetings โ to exercise realistic relational queries and multi-hop relationships.
What makes this an "AI Database Assistant," not just a SQL executor
Capability | Tool |
Schema exploration |
|
Safe, validated querying |
|
Relationship discovery |
|
AI-assisted SQL |
|
Business reasoning |
|
The database is the source of truth for all facts; the LLM is used for reasoning, translation, and interpretation โ never as a substitute for real query execution.
Architecture
MCP Layer (tools/) โ thin, declares tools only
Service Layer (services/) โ business logic, orchestration
Repository Layer (repositories/) โ raw SQL / SQLAlchemy queries
Database Layer (db/) โ async engine, connection pooling
LLM Client Layer (llm/) โ Groq abstraction, provider-agnosticEach layer only knows about the one below it โ MCP tools never touch the database directly, and the LLM provider is swappable behind an interface (llm/base.py) without touching services.
Folder Structure
postgres-mcp-server/
โโโ src/postgres_mcp/
โ โโโ config.py, server.py, logging_config.py, exceptions.py
โ โโโ db/ # async engine, session management
โ โโโ models/ # SQLAlchemy models (11 tables)
โ โโโ repositories/ # raw SQL against Postgres
โ โโโ services/ # business logic
โ โโโ llm/ # Groq provider (swappable interface)
โ โโโ tools/ # MCP tool registration
โ โโโ utils/ # SQL injection defenses (sql_guard.py)
โโโ scripts/ # check_connection, check_llm, seed_database
โโโ alembic/ # schema migrations
โโโ tests/
โ โโโ unit/ # sql_guard, schema_service, insight_service
โ โโโ integration/ # real Neon queries
โโโ Dockerfile, docker-compose.yml
โโโ alembic.iniDatabase Schema
11 tables modeling a software consultancy: departments, employees (self-referencing manager hierarchy), clients, projects, project_assignments (many-to-many), products, orders, invoices, support_tickets, meetings, meeting_attendees (many-to-many). Full relational integrity via foreign keys, check constraints (e.g., positive order quantities, valid status enums), and indexes on frequently-filtered columns.
Installation
Prerequisites
Python 3.12+
A Neon PostgreSQL database (free tier works)
A Groq API key (free tier works)
Docker (optional, for containerized runs)
Setup
git clone <your-repo-url>
cd postgres-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
# fill in .env with your real Neon connection string and Groq API keyEnvironment Variables
Variable | Description |
| Neon connection string, async form: |
| Your Groq API key |
| Model name (default: |
| Logging verbosity (default: |
|
|
Neon Setup
Create a free account and project at neon.tech
Copy the connection string from your project dashboard
Convert it to async form: change
postgresql://topostgresql+asyncpg://, andsslmode=requiretossl=require, dropping anychannel_bindingparam
Database Setup
alembic upgrade head # creates all 11 tables
python scripts/seed_database.py # populates realistic fictional dataRunning Locally
python -m postgres_mcp.serverThis starts the MCP server over stdio transport. To test it interactively:
npx @modelcontextprotocol/inspector@latest python -m postgres_mcp.serverPublic MCP Endpoint
The hosted MCP server is available at:
https://aman-postgres-mcp-server.fastmcp.app/mcpRunning with Docker
docker build -t postgres-mcp-server:latest .
docker run -i --env-file .env postgres-mcp-server:latestOr via Docker Compose:
docker compose up --buildPre-built image available on Docker Hub:
docker pull amankhan1009/postgres-mcp-server:latestTesting
pytest -m "not integration" -v # unit + mocked tests (fast, no DB needed)
pytest -m integration -v # integration tests (hits real Neon)
pytest -v # everything22 tests passing: 20 unit/mocked (including full sql_guard injection-defense coverage) + 2 integration tests against real seeded data.
Example Tool Calls
list_tables()
["clients", "departments", "employees", "invoices", "meeting_attendees",
"meetings", "orders", "products", "project_assignments", "projects", "support_tickets"]business_insights("which department has the highest average employee salary?")
The department with the highest average employee salary is Engineering, with an average salary of $101,125.
find_related_tables("employees", max_depth=2)
{
"table_name": "employees",
"related_tables": {
"departments": 1, "project_assignments": 1, "meeting_attendees": 1, "support_tickets": 1,
"projects": 2, "clients": 2, "meetings": 2
}
}Security
All user/LLM-supplied SQL passes through
sql_guard.py: single-statement enforcement, forbidden keyword/function blocking, and a hard row limitEvery query runs inside a
READ ONLYPostgres transaction as a final safety netTable names from tool inputs are validated against a live whitelist (
list_tables()) before being used in any query, since identifiers can't be parameterized like valuesSecrets are never baked into the Docker image โ passed only at runtime via
--env-fileContainer runs as a non-root user
Future Improvements
Optional, separately-hardened write capability (structured
insert_row-style tools with strict table/column whitelisting, audit logging, and confirmation steps) โ deliberately out of scope for this version, which is read-only by designSupport for a second LLM provider (OpenAI/Anthropic) via the existing
LLMProviderinterfaceQuery result caching for repeated
describe_table/list_tablescallsRate limiting on
execute_selectand LLM-powered tools
Built as a portfolio project to demonstrate production-grade backend architecture, PostgreSQL fluency, and safe AI-database integration via MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/Amankhan1009/postgres-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server