Problem
With the cloud-context MCP scaffold, harness, and Provider interface in place (#45), this sub-issue implements the GCP provider so the operator agent can ground an incident in GCP context: inventory, identity, and — via the gated CLI — reachability, permissions, GKE config, logs, and audit trail.
Approach
Add pkg/mcp/cloud/providers/gcp implementing cloud.Provider over the gcloud CLI (no cloud SDK, per the package convention): Binary() resolves gcloud; DefaultAllowlist() loads an embedded default_commands.json of read-only gcloud verbs; DenyFloorAdditions() contributes GCP-specific dangerous subcommands (e.g. compute ssh, compute scp, functions call).
Typed tools shell gcloud through the harness and project the output:
Identity — gcloud auth list (+ the impersonation target); Valid requires the resolved identity to equal the pinned service account.
Inventory — gcloud projects list, projected to id + name.
Impersonation is pinned by the launcher via CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT in the subprocess env; the provider never selects it (--impersonate-service-account stays on the agent deny floor). Wire --provider=gcp to construct the provider in serve.go. Long-tail axes are reachable through run_cli against the allowlist and promotable to typed tools later.
Verification
make test passes, including provider_test.go table tests over captured gcloud ... --format=json fixtures → projection structs.
make lint clean.
- Manual: with the pinned read-only SA impersonated,
session_status and list_inventory return curated output, and no tool exposes a mutating operation.
Out of scope
Context
Sub-issue of #44. Builds on the contract from the scaffold sub-issue.
Problem
With the cloud-context MCP scaffold, harness, and
Providerinterface in place (#45), this sub-issue implements the GCP provider so the operator agent can ground an incident in GCP context: inventory, identity, and — via the gated CLI — reachability, permissions, GKE config, logs, and audit trail.Approach
Add
pkg/mcp/cloud/providers/gcpimplementingcloud.Providerover thegcloudCLI (no cloud SDK, per the package convention):Binary()resolvesgcloud;DefaultAllowlist()loads an embeddeddefault_commands.jsonof read-onlygcloudverbs;DenyFloorAdditions()contributes GCP-specific dangerous subcommands (e.g.compute ssh,compute scp,functions call).Typed tools shell
gcloudthrough the harness and project the output:Identity—gcloud auth list(+ the impersonation target);Validrequires the resolved identity to equal the pinned service account.Inventory—gcloud projects list, projected to id + name.Impersonation is pinned by the launcher via
CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNTin the subprocess env; the provider never selects it (--impersonate-service-accountstays on the agent deny floor). Wire--provider=gcpto construct the provider inserve.go. Long-tail axes are reachable throughrun_cliagainst the allowlist and promotable to typed tools later.Verification
make testpasses, includingprovider_test.gotable tests over capturedgcloud ... --format=jsonfixtures → projection structs.make lintclean.session_statusandlist_inventoryreturn curated output, and no tool exposes a mutating operation.Out of scope
Providerinterface and harness (Build the cloud-context MCP package, Provider interface, and shared tool surface #45); launcher wiring and the connections pill (launcher sub-issue); the AWS provider (Implement the AWS provider for the cloud-context MCP #46); any write operation; a cloud SDK dependency.Context
Sub-issue of #44. Builds on the contract from the scaffold sub-issue.