MCP server giving Claude Desktop read-only access to the BairesDev gong-nl-db Cloud SQL Postgres instance.
Project description
gong-nl-db-mcp
Read-only Claude Desktop access to the BairesDev gong-nl-db Cloud SQL
Postgres instance.
This is an MCP server that colleagues install on their Mac. Once set up, they can ask Claude Desktop questions like "what tables are in gong-nl-db?" or "show me last week's top 10 accounts by call volume" and Claude will query the database directly — always read-only, always audited to their personal @bairesdev.com identity.
For colleagues (one-time setup, ~3 minutes)
You need:
- macOS
- Claude Desktop (download)
- A Google Cloud SDK install — if you don't have
gcloud:brew install --cask google-cloud-sdk
Then run:
curl -LsSf https://raw.githubusercontent.com/andyhorvitz/gong-nl-db-mcp/main/scripts/install.sh | bash
The installer will:
- Install
uv(tiny Python runner) if you don't have it. - Prompt you to sign in to Google with
gcloud auth application-default login. Use your@bairesdev.comaccount. - Register the
gong-nl-dbMCP server in Claude Desktop's config.
Restart Claude Desktop and try asking it: "List the schemas in gong-nl-db."
If you get a permissions error, ping Andy — he needs to grant your Google account access to the Cloud SQL instance (see the owner setup section below).
What you can do
Claude will have these tools available under the gong-nl-db MCP server:
| Tool | What it does |
|---|---|
list_schemas |
Show non-system schemas |
list_tables(schema) |
Show tables/views in a schema |
describe_table(table, schema) |
Show columns, types, nullability |
sample_rows(table, schema, limit) |
Return up to 50 sample rows |
run_query(sql, limit) |
Run a read-only SELECT / WITH / set-op (max 1000 rows) |
explain_query(sql) |
Return the query plan |
What you can't do
Every query is checked against a read-only allow-list before it reaches
the database. Attempting INSERT, UPDATE, DELETE, DROP, TRUNCATE,
COPY, CALL, VACUUM, SET, etc. will be rejected. Even if that layer
somehow let a write through, the Postgres role you connect as only has
SELECT grants and the transaction is explicitly READ ONLY. Four layers
of defense — you are not going to accidentally drop prod.
For the owner (Andy): initial Cloud SQL setup
This is a one-time-per-instance setup. After this, each new colleague just needs the per-user steps below.
1. Enable IAM database authentication on the instance
gcloud sql instances patch gong-nl-db \
--database-flags=cloudsql.iam_authentication=on,cloudsql.enable_pgaudit=on,pgaudit.log=read
2. Create the read-only Postgres role
Connect as a superuser (e.g. via cloud-sql-proxy + psql):
CREATE ROLE readonly_analysts;
GRANT CONNECT ON DATABASE <db> TO readonly_analysts;
GRANT USAGE ON SCHEMA public TO readonly_analysts;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_analysts;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO readonly_analysts;
ALTER DATABASE <db> SET default_transaction_read_only = on;
Repeat the GRANT USAGE / GRANT SELECT / ALTER DEFAULT PRIVILEGES block
for each additional schema you want to expose.
3. For each colleague (e.g. alice@bairesdev.com)
# GCP IAM — lets them authenticate to the instance
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member=user:alice@bairesdev.com --role=roles/cloudsql.client
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member=user:alice@bairesdev.com --role=roles/cloudsql.instanceUser
# Cloud SQL — registers them as an IAM DB user on the instance
gcloud sql users create alice@bairesdev.com \
--instance=gong-nl-db --type=cloud_iam_user
Then, in Postgres:
GRANT readonly_analysts TO "alice@bairesdev.com";
4. Configure the installer
Edit scripts/install.sh and replace the REPLACE_ME placeholders with:
INSTANCE_CONNECTION_NAME—<project>:<region>:gong-nl-dbDB_NAME— the Postgres database name
Commit, push to main. Next colleague who re-runs the one-liner picks up the
new config.
Development
uv venv --python 3.12
uv pip install -e ".[dev]"
.venv/bin/pytest # run the safety test suite
Test the MCP server locally against a running Cloud SQL Auth Proxy or the live instance:
INSTANCE_CONNECTION_NAME=... DB_NAME=... \
.venv/bin/gong-nl-db-mcp # speaks MCP over stdio
Releasing
Tag-driven: git tag v0.2.0 && git push --tags triggers
.github/workflows/release.yml, which publishes to PyPI. Colleagues' uvx gong-nl-db-mcp@latest picks it up automatically.
The safety guarantee
src/gong_nl_db_mcp/safety.py is the statement-level allow-list. Any
change to that file must go through PR review. The file's git history is
the audit trail for the read-only guarantee. See tests/test_safety.py for
the allow/deny corpus.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gong_nl_db_mcp-0.1.0.tar.gz.
File metadata
- Download URL: gong_nl_db_mcp-0.1.0.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a736b329c22420344ec3f2c1bb2b326c070b0af94919e48eae7278315325aa6e
|
|
| MD5 |
1d90d8ecc7a82ec54a487370970017a3
|
|
| BLAKE2b-256 |
390e8bffa418a63e84762465cb22d303443319afa785803d60f95d28119ee8ac
|
File details
Details for the file gong_nl_db_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gong_nl_db_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12e38c4f79f5481c8f2637dd0de899469055944e2827b609ab7ea69839f62bbc
|
|
| MD5 |
75cb6c1af90314207afc601f4b8a4d2a
|
|
| BLAKE2b-256 |
70f7ae037772a29353d226b46bbc146bbc9962643b5c36fae325a5d878c6b49e
|