Release 1.32.0 - Forward-Proxy Egress, Ingress Hostnames, and a Login Regression Fix
October 2026
Upgrading from 1.31.0
This section covers everything you need to know to upgrade from 1.31.0 to 1.32.0.
Breaking Changes
There are no breaking changes in this release.
Two notes for operators who already export proxy variables. EGRESS_FORWARD_PROXY_ENABLED defaults to false, so exporting HTTP_PROXY or HTTPS_PROXY alone changes nothing and does not enable the new routing. If you do set the flag to true, the process refuses to start unless NO_PROXY excludes the three cloud credential endpoints; see the new environment variables below.
New Environment Variables
| Variable | Default | Description |
|---|---|---|
EGRESS_FORWARD_PROXY_ENABLED
| false
| Route SSRF-guarded and plain egress through the forward proxy named in HTTPS_PROXY / HTTP_PROXY, for targets that resolve exclusively to public addresses. Internal targets stay direct and IP-pinned with no further configuration. Relaxes DNS-rebinding protection for public destinations only, so it is opt-in. Consumed by the registry and the auth-server.
|
EGRESS_FORWARD_PROXY_CA_BUNDLE
| ""
| Path inside the container to a PEM CA bundle trusted in addition to the default roots, for a forward proxy that terminates TLS and re-signs with an internal CA. A missing or malformed file fails at startup. Deliberately not SSL_CERT_FILE, which replaces the trust store rather than adding to it.
|
AWS_EC2_METADATA_DISABLED
| false on Compose
| Closes boto3's IMDS credential fallback. Now settable on Docker Compose, which previously had no way to set it at all. Defaults to false there, exactly equivalent to unset, because an EC2-hosted Compose deployment often uses the instance role for Amazon Bedrock and AgentCore. Helm and Terraform/ECS already default to true, where task roles and IRSA supply credentials (#1839).
|
SECURITY_BLOCK_ON_SCAN_FAILURE
| true
| Whether a security scan that could not run blocks a server. A scan that failed to execute is no longer treated as an unsafe verdict (#1766). |
HTTP_PROXY, HTTPS_PROXY and NO_PROXY are ecosystem-standard variables rather than new settings. They are read from the environment when the flag is on and ride each surface's existing arbitrary-environment pass-through, so they need no new plumbing and are deliberately absent from the charts' reserved-name lists.
When the proxy flag is enabled, NO_PROXY must exclude 169.254.169.254, 169.254.170.2 and 169.254.170.23. This is enforced at startup, at helm install, and at terraform plan. Setting HTTP_PROXY re-points every proxy-aware SDK in the process, so the AWS SDK would otherwise send IAM credential requests to the proxy, over plain HTTP and from the proxy's own network position. AWS_EC2_METADATA_DISABLED=true is not a substitute, because botocore applies it only to 169.254.169.254 and not to the container-credential endpoints.
Upgrade Instructions
Docker Compose
cd mcp-gateway-registry
git pull origin main
git checkout 1.32.0
# Review new env vars in .env.example and update your .env if needed
# Then rebuild and restart:
./build_and_run.shKubernetes / Helm (EKS)
cd mcp-gateway-registry
git pull origin main
git checkout 1.32.0
# REQUIRED: 30 files changed under charts/ in this release, including subchart
# templates and values. The packaged .tgz subcharts inside
# charts/mcp-gateway-registry-stack/charts/ are gitignored and only repackage
# when you run these, so a plain git pull plus helm upgrade would deploy the
# OLD subcharts and silently miss the changes.
cd charts/mcp-gateway-registry-stack
helm dependency build
helm dependency update
# Update values.yaml if needed, then upgrade:
helm upgrade mcp-gateway . -f your-values.yamlTerraform / ECS
cd mcp-gateway-registry
git pull origin main
git checkout 1.32.0
# Update your .tfvars with any new variables
cd terraform/aws-ecs
terraform plan
terraform applyOn ECS the new variables live in the task definition, so terraform apply is required to pick them up. Pushing a new image alone leaves the flag absent, the feature off, and nothing in the logs to explain why.
Major Features
Forward-proxy egress for the SSRF-guarded and plain clients
The registry's egress clients build their httpx clients with a custom transport, and httpx enables environment-proxy support only when no custom transport is supplied. HTTP_PROXY and HTTPS_PROXY were therefore ignored on every guarded fetch, and separately on the pooled plain client that the login callback uses. In a network whose only outbound path is a corporate forward proxy, that left every external MCP server permanently unroutable and browser sign-in broken.
Both clients are now proxy aware behind one opt-in flag:
- A target is sent through the proxy only when every address it resolves to is on the public internet. An internal target stays direct and IP-pinned with no configuration, so in-cluster servers are unaffected whether or not anyone listed them in
NO_PROXY. - Resolution and classification still run in full before any
CONNECT, so the cloud credential, metadata, link-local, reserved and multicast denials all still execute and one blocked answer denies the request. - Requests that carry a secret accept only
httpsthrough a proxy, so a credential rides inside the tunnel and the proxy sees onlyhost:port. EGRESS_FORWARD_PROXY_CA_BUNDLEsupports a proxy that terminates TLS, loading the bundle on top of the default roots.- Enabling the flag refuses to start unless
NO_PROXYexcludes the cloud credential endpoints, because settingHTTP_PROXYalso re-points the AWS SDK.
The relaxation this buys is narrow and documented: for a proxied target, IP-rebind pinning is dropped, because a CONNECT tunnel takes its TLS hostname from the request URL and cannot carry a pinned address. Operator guidance is for the proxy itself to deny CONNECT to RFC-1918, loopback and link-local destinations.
PR #1838 · Forward-Proxy Egress FAQ · Operator guide
Configurable registry subdomain and additional ingress hostnames
The ingress can now be configured with a registry subdomain and additional hostnames, so a deployment is no longer limited to a single host for the registry.
Explainer skill, prose linter, and rendered design documents
A skill that turns a GitHub issue or pull request into a verified explainer at three levels of depth, writing both markdown and a self-contained HTML version. Alongside it, scripts/prose-scan.py checks prose for the phrase-level tells that make generated writing obvious, and design and review documents now render to HTML.
What's New
Security
- A security scan that could not run is no longer treated as an unsafe verdict, and
SECURITY_BLOCK_ON_SCAN_FAILUREmakes the behaviour explicit (#1766, #1816). - A 401 from any authenticated path returned two conflicting
Content-Typevalues, the first beingapplication/octet-stream, because the nginx handlers set it withadd_header(which appends) rather thandefault_type. A client told the body is binary does not parse the JSON, so every auth failure across every MCP path surfaced as a parse error rather than an authentication problem, sending operators to look at the gateway instead of their token. All four handlers now usedefault_type, and two unreachableadd_headerlines after areturnwere removed (#1842). - Three generalized entries added to the security guidelines: the conditions a transport-level egress relaxation must meet, why a proxy belongs in the guarded transport rather than on the client, and why a CA-bundle setting must add to the trust store rather than replace it (#1838).
Deployment
EGRESS_FORWARD_PROXY_ENABLEDandEGRESS_FORWARD_PROXY_CA_BUNDLEwired through Docker Compose, Terraform/ECS and Helm, including a newcaBundleblock on the registry and auth-server subcharts for mounting a PEM from a ConfigMap or Secret (#1838).- Helm and Terraform both reject a proxy-enabled configuration whose
NO_PROXYdoes not exclude the cloud credential endpoints, so the error arrives at install or plan time rather than as a crash loop (#1838).
Egress and Discovery
- The egress vault id is no longer resolved across identifier namespaces (#1709).
- An unconfigured Connect is refused early, and the misleading "Connection failed" message is gone (#1802).
- A designated identity that is not connected is now surfaced rather than silently ignored (#1803).
- mcpgw returns the custom records and asset metadata the registry already sends (#1765), and its metadata docstrings and discovery-receipt ranking are corrected (#1812).
Documentation
- A forward-proxy FAQ with per-surface instructions, and an operator guide covering the security trade-off, the required
NO_PROXY, and verification (#1838). AGENTS.mdconsolidated, with stale claims corrected and a section on finding the running deployment to debug against (#1836, #1837).- The OpenAPI spec gains the toggle-tool paths it was missing (#1800).
- The claim that an OAuth-protected server could not be onboarded is removed (#1790), and the slide deck is published as HTML (#1797).
Bug Fixes
- Forward-proxy-aware egress for the guarded and plain clients, fixing permanently unhealthy external servers and a browser-login regression (#1838).
PATCH /api/servers/{path}is now a field-scoped, revision-guarded write rather than a non-atomic full-card write (#1722).- IAM group edits no longer discard Group Mappings changes (#1830).
registry-onlymode no longer returns 503 for the registry's own routes, including/docs, the SPA and/rum.js(#1828).- A security scan that could not run no longer produces an unsafe verdict (#1766).
- The egress vault id is no longer resolved across identifier namespaces (#1709).
- Flat-layout import bugs are now caught by tests, and a Hypothesis flake is fixed (#1799).
- A 401 from an authenticated gateway path no longer carries duplicate, conflicting
Content-TypeandConnectionheaders, so an MCP client reports an auth failure instead of a JSON parse error (#1842). AWS_EC2_METADATA_DISABLEDis settable on Docker Compose, closing a gap where that surface alone had no way to disable boto3's IMDS credential fallback (#1839).
Closed Issues
| Issue | Title | Closed By |
|---|---|---|
| #1834 | 1.31.0 Regression: browser login (OAuth2 callback) fails behind an HTTP(S)_PROXY | PR #1838 |
| #1832 | SSRF-guarded client ignores HTTP(S)_PROXY, making proxy-only external downstream MCP permanently unhealthy | PR #1838 |
| #1842 | Malformed 401: @auth_error duplicates Content-Type and Connection
| this release |
| #1839 | Wire AWS_EC2_METADATA_DISABLED on Docker Compose
| this release |
| #1829 | IAM group edit silently discards Group Mappings changes | PR #1830 |
| #1827 | registry-only mode returns 503 for the registry's own routes (/docs, SPA, /rum.js) | PR #1828 |
| #1716 | PATCH /api/servers/{path} fails and uses non-atomic full-card write on MongoDB CE | PR #1722 |
| #1461 | Egress OBO: Keycloak RFC 8693 token-exchange path (Phase 4 follow-up to #1269) | manual |
| #966 | Feature request: Separate discovery/scan authentication from runtime authentication for MCP servers | manual |
Pull Requests Included
| PR | Title |
|---|---|
| #1838 | fix(url_guard): forward-proxy-aware egress for the guarded and plain clients (#1832, #1834) |
| #1837 | docs: add a section on finding the running deployment to debug against |
| #1836 | docs: AGENTS.md, correct stale claims, add the rules we kept repeating |
| #1835 | feat(skills): explainer skill, prose linter, and HTML rendering for design and review documents |
| #1833 | feat(skills): add explainer skill, track writing skill, add prose-scan |
| #1830 | fix(iam): send group_mappings when updating a group |
| #1828 | fix(registry-only): stop 503ing the registry's own routes (/docs, SPA, /rum.js) |
| #1816 | docs(security): document SECURITY_BLOCK_ON_SCAN_FAILURE where operators read |
| #1812 | fix(mcpgw): correct the metadata docstrings and rank the discovery receipt |
| #1807 | chore(deps): weekly lockfile update (2026-09-28) |
| #1806 | chore(deps): bump the actions group in /.github/workflows with 8 updates |
| #1803 | fix(discovery): surface a designated identity that is not connected |
| #1802 | fix(egress): refuse an unconfigured Connect early, and stop saying "Connection failed" |
| #1800 | docs(api): add the toggle-tool paths the spec was missing |
| #1799 | test: catch flat-layout import bugs, and stop the Hypothesis flake |
| #1797 | docs(slides): publish the deck as HTML, and drop the appendix |
| #1790 | docs: stop claiming an OAuth-protected server could not be onboarded |
| #1789 | chore: update image tags to 1.31.0 |
| #1783 | feat(ingress): configure registry subdomain and additional hostnames |
| #1766 | fix(security): a scan that could not run is not an unsafe verdict |
| #1765 | fix(mcpgw): return the custom records and asset metadata the registry already sends |
| #1722 | fix(servers): make PATCH a field-scoped, revision-guarded write |
| #1709 | fix(egress): stop resolving the egress vault id across identifier namespaces |
Security Dependency Updates
| Package | Previous | Updated | Scope |
|---|---|---|---|
| GitHub Actions (actions group) | various | 8 updates | CI workflows (#1806) |
| Python lockfile | various | weekly refresh | runtime and dev dependencies (#1807) |
Contributors
Thank you to all contributors for this release:
- Amit Arora (@aarora79)
- Gonçalo Faustino (@go-faustino)
- Andrzej Piorkowski (@endriu0)
- Atirna (@atirna)
Support
Full Changelog: 1.31.0...1.32.0
What's Changed
- docs: stop claiming an OAuth-protected server could not be onboarded by @aarora79 in #1790
- docs(slides): publish the deck as HTML, and drop the appendix by @aarora79 in #1797
- test: catch flat-layout import bugs, and stop the Hypothesis flake by @aarora79 in #1799
- docs(api): add the toggle-tool paths the spec was missing by @aarora79 in #1800
- fix(egress): refuse an unconfigured Connect early, and stop saying "Connection failed" by @aarora79 in #1802
- fix(discovery): surface a designated identity that is not connected by @aarora79 in #1803
- chore(deps): bump the actions group in /.github/workflows with 8 updates by @dependabot[bot] in #1806
- chore(deps): weekly lockfile update (2026-09-28) by @github-actions[bot] in #1807
- fix(mcpgw): return the custom records and asset metadata the registry already sends by @go-faustino in #1765
- fix(mcpgw): correct the metadata docstrings and rank the discovery receipt by @aarora79 in #1812
- fix(egress): stop resolving the egress vault id across identifier namespaces by @go-faustino in #1709
- fix(servers): make PATCH a field-scoped, revision-guarded write by @atirna in #1722
- fix(security): a scan that could not run is not an unsafe verdict by @go-faustino in #1766
- docs(security): document SECURITY_BLOCK_ON_SCAN_FAILURE where operators read by @aarora79 in #1816
- feat(ingress): configure registry subdomain and additional hostnames by @endriu0 in #1783
- fix(registry-only): stop 503ing the registry's own routes (/docs, SPA, /rum.js) by @aarora79 in #1828
- fix(iam): send group_mappings when updating a group by @aarora79 in #1830
- feat(skills): add explainer skill, track writing skill, add prose-scan by @aarora79 in #1833
- feat(skills): explainer skill, prose linter, and HTML rendering for design and review documents by @aarora79 in #1835
- docs: AGENTS.md, correct stale claims, add the rules we kept repeating by @aarora79 in #1836
- docs: add a section on finding the running deployment to debug against by @aarora79 in #1837
- fix(url_guard): forward-proxy-aware egress for the guarded and plain clients (#1832, #1834) by @aarora79 in #1838
- docs: add 1.32.0 release notes by @aarora79 in #1843
- fix(nginx,compose): single-value 401 headers, and the IMDS toggle on Compose by @aarora79 in #1845
- chore: update image tags to 1.32.0 by @github-actions[bot] in #1844
New Contributors
Full Changelog: 1.31.0...1.32.0