Project · gcp-mcp-standalone

GCP + Tailscale Connectors

Two **Native** mcp-broker connectors (in-process tools, `auth_mode=none` — no browser OAuth, no broker token store) added 2026-07-07. They give every broker client (claude.ai, Claude Code, the Telegram bot) least-privilege visibility and limited control over the GCP project and the tailnet. Spec + plan live in

type componentstatus activemcp · gcp · tailscale · connector

gcp-mcp-standalone/docs/superpowers/ (specs 2026-07-06-gcp-tailscale-connectors-design.md).

Key points

  • GCP (/proxy/gcp) — 7 tools: list_instances, get_instance, get_serial_output, list_log_entries, stop_instance, start_instance, reset_instance. Credential: keyless — short-lived token from the GCE metadata server (169.254.169.254) as mcp-broker-sa. Power comes from custom role mcpBrokerOps (view + power-cycle ONLY; no create/delete/setMetadata) + roles/logging.viewer. Project/zone pinned server-side (GCP_PROJECT/GCP_ZONE in .env), never tool params.
  • Tailscale (/proxy/tailscale) — 3 tools: list_devices, get_device, expire_device_key. Credential: scoped OAuth client (devices:core read-only), client-credentials grant, short-lived tokens fetched on demand; secret in Secret Manager tailscale-oauth-client-secret, restored on rebuild by Ansible.
  • Why read-only Tailscale: write scopes on Tailscale OAuth clients are tag-bound and cannot touch untagged personal devices — so write bought nothing. expire_device_key is implemented but returns a sanitized 403 until a write-scoped credential replaces the read-only one.
  • Security model (two independent layers): the credential cannot exceed the custom role/scope, and the tools implement only the verbs above. Worst realistic abuse (e.g. prompt injection in a chat with broker tools): VM power-cycled, infra metadata/logs disclosed. Nothing can be created, deleted, or reconfigured.

Details

Code: BobMck/mcp-broker branch connectors, src/connectors/{gcp,tailscale}/ (15 unit tests; suite 995 green). Infra: main.tf (role + bindings, incl. the iam.serviceAccountUser self-grant required to start a VM that runs as an SA), ansible/install.yml (env injection, no_log), ansible/templates/settings.yaml.j2 (connector + allowed_connectors registration). Verified live 2026-07-07: instance list, device list, and log query all succeed from inside the broker container.

Sources

Compiled from wiki/projects/gcp-mcp-standalone/connectors-gcp-tailscale.md · git is the source of truth