An MCP server for Claude Code (and other MCP clients) to connect to and query GCP Cloud SQL PostgreSQL instances — including customer environments.
| Tool | Description |
|---|---|
cloudsql_connect |
Establish a connection (Connector / Auth Proxy / direct) |
cloudsql_disconnect |
Close the connection |
cloudsql_status |
Check connection and server info |
cloudsql_query |
Execute read-only SELECT queries |
cloudsql_list_tables |
List tables and views |
cloudsql_describe_table |
Show column definitions |
cloudsql_search_schema |
Search tables/columns by name pattern |
cloudsql_execute |
Execute write statements (INSERT/UPDATE/DELETE/DDL) — requires confirm: true |
cloudsql_explain |
Run EXPLAIN / EXPLAIN ANALYZE on a query |
cloudsql_list_indexes |
Show table indexes with columns, type, and constraints |
cloudsql_list_environments |
List pre-configured environments from environments.json |
Define environments in environments.json (repo root or ~/.config/gcp-cloudsql-mcp/). Each environment bundles connection credentials and an optional IAP tunnel config:
{
"my-env": {
"tunnel": {
"project": "my-gcp-project",
"zone": "me-central2-a",
"bastion": "qa-db-bastion",
"remoteHost": "10.2.3.8",
"remotePort": 5432,
"localPort": 5432
},
"connection": {
"database": "mydb",
"user": "myuser",
"password": "secret"
}
}
}Then connect with a single parameter:
cloudsql_connect:
environment: "my-env"
This will automatically:
- Start an IAP tunnel via
gcloud compute ssh --tunnel-through-iap - Wait for the tunnel to become ready
- Connect to the database through the tunnel
- Stop the tunnel on disconnect or server shutdown
If the local port is already in use (e.g. you started the tunnel manually), it will reuse the existing tunnel.
Uses the Cloud SQL Node Connector — handles IAM auth and SSL automatically. Requires Application Default Credentials.
gcloud auth application-default login
# or set GOOGLE_APPLICATION_CREDENTIALS=/path/to/sa-key.jsonConnect in Claude:
cloudsql_connect:
instance_connection_name: "myproject:europe-west1:my-instance"
database: "mydb"
user: "myuser"
password: "secret"
ip_type: "PSC" # PUBLIC, PRIVATE, or PSC (default: PSC)
cloudsql_connect:
instance_connection_name: "myproject:europe-west1:my-instance"
database: "mydb"
user: "sa@myproject.iam" # service account email
use_iam_auth: true
The DB user must be created in PostgreSQL as:
CREATE USER "sa@myproject.iam" WITH LOGIN;
GRANT CONNECT ON DATABASE mydb TO "sa@myproject.iam";Run the proxy locally:
cloud-sql-proxy myproject:europe-west1:my-instance --port 5432Then connect:
cloudsql_connect:
host: "127.0.0.1"
port: 5432
database: "mydb"
user: "myuser"
password: "secret"
npm install
npm run buildclaude mcp add gcp-cloudsql -- node /path/to/gcp-cloudsql-mcp-server/dist/index.jsOr edit ~/.claude/claude.json manually:
{
"mcpServers": {
"gcp-cloudsql": {
"command": "node",
"args": ["/path/to/gcp-cloudsql-mcp-server/dist/index.js"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/sa-key.json"
}
}
}
}Open Cursor Settings > MCP and add a new server, or edit .cursor/mcp.json in your project:
{
"mcpServers": {
"gcp-cloudsql": {
"command": "node",
"args": ["/path/to/gcp-cloudsql-mcp-server/dist/index.js"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/sa-key.json"
}
}
}
}TRANSPORT=http PORT=3000 node dist/index.jsAdd to Claude Code:
{
"mcpServers": {
"gcp-cloudsql": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}- Read-only queries run inside
BEGIN READ ONLYtransactions — cannot modify data. - Write statements (
cloudsql_execute) requireconfirm: trueas an explicit gate. - Statement timeout is 30s for reads, 60s for writes.
- Results are capped at 200 rows by default (configurable up to 1000).
- Use parameterized queries (
$1, $2, ...) to prevent SQL injection.
On successful connect, the server saves connection config to ~/.config/gcp-cloudsql-mcp/connection.json (file permissions 0600). On next server start, it automatically restores the last connection. Calling cloudsql_connect again overwrites the saved config.
For switching between customer environments, simply call cloudsql_connect again with new parameters — it will close the previous connection automatically.
The service account / user needs:
roles/cloudsql.client(to connect via Cloud SQL Connector)- Database-level permissions granted via SQL (
GRANT SELECT ON ALL TABLES...)