Repository navigation
feat: multi-account AWS MCP profiles; persist SSO tokens across rebuilds - #31
Merged
Merged
Conversation
Three changes to the Agent Toolkit for AWS wiring, all still unreleased. AWS_MCP_PROFILES — the proxy's --profile flag is variadic, so one MCP server can span an AWS Organization: the first profile in the list is the default identity and the rest are selectable PER TOOL CALL via its `aws_profile` parameter, with no restart between accounts. Empty by default (profile names are host-specific); set per host in .env, which gen-env.sh never rewrites once generated. The boot credential probe now targets the default profile rather than the ambient chain — with a list configured those are different identities, and only the first governs whether the handshake succeeds. AWS_MCP_READ_ONLY now defaults to 0 (writes enabled). The MCP tools act with the full IAM permissions of the selected profile and can create, modify and delete real resources in ANY account in the list, not just the default — so the list is documented least-privileged-first, since position 1 is what an unqualified call uses. seed/CLAUDE.md tells Claude to confirm the target account before mutating. Fix: `aws sso login` did not survive a rebuild. AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE relocate only `config` and `credentials`, but the SSO/OIDC token cache path is NOT configurable — the CLI always writes ~/.aws/cli/cache/session.db and ~/.aws/sso/cache/, which live in the container layer and die with every `make rebuild`. Config persisted, tokens didn't, so every profile needed a fresh login after each rebuild. seed-claude.sh now points ~/.aws at ~/.claude/aws as a DIRECTORY symlink, same fix and same per-file-symlink trap (temp-file + atomic rename) as ~/.ssh. An existing ~/.aws is migrated in with `cp -an` so a live token cache is preserved. boot-check requires the new seed.aws.linked event. Because ~/.aws IS ~/.claude/aws now, the toolkit's skills stamp moved to ~/.claude/aws-toolkit/ so its bookkeeping never surfaces inside the user's AWS dir; the old stamp is migrated, not discarded, so existing containers don't re-download all 23 skills. Verified: make lint / smoke / boot-check green; ~/.aws resolves onto the volume with the pre-existing session.db carried over; the server registers with all seven profiles and no --read-only; the probe reports against `sandbox` specifically; a restart hits the migrated stamp (aws.skills.current, no re-download). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #30. Answers "can the MCP server authenticate from a profile?" — yes, and better than one-profile-at-a-time.
AWS_MCP_PROFILES— one server, many accountsThe proxy's
--profileflag is variadic:So the first name is the server's default identity and the rest are selectable per tool call — read from one account and act in another in the same conversation, no restart. Set it per host in
.devcontainer/.env(gen-env.shnever rewrites an existing.env, so added lines survive); shipped empty since profile names are host-specific. Documented in.env.example.The boot credential probe now targets the default profile rather than the ambient chain — with a list configured those are different identities, and only the first one determines whether the handshake succeeds.
⚠
AWS_MCP_READ_ONLYnow defaults to0Writes are enabled by default. The MCP tools act with the full IAM permissions of the selected profile and can create, modify, and delete real resources — in any account in
AWS_MCP_PROFILES, not just the default. The list is documented least-privileged-first because position 1 is what an unqualified call uses, andseed/CLAUDE.mdnow instructs Claude to confirm the target account before mutating.AWS_MCP_READ_ONLY=1restores describe-only.Fix:
aws sso logindid not survive a rebuildFound while checking where the tokens actually land:
AWS_CONFIG_FILE/AWS_SHARED_CREDENTIALS_FILErelocate onlyconfigandcredentials. The SSO/OIDC token cache path is not configurable — the CLI always writes~/.aws/cli/cache/session.dband~/.aws/sso/cache/. So config persisted but tokens didn't, and every profile needed a fresh login after eachmake rebuild.seed-claude.shnow points~/.awsat~/.claude/awsas a directory symlink — the same fix, and the same per-file-symlink trap (temp-file + atomic rename), as the existing~/.sshtreatment. An existing~/.awsis migrated in withcp -anfirst, so a live token cache is preserved rather than dropped.make boot-checkrequires the newseed.aws.linkedevent.Since
~/.awsis~/.claude/awsnow, the toolkit's skills stamp moved to~/.claude/aws-toolkit/so its bookkeeping never surfaces inside the user's AWS directory. The old stamp is migrated rather than discarded, so existing containers don't re-download all 23 skills.Verification
make lintclean;make smoke→ smoke OK;make boot-check→ boot-check OK (now includingseed.aws.linked).~/.awsresolves to/home/claude/.claude/awson/dev/vda1, with the pre-existingcli/cache/session.dbcarried across the migration.--read-only;aws.mcp.registeredrecordsdefault_profile=sandbox,read_only=0.sandboxspecifically (aws.credentials.absent profile=sandbox), not the ambient chain.aws.skills.current, no re-download.ENVIRONMENT.mdrenders the active profile list, the write posture, and live credential status.🤖 Generated with Claude Code