Skip to content

Conversation

@samthanawalla
Copy link
Contributor

@samthanawalla samthanawalla commented Sep 29, 2025

This is a preliminary implementation of OAuth 2.1 for the client.

When a StreamableClientTransport encounters a 401 Unauthorized response
from the server, it initiates the OAuth flow described in thec
authorization section of the MCP spec
(https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization).
On success, the transport obtains an access token which it passes
to all subsequent requests.

Much remains to be done here:

  • Resource Indicators, as described in section 2.5.1 of the MCP spec.

  • All of this is unexported, so it is available only to our own
    StreamingClientTransport. We should add API so people can use it
    with their own transports.

  • And, of course, tests. We should test against fake implementations
    but also, if we can find any, real reference implementations.

For #19
Co-authored-by: Jonathan Amsterdam jba@google.com

jba and others added 3 commits September 29, 2025 20:03
This is a preliminary implementation of OAuth 2.1 for the client.

It provides an http.RoundTripper, auth.HTTPTransport, that invokes
a user-provided callback of type auth.OAuthHandler.
The latter is responsible for all the OAuth work.
We will add code to make that easier in later PRs.

Much remains to be done :

Dynamic client registration is not implemented. Since it is optional,
we also need another way of supplying the client ID and secret to
this code.

Resource Indicators, as described in section 2.5.1 of the MCP spec.

And, of course, tests. We should test against fake implementations
but also, if we can find any, real reference implementations.
jba
jba previously approved these changes Sep 30, 2025
@jba
Copy link
Contributor

jba commented Sep 30, 2025 via email

@samthanawalla samthanawalla marked this pull request as ready for review September 30, 2025 15:14
@samthanawalla samthanawalla merged commit 069aae1 into modelcontextprotocol:main Sep 30, 2025
5 checks passed
}
t.opts.Base = &oauth2.Transport{Base: t.opts.Base, Source: ts}
}
return t.opts.Base.RoundTrip(req.Clone(req.Context()))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In cagent we use the same trick for OAuth. I just spent the morning debugging and fixing our code for streamable mcp servers and thought I'd tell you what was wrong, might be useful for you.

This second request that comes after the oauth flow has a half-broken request, the body of the request was already read by the first call on line 70, so you would get a 400 Bad Request back from the server. You need to hold on the original body and put it back here before sending a second RoundTrip.

docker/cagent#547

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.

3 participants