@@ -669,9 +669,8 @@ impl OAuthClientConfig {
669669///
670670/// ```rust,ignore
671671/// let request = AuthorizationRequest::new("http://localhost:8080/callback")
672- /// // pass no scopes to let the SDK auto-select from server metadata
673- /// .with_scopes(["mcp", "profile"])
674- /// // used when the server supports CIMD and no pre-registered client is set
672+ /// // Omit `with_scopes` to let the SDK auto-select scopes from server metadata.
673+ /// // Used when the server supports CIMD and no pre-registered client is set.
675674/// .with_client_metadata_url("https://example.com/client-metadata.json")
676675/// // used for dynamic client registration as a last resort
677676/// .with_client_name("My MCP Client");
@@ -3071,8 +3070,14 @@ impl AuthorizationSession {
30713070 /// retry without losing the original configuration and stores.
30723071 pub async fn new (
30733072 mut auth_manager : AuthorizationManager ,
3074- request : AuthorizationRequest ,
3073+ mut request : AuthorizationRequest ,
30753074 ) -> Result < Self , ( AuthorizationManager , AuthError ) > {
3075+ if request. scopes . is_empty ( ) {
3076+ request. scopes = auth_manager. select_scopes ( None , & [ ] ) ;
3077+ } else {
3078+ auth_manager. add_offline_access_if_supported ( & mut request. scopes ) ;
3079+ }
3080+
30763081 let redirect_uri = request. redirect_uri . clone ( ) ;
30773082 let scopes = request. scopes . clone ( ) ;
30783083 let scope_refs: Vec < & str > = scopes. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
@@ -3403,7 +3408,7 @@ impl OAuthState {
34033408 /// without losing the original configuration and stores.
34043409 pub async fn start_authorization (
34053410 & mut self ,
3406- mut request : AuthorizationRequest ,
3411+ request : AuthorizationRequest ,
34073412 ) -> Result < ( ) , AuthError > {
34083413 let placeholder = self . placeholder ( ) . await ?;
34093414 let old = std:: mem:: replace ( self , placeholder) ;
@@ -3422,11 +3427,6 @@ impl OAuthState {
34223427 }
34233428 } ;
34243429 manager. metadata = Some ( metadata) ;
3425- if request. scopes . is_empty ( ) {
3426- request. scopes = manager. select_scopes ( None , & [ ] ) ;
3427- } else {
3428- manager. add_offline_access_if_supported ( & mut request. scopes ) ;
3429- }
34303430 debug ! ( "start session" ) ;
34313431 match AuthorizationSession :: new ( manager, request) . await {
34323432 Ok ( session) => {
@@ -3642,10 +3642,10 @@ mod tests {
36423642
36433643 use super :: {
36443644 AuthError , AuthorizationCallback , AuthorizationManager , AuthorizationMetadata ,
3645- AuthorizationRequest , CredentialStore , InMemoryCredentialStore , InMemoryStateStore ,
3646- OAuthClientConfig , OAuthHttpClient , OAuthHttpClientError , OAuthHttpClientFuture ,
3647- OAuthHttpRedirectPolicy , OAuthHttpRequest , ScopeUpgradeConfig , StateStore ,
3648- StoredAuthorizationState , is_https_url,
3645+ AuthorizationRequest , AuthorizationSession , CredentialStore , InMemoryCredentialStore ,
3646+ InMemoryStateStore , OAuthClientConfig , OAuthHttpClient , OAuthHttpClientError ,
3647+ OAuthHttpClientFuture , OAuthHttpRedirectPolicy , OAuthHttpRequest , ScopeUpgradeConfig ,
3648+ StateStore , StoredAuthorizationState , is_https_url,
36493649 } ;
36503650 use crate :: transport:: auth:: VendorExtraTokenFields ;
36513651
@@ -4149,22 +4149,25 @@ mod tests {
41494149 }
41504150
41514151 #[ tokio:: test]
4152- async fn preregistered_client_selects_default_scopes_when_none_provided ( ) {
4152+ async fn authorization_session_selects_default_scopes_when_none_provided ( ) {
41534153 let client = RecordingOAuthHttpClient :: with_responses ( preregistered_discovery_responses ( ) ) ;
4154- let mut state = super :: OAuthState :: new_with_oauth_http_client (
4154+ let mut manager = AuthorizationManager :: new_with_oauth_http_client (
41554155 "https://mcp.example.com/mcp" ,
4156- Arc :: new ( client. clone ( ) ) ,
4156+ Arc :: new ( client) ,
41574157 )
41584158 . await
41594159 . unwrap ( ) ;
4160+ manager. metadata = Some ( manager. discover_metadata ( ) . await . unwrap ( ) ) ;
41604161
41614162 let request = AuthorizationRequest :: new ( "http://localhost:8080/callback" )
41624163 . with_preregistered_client ( "preregistered-client" ) ;
4163- state. start_authorization ( request) . await . unwrap ( ) ;
4164+ let session = match AuthorizationSession :: new ( manager, request) . await {
4165+ Ok ( session) => session,
4166+ Err ( ( _, error) ) => panic ! ( "authorization session creation failed: {error}" ) ,
4167+ } ;
41644168
4165- // empty request scopes fall back to the discovered scopes_supported
4166- let auth_url = state. get_authorization_url ( ) . await . unwrap ( ) ;
4167- let query = auth_url_query ( & auth_url) ;
4169+ // Empty request scopes fall back to the discovered scopes_supported.
4170+ let query = auth_url_query ( & session. auth_url ) ;
41684171 assert_eq ! ( query. get( "scope" ) . unwrap( ) , "read write offline_access" ) ;
41694172 }
41704173
0 commit comments