README
¶
aura-tracker-gcp
Give your LLM the full aura of your GCP infrastructure — and the confidence to act on it safely.
aura-tracker-gcp is an open-source, model-agnostic Model Context Protocol (MCP) server written in Go. It connects Claude (or any MCP-compatible LLM) to live Google Cloud Platform state — error rates, memory pressure, IAM gaps, cross-service dependency graphs, cost anomalies, and composite health scores — all queryable in plain English, with mandatory human approval before any infrastructure change.
69 Tools · 10 Resources · 3 Prompts · 26 Modules
For architecture deep-dives, per-service guides, and full configuration reference, see the GitHub Wiki.
Why Aura Tracker GCP?
Safety First, by Default
Every opt-in feature that costs money or could expose sensitive data is off by default:
| Feature | Env var | Default |
|---|---|---|
| Cloud Recommender API integration | RECOMMENDER_ENABLED |
on — disable with =false |
| Recommender BigQuery export tool | RECOMMENDER_BQ_EXPORT_ENABLED |
off |
| PII / credential scrubbing | ANONYMIZE_ENABLED |
off |
| HITL mutation confirmation | SAFETY_ENABLED |
on — the one default that is on by design |
No surprises on your GCP bill. No accidental credential exposure. Two tools mutate GCP state (gcp_gke_scale_deployment, gcp_cloudrun_update_traffic); all 67 others are strictly read-only list/get API calls. Mutation tools require explicit opt-in at every call through a mandatory two-step flow.
Human-in-the-Loop for Every Mutation
No GCP resource can be modified without first generating a preview plan, then explicitly confirming it:
- Call with
dry_run: true→ receive aplan_idand a before/after preview. The plan expires in 10 minutes and is single-use. - Call again with
confirm_plan_id: <plan_id>→ the change executes using the exact parameters locked at dry-run time.
Calling a mutation tool without a plan returns a confirmation required error with step-by-step instructions. Every confirmed execution is audit-logged to Cloud Logging (jsonPayload.msg="safety: mutation confirmed"). This protocol is enforced in internal/safety/ at the port boundary — it cannot be bypassed by the LLM.
Development override: Set
SAFETY_ENABLED=falseto skip the plan/confirm flow. Never use this in production.
Token Efficiency: Load Only What You Need
All 69 tools are registered by default, which consumes LLM context on every turn. Use --modules to load only the services relevant to your workflow — each excluded module also skips its GCP client connections at startup:
"args": ["--modules=cloudrun,aura,monitoring,iam"]
| Workflow | --modules |
Tools |
|---|---|---|
| Cloud Run + functions | cloudrun,functions,eventarc,scheduler,aura,monitoring,iam |
14 |
| GKE cluster health | gke,aura,monitoring,logging |
8 |
| Serverless event graph | serverlessgraph,cloudrun,functions,eventarc,scheduler,workflows,tasks,pubsub,secretmanager,vpcaccess,cloudsql |
20 |
| Data / logging | logging,monitoring,iam |
4 |
| Storage inspection | storage |
3 |
| Full toolkit | (omit flag) | 69 |
See the full module list in Quick Start.
Quick Start
Step 1 — Install
Homebrew (macOS / Linux) — recommended
brew install asbrodova/tap/aura-tracker-gcp
macOS Gatekeeper: On first run macOS may block the binary with a "cannot be opened" warning. Fix with either:
xattr -d com.apple.quarantine $(which aura-tracker-gcp)in your terminal, then restart Claude Desktop.- System Settings → Privacy & Security → scroll down to
aura-tracker-gcp→ click Allow Anyway, then restart Claude Desktop.
Direct binary download (all platforms)
Download the archive for your platform from the latest release, extract, and place the binary on your PATH.
# macOS Apple Silicon example
curl -L https://github.com/asbrodova/aura-tracker-gcp/releases/latest/download/aura-tracker-gcp_darwin_arm64.tar.gz \
| tar xz
sudo mv aura-tracker-gcp /usr/local/bin/
Go toolchain
go install github.com/asbrodova/aura-tracker-gcp/cmd/aura-tracker-gcp@latest
Docker (Raspberry Pi, hosted environments, or anywhere with a container runtime)
docker run --rm \
-e GCP_PROJECT_ID=my-project \
-v "$HOME/.config/gcloud/application_default_credentials.json:/creds.json:ro" \
-e GOOGLE_APPLICATION_CREDENTIALS=/creds.json \
ghcr.io/asbrodova/aura-tracker-gcp:latest
Step 2 — Authenticate with GCP
gcloud auth application-default login
If credentials are missing the server prints a clear error on startup with the exact command to run:
aura-tracker-gcp: no GCP credentials found.
Run: gcloud auth application-default login
Or set GOOGLE_APPLICATION_CREDENTIALS to a service account key file.
Step 3 — Wire it into Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Optional: reduce context usage with --modules
By default all 69 tools are registered. Use the --modules flag to load only the services you work with — each excluded module also skips its GCP client connection at startup.
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=cloudrun,aura,monitoring,iam"],
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Available module names: gke · cloudrun · functions · eventarc · scheduler · workflows · tasks · pubsub · secretmanager · vpcaccess · cloudsql · logging · monitoring · iam · topology · aura · storage · serverlessgraph · gke_workloads · gke_mesh · networking · datastores · supplychain · coverage · archgraph · tagging. Use --modules=none to register zero tools (resources and prompts are always available). Omit the flag to keep the default all-tools behaviour.
| Workflow | Suggested --modules |
Tools loaded |
|---|---|---|
| Cloud Run + functions | cloudrun,functions,eventarc,scheduler,aura,monitoring,iam |
14 |
| Serverless event graph | serverlessgraph,cloudrun,functions,eventarc,scheduler,workflows,tasks,pubsub,secretmanager,vpcaccess,cloudsql |
20 |
| GKE cluster health | gke,aura,monitoring,logging |
8 |
| Storage inspection | storage |
3 |
| Data / logging | logging,monitoring,iam |
4 |
| Full toolkit | (omit flag) | 69 |
Restart Claude Desktop. Tools, Resources, and Prompts appear automatically. Now ask:
"Are there any bottlenecks in my-cluster in us-central1? Look back 60 minutes."
Getting Started by Service
Each snippet below is a minimal mcpServers config for that service. Paste it into your claude_desktop_config.json or .claude/settings.json, replace my-project, and restart.
GKE
Modules: gke (cluster health) · add gke_workloads + gke_mesh for workload / mesh introspection
IAM role: roles/container.viewer · add roles/container.admin for node pool scaling
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=gke,aura,monitoring,logging"],
"env": { "GCP_PROJECT_ID": "my-project" }
}
}
}
Try it:
"List all GKE clusters in my-project across all locations."
"Are there any bottlenecks in my-cluster in us-central1? Look back 60 minutes."
"Give me a deep Aura Score for my-cluster — include per-node-pool autoscaling audit."
"Scale the default-pool node pool in my-cluster to 5 nodes — show me a plan first."
The last prompt triggers the two-step HITL flow: the LLM calls gcp_gke_scale_deployment with dry_run: true first, shows you a plan, then waits for your confirmation before executing.
Cloud Run
Modules: cloudrun · add functions, eventarc for the full serverless tier
IAM role: roles/run.viewer · add roles/run.admin for traffic split mutations
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=cloudrun,functions,eventarc,aura,monitoring,iam"],
"env": { "GCP_PROJECT_ID": "my-project" }
}
}
}
Try it:
"List all Cloud Run services in my-project."
"What's the traffic split for the api-gateway service in us-central1?"
"Show me the last 50 ERROR logs from my-service."
"Update the api-gateway traffic split to send 10% to revision-2 — show me a plan first."
Pub/Sub
Module: pubsub
IAM role: roles/pubsub.viewer
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=pubsub,monitoring,iam"],
"env": { "GCP_PROJECT_ID": "my-project" }
}
}
}
Try it:
"List all Pub/Sub topics in my-project with their subscription counts."
"Is there any subscription lag on the orders-topic?"
"Show me the dead-letter configuration for the payment-events subscription."
BigQuery
BigQuery uses MCP Resources, not tools. There is no
--modules=bigqueryflag. Resources (gcp://…/bigquery/…) are always available regardless of which modules are loaded.
IAM role: roles/bigquery.metadataViewer
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=monitoring,iam"],
"env": { "GCP_PROJECT_ID": "my-project" }
}
}
}
The LLM reads BigQuery state through three resource URIs before generating SQL or analysis:
gcp://{project}/bigquery/datasets— discover all datasetsgcp://{project}/bigquery/{dataset}/tables— list tables with row counts and sizesgcp://{project}/bigquery/{dataset}/{table}/schema— full field definitions
This three-step read prevents hallucinated column names — the model knows actual column types before writing SQL.
Try it:
"What BigQuery datasets exist in my-project?"
"Show me the schema for the orders table in the analytics dataset."
"What are the five largest tables in the events dataset by storage size?"
"Use the optimize-bigquery-costs prompt on my-project to identify partitioning opportunities."
Firebase / Firestore
Firestore is available through the datastores module (Phase 2), which also covers Cloud Spanner, AlloyDB, and Memorystore for Redis. It lists Firestore databases in both Native and Datastore mode — it does not read collection or document data.
Module: datastores
IAM role: roles/datastore.viewer
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=datastores,iam"],
"env": { "GCP_PROJECT_ID": "my-project" }
}
}
}
Try it:
"List all Firestore databases in my-project and tell me which are in Native mode."
"What data stores does my-project use? Show me Spanner, AlloyDB, Firestore, and Redis."
Cloud SQL
Module: cloudsql
IAM role: roles/cloudsql.viewer
Recommender signals are included by default (12h cache, safe 429 handling). Disable with RECOMMENDER_ENABLED=false.
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"args": ["--modules=cloudsql,aura,monitoring,iam"],
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Try it:
"List all Cloud SQL instances in my-project with their machine tier and state."
"Give me an Aura Score for the main-db Cloud SQL instance."
"Show me the Aura Score summary for all resources in my-project — are any SQL instances idle?"
Tools
69 tools across 26 modules. Load only what you need with --modules.
| Module | Flag | Tools | Mutation? |
|---|---|---|---|
| GKE | gke |
4 | node pool scale |
| GKE Workloads | gke_workloads |
5 | — |
| GKE Service Mesh | gke_mesh |
1 | — |
| Networking | networking |
7 | — |
| Cloud Run | cloudrun |
6 | traffic split |
| Cloud Functions | functions |
2 | — |
| Eventarc | eventarc |
2 | — |
| Cloud Scheduler | scheduler |
1 | — |
| Workflows | workflows |
2 | — |
| Cloud Tasks | tasks |
1 | — |
| Pub/Sub | pubsub |
3 | — |
| Secret Manager | secretmanager |
1 | — |
| Serverless VPC Access | vpcaccess |
1 | — |
| Cloud SQL | cloudsql |
1 | — |
| Cloud Logging | logging |
1 | — |
| Cloud Monitoring | monitoring |
9 | — |
| IAM | iam |
3 | — |
| Topology & Aura Score | topology, aura |
6 | — |
| Cloud Storage | storage |
3 | — |
| Data Stores | datastores |
4 | — |
| Supply Chain | supplychain |
4 | — |
| Serverless Graph | serverlessgraph |
1 | — |
| Architecture Graph | archgraph |
1 | — |
| Observability Coverage | coverage |
1 | — |
| Resource Tagging | tagging |
1 | — |
→ Full tool reference with parameters and descriptions: Module Reference
What You Can Ask
Health & Incident Response
"Are there any bottlenecks in my-cluster in us-central1? Look back 60 minutes."
"What's the Aura Score for all resources in my-project? Show me the worst first."
"Show me ERROR logs from the api-gateway Cloud Run service in the last hour."
"Which Cloud Run services have an error rate above 1% right now?"
Infrastructure Exploration
"What does the payment-service depend on? Show me its full dependency graph."
"List all Pub/Sub topics with subscription lag above 10,000 unacked messages."
"What IAM permissions does my current service account have — and what's missing?"
"Export a full serverless event graph for my-project."
Cost & Efficiency
"Which Cloud SQL instances are idle or over-provisioned? Estimate monthly savings."
"Show me GCS buckets without lifecycle rules or public access prevention."
"Give me an Aura Score for the legacy-db Cloud SQL instance."
Safe Mutations (two-step confirmation required)
"Scale the default-pool node pool in my-cluster to 5 nodes — show me a plan first."
"Update the api-gateway traffic split to send 10% to revision-2 — dry run first."
Resources
10 MCP Resources expose GCP state as browsable context the LLM reads before deciding which tool to call — preventing hallucinated BigQuery column names, IAM surprises, and wasted tool calls.
Covers BigQuery datasets / table schemas, Cloud Run service snapshots and revisions, Cloud Storage bucket metadata, and IAM permission splits. All URIs follow the gcp://{project}/{service}/{resource-path} pattern.
→ Full resource catalog, URI patterns, token budget, and schema discovery workflow: MCP Resources Reference
Prompts
Prompt Templates pre-configure the AI for complex multi-step GCP workflows. Invoke via prompts/get in any MCP client, or by asking Claude to "use the incident-response-helper prompt".
| Prompt | Arguments | What it does |
|---|---|---|
audit-security-posture |
project_id (required), focus (iam|network|all) |
Reads IAM permissions + Cloud Run ingress config; returns severity-ranked findings with gcloud remediation commands |
optimize-bigquery-costs |
project_id (required), dataset_id (optional) |
Reads schemas + slot usage metrics; recommends partitioning, clustering, expiration, and slot rightsizing |
incident-response-helper |
project_id, service_name, region (all required) |
Pulls error logs + request metrics + Aura score; synthesises a structured incident report with rollback commands |
Aura Score
The Aura Score is a composite 0–100 metric that tells an LLM not just that a resource exists, but whether it is healthy and cost-effective — two things that previously required separate queries to Cloud Monitoring, the Recommender API, and manual judgment to combine.
Two tools expose it:
gcp_get_aura_score— scores a single named resource on demand (Cloud Run, Cloud SQL, BigQuery, GKE cluster, or GCS bucket)gcp_project_aura_summary— auto-discovers all Cloud Run services, Cloud SQL instances, BigQuery datasets, and GKE clusters in a project, scores each, and returns them sorted worst-first with a pre-formatted block the LLM can read at a glancegcp_gke_get_aura_score— deep GKE analysis: 5 health signals including version drift against the release channel, plus a per-node-pool autoscaling auditgcp_gcs_get_aura_score— security-posture and cost-efficiency score for a GCS bucket, including PAP enforcement, UBLA status, lifecycle rule presence, and storage class fit
Example output
🔴 Cloud SQL: legacy-db | Aura: 28 (Idle Resource (GCP Recommender))
🟡 Cloud Run: api-gateway | Aura: 62 (Healthy, Over-provisioned)
🟢 Cloud Run: auth-service | Aura: 91 (Healthy & Scaled)
Each resource also returns a reasons array the LLM uses to suggest concrete actions:
{
"display": "🔴 Cloud SQL: legacy-db | Aura: 28 (Idle Resource (GCP Recommender))",
"score": 28,
"health_score": 62,
"efficiency_score": 20,
"health_signals": [
{ "name": "cpu_util", "value": 0.04, "score": 60, "label": "Warning" },
{ "name": "memory_util", "value": 0.12, "score": 60, "label": "Warning" },
{ "name": "disk_util", "value": 0.31, "score": 100,"label": "OK" },
{ "name": "recommender_idle", "value": 43.20, "score": 20, "label": "Warning" }
],
"reasons": [
"GCP Recommender: resource is idle — estimated $43.20/mo savings if deleted or stopped",
"CPU at 4% — instance may be idle; consider a smaller machine type"
]
}
Band mapping: 🟢 80–100 Healthy · 🟡 50–79 Warning · 🔴 0–49 Critical
Scores are cached in-process for 5 minutes. Recommender signals (idle/overprovisioned + estimated monthly USD savings) are active by default with a 12-hour result cache and safe quota handling. Set RECOMMENDER_ENABLED=false to disable.
→ Scoring formula, signal weights per resource type, GCP Recommender integration, and quota details: Aura Score
Using with MCP Clients
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Restart Claude Desktop. The tools will appear automatically in the tool list.
Claude Code (CLI)
Add to your project's .claude/settings.json or global ~/.claude/settings.json:
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "aura-tracker-gcp",
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Or run inline from the repo (no install needed):
{
"mcpServers": {
"aura-tracker-gcp": {
"command": "go",
"args": ["run", "./cmd/aura-tracker-gcp"],
"cwd": "/path/to/aura-tracker-gcp",
"env": {
"GCP_PROJECT_ID": "my-project"
}
}
}
}
Any MCP-compatible client
The server speaks JSON-RPC 2.0 over stdio — the transport used by every MCP client. Point any client at the binary and set GCP_PROJECT_ID.
Example prompts
"List all GKE clusters in project my-project across all locations."
"Are there any bottlenecks in my-cluster in us-central1? Look back 60 minutes."
"What IAM permissions does the current service account have on project my-project?"
"Scale the default-pool node pool in my-cluster to 5 nodes — show me a plan first, then I'll confirm."
"Show me the last 50 ERROR logs from the my-service Cloud Run service."
"What does my-api depend on? Show me its full dependency graph at depth 2."
"Give me an Aura Score for the auth-service Cloud Run service in us-central1."
"Show me the Aura Score summary for all resources in my-project — sorted by worst health first."
"What BigQuery datasets exist in my-project? Then show me the schema for the orders table in the analytics dataset."
"Check my IAM permissions and tell me which GCP tools you can and cannot use in this project."
"Use the incident-response-helper prompt for the api-gateway service in us-central1."
"Run the audit-security-posture prompt on my-project and focus on network exposure."
Prerequisites
- Go 1.26+ (or Docker / Homebrew — no Go required)
- A GCP project with Application Default Credentials configured
- IAM roles for the modules you use — run the setup script below or check what you have with
gcp_iam_test_permissions
The scripts/setup-iam.sh script creates the aura-tracker-mcp service account with least-privilege roles in one command:
PROJECT_ID=my-project bash scripts/setup-iam.sh
# With mutation tools (node pool scale, traffic split)
PROJECT_ID=my-project MUTATION_ROLES=true bash scripts/setup-iam.sh
# With Recommender API (on by default — grant role to avoid silent permission errors)
PROJECT_ID=my-project RECOMMENDER_ROLES=true bash scripts/setup-iam.sh
→ Full per-module IAM role table: Getting Started — IAM Setup
Environment Variables
| Variable | Required | Description |
|---|---|---|
GCP_PROJECT_ID |
Yes* | Default GCP project used when initialising SDK clients. Can be omitted if project_id is set in ~/.aura-tracker.yaml. |
GOOGLE_APPLICATION_CREDENTIALS |
No | Path to service account JSON key (optional if ADC is configured via gcloud) |
ANONYMIZE_ENABLED |
No | Set true to enable PII/credential scrubbing on all tool outputs |
ANONYMIZE_CONFIG_PATH |
No | Path to a YAML config file for the anonymization engine (custom patterns, whitelist, audit mode) |
ANONYMIZE_PROJECT_ID |
No | Set true to mask the GCP project ID in all tool outputs as [GCP_PROJECT_ID_1]. Off by default. Useful for demos. Can be combined with ANONYMIZE_ENABLED. |
RECOMMENDER_ENABLED |
No | Set false to disable Cloud Recommender API integration. On by default. Aura Scores include idle/over-provisioned signals with estimated monthly USD savings. Results are cached for 12 h; 429 quota errors emit an explicit LLM stop signal instead of retrying. Requires the Recommender Viewer role. |
RECOMMENDER_BQ_EXPORT_ENABLED |
No | Set true to register the gcp_export_recommendations_to_bq tool. Off by default. |
RECOMMENDER_BQ_EXPORT_DATASET |
No | BigQuery dataset name used by gcp_export_recommendations_to_bq. Overrides recommender_export.dataset in ~/.aura-tracker.yaml. |
SAFETY_ENABLED |
No | Set false to bypass the two-step HITL confirmation protocol for mutation tools. Development/testing only — safety is on by default. |
TRACE_BACKEND |
No | Backend for gcp_trace_list_services: trace (Cloud Trace v1 REST, default) or monitoring (Monitoring metric proxy). Use monitoring if Cloud Trace API is disabled but OpenCensus/OpenTelemetry metrics exist. |
GRAPH_TIMEOUT_SECONDS |
No | Outer context timeout in seconds for gcp_export_serverless_graph. Default: 120. Individual sub-calls still use callTimeout (30 s). |
MCP_TRANSPORT |
No | Transport mode: stdio (default, for Claude Desktop) or sse (for Cloud Run / web-based MCP clients) |
PORT |
No | HTTP port when MCP_TRANSPORT=sse. Cloud Run sets this automatically. Defaults to 8080. |
MCP_BASE_URL |
No | Public HTTPS URL of the SSE server (e.g. https://my-service-xyz.run.app). Required for correct SSE endpoint URLs when deployed to Cloud Run. Defaults to http://localhost:PORT for local testing. |
User Config File
Avoid setting GCP_PROJECT_ID on every launch by adding a ~/.aura-tracker.yaml:
project_id: my-gcp-project-id
The environment variable takes precedence when both are set.
IAM Setup
scripts/setup-iam.sh is a one-time team-admin setup. Run it once per GCP project to create the aura-tracker-mcp service account with least-privilege roles. If the SA already exists, the script prints onboarding instructions for other team members and exits without making any changes.
# First-time setup (team admin only)
PROJECT_ID=my-project bash scripts/setup-iam.sh
# With mutation tools (gcp_gke_scale_deployment, gcp_cloudrun_update_traffic)
PROJECT_ID=my-project MUTATION_ROLES=true bash scripts/setup-iam.sh
# With Recommender API
PROJECT_ID=my-project RECOMMENDER_ENABLED=true bash scripts/setup-iam.sh
For developers joining the team: the SA already exists. Either ask your admin for a key file (GOOGLE_APPLICATION_CREDENTIALS=/path/to/sa-key.json) or use gcloud auth application-default login with your own account if it already has the required roles.
Why not roles/owner? Primitive roles grant write access to every GCP service in the project — a compromised MCP session could delete databases, modify firewall rules, or exfiltrate secrets. The read-only set grants only list/get on the specific services this server calls. Mutation roles (roles/container.admin, roles/run.admin) are opt-in and always gated by the two-step HITL confirmation protocol.
Audit granted roles:
gcloud projects get-iam-policy PROJECT_ID \
--flatten='bindings[].members' \
--filter="bindings.members:aura-tracker-mcp@PROJECT_ID.iam.gserviceaccount.com" \
--format='table(bindings.role)'
Security Model
The server runs under a specific service account (Application Default Credentials) and implements least-privilege by design:
- Permission-denied errors are surfaced to the LLM as tool errors with clear remediation guidance, not server crashes
- Rate limiting is applied at the port boundary: 10 requests/second, burst 20 — configurable at startup
- Two-step HITL confirmation for mutation tools: no GCP resource can be changed without first generating a preview plan (
dry_run: true→plan_id) and then confirming it (confirm_plan_id: <id>). Plans expire after 10 minutes and are single-use — replay attacks are prevented at the store level. Every confirmed execution is audit-logged to Cloud Logging (jsonPayload.msg="safety: mutation confirmed") - Idempotency: scaling to the current replica count returns
no_change_needed: truewithout generating a plan or issuing an API call - Read-only guarantees: all 67 non-mutation tools are strictly read-only — they call only
list/getGCP API methods and never modify any resource state. The two mutation tools (gcp_gke_scale_deployment,gcp_cloudrun_update_traffic) require the two-step HITL confirmation flow described above. - Secret Manager safety:
gcp_secretmanager_listreturns secret metadata only (name, labels, create time, replication). Thesecretmanager.projects.secrets.versions.accessAPI is never called — secret values cannot be read or returned by any tool in this server. The required role (roles/secretmanager.viewer) does not grantsecretAccessorpermissions. - MCP annotations: all 69 tools carry standard
readOnlyHint/destructiveHint/idempotentHintannotations — clients like Claude Desktop use these to decide whether to present a confirmation UI before calling a tool - PII anonymization (opt-in): set
ANONYMIZE_ENABLED=trueto scrub IPs, emails, service account names, and GCP API keys from every tool result before the LLM sees it — see PII Anonymization for full configuration options
PII Anonymization
Tool outputs can contain IPs, emails, service account names, and API keys. The anonymization engine scrubs them before the LLM sees the response. It is off by default and adds zero overhead when disabled.
Running with defaults
ANONYMIZE_ENABLED=true GCP_PROJECT_ID=my-project aura-tracker-gcp
Defaults when enabled:
- Mode:
local— fast, regex-based, no extra GCP API calls - Patterns:
internal_ip,public_ip,email,service_account,gcp_api_key - Masking on (not audit-only)
- No JSON key whitelist
Matched values are replaced with stable indexed tokens — the same raw value always gets the same token within one tool call, so the LLM can still correlate occurrences:
10.0.0.1 → [INTERNAL_IP_1]
admin@corp.com → [EMAIL_1]
10.0.0.1 → [INTERNAL_IP_1] ← same token, same value
To persist the setting, add "ANONYMIZE_ENABLED": "true" to the env block in your MCP config.
Three modes are available: local (fast regex, no extra API calls), dlp (GCP Data Loss Prevention API, higher recall, billed), and both (local first, then DLP). An audit_only flag previews what would be masked without modifying output — useful for tuning patterns before enabling real scrubbing.
→ YAML config schema, built-in patterns, DLP mode, JSON key whitelist, and audit mode: Configure Your Environment — PII Anonymization
Troubleshooting
Cloud Monitoring: Empty Results or "No Data" for a Cloud Run Service
Symptom: gcp_monitoring_get_metrics returns an empty points array even though the service is running.
Cause 1 — Wrong metric type name.
Metric type strings must exactly match the Cloud Monitoring descriptor. Common mistakes:
| Wrong | Correct |
|---|---|
cloudrun.googleapis.com/request_count |
run.googleapis.com/request_count |
cloudrun.googleapis.com/container/cpu |
run.googleapis.com/container/cpu/utilizations |
container.googleapis.com/cpu |
kubernetes.io/container/cpu/request_utilization |
Use gcp_monitoring_list_metric_descriptors to discover exact type strings for any service:
"List all metric descriptors in my-project with the prefix
run.googleapis.com."
Cause 2 — Region scoping.
Cloud Run metrics require the resource label location to match the region where the service runs. Pass resource_labels explicitly to gcp_monitoring_get_metrics:
{
"metric_type": "run.googleapis.com/request_count",
"resource_labels": {
"service_name": "my-service",
"location": "us-central1"
}
}
Cause 3 — Distribution metric with incompatible aligner.
Some Cloud Run metrics are DELTA DISTRIBUTION types (run.googleapis.com/request_latencies, run.googleapis.com/container/cpu/utilizations). Calling gcp_monitoring_get_metrics on them directly may return:
The per-series aligner ALIGN_MEAN is not compatible with the value type DISTRIBUTION
Use gcp_get_aura_score instead — it selects the correct percentile aligner per metric automatically, and its 5-minute in-process cache means repeat calls are free.
Cloud Logging: Zero Results for a Cloud Run Service
Symptom: gcp_logging_query_recent returns no entries for a Cloud Run service.
The tool's filter uses resource.type to scope logs to a specific GCP resource. Common mistakes:
| Resource | Correct resource_type |
|---|---|
| Cloud Run service | cloud_run_revision |
| GKE cluster | k8s_cluster |
| GKE container | k8s_container |
| Cloud Function | cloud_function |
Using cloud_run_service (which looks correct) returns zero results — the actual monitored resource type is cloud_run_revision.
Severity values must be uppercase. The valid values are DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY. Lowercase values like "error" are silently treated as the zero value by the Logging API, returning all severities regardless of the filter.
Short lookback windows. If lookback_minutes is less than 15 for an infrequently accessed service, no logs may exist in the window. Start with 60 and narrow down.
Permission Errors on Monitoring or Logging API Calls
Symptom: Tools return PermissionDeniedError on Monitoring or Logging calls.
Use gcp_iam_test_permissions to identify exactly which roles are missing before diagnosing further:
"Test my IAM permissions on project my-project and tell me what GCP tools you can and cannot call."
Commonly missing roles:
| Missing role | Affected tools |
|---|---|
roles/monitoring.viewer |
gcp_monitoring_get_metrics, gcp_monitoring_list_metric_descriptors, all Aura Score tools |
roles/cloudtrace.user |
gcp_trace_list_services, gcp_trace_list_dependency_edges |
roles/logging.viewer |
gcp_logging_query_recent |
roles/recommender.viewer |
Aura Score efficiency signals (Recommender integration is on by default; set RECOMMENDER_ENABLED=false to disable) |
Run scripts/setup-iam.sh to provision all least-privilege roles automatically:
PROJECT_ID=my-project bash scripts/setup-iam.sh
Server Fails to Start: Missing GCP Credentials
aura-tracker-gcp: no GCP credentials found.
Run: gcloud auth application-default login
Or set GOOGLE_APPLICATION_CREDENTIALS to a service account key file.
For Cloud Run deployments (MCP_TRANSPORT=sse): ensure Workload Identity is configured on the service account, or set GOOGLE_APPLICATION_CREDENTIALS to a mounted service account key.
Architecture
The server uses Hexagonal Architecture (Ports and Adapters) to ensure the MCP protocol layer is completely decoupled from the Google Cloud SDK. Swap the GCP adapter for a mock or another cloud without touching a single tool handler.
┌─────────────────────────────────────────────────────────────────┐
│ LLM (Claude / any model) │
│ reads Resources · invokes Prompts · calls Tools via stdio │
└─────────────────────────────┬───────────────────────────────────┘
│ mcp-go StdioServer
┌─────────────────────────────▼───────────────────────────────────┐
│ internal/mcp/ (MCP Protocol Layer) │
│ server.go — tool + resource + prompt registration │
│ tools/ gke · cloudrun · functions · eventarc · scheduler │
│ workflows · tasks · pubsub · secretmanager │
│ vpcaccess · cloudsql · logging · monitoring │
│ iam · topology · aura · storage · serverlessgraph │
│ resources/ bigquery · cloudrun · storage · iam │
│ prompts/ audit-security · optimize-bq · incident-response │
└─────────────────────────────┬───────────────────────────────────┘
│ calls only ▼
┌─────────────────────────────▼───────────────────────────────────┐
│ ports/gcp_service.go (Hexagon Boundary) │
│ GCPService interface (38 methods) │
└─────────────────────────────┬───────────────────────────────────┘
│ implements ▼
┌─────────────────────────────▼───────────────────────────────────┐
│ internal/safety/ (Safety Decorator) │
│ decorator.go — two-step HITL confirmation for mutations │
│ store.go — TTL plan store, single-use UUID plan IDs │
│ (read-only methods pass through unchanged) │
└─────────────────────────────┬───────────────────────────────────┘
│ wraps ▼
┌─────────────────────────────▼───────────────────────────────────┐
│ internal/gcp/ (GCP Adapter Layer) │
│ client.go — SDK factory, rate limiter (10 rps), 30s timeout │
│ gke · gke_bottleneck · cloudrun · functions · eventarc │
│ scheduler · workflows · tasks · secretmanager · vpcaccess │
│ cloudsql · pubsub · logging · monitoring · iam │
│ topology · aura · bigquery · storage · serverlessgraph │
│ regions (discoverRegions helper, 3-tier fallback + 10-min TTL) │
└─────────────────────────────┬───────────────────────────────────┘
│ Google Cloud Go SDK (gRPC / REST)
GCP APIs
Dependency rule: internal/mcp never imports internal/gcp. Both depend only on ports/. internal/safety sits at the port boundary — it implements GCPService and wraps the real adapter, wired exclusively in cmd/. The model sees only tool names and JSON schemas.
Set MCP_TRANSPORT=sse to switch from stdio to HTTP/SSE for Cloud Run deployments. The MCP protocol layer is identical in both modes.
→ Architectural decisions, hexagonal boundary rules, SSE deployment, and contributor guide: Architecture & Contributing
Development
make build # compile the binary
make test # run all tests with race detector
make lint # golangci-lint (auto-installs on first run)
make smoke # stdio round-trip — prints "OK — N tools registered"
make test-cover # generate coverage.html
See CONTRIBUTING.md for the full contribution guide and architectural rules.
Raw commands (if you prefer not to use make):
go build ./...
go test -race ./...
go vet ./...
# Smoke-test tools/list via stdin
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| GCP_PROJECT_ID=my-project go run ./cmd/aura-tracker-gcp
Project Layout
The repository follows hexagonal architecture: internal/mcp (MCP protocol layer) and internal/gcp (GCP SDK adapter) are fully decoupled — both depend only on ports/gcp_service.go. internal/safety wraps the adapter at the port boundary to enforce HITL confirmation. pkg/models holds all input/output structs with zero GCP dependencies.
→ Full annotated project layout and contributor guide: Architecture & Contributing
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
aura-tracker-gcp
command
|
|
|
internal
|
|
|
anonymize
Package anonymize provides a pluggable PII/credential scrubbing layer for MCP tool results.
|
Package anonymize provides a pluggable PII/credential scrubbing layer for MCP tool results. |
|
config
Package config loads optional user-level defaults from ~/.aura-tracker.yaml.
|
Package config loads optional user-level defaults from ~/.aura-tracker.yaml. |
|
gcp
Package gcp implements the ports.GCPService interface using the Google Cloud Go SDK.
|
Package gcp implements the ports.GCPService interface using the Google Cloud Go SDK. |
|
gcp/resolution
Package resolution implements the edge-inference rules engine for the architecture graph.
|
Package resolution implements the edge-inference rules engine for the architecture graph. |
|
mcp
Package mcp wires the MCP protocol layer.
|
Package mcp wires the MCP protocol layer. |
|
mcp/middleware
Package middleware provides cross-cutting concerns for MCP tool handlers: request correlation IDs and structured logging helpers.
|
Package middleware provides cross-cutting concerns for MCP tool handlers: request correlation IDs and structured logging helpers. |
|
mcp/prompts
Package prompts implements MCP Prompt Templates for complex GCP workflows.
|
Package prompts implements MCP Prompt Templates for complex GCP workflows. |
|
mcp/resources
Package resources implements MCP Resource handlers for GCP services.
|
Package resources implements MCP Resource handlers for GCP services. |
|
mcp/tools
Package tools implements MCP tool handlers for each GCP domain.
|
Package tools implements MCP tool handlers for each GCP domain. |
|
safety
Package safety implements a port-level safety decorator that enforces two-step HITL confirmation for all mutation methods on ports.GCPService.
|
Package safety implements a port-level safety decorator that enforces two-step HITL confirmation for all mutation methods on ports.GCPService. |
|
testutil
Package testutil provides shared test doubles for the ports.GCPService interface.
|
Package testutil provides shared test doubles for the ports.GCPService interface. |
|
pkg
|
|
|
models
Package models defines the request/response types that cross the hexagonal boundary between the MCP protocol layer and the GCP adapter layer.
|
Package models defines the request/response types that cross the hexagonal boundary between the MCP protocol layer and the GCP adapter layer. |
|
Package ports defines the hexagon boundary between the MCP protocol layer and the GCP adapter layer.
|
Package ports defines the hexagon boundary between the MCP protocol layer and the GCP adapter layer. |