Skip to main content
Glama
thecuriousarchitect09

mcp-postgres-db-claude

I Gave Claude Access to My PostgreSQL Database

A practical MCP project for The Curious Architect.

The project connects:

Claude → MCP → Python MCP Server → PostgreSQL

Claude can inspect the database schema and ask the MCP server to run read-only SQL queries.

What this demonstrates

  • MCP tools

  • MCP resources

  • Streamable HTTP transport

  • Python MCP SDK v2

  • PostgreSQL with psycopg

  • Schema discovery

  • AI-generated SQL

  • Read-only database access

  • A dedicated PostgreSQL read-only user

  • Query result limiting and statement timeout

Related MCP server: postgres-mcp-server

Project structure

mcp-postgres-claude/
├── server.py
├── pyproject.toml
├── .env.example
├── docker-compose.yml
├── db/
│   └── init.sql
└── README.md

1. Start PostgreSQL

Make sure Docker is installed, then:

docker compose up -d

The demo database contains:

  • customers

  • orders

Check it:

docker compose ps

2. Create the Python environment

Python 3.10+ is required.

Using uv:

python3 -m venv .venv
source .venv/bin/activate
uv pip install -e .

Or with pip:

python -m venv .venv
source .venv/bin/activate
pip install -e .

The current official MCP Python SDK is v2, and pip install mcp now installs the v2 line. The server therefore uses from mcp.server import MCPServer rather than the old v1 FastMCP import.

3. Configure the database

cp .env.example .env

The example points to the Docker PostgreSQL instance:

DATABASE_URL=postgresql://mcp_readonly:mcp_readonly_password@localhost:5432/company

The database user is intentionally read-only.

4. Start the MCP server

python server.py

The server starts at:

http://127.0.0.1:8000/mcp

You can also use the MCP CLI during development:

mcp dev server.py

5. Test with MCP Inspector

For the HTTP server, connect the Inspector to:

http://127.0.0.1:8000/mcp

Try:

list_tables

What tables are available?

describe_table

Describe the orders table.

query_database

SELECT
    c.country,
    COUNT(*) AS orders,
    SUM(o.amount) AS revenue
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'paid'
GROUP BY c.country
ORDER BY revenue DESC

The model can generate this query from a natural-language request such as:

Show me revenue by country for paid orders.

6. Connect Claude

Expose the local MCP endpoint through a secure tunnel if your Claude setup requires a public HTTPS endpoint.

For example, with ngrok:

ngrok config add-authtoken <TOKEN>
ngrok http 8000

Use the HTTPS MCP endpoint:

https://YOUR-NGROK-DOMAIN/mcp

Then add it as an MCP connector in the Claude environment you are using.

Do not expose a production database directly to the public internet.

Available MCP primitives

Tools

list_tables

Returns tables in the public schema.

describe_table

Returns column names, data types, nullability, and defaults.

query_database

Runs one read-only SELECT or WITH query and returns structured rows.

Resource

postgres://schema

Provides a compact representation of the database schema so an MCP host can understand the available tables and columns.

Safety design

This project is intentionally designed as a demo with multiple read-only boundaries.

1. Database user

The MCP server connects as:

mcp_readonly

That user receives SELECT permission only.

2. Read-only transaction

Every query is executed inside a PostgreSQL read-only transaction.

3. SQL validation

The MCP tool only accepts queries beginning with SELECT or WITH and blocks common write/administrative operations.

4. Row limit

Results are capped by MAX_ROWS, defaulting to 50.

5. Statement timeout

Queries are limited by STATEMENT_TIMEOUT_MS, defaulting to 5000 ms.

These are demo safeguards, not a complete production security model. For production, add authentication/authorization, stronger SQL policy enforcement, auditing, least-privilege schemas, network controls, and carefully designed domain-specific tools.

Good Claude demo prompts

Try these in the video:

What tables do I have?
How many customers are in each country?
Which customer generated the most paid revenue?
Show me monthly paid revenue for 2026.
What is the average paid order value?
Find customers who have never placed an order.

A stronger demo is:

Analyze the database and tell me the top 3 countries by paid revenue.
Explain how you calculated it and show the SQL query you used.

Architecture

                    Natural language
                           │
                           ▼
                     ┌───────────┐
                     │  Claude   │
                     └─────┬─────┘
                           │ MCP
                           ▼
                ┌─────────────────────┐
                │ Python MCP Server   │
                │                     │
                │ list_tables         │
                │ describe_table      │
                │ query_database      │
                │ postgres://schema   │
                └──────────┬──────────┘
                           │ psycopg
                           ▼
                ┌─────────────────────┐
                │     PostgreSQL      │
                │                     │
                │ customers           │
                │ orders              │
                └─────────────────────┘

Video positioning

The point of this project is not to teach PostgreSQL.

The story is:

What happens when an AI assistant can actually understand and query a real database?

MCP is the bridge that exposes controlled database capabilities to Claude.

Next project ideas

This can naturally lead into:

  1. MCP + PostgreSQL + authentication

  2. MCP + PostgreSQL + charts

  3. MCP + multiple databases

  4. MCP + APIs + PostgreSQL

  5. Build an AI Data Analyst with MCP

Related MCP Connectors

Related MCP Servers