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.
npm install
npm run buildOnce 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-mcpEquivalent forms also work:
npx --yes --package=git+https://github.com/OWNER/postgres-mcp.git postgres-mcpBecause this package builds to dist/, the repo includes a prepare script so npm compiles it automatically during Git-based installs.
The server uses a PostgreSQL connection string supplied through DATABASE_URL.
Connection string format: postgresql://user:password@host:port/database
Required PostgreSQL connection string used for all queries.
Customizes the MCP server name. This is useful when running multiple PostgreSQL MCP instances side by side.
Example:
MCP_SERVER_NAME="postgres-production" npm startControls whether the server enforces read-only mode. Defaults to true for safety.
READ_ONLY_MODE=true(default): Blocks INSERT, UPDATE, DELETE, CREATE, ALTER, DROP operationsREAD_ONLY_MODE=false: Allows all operations permitted by the database user
Selects how the server is exposed.
stdio(default): Launch as a local MCP subprocesshttp: Expose a Streamable HTTP endpoint
Used only when MCP_TRANSPORT=http.
MCP_HTTP_HOST: Bind address. Defaults to127.0.0.1MCP_HTTP_PORT: Bind port. Defaults to3000MCP_HTTP_PATH: MCP endpoint path. Defaults to/mcpMCP_HTTP_ALLOWED_HOSTS: Optional comma-separated Host header allowlist for non-loopback deploymentsMCP_HTTP_ENABLE_DNS_REBINDING_PROTECTION: Optional override for DNS rebinding protection (trueorfalse)
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-mcpRun the server as a local MCP subprocess:
DATABASE_URL="postgresql://myuser:mypassword@localhost:5432/mydb" \
MCP_SERVER_NAME="postgres-production" \
npm startRun 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:httpThe MCP endpoint will be available at http://127.0.0.1:8811/mcp.
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"
}
}
}
}Execute a PostgreSQL query.
Parameters:
query(required): SQL query to executemaxRows(optional): Server-side row cap applied to top-levelSELECTqueries. Defaults to10
Example:
{
"query": "SELECT * FROM users",
"maxRows": 25
}List non-system PostgreSQL view definitions.
Parameters:
schema(optional): Limit results to a specific schemaview(optional): Limit results to a specific view namemaxRows(optional): Row cap for the result set
Generate CREATE TABLE statements, including table and column comments.
Parameters:
schema(optional): Limit results to a specific schematable(optional): Limit results to a specific table namemaxRows(optional): Row cap for the result set