Allow MCPRemoteProxy to work without upstream or client auth#4168
Allow MCPRemoteProxy to work without upstream or client auth#4168aron-muon wants to merge 3 commits intostacklok:mainfrom
Conversation
e7fec58 to
1c8c7cd
Compare
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4168 +/- ##
==========================================
- Coverage 68.95% 68.40% -0.55%
==========================================
Files 467 467
Lines 46981 47130 +149
==========================================
- Hits 32395 32239 -156
- Misses 11965 12072 +107
- Partials 2621 2819 +198 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
0aa7f12 to
68e79e9
Compare
Large PR justification has been provided. Thank you!
|
✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review. |
68e79e9 to
1037865
Compare
1037865 to
5b110c0
Compare
5b110c0 to
010f7fc
Compare
The embedded auth server always injected upstream IdP tokens into requests forwarded to backend MCP servers. This made it impossible to use the embedded auth server for client-facing OAuth flows when the upstream MCP server is public and doesn't require authentication — the injected token caused 401 rejections from the upstream. Add a `disableUpstreamTokenInjection` field to EmbeddedAuthServerConfig that skips the upstream swap middleware while keeping the embedded auth server running for client authentication. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCPRemoteProxy previously required oidcConfig, making it impossible to proxy public MCP servers without configuring authentication. Make the oidcConfig field optional — when omitted, the proxy allows anonymous access and forwards requests to the upstream without any authentication on either side. This enables "case 1" where both the upstream MCP and the proxy are fully public. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three issues prevented MCPRemoteProxy from connecting to third-party upstream MCP servers that use HTTP redirects: 1. X-Forwarded-Host leaked the proxy's hostname to the upstream. The upstream used it to construct 307 redirect URLs pointing back to the proxy, creating a redirect loop. Fix: skip SetXForwarded() for remote upstreams (isRemote == true). 2. Go's http.Transport.RoundTrip does not follow redirects, but httputil.ReverseProxy uses Transport directly. Upstream 307/308 redirects (e.g. HTTPS→HTTP scheme changes, path canonicalization) were returned to the MCP client which cannot follow them through the proxy. Fix: add forwardFollowingRedirects that transparently follows up to 10 redirects, preserving method and body for 307/308 (RFC 7538). 3. When disableUpstreamTokenInjection is true, the client's ToolHive JWT was still forwarded to the upstream in the Authorization header. Fix: add strip-auth middleware that removes the Authorization header before forwarding. Also adds debug logging for outbound request headers and upstream response status codes to aid diagnosis of remote proxy issues. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
010f7fc to
49e9690
Compare
Summary
MCPRemoteProxy required OIDC authentication and always injected upstream tokens when the
embedded auth server was configured. This made two common deployment patterns impossible
and the transparent proxy could not reach upstream servers behind HTTP redirects.
Why: Operators sometimes need to proxy third-party public MCP servers (e.g., documentation APIs)
with client authentication (Okta, GitHub) but without injecting tokens upstream — the upstream
is public and doesn't expect auth headers. Additionally, third-party servers may use HTTP
redirects (API gateways, scheme changes, path canonicalization) that the proxy must follow
transparently.
What changed (3 commits):
Add
disableUpstreamTokenInjection— whentrue, the embedded auth server stillhandles OAuth flows for clients but does not inject upstream IdP tokens into outgoing
requests. A
strip-authmiddleware removes the client's ToolHive JWT from theAuthorization header to prevent it leaking to the upstream.
Make
oidcConfigoptional — when omitted, the proxy allows anonymous access with noauthentication on either side.
Fix transparent proxy for remote servers behind redirects — three issues prevented
MCPRemoteProxy from connecting to third-party upstreams that use redirects:
X-Forwarded-Hostleaked the proxy's hostname; the upstream used it to build 307redirect URLs pointing back to the proxy (redirect loop). Fix: skip
SetXForwarded()for remote upstreams.
http.Transport.RoundTripdoes not follow redirects, buthttputil.ReverseProxyuses Transport directly. Fix: add
forwardFollowingRedirectsthat follows up to 10redirects, preserving method/body for 307/308 (RFC 7538).
Type of change
Test plan
task test)task lint-fix)Deployed MCPRemoteProxy with embedded auth server +
disableUpstreamTokenInjection: trueproxying a public third-party MCP server behind an API gateway that 307-redirects
(HTTPS→HTTP scheme change). Verified:
tools/list,prompts/list,resources/listall return 200Changes
api/v1alpha1/mcpexternalauthconfig_types.goDisableUpstreamTokenInjectiontoEmbeddedAuthServerConfigCRDpkg/authserver/config.goDisableUpstreamTokenInjectionto runtimeRunConfigpkg/runner/middleware.gostrip-authmiddleware; skip upstream swap when injection disabledpkg/runner/middleware_test.gocontrollerutil/authserver.goapi/v1alpha1/mcpremoteproxy_types.goOIDCConfigoptional (value to pointer)controllers/mcpremoteproxy_controller.gocontrollers/mcpremoteproxy_deployment.gocontrollers/mcpremoteproxy_runconfig.goproxy/transparent/transparent_proxy.goSetXForwarded()for remote upstreams; addforwardFollowingRedirects; add outbound/response debug loggingDoes this introduce a user-facing change?
Yes. Three new capabilities for MCPRemoteProxy:
oidcConfigto allow unauthenticated access to a proxied MCP server.disableUpstreamTokenInjection: trueon anembeddedAuthServerMCPExternalAuthConfig to authenticate clients without injecting tokens upstream.Large PR Justification
Generated with Claude Code