Skip to main content
Glama
RISHAB-SIKKA

PostgreSQL MCP Server

by RISHAB-SIKKA

PostgreSQL MCP Server

Safe, tool-based access to a multi-tenant PostgreSQL setup — for Cursor, Claude Desktop, or any MCP client.

One admin database holds tenant connection records. Every tenant gets its own isolated database. The agent discovers tenants, explores schemas, and runs queries — all through natural language, with reads and writes kept in separate tools so nothing destructive happens by accident.

Stack: TypeScript · Official MCP SDK · pg · stdio transport


Table of Contents


Related MCP server: postgres-mcp-server

Why this exists

In a multi-tenant architecture, every tenant's data lives in its own database — great for isolation, painful for day-to-day access. Checking a tenant's data normally means finding the right connection string, opening a DB client, and writing SQL by hand, every single time.

This server removes that friction. Point your MCP client at it, and you can ask things like "which tenant has the most users?" — the agent resolves the tenant, opens the right connection, and runs the query for you.


Architecture

MCP Client (Cursor / Claude Desktop / etc.)
        │  stdio · JSON-RPC
        ▼
postgres-mcp-server (this repo)
        │
        ├── Admin DB  →  "Tenant" registry
        │                 (id, dbHost, dbName, dbUsername, dbPassword)
        │
        └── Tenant DBs → one connection pool per tenantId
                          (cached, max 3 connections each)

How a request flows:

  1. On startup, the server opens a pool to the admin DB via ADMIN_DATABASE_URL.

  2. When a tool call includes a tenantId, the server looks up that tenant's connection details in the "Tenant" table.

  3. A dedicated pool is opened (or reused, if cached) for that tenant only.

  4. Every data tool requires an explicit tenantId — there is no code path that spans two tenants in one query.


Tools

Tool

Access

Purpose

list_tenants

Read

List all tenants from the admin DB — your entry point for a tenantId

list_tables

Read

List tables in a tenant's database

describe_table

Read

Column names, types, nullability, defaults

table_counts

Read

Approximate row counts per table

query

Read

Run SELECT / WITH statements (supports $1, $2… params)

admin_query

Read

Run SELECT against the admin database itself

execute

Write

INSERT / UPDATE / DELETEWHERE is required for update/delete

execute_ddl

Schema

CREATE / ALTER / DROP / TRUNCATE

Read, write, and schema operations are split into separate tools on purpose — you can disable an entire category (e.g. remove write access) by commenting out one tool registration.


Requirements

  • Node.js 18+

  • An admin PostgreSQL database with a "Tenant" table (see below)

  • Tenant databases reachable from the machine running the MCP client

Admin "Tenant" table

CREATE TABLE IF NOT EXISTS "Tenant" (
  id             TEXT PRIMARY KEY,
  "dbHost"       TEXT NOT NULL,
  "dbName"       TEXT NOT NULL,
  "dbUsername"   TEXT NOT NULL,
  "dbPassword"   TEXT NOT NULL
);

Register a tenant:

INSERT INTO "Tenant" (id, "dbHost", "dbName", "dbUsername", "dbPassword")
VALUES ('tenant-001', 'db.example.com', 'my_tenant_db', 'db_user', 'db_password');

Setup

git clone https://github.com/RISHAB-SIKKA/PostgreSQL-MCP-Server.git
cd PostgreSQL-MCP-Server
npm install
npm run build

Quick smoke test — the process should stay running:

export ADMIN_DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/ADMIN_DB?sslmode=require"
node build/index.js
# → Multi-tenant Postgres MCP server running (stdio).

Press Ctrl+C to stop.


Connect to an MCP client

Cursor

Add to ~/.cursor/mcp.json (or a project-level .cursor/mcp.json):

{
  "mcpServers": {
    "postgres-db": {
      "command": "node",
      "args": ["/absolute/path/to/PostgreSQL-MCP-Server/build/index.js"],
      "env": {
        "ADMIN_DATABASE_URL": "postgresql://USER:PASSWORD@HOST:5432/ADMIN_DB?sslmode=require",
        "DB_PORT": "5432",
        "DATABASE_SCHEMA": "public",
        "NODE_TLS_REJECT_UNAUTHORIZED": "0"
      }
    }
  }
}

Open Customize → MCPs, confirm postgres-db shows as connected, then ask in Agent chat: "List all tenants."

Claude Desktop

Add to claude_desktop_config.json:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "postgres-db": {
      "command": "node",
      "args": ["/absolute/path/to/PostgreSQL-MCP-Server/build/index.js"],
      "env": {
        "ADMIN_DATABASE_URL": "postgresql://USER:PASSWORD@HOST:5432/ADMIN_DB?sslmode=require",
        "DB_PORT": "5432",
        "DATABASE_SCHEMA": "public"
      }
    }
  }
}

Environment variables

Variable

Required

Default

Notes

ADMIN_DATABASE_URL

Yes

Connection string for the admin database

DB_PORT

Recommended

5433

Port used for all tenant connections — set this to match your tenants

DATABASE_SCHEMA

No

public

search_path applied to tenant pools

NODE_TLS_REJECT_UNAUTHORIZED

Sometimes

Set to 0 only if corporate TLS or a managed host fails cert verification (dev only — don't use in production)

Port tip: Tenant host, username, and password come from the "Tenant" table, but the port always comes from DB_PORT. If your tenants listen on a non-default port (e.g. 1186), set DB_PORT accordingly — it applies to every tenant connection.


Example prompts

  • "List all tenants."

  • "Show tables for tenant tenant-001."

  • "Describe the users table for that tenant."

  • "Run a read-only query counting rows created this month."

  • "Which tenant has the most registered users?"

Typical flow: list_tenantslist_tables / describe_tablequery


Project layout

src/index.ts      # MCP server + tool definitions
build/            # tsc output (gitignored)
package.json
tsconfig.json

Security notes

  • query and admin_query are gated to SELECT / WITH only; execute refuses UPDATE / DELETE without a WHERE clause. These checks catch statement type, not injected SQL inside a statement — always pass values via $1, $2… params rather than string-concatenating them into sql.

  • Tenant credentials (dbPassword) are stored in plaintext in the "Tenant" table. Consider encrypting at rest or moving to a secrets manager for production use.

  • NODE_TLS_REJECT_UNAUTHORIZED=0 disables certificate verification — fine for local dev against self-signed/managed hosts, but should never ship to production.

  • execute_ddl has no confirmation step. If you don't need schema changes from the agent, comment out that tool registration.


License

ISC

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to interact with PostgreSQL databases, providing tools for querying, table listing, schema exploration, and multi-environment management with write protection and schema scoping.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only natural-language database agent that exposes PostgreSQL schema-discovery and SELECT tools via MCP, enabling users to query databases in plain English.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to securely interact with PostgreSQL databases through a standardized MCP interface, supporting SQL queries, schema inspection, and database management.
    MIT

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/RISHAB-SIKKA/PostgreSQL-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server