Skip to content

fix(mcptoolset): keep the Config.Auth credential on the endpoint's origin across redirects - #1986

Draft
wolo-lab wants to merge 1 commit into
mainfrom
wolo/mcptoolset-check-redirect
Draft

wolo-lab wants to merge 1 commit into
mainfrom
wolo/mcptoolset-check-redirect

Conversation

@wolo-lab

Copy link
Copy Markdown
Contributor

Problem

With Config.Auth set, tool/mcptoolset hands the configured credential to whatever host a redirect names. httpClient installs auth.Transport, which applies the credential to every request it sends, redirect hops included. That runs below the layer where net/http strips Authorization on a cross-host redirect, and the client never sets CheckRedirect, so net/http's default policy follows the redirect and the credential goes with it. An https to http redirect sends it in cleartext.

The auth/gcp provider already requires that the client carrying auth.Transport refuse cross-host redirects, and agent/remoteagent/v2 enforces the same for A2AConfig.Auth.

modelcontextprotocol/go-sdk#1440 restricts redirects to the same origin in the SDK, but it is not in a release yet, and it steps aside whenever the http.Client sets its own CheckRedirect or MCPGODEBUG=followallredirects=1 is set. Either one lets the credential follow a cross-origin redirect again, which is the open question on #1965.

Summary

  • With Config.Auth set, the toolset's HTTP client refuses a redirect unless it stays on the endpoint's host and port and either keeps the scheme or upgrades http to https. The call fails with an error and the other host is never contacted. A same-origin redirect such as /mcp to /mcp/, which Starlette and FastMCP mounts send, is still followed with the credential.
  • A CheckRedirect on a caller-supplied HTTPClient runs after this check, so it can refuse more redirects but cannot let the credential reach another origin. Without one, the client keeps net/http's limit of 10 requests per chain. Toolsets without Config.Auth are unchanged.
  • The rule is the one agent/remoteagent/v2 already applies, moved unchanged into internal/credredirect so both auth paths share one implementation. remoteagent/v2 keeps its behavior and error messages.

The redirect is refused rather than followed without the credential, for three reasons. It matches remoteagent/v2 and the MCP SDKs (modelcontextprotocol/go-sdk#1440, modelcontextprotocol/python-sdk#3397). Following it would still send the JSON-RPC request body, tool arguments included, to the other host. And an endpoint that requires the credential would answer the unauthenticated request with an error anyway. adk-python is closer to the second option: _RefreshableAsyncCredentials skips the google-auth token when the redirect's host and port differ from the endpoint's, and httpx strips a static Authorization header on a cross-origin redirect. Both still follow the redirect.

Once a go-sdk release with #1440 is picked up, a toolset with Config.Auth uses this policy instead of the SDK's, because the SDK defers to any CheckRedirect. The SDK's policy also refuses a redirect that changes the HTTP method or the URL userinfo. Those two checks will not apply with Config.Auth unless they are added here too.

Fixes #1965

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tool/mcptoolset: credential forwarded across cross-host redirect — httpClient never sets CheckRedirect (contradicts auth/gcp provider contract)

1 participant