Skip to content

Latest commit

 

History

History
172 lines (122 loc) · 4.31 KB

File metadata and controls

172 lines (122 loc) · 4.31 KB

PostgreSQL MCP Server

A Model Context Protocol (MCP) server for querying PostgreSQL databases over either stdio or Streamable HTTP.

I built this because clients had trouble with the reference Postgres MCP server when there were multiple databases. This version passes through a user-specified server name so federated clients can distinguish tool namespaces cleanly.

Installation

npm install
npm run build

Run via npx from a Git repo

Once the repo is reachable on GitHub, npx can install it directly from the Git URL and run the postgres-mcp bin:

npx --yes --package=github:OWNER/postgres-mcp postgres-mcp

Equivalent forms also work:

npx --yes --package=git+https://github.com/OWNER/postgres-mcp.git postgres-mcp

Because this package builds to dist/, the repo includes a prepare script so npm compiles it automatically during Git-based installs.

Configuration

The server uses a PostgreSQL connection string supplied through DATABASE_URL.

Connection string format: postgresql://user:password@host:port/database

Environment Variables

DATABASE_URL

Required PostgreSQL connection string used for all queries.

MCP_SERVER_NAME

Customizes the MCP server name. This is useful when running multiple PostgreSQL MCP instances side by side.

Example:

MCP_SERVER_NAME="postgres-production" npm start

READ_ONLY_MODE

Controls whether the server enforces read-only mode. Defaults to true for safety.

  • READ_ONLY_MODE=true (default): Blocks INSERT, UPDATE, DELETE, CREATE, ALTER, DROP operations
  • READ_ONLY_MODE=false: Allows all operations permitted by the database user

MCP_TRANSPORT

Selects how the server is exposed.

  • stdio (default): Launch as a local MCP subprocess
  • http: Expose a Streamable HTTP endpoint

HTTP transport settings

Used only when MCP_TRANSPORT=http.

  • MCP_HTTP_HOST: Bind address. Defaults to 127.0.0.1
  • MCP_HTTP_PORT: Bind port. Defaults to 3000
  • MCP_HTTP_PATH: MCP endpoint path. Defaults to /mcp
  • MCP_HTTP_ALLOWED_HOSTS: Optional comma-separated Host header allowlist for non-loopback deployments
  • MCP_HTTP_ENABLE_DNS_REBINDING_PROTECTION: Optional override for DNS rebinding protection (true or false)

Usage

Docker

Build the image:

docker build -t postgres-mcp .

Run an HTTP MCP endpoint:

docker run --rm \
  -e DATABASE_URL="postgresql://myuser:mypassword@host.docker.internal:5432/mydb" \
  -e MCP_SERVER_NAME="postgres-production" \
  -e MCP_TRANSPORT=http \
  -e MCP_HTTP_HOST=0.0.0.0 \
  -e MCP_HTTP_PORT=8811 \
  -p 8811:8811 \
  postgres-mcp

Usage

Stdio transport

Run the server as a local MCP subprocess:

DATABASE_URL="postgresql://myuser:mypassword@localhost:5432/mydb" \
MCP_SERVER_NAME="postgres-production" \
npm start

Streamable HTTP transport

Run the server as an HTTP MCP endpoint:

DATABASE_URL="postgresql://myuser:mypassword@localhost:5432/mydb" \
MCP_SERVER_NAME="postgres-production" \
MCP_TRANSPORT=http \
MCP_HTTP_HOST=127.0.0.1 \
MCP_HTTP_PORT=8811 \
npm run start:http

The MCP endpoint will be available at http://127.0.0.1:8811/mcp.

Using with Claude Desktop

Add this to your Claude Desktop configuration:

{
  "mcpServers": {
    "postgres": {
      "command": "node",
      "args": ["/path/to/postgres-mcp/dist/index.js"],
      "env": {
        "DATABASE_URL": "postgresql://myuser:mypassword@localhost:5432/mydb",
        "MCP_SERVER_NAME": "postgres-production"
      }
    }
  }
}

Available Tools

query

Execute a PostgreSQL query.

Parameters:

  • query (required): SQL query to execute
  • maxRows (optional): Server-side row cap applied to top-level SELECT queries. Defaults to 10

Example:

{
  "query": "SELECT * FROM users",
  "maxRows": 25
}

view_schemas

List non-system PostgreSQL view definitions.

Parameters:

  • schema (optional): Limit results to a specific schema
  • view (optional): Limit results to a specific view name
  • maxRows (optional): Row cap for the result set

table_schemas

Generate CREATE TABLE statements, including table and column comments.

Parameters:

  • schema (optional): Limit results to a specific schema
  • table (optional): Limit results to a specific table name
  • maxRows (optional): Row cap for the result set