@@ -196,6 +196,7 @@ pub struct HttpServiceBuilder<'a> {
196196 pub timeout : u64 ,
197197 pub scopes : & ' a [ String ] ,
198198 pub headers : & ' a HashMap < String , String > ,
199+ pub oauth_config : & ' a Option < crate :: cli:: chat:: tools:: custom_tool:: OAuthConfig > ,
199200 pub messenger : & ' a dyn Messenger ,
200201}
201202
@@ -207,6 +208,7 @@ impl<'a> HttpServiceBuilder<'a> {
207208 timeout : u64 ,
208209 scopes : & ' a [ String ] ,
209210 headers : & ' a HashMap < String , String > ,
211+ oauth_config : & ' a Option < crate :: cli:: chat:: tools:: custom_tool:: OAuthConfig > ,
210212 messenger : & ' a dyn Messenger ,
211213 ) -> Self {
212214 Self {
@@ -216,6 +218,7 @@ impl<'a> HttpServiceBuilder<'a> {
216218 timeout,
217219 scopes,
218220 headers,
221+ oauth_config,
219222 messenger,
220223 }
221224 }
@@ -231,6 +234,7 @@ impl<'a> HttpServiceBuilder<'a> {
231234 timeout,
232235 scopes,
233236 headers,
237+ oauth_config,
234238 messenger,
235239 } = self ;
236240
@@ -292,7 +296,9 @@ impl<'a> HttpServiceBuilder<'a> {
292296 cred_full_path. clone ( ) ,
293297 reg_full_path. clone ( ) ,
294298 scopes,
299+ oauth_config,
295300 messenger,
301+ os,
296302 )
297303 . await ?;
298304
@@ -452,7 +458,9 @@ async fn get_auth_manager(
452458 cred_full_path : PathBuf ,
453459 reg_full_path : PathBuf ,
454460 scopes : & [ String ] ,
461+ oauth_config : & Option < crate :: cli:: chat:: tools:: custom_tool:: OAuthConfig > ,
455462 messenger : & dyn Messenger ,
463+ os : & Os ,
456464) -> Result < AuthorizationManager , OauthUtilError > {
457465 let cred_as_bytes = tokio:: fs:: read ( & cred_full_path) . await ;
458466 let reg_as_bytes = tokio:: fs:: read ( & reg_full_path) . await ;
@@ -474,7 +482,7 @@ async fn get_auth_manager(
474482 _ => {
475483 info ! ( "Error reading cached credentials" ) ;
476484 debug ! ( "## mcp: cache read failed. constructing auth manager from scratch" ) ;
477- let ( am, redirect_uri) = get_auth_manager_impl ( oauth_state, scopes, messenger) . await ?;
485+ let ( am, redirect_uri) = get_auth_manager_impl ( oauth_state, scopes, oauth_config , messenger, os ) . await ?;
478486
479487 // Client registration is done in [start_authorization]
480488 // If we have gotten past that point that means we have the info to persist the
@@ -509,9 +517,21 @@ async fn get_auth_manager(
509517async fn get_auth_manager_impl (
510518 mut oauth_state : OAuthState ,
511519 scopes : & [ String ] ,
520+ oauth_config : & Option < crate :: cli:: chat:: tools:: custom_tool:: OAuthConfig > ,
512521 messenger : & dyn Messenger ,
522+ _os : & Os ,
513523) -> Result < ( AuthorizationManager , String ) , OauthUtilError > {
514- let socket_addr = SocketAddr :: from ( ( [ 127 , 0 , 0 , 1 ] , 0 ) ) ;
524+ // Get port from per-server oauth config, or use 0 for random port assignment
525+ let port = oauth_config
526+ . as_ref ( )
527+ . and_then ( |cfg| cfg. redirect_uri . as_ref ( ) )
528+ . and_then ( |uri| {
529+ // Parse port from redirect_uri like "127.0.0.1:7778" or ":7778"
530+ uri. split ( ':' ) . last ( ) . and_then ( |p| p. parse :: < u16 > ( ) . ok ( ) )
531+ } )
532+ . unwrap_or ( 0 ) ; // Port 0 = OS assigns random available port
533+
534+ let socket_addr = SocketAddr :: from ( ( [ 127 , 0 , 0 , 1 ] , port) ) ;
515535 let cancellation_token = tokio_util:: sync:: CancellationToken :: new ( ) ;
516536 let ( tx, rx) = tokio:: sync:: oneshot:: channel :: < ( String , String ) > ( ) ;
517537
0 commit comments