Skip to content

Instantly share code, notes, and snippets.

@aseba
Last active February 24, 2026 18:07
Show Gist options
  • Select an option

  • Save aseba/9dca16dfc23e8a870157a25b57e01efb to your computer and use it in GitHub Desktop.

Select an option

Save aseba/9dca16dfc23e8a870157a25b57e01efb to your computer and use it in GitHub Desktop.
Install Postgres MCP for Cursor (read-only, with cloud-sql-proxy)
#!/bin/bash
# Install Postgres MCP for Cursor
# Usage: bash <(curl -fsSL https://gist.githubusercontent.com/aseba/9dca16dfc23e8a870157a25b57e01efb/raw/install-postgres-mcp.sh)
#
# Installs .cursor/mcp.json and .cursor/start-postgres-mcp.sh into the current directory.
# Installs missing dependencies: brew, gcloud, cloud-sql-proxy, uv/uvx
set -euo pipefail
echo "πŸ”§ Installing Postgres MCP for Cursor..."
# --- Create .cursor directory ---
mkdir -p .cursor
# --- Install missing dependencies (runs in terminal, interactive OK) ---
# Homebrew
if ! command -v brew &>/dev/null; then
echo "πŸ“¦ Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || eval "$(/usr/local/bin/brew shellenv)" 2>/dev/null
fi
# gcloud
if ! command -v gcloud &>/dev/null; then
echo "πŸ“¦ Installing gcloud CLI..."
brew install --cask google-cloud-sdk
fi
# cloud-sql-proxy
if ! command -v cloud-sql-proxy &>/dev/null; then
echo "πŸ“¦ Installing cloud-sql-proxy..."
brew install cloud-sql-proxy
fi
# uv / uvx
if ! command -v uvx &>/dev/null; then
export PATH="$HOME/.local/bin:$PATH"
fi
if ! command -v uvx &>/dev/null; then
echo "πŸ“¦ Installing uv..."
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
fi
# --- Write start-postgres-mcp.sh (check-only, no interactive installs) ---
cat > .cursor/start-postgres-mcp.sh << 'WRAPPER'
#!/bin/bash
# Wrapper script to ensure cloud-sql-proxy is running before starting postgres-mcp.
# Used by Cursor MCP integration (.cursor/mcp.json).
#
# Expects DATABASE_URI env var to be set by Cursor config.
set -euo pipefail
INSTANCE="remotely-platform:us-central1:platform-master-replica"
PROXY_PORT=5432
# --- Load .env for database credentials ---
if [ -n "${DOTENV_PATH:-}" ] && [ -f "$DOTENV_PATH" ]; then
set -a
source "$DOTENV_PATH"
set +a
fi
export DATABASE_URI="postgresql://ci:${PLATFORM_DB_PASSWORD:-}@127.0.0.1:5432/platform"
# --- Ensure PATH includes common install locations (Cursor launches with minimal env) ---
eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || eval "$(/usr/local/bin/brew shellenv)" 2>/dev/null || true
export PATH="$HOME/.local/bin:$PATH"
# Find gcloud via Spotlight (instant on macOS)
if ! command -v gcloud &>/dev/null; then
GCLOUD_INC=$(mdfind -name "path.bash.inc" 2>/dev/null | grep google-cloud-sdk | head -1)
if [ -n "$GCLOUD_INC" ]; then
source "$GCLOUD_INC"
fi
fi
# --- Check dependencies (no interactive installs β€” Cursor runs this non-interactively) ---
MISSING=()
if ! command -v brew &>/dev/null; then
MISSING+=("brew: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"")
fi
if ! command -v gcloud &>/dev/null; then
MISSING+=("gcloud: brew install --cask google-cloud-sdk && gcloud auth login")
fi
if ! command -v cloud-sql-proxy &>/dev/null; then
MISSING+=("cloud-sql-proxy: brew install cloud-sql-proxy")
fi
if ! command -v uvx &>/dev/null; then
MISSING+=("uvx: curl -LsSf https://astral.sh/uv/install.sh | sh")
fi
if [ ${#MISSING[@]} -gt 0 ]; then
echo "ERROR: Missing dependencies. Run these in your terminal:" >&2
for m in "${MISSING[@]}"; do
echo " $m" >&2
done
echo "Then restart Cursor." >&2
exit 1
fi
# Start cloud-sql-proxy with gcloud auth if not already running on our port
if ! lsof -i ":$PROXY_PORT" -sTCP:LISTEN &>/dev/null; then
cloud-sql-proxy "$INSTANCE" --port "$PROXY_PORT" -g >/dev/null 2>&1 &
PROXY_PID=$!
# Wait up to 10 seconds for proxy to be ready
for _ in $(seq 1 20); do
if lsof -i ":$PROXY_PORT" -sTCP:LISTEN &>/dev/null; then
break
fi
sleep 0.5
done
if ! lsof -i ":$PROXY_PORT" -sTCP:LISTEN &>/dev/null; then
echo "ERROR: cloud-sql-proxy failed to start on port $PROXY_PORT" >&2
echo "Try: gcloud auth login" >&2
kill "$PROXY_PID" 2>/dev/null
exit 1
fi
fi
# Start postgres-mcp in restricted (read-only) mode via stdio
exec uvx --python 3.12 postgres-mcp --access-mode=restricted
WRAPPER
chmod +x .cursor/start-postgres-mcp.sh
# --- Write mcp.json ---
cat > .cursor/mcp.json << 'MCPJSON'
{
"mcpServers": {
"postgres": {
"command": "bash",
"args": [
"${workspaceFolder}/.cursor/start-postgres-mcp.sh"
],
"env": {
"DOTENV_PATH": "${workspaceFolder}/.cursor/.env"
}
}
}
}
MCPJSON
# --- Prompt for DB password ---
if [ -f .cursor/.env ] && grep -q '[^=]$' .cursor/.env 2>/dev/null; then
echo "βœ… .cursor/.env already has a password set"
else
echo ""
read -rsp "πŸ”‘ Enter PLATFORM_DB_PASSWORD (get from platform/database-env or a colleague): " DB_PASS
echo ""
if [ -n "$DB_PASS" ]; then
echo "PLATFORM_DB_PASSWORD=$DB_PASS" > .cursor/.env
else
echo "PLATFORM_DB_PASSWORD=" > .cursor/.env
echo "⚠️ No password entered. Set it later: echo 'PLATFORM_DB_PASSWORD=<PASSWORD>' > .cursor/.env"
fi
fi
echo ""
echo "βœ… Created .cursor/mcp.json"
echo "βœ… Created .cursor/start-postgres-mcp.sh"
echo "βœ… Created .cursor/.env (add your password here)"
echo ""
# --- Check manual steps ---
NEEDS_ACTION=false
if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null | grep -q .; then
echo "⚠️ Run: gcloud auth login"
NEEDS_ACTION=true
fi
if ! grep -q '[^=]$' .cursor/.env 2>/dev/null; then
NEEDS_ACTION=true
fi
if [ "$NEEDS_ACTION" = true ]; then
echo ""
echo "After completing the steps above, restart Cursor (Cmd+Q) to activate the MCP."
else
echo ""
echo "πŸš€ All set! Restart Cursor (Cmd+Q) to activate the Postgres MCP."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment