How do I bulk-register all AgentCore Gateways and Runtimes from my AWS account?¶
The AgentCore scanner CLI discovers all READY gateways and agent runtimes in your AWS account and registers them in the MCP Gateway Registry in a single command. This FAQ walks through the complete procedure step by step.
Step 0: IAM Permissions¶
Before running the scanner, you need AWS credentials with permissions to call the Amazon Bedrock AgentCore control-plane APIs. The CLI uses the standard boto3 credential chain, so any of the usual methods work (environment variables, AWS CLI profile, instance profile).
Required IAM Policy¶
Attach this policy to the IAM user or role that will run the CLI:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AgentCoreDiscovery",
"Effect": "Allow",
"Action": [
"bedrock-agentcore:ListGateways",
"bedrock-agentcore:GetGateway",
"bedrock-agentcore:ListGatewayTargets",
"bedrock-agentcore:GetGatewayTarget",
"bedrock-agentcore:ListAgentRuntimes",
"bedrock-agentcore:GetAgentRuntime",
"sts:GetCallerIdentity"
],
"Resource": "*"
}
]
}
What each permission does:
| Permission | Purpose |
|---|---|
bedrock-agentcore:ListGateways | Discover all gateways in the account |
bedrock-agentcore:GetGateway | Read gateway details (URL, authorizer config) |
bedrock-agentcore:ListGatewayTargets | List targets behind each gateway |
bedrock-agentcore:GetGatewayTarget | Read target details (URL, type) |
bedrock-agentcore:ListAgentRuntimes | Discover all agent runtimes in the account |
bedrock-agentcore:GetAgentRuntime | Read runtime details (protocol, invocation URL) |
sts:GetCallerIdentity | Verify credentials are valid |
Configure Credentials¶
Use one of:
# Option A: Environment variables
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1
# Option B: Named profile
aws configure --profile agentcore-sync
export AWS_PROFILE=agentcore-sync
export AWS_REGION=us-east-1
# Option C: Instance profile (no config needed if running on EC2/ECS with the right role)
Step 1: Preview with Dry-Run¶
Before registering anything, run the scanner in dry-run mode to see what it will discover and what auth type each resource uses:
uv run python -m cli.agentcore sync \
--registry-url http://localhost \
--token-file .token \
--dry-run
This scans your AWS account for all READY gateways and runtimes, but does not register them. It produces a summary table like this:
================================================================================
AGENTCORE SYNC SUMMARY
================================================================================
MODE: DRY-RUN (no changes made)
Would register: 13
DETAILS:
-----------------------------------------------------------------------------------------------
Type Name Path Auth Status
-----------------------------------------------------------------------------------------------
gateway customersupport-gw /customersupport-gw CUSTOM_JWT dry_run
gateway geo-mcp /geo-mcp CUSTOM_JWT dry_run
gateway SRE-Gateway /sre-gateway CUSTOM_JWT dry_run
gateway TestGWforLambda /testgwforlambda CUSTOM_JWT dry_run
gateway weather-time-observability-gat /weather-time-observabili CUSTOM_JWT dry_run
runtime weather_time_observability_age /weather-time-observabili IAM dry_run
runtime sre_agent_simple /sre-agent-simple IAM dry_run
runtime sre_agent /sre-agent IAM dry_run
runtime simple_strands_cognito_agent /simple-strands-cognito-a IAM dry_run
runtime simple_strands_agent /simple-strands-agent IAM dry_run
runtime simple_a2a_strands_agent /simple-a2a-strands-agent IAM dry_run
runtime my_simple_agent /my-simple-agent IAM dry_run
runtime my_custom_sre_agent /my-custom-sre-agent IAM dry_run
===============================================================================================
Understanding the Auth Column¶
| Auth Type | Meaning | Action Required |
|---|---|---|
CUSTOM_JWT | Gateway expects an OAuth2 JWT token from an external IdP (Cognito, Auth0, Entra, Okta, Keycloak) | You will need to configure a client secret for the token refresher (Step 3) |
IAM | Runtime uses AWS IAM (SigV4) for authentication | No additional configuration needed; the registry proxies with IAM credentials |
NONE | No authentication required | No configuration needed |
The dry-run also reports how many manifest entries it would write. The manifest is used by the token refresher to know which gateways need periodic JWT refresh.
Step 2: Run the Actual Sync¶
Once you are satisfied with the dry-run output, remove the --dry-run flag to register all discovered resources:
This will: 1. Register each gateway as an MCP Server (tagged #agentcore, #gateway, #auto-registered) 2. Register each runtime as an Agent (tagged #agentcore, #runtime, #auto-registered) 3. Write token_refresh_manifest.json listing all CUSTOM_JWT gateways that need token refresh
If resources were previously registered, the CLI skips them. Use --overwrite to update existing registrations:
uv run python -m cli.agentcore sync \
--registry-url http://localhost \
--token-file .token \
--overwrite
Step 3: Configure Client Secrets (for CUSTOM_JWT Gateways)¶
If the dry-run showed any gateways with CUSTOM_JWT auth, the token refresher needs a client secret to obtain JWTs on behalf of the registry. Whether you need to configure anything depends on which IdP your gateways use.
Do I Need to Configure a Secret?¶
| IdP Vendor | Configuration Required? | How |
|---|---|---|
| Cognito | No | Auto-retrieved via AWS API (describe_user_pool_client). Just ensure your IAM credentials have cognito-idp:DescribeUserPoolClient permission. |
| Entra | Yes | Set ENTRA_CLIENT_SECRET in your .env file |
| Auth0 | Yes | Set AUTH0_CLIENT_SECRET in your .env file |
| Okta | Yes | Set OKTA_CLIENT_SECRET in your .env file |
| Keycloak | Yes | Set KEYCLOAK_CLIENT_SECRET in your .env file |
If all your gateways are Cognito (which is the most common case for AgentCore), you can skip the rest of this step and go directly to Step 4.
What is the Client ID?¶
Each AgentCore gateway with CUSTOM_JWT auth has an allowedClients list configured in its authorizer. These are OAuth2 application client IDs registered in the identity provider. The client ID identifies which application is authorized to call the gateway.
The token refresher performs the OAuth2 client_credentials grant (machine-to-machine flow) using: - The client_id from allowedClients (discovered automatically by the scanner) - The client_secret you provide via environment variables (or auto-retrieved for Cognito) - The token endpoint (auto-discovered from the gateway's OIDC discovery URL)
How to Find the Client ID¶
The scanner writes the client IDs into token_refresh_manifest.json. After running sync, inspect the manifest:
Example output (multiple gateways, all using Cognito):
[
{
"server_path": "/customersupport-gw",
"gateway_arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/customersupport-gw-abc123def",
"discovery_url": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_YourPoolId1/.well-known/openid-configuration",
"allowed_clients": [
"yourAlphaNumericClientId1abc"
],
"allowed_audience": [],
"idp_vendor": "cognito"
},
{
"server_path": "/geo-mcp",
"gateway_arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/geo-mcp-xyz789uvw",
"discovery_url": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_YourPoolId2/.well-known/openid-configuration",
"allowed_clients": [
"yourAlphaNumericClientId2def"
],
"allowed_audience": [],
"idp_vendor": "cognito"
},
{
"server_path": "/sre-gateway",
"gateway_arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/sre-gateway-qrs456tuv",
"discovery_url": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_YourPoolId3/.well-known/openid-configuration",
"allowed_clients": [
"yourAlphaNumericClientId3ghi"
],
"allowed_audience": [],
"idp_vendor": "cognito"
},
{
"server_path": "/weather-time-observability-gateway",
"gateway_arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/weather-time-observability-gateway-lmn012opq",
"discovery_url": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_YourPoolId4/.well-known/openid-configuration",
"allowed_clients": [
"yourAlphaNumericClientId4jkl"
],
"allowed_audience": [],
"idp_vendor": "cognito"
}
]
Each allowed_clients entry is an alphanumeric client ID (typically 26 characters for Cognito, a UUID for Entra). This is the identifier the token refresher uses to authenticate with the IdP.
Configure Secrets (Non-Cognito IdPs)¶
For Entra, Auth0, Okta, or Keycloak gateways, add the appropriate secret to your .env file.
Scenario A: All your gateways use the same IdP app registration¶
If you registered all your AgentCore gateways with the same app registration in your IdP (one client ID, one secret), set a single vendor-level variable:
# All Entra gateways share one app registration -> one secret covers them all
# Get this from: Azure Portal -> App registrations -> your app -> Certificates & secrets
ENTRA_CLIENT_SECRET=your-entra-client-secret-value
The token refresher uses this secret for every gateway where idp_vendor is entra.
Same pattern for other IdPs:
AUTH0_CLIENT_SECRET=your-auth0-client-secret-value
OKTA_CLIENT_SECRET=your-okta-client-secret-value
KEYCLOAK_CLIENT_SECRET=your-keycloak-client-secret-value
Scenario B: Your gateways use different app registrations (different secrets)¶
If each gateway has its own app registration in the IdP (each with a unique client ID and its own secret), use the per-client form. The client ID comes from the allowed_clients field in token_refresh_manifest.json.
Example: you have 3 Entra gateways, each with a different app registration:
# Gateway /customersupport-gw uses Entra app "cs-app" with client_id = a1b2c3d4-...
OAUTH_CLIENT_SECRET_a1b2c3d4-e5f6-7890-abcd-ef1234567890=secret-for-cs-app
# Gateway /sre-gateway uses Entra app "sre-app" with client_id = f9e8d7c6-...
OAUTH_CLIENT_SECRET_f9e8d7c6-b5a4-3210-fedc-ba0987654321=secret-for-sre-app
# Gateway /geo-mcp uses Entra app "geo-app" with client_id = 11223344-...
OAUTH_CLIENT_SECRET_11223344-5566-7788-99aa-bbccddeeff00=secret-for-geo-app
Scenario C: Mix of both¶
You can combine the two approaches. The per-client secret takes priority over the vendor-level secret:
# Default secret for all Entra gateways (most gateways use the same app)
ENTRA_CLIENT_SECRET=shared-entra-secret
# Override for one specific gateway that has its own app registration
OAUTH_CLIENT_SECRET_a1b2c3d4-e5f6-7890-abcd-ef1234567890=special-secret-for-this-one
Secret Resolution Priority¶
The token refresher resolves secrets in this order (first match wins):
- Per-client:
OAUTH_CLIENT_SECRET_<client_id>(specific to one gateway) - Cognito auto-retrieval: via AWS API, no config needed (Cognito only)
- Vendor-level:
ENTRA_CLIENT_SECRET,AUTH0_CLIENT_SECRET,OKTA_CLIENT_SECRET, orKEYCLOAK_CLIENT_SECRET(shared across all gateways for that IdP)
Step 4: Run the Token Refresher¶
The token refresher reads the manifest, resolves secrets, fetches OAuth2 tokens, and PATCHes them into the registry:
# One-time refresh
uv run python -m cli.agentcore.token_refresher \
--manifest token_refresh_manifest.json \
--registry-url http://localhost \
--token-file .token
# Continuous mode (refreshes every 45 minutes)
uv run python -m cli.agentcore.token_refresher \
--manifest token_refresh_manifest.json \
--registry-url http://localhost \
--token-file .token \
--loop --interval 2700
After the token refresher runs, the gateways will have valid egress tokens. However, they are still disabled by default.
Step 5: Enable the Registered Servers and Agents¶
Newly registered assets start in a disabled state. You need to enable each one before it appears in search results and health checks begin.
Enable all CUSTOM_JWT gateways from the manifest¶
Use the token_refresh_manifest.json to loop through all gateway paths and enable them in one shot:
TOKEN=$(cat .token | python3 -c "import sys,json; print(json.load(sys.stdin)['tokens']['access_token'])")
for path in $(python3 -c "import json; [print(e['server_path']) for e in json.load(open('token_refresh_manifest.json'))]"); do
echo "Enabling: $path"
curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-F "path=$path" \
-F "new_state=true" \
"http://localhost/api/servers/toggle"
echo
done
Expected output:
Enabling: /customersupport-gw
{"message":"Toggle request for /customersupport-gw processed.","service_path":"/customersupport-gw","new_enabled_state":true,"status":"healthy",...}
Enabling: /geo-mcp
{"message":"Toggle request for /geo-mcp processed.","service_path":"/geo-mcp","new_enabled_state":true,"status":"healthy",...}
...
Enable individual servers or agents¶
# Enable a single server
curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-F "path=/geo-mcp" \
-F "new_state=true" \
"http://localhost/api/servers/toggle"
# Enable a single agent
curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-F "path=/my-simple-agent" \
-F "new_state=true" \
"http://localhost/api/agents/toggle"
You can also enable them from the registry UI by clicking the toggle switch on each asset's card.
Once enabled, the registry begins health-checking the assets. After a few seconds they should transition to "Healthy" (assuming the token refresher has already run for CUSTOM_JWT gateways).
Step 6: Verify Registration¶
Check that the servers and agents are registered and healthy:
# List registered servers
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
list
# Check a specific server
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
server-get --path /geo-mcp
Or verify in the registry UI: registered assets will show with #agentcore, #gateway (or #runtime), and #auto-registered tags.
Deregistering All Auto-Registered Assets¶
To remove all previously auto-registered assets (e.g., before a clean re-registration):
# Remove a server
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
remove --path /geo-mcp --force
# Remove an agent
uv run python api/registry_management.py \
--registry-url http://localhost \
--token-file .token \
agent-delete --path /my-simple-agent --force
Replace the paths with your actual registered paths. You can find all auto-registered assets by filtering on the #auto-registered tag in the UI or API.
Troubleshooting¶
| Problem | Cause | Solution |
|---|---|---|
AccessDeniedException during discovery | Missing IAM permissions | Attach the IAM policy from Step 0 |
| "Already registered - skipping" | Resource already exists | Use --overwrite flag |
| Token refresher returns HTTP 500 | Registry auth token expired | Regenerate with python credentials-provider/oauth/ingress_oauth.py |
| Gateway shows unhealthy after sync | Missing egress token | Run the token refresher (Step 4) |
| No CUSTOM_JWT entries in manifest | All gateways use IAM or NONE auth | No token refresh needed |