Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,59 @@ The Postgres MCP Pro Docker image will automatically remap the hostname `localho
Replace `postgresql://...` with your [Postgres database connection URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).


##### Multiple Database Connections

Postgres MCP Pro supports connecting to multiple databases simultaneously. This is useful when you need to work across different databases (e.g., application database, ETL database, analytics database).

To configure multiple connections, define additional environment variables with the pattern `DATABASE_URI_<NAME>`:

```json
{
"mcpServers": {
"postgres": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e", "DATABASE_URI_APP",
"-e", "DATABASE_URI_ETL",
"-e", "DATABASE_URI_ANALYTICS",
"-e", "DATABASE_DESC_APP",
"-e", "DATABASE_DESC_ETL",
"-e", "DATABASE_DESC_ANALYTICS",
"crystaldba/postgres-mcp",
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI_APP": "postgresql://user:pass@localhost:5432/app_db",
"DATABASE_URI_ETL": "postgresql://user:pass@localhost:5432/etl_db",
"DATABASE_URI_ANALYTICS": "postgresql://user:pass@localhost:5432/analytics_db",
"DATABASE_DESC_APP": "Main application database with user data and transactions",
"DATABASE_DESC_ETL": "ETL staging database for data processing pipelines",
"DATABASE_DESC_ANALYTICS": "Read-only analytics database with aggregated metrics"
}
}
}
}
```

Each connection is identified by its name (the part after `DATABASE_URI_`, converted to lowercase):
- `DATABASE_URI_APP` → connection name: `"app"`
- `DATABASE_URI_ETL` → connection name: `"etl"`
- `DATABASE_URI_ANALYTICS` → connection name: `"analytics"`

**Connection Descriptions**: You can optionally provide descriptions for each connection using `DATABASE_DESC_<NAME>` environment variables. These descriptions help the AI assistant understand which database to use for different tasks. The descriptions are:
- Automatically displayed in the server context (visible to the AI without requiring a tool call)
- Useful for guiding the AI to select the appropriate database

When using tools, the LLM will specify which connection to use via the `conn_name` parameter:
- `list_schemas(conn_name="app")` - Lists schemas in the app database
- `explain_query(conn_name="etl", sql="SELECT ...")` - Explains query in the ETL database

For backward compatibility, `DATABASE_URI` (without a suffix) maps to the connection name `"default"`.


##### Access Mode

Postgres MCP Pro supports multiple *access modes* to give you control over the operations that the AI agent can perform on the database:
Expand Down
51 changes: 51 additions & 0 deletions src/postgres_mcp/env_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Utility functions for environment variable handling."""

import os


def discover_database_connections() -> dict[str, str]:
"""
Discover all DATABASE_URI_* environment variables.

Returns:
Dict mapping connection names to connection URLs
- DATABASE_URI -> "default"
- DATABASE_URI_APP -> "app"
- DATABASE_URI_ETL -> "etl"
"""
discovered = {}

for env_var, url in os.environ.items():
if env_var == "DATABASE_URI":
discovered["default"] = url
elif env_var.startswith("DATABASE_URI_"):
# Extract postfix and lowercase it
postfix = env_var[len("DATABASE_URI_") :]
conn_name = postfix.lower()
discovered[conn_name] = url

return discovered


def discover_database_descriptions() -> dict[str, str]:
"""
Discover all DATABASE_DESC_* environment variables.

Returns:
Dict mapping connection names to descriptions
- DATABASE_DESC -> "default"
- DATABASE_DESC_APP -> "app"
- DATABASE_DESC_ETL -> "etl"
"""
descriptions = {}

for env_var, desc in os.environ.items():
if env_var == "DATABASE_DESC":
descriptions["default"] = desc
elif env_var.startswith("DATABASE_DESC_"):
# Extract postfix and lowercase it
postfix = env_var[len("DATABASE_DESC_") :]
conn_name = postfix.lower()
descriptions[conn_name] = desc

return descriptions
Loading