Problem
With the cloud-context MCP scaffold, harness, and Provider interface in place (#45), this sub-issue implements the AWS provider so the operator agent can ground an incident in AWS context: inventory, identity, and — via the gated CLI — reachability, permissions, EKS config, logs, and audit trail.
Approach
Add pkg/mcp/cloud/providers/aws implementing cloud.Provider over the aws CLI (no cloud SDK, per the package convention): Binary() resolves aws; DefaultAllowlist() loads an embedded default_commands.json of read-only aws describe/get/list verbs; DenyFloorAdditions() contributes AWS-specific dangerous subcommands (e.g. ec2 get-password-data and anything returning credential material).
Typed tools shell aws through the harness and project the output:
Identity — aws sts get-caller-identity; Valid requires the resolved ARN to match the pinned assumed role.
Inventory — aws organizations list-accounts, falling back to the single caller account on AccessDenied.
The assumed role is pinned by the launcher via AWS_PROFILE (a profile whose role_arn is the read-only role, with the operator's base as source_profile); the provider never selects it (--profile stays on the agent deny floor). Wire --provider=aws in serve.go. Long-tail axes are reachable through run_cli against the allowlist and promotable later.
Verification
make test passes, including provider_test.go table tests over captured aws ... --output json fixtures → projection structs (including the single-account fallback).
make lint clean.
- Manual: with the pinned read-only role assumed,
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 AWS provider so the operator agent can ground an incident in AWS context: inventory, identity, and — via the gated CLI — reachability, permissions, EKS config, logs, and audit trail.Approach
Add
pkg/mcp/cloud/providers/awsimplementingcloud.Providerover theawsCLI (no cloud SDK, per the package convention):Binary()resolvesaws;DefaultAllowlist()loads an embeddeddefault_commands.jsonof read-onlyawsdescribe/get/listverbs;DenyFloorAdditions()contributes AWS-specific dangerous subcommands (e.g.ec2 get-password-dataand anything returning credential material).Typed tools shell
awsthrough the harness and project the output:Identity—aws sts get-caller-identity;Validrequires the resolved ARN to match the pinned assumed role.Inventory—aws organizations list-accounts, falling back to the single caller account onAccessDenied.The assumed role is pinned by the launcher via
AWS_PROFILE(a profile whoserole_arnis the read-only role, with the operator's base assource_profile); the provider never selects it (--profilestays on the agent deny floor). Wire--provider=awsinserve.go. Long-tail axes are reachable throughrun_cliagainst the allowlist and promotable later.Verification
make testpasses, includingprovider_test.gotable tests over capturedaws ... --output jsonfixtures → projection structs (including the single-account fallback).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 GCP provider (Implement the GCP provider for the cloud-context MCP #43); any write operation; a cloud SDK dependency.Context
Sub-issue of #44. Builds on the contract from the scaffold sub-issue.