July 2026
This release takes the per-user egress auth story most of the way there: both 3LO (per-user OAuth, tokens vaulted by the gateway) and OBO (on-behalf-of token exchange for same-trust-domain backends) are now fully implemented and work across providers. Direct PAT (personal access token) egress is still to come, so this is one big step closer rather than the finish line. On top of that, it adds more gateway-centric capabilities. With A2A reverse-proxy routing, you can now optionally route inter-agent (agent-to-agent) traffic through the gateway too, so agent calls get the same fine-grained access control (FGAC) governance we already apply to MCP servers, each agent gated per call with its own invoke_agent grant while its real backend stays private. And with application-level rate limiting, the gateway now does AI traffic management: identity-, group-, and target-aware request limits enforced at the auth-server hop, so you can cap a caller or protect a busy MCP server / A2A agent, complementary to the coarse per-IP edge limiting. The release also lands a broad security-hardening pass across the auth, proxy, data, and frontend layers.
This section covers everything you need to know to upgrade from 1.26.0 to 1.27.0.
There are no breaking changes in this release. All new behavior is opt-in and defaults preserve the prior behavior:
- Rate limiting is off by default (
RATE_LIMITING_ENABLED=false). With it unset,/validatebehaves exactly as before. - The registry configuration endpoints now require authentication.
GET /api/config/*previously served without auth; it now requires a valid session/token. If you had tooling reading/api/configanonymously, give it an authenticated token. The anonymous/healthprobe no longer leaks deployment topology. - Internal service tokens are now single-use and M2M token audience is validated against an explicit allowlist. If you mint internal tokens outside the shipped flow, they must be single-use; M2M callers must present a token whose audience is allowlisted.
| Variable | Default | Description |
|---|---|---|
RATE_LIMITING_ENABLED |
false |
Master switch for application-level rate limiting. false = no checks (prior behavior). |
RATE_LIMIT_BACKEND |
documentdb |
Counter backend. Only documentdb is implemented in v1. |
RATE_LIMIT_FAIL_OPEN |
true |
Global fail-open on backend error (a per-limit fail_closed overrides to closed). Prevents a counter-store blip from becoming a full gateway outage. |
RATE_LIMIT_DEFINITIONS_CACHE_TTL_SECONDS |
30 |
In-process cache TTL for definition reads (zero DB reads in steady state). |
RATE_LIMIT_BACKEND_TIMEOUT_MS |
250 |
Hard per-op timeout for each counter operation, so a slow store fails fast into the fail-open/closed policy rather than hanging /validate. |
RATE_LIMIT_USER_FLOOR_PER_MIN |
20 |
Lockout-safeguard floor: a group whose short-window user limit falls below this is rejected at config time. |
RATE_LIMIT_AGENT_FLOOR_PER_MIN |
10 |
Lockout-safeguard floor for the agent (M2M) caller limit. |
AUDIT_LOG_REQUIRE_DURABLE |
true |
Require the audit trail to be durable-by-default; a non-durable audit sink fails closed. |
EGRESS_OBO_ALLOWED_AUDIENCES |
(empty) | Explicit, audited allowlist of internal server audiences the OBO token-exchange may target. Empty denies OBO. |
RUM_ALLOWED_HOSTS |
(empty) | Comma-separated allowlist of hosts the RUM snippet may reference (script src + beacon). A snippet referencing any other host is rejected (fail closed). Empty disables RUM. |
TRUSTED_PROXY_HOPS |
1 |
Number of trusted reverse-proxy hops when resolving the client IP (rightmost-trusted XFF). |
TRUSTED_EXTERNAL_HOSTS |
(empty) | Allowlisted external Host values (e.g. a CloudFront domain) used when building redirect URIs. |
TRUSTED_REAL_IP_CIDRS |
(empty) | CIDRs of trusted upstreams (e.g. an ALB subnet) whose forwarded client IP is honored. |
SSRF_ALLOWED_HOSTS |
(empty) | Opt-in allowlist of internal hosts the SSRF guard may reach (for private A2A/MCP backends). |
SSRF_ALLOWED_CIDRS |
(empty) | Opt-in allowlist of internal CIDRs the SSRF guard may reach. Prefer SSRF_ALLOWED_HOSTS when you can name the hosts. |
Rate-limit definitions and group memberships are managed at runtime (admin API /api/rate-limits, the rate-limit-* CLI commands, or Settings -> IAM -> Rate Limits in the UI), not via environment variables.
cd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# Review new env vars in .env.example and update your .env if needed
# (rate limiting, SSRF allowlists, trusted-proxy, OBO audiences all default to
# prior behavior when unset). Then rebuild and restart:
./build_and_run.shcd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# REQUIRED: subchart templates/values changed in this release. Rebuild deps so
# the packaged .tgz subcharts pick up the changes (a plain helm upgrade would
# otherwise use the stale packaged subcharts).
cd charts/mcp-gateway-registry-stack
helm dependency build
helm dependency update
# Update values.yaml if needed (new rate-limiting, egress OBO, and
# trusted-request-source values), then upgrade:
helm upgrade mcp-gateway . -f your-values.yamlcd mcp-gateway-registry
git pull origin main
git checkout 1.27.0
# Update your .tfvars with any new variables (rate-limiting floors, SSRF
# allowlists, OBO audiences), then:
cd terraform/aws-ecs
terraform plan
terraform applyIdentity-, group-, and target-aware request limiting enforced at the auth-server /validate hop, complementary to the coarse per-IP nginx edge limiting. Two axes compose: a caller limit caps a user or agent (resolved by rate-limit group membership, kept in a dedicated collection and deliberately decoupled from the token's authz groups so adding a limit never changes a caller's scopes), and a target limit caps aggregate load on an MCP server or A2A agent regardless of caller. Each limit is per time window; multiple windows stack, and a request denied by a tighter window never consumes a wider window's quota. Lockout safeguards: admins bypass caller limits, caller limits apply to data-plane MCP/A2A calls only (never the dashboard or /api/*), and config-time floors reject a group whose short-window limit falls below the configured minimum. Counters live in DocumentDB (shared across replicas) via an atomic conditional increment; a per-op timeout fails fast into a fail-open availability guardrail by default, or fail-closed per-limit for security-critical caps. Throttled calls return HTTP 429 with X-RateLimit-* and Retry-After headers, plus an OTel metric and an attributable app-log line. Off by default; managed at runtime via the admin API, CLI, or the Settings -> IAM -> Rate Limits UI.
Agent (machine-to-machine) callers can now authenticate with Amazon Cognito client_credentials tokens, with provider-aware caller classification so a genuine M2M token is treated as an agent for rate limiting and authorization.
For same-trust-domain backends, the gateway now supports an obo_exchange egress mode (Microsoft Entra jwt-bearer today): it exchanges the caller's ingress token for a backend-audience token at call time, preserving the user's identity with nothing to vault. The target audiences are gated to an explicit, audited allowlist (EGRESS_OBO_ALLOWED_AUDIENCES). This complements the existing 3LO per-user vault, and 3LO itself now works across providers (including Entra).
Opt in to route agent-to-agent traffic through the gateway the same way MCP servers are proxied: each enabled agent gets authenticated /agent/{path} routes, its real backend stays private (proxy_pass_url) and is redacted from non-admin reads, discovery advertises the gateway URL, and every call is gated per-agent with an invoke_agent grant. The egress trust model keeps the gateway a policy gate, not a credential broker: the caller's gateway token rides in X-Authorization (stripped at egress) while the target agent's own credential rides in Authorization (forwarded end to end).
Custom OIDC egress providers can now emit an RFC 8707 resource indicator on the authorize request and both token grants, binding the minted token to one protected resource. This is required by resource servers that issue per-resource tokens (for example Atlassian's Rovo MCP).
This release lands a broad, systematic security-hardening pass across the auth, proxy, data, and frontend layers:
- OAuth CSRF hardening: validate the
stateat the token-exchange point (#1429) - Internal service tokens are now single-use to prevent replay (#1430)
- Enforce M2M token audience against an explicit allowlist (#1418)
- Require authentication for the registry configuration endpoints; stop leaking deployment topology from the anonymous
/healthprobe (#1445) - Enforce scope-based server and tool access on the tool catalog and single-server reads (#1444)
- Fix a skill-visibility bypass via cross-resource permission confusion (#1439)
- Honor the disabled flag when enriching token groups from the database (#1443)
- Authorization hardening: delete-ownership enforcement, path canonicalization before authz, credential-destination re-validation, group-enrichment gating, and token-mint session reconciliation (#1468)
- Intra-admin safety guards and follow-up: refuse self-delete and last-admin removal/demotion (#1428, #1437)
- Harden the audit trail: durable-by-default with per-instance attribution, and record raw human-readable identity across all audit streams (#1438, #1432)
- Validate override endpoint fields through the canonical SSRF guard (#1470)
- Close a potential regex-injection vector (#1417)
- Tighten CLI credential handling (#1419)
- Harden legacy static admin/privilege-granting tokens: validate strength, least-privilege federation scope (#1466, plus static-token bypass hardening)
- AgentCore IAM scoping to least privilege (#1442)
- Constrain auto-generated secret characters to a URI-safe, AWS-safe set (#1362)
- Add a repository security-guidelines catalog and wire it into the review skills (#1416)
- CDK / Terraform parity: embed CloudFront, drop the 8888/7860 listeners,
sslRequired=external(#1435) - Fix DocumentDB rotation IAM to use the
rds:*action namespace the boto3docdbclient actually evaluates, in both Terraform and CDK (#1406, #1474) - Generic bring-your-own RUM (Real User Monitoring) injection hook for the frontend, host-allowlisted and fail-closed (#1472)
- Configurable Claude Code connect-snippet scope via
IDE_CONNECT_SCOPE(#1464) - nginx edge rate limiting (#1431)
- Page through the list APIs so the dashboard is not hard-capped at the first page (#1436)
- New 3LO (per-user OAuth) AgentCore gateway FAQ, with a Cognito + Claude Code worked example (#1473)
- Correct the egress runtime-sequence diagram to match the implementation (#1483)
- README refactor: audience-routed rewrite, theory-of-the-system and executive brief, feature/release highlights, and MkDocs strict-mode nav cleanup (#1422, #1423, #1424, #1425)
- Move release notes out of the main README into the docs site (#1411, #1421)
- Update the 3LO demo video link across docs and README (#1482)
- Align the repository to pre-commit and enforce it (#1440)
- Use a slim detect-secrets baseline to stop line-number churn (#1480)
- Use the lockfile for docs builds (#1465)
- Weekly dependency and GitHub Actions updates (#1408, #1409, #1462, #1463)
- fix(scopes): grant
publish_skillto the admin seed scopes (#1479) - fix(a2a): pass a dict to
update_agentin the security-pending-tag path (#1441) - fix(rate-limiting): provider-aware caller classification, correct human-vs-agent classification, surface throttle as 429 through nginx
auth_request, and capture the actualRetry-Afterheader (#1467) - fix(readme): replace the PAT-gated star-history chart with shields.io badges (#1481)
| Issue | Title | Closed By |
|---|---|---|
| #1471 | Add a generic RUM injection hook for the frontend | PR #1472 |
| #1433 | Failed to get admin token (admin publish_skill permission) | PR #1479 |
| #1410 | Remove "What's New" from README.md | PR #1411 |
| #1354 | Auto-generated secrets with special characters break deployment | PR #1362 |
| #1348 | DocumentDB secret rotation fails: docdb:* vs rds:* namespace |
PR #1406 |
| #1282 | SSRF hardening: validate outbound URL on agent card fetch | PR #1470 |
| #1269 | Egress: token-exchange (OBO) for same-trust-domain backends | PR #1420 |
| #880 | Implement proper frontend pagination for servers, agents, skills | PR #1436 |
| #847 | Add reverse-proxy gateway support for A2A agents | PR #1355 |
| #295 | Application-level rate limiting | PR #1467 |
| PR | Title |
|---|---|
| #1483 | docs: correct egress runtime-sequence diagram to match implementation |
| #1482 | docs: update 3LO demo video link across docs and README |
| #1481 | fix(readme): replace PAT-gated star-history chart with shields.io badges |
| #1480 | chore(ci): use slim detect-secrets baseline to stop line-number churn |
| #1479 | fix(scopes): grant publish_skill to admin seed scopes |
| #1474 | fix(cdk): use rds:* actions for DocumentDB rotation IAM (Terraform parity) |
| #1473 | docs: add FAQ for 3LO (per-user OAuth) AgentCore gateways |
| #1472 | Add generic bring-your-own RUM hook for the frontend |
| #1470 | Validate override endpoint fields through the canonical SSRF guard |
| #1469 | chore(usage-report): bump install-forecast target to 2,000 |
| #1468 | Authorization hardening: delete ownership, path canonicalization, credential re-validation, enrichment gating, mint reconciliation |
| #1467 | feat: application-level rate limiting + Cognito M2M support |
| #1466 | Harden legacy static admin token |
| #1465 | use lockfile for docs builds |
| #1464 | feat(connect): configurable Claude Code snippet scope (IDE_CONNECT_SCOPE) |
| #1463 | chore(deps): weekly lockfile update (2026-07-13) |
| #1462 | build(deps): bump the actions group with 7 updates |
| #1445 | Require authentication for the registry configuration |
| #1444 | Enforce scope-based server and tool access on the tool catalog and single-server reads |
| #1443 | Honor the disabled flag when enriching token groups from the database |
| #1442 | Agentcore scoping |
| #1441 | fix(a2a): pass dict to update_agent in security-pending-tag path |
| #1440 | fix: align repository to pre-commit and enforce pre-commit |
| #1439 | Fix skill visibility bypass via cross-resource permission confusion |
| #1438 | Harden the audit trail: durable-by-default and per-instance attribution |
| #1437 | admin safety guards followup |
| #1436 | fix(frontend): page through list APIs so dashboard is not hard-capped |
| #1435 | feat(infra): CDK / Terraform parity, embed CloudFront, drop 8888/7860 listeners |
| #1434 | feat(a2a): egress trust model, {agent,actions} scopes, gateway-aware discovery |
| #1432 | fix(audit): record raw human-readable identity across all audit streams |
| #1431 | nginx rate limiting |
| #1430 | Make internal service tokens single-use |
| #1429 | OAuth CSRF Hardening |
| #1428 | Intra-admin safety guards |
| #1427 | feat(egress): add RFC 8707 resource indicator for custom OAuth providers |
| #1425 | docs: replace MkDocs site with a README-generated landing page |
| #1424 | docs: fix all mkdocs --strict warnings and auto-generate nav |
| #1423 | docs: rewrite README (audience-routed) + regrowth prevention |
| #1422 | docs: add theory-of-the-system, executive brief, and feature/release highlights |
| #1421 | Add redirect stubs for moved release notes; fix stale path references |
| #1420 | Egress OBO: add obo_exchange mode + make 3LO work on Entra / across providers |
| #1419 | tighten cli credentials |
| #1418 | Enforce M2M token audience against an explicit allowlist |
| #1417 | close potential regex injection |
| #1416 | add security guidelines |
| #1413 | docs(skills): add security-patterns catalog and wire into review skills |
| #1412 | skill credential handling |
| #1411 | remove releases notes from main repo README and add to mkdocs |
| #1409 | chore(deps): weekly lockfile update (2026-07-06) |
| #1408 | build(deps): bump the actions group with 7 updates |
| #1406 | Fix DocumentDB rotation IAM actions |
| #1362 | fix: constrain secret characters to URI-safe, AWS-safe set |
| #1355 | feat(a2a): add reverse-proxy gateway support for A2A agents |
Thank you to all contributors for this release:
- Amit Arora (@aarora79)
- omrishiv (@omrishiv)
- Harshit Gupta (@harshitkgupta)
- Gonçalo Faustino (@go-faustino)
- Lucas Anjos (@anjosluc)
- TechSphrex TA (@KhaiTrang1995)
- ahfoysal (@ahfoysal)
- zsxh1990 (@zsxh1990)
- ceng (@ceng-p)
Full Changelog: 1.26.0...1.27.0