feat: classify authorization-required errors (#1056)

This commit is contained in:
Dale Seo 2026-07-31 09:00:23 -04:00 • committed by GitHub
commit 65f05e9924
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 142 additions and 0 deletions

View file

@ -111,6 +111,17 @@ impl ClientInitializeError {
}
None
}
/// Returns whether client initialization failed because authorization is required.
///
/// This covers both missing or expired local OAuth authorization and an HTTP
/// authorization challenge from the MCP server.
pub fn is_authorization_required(&self) -> bool {
matches!(
self,
Self::TransportError { error, .. } if error.is_authorization_required()
)
}
}
/// Helper function to get the next message from the stream

View file

@ -272,6 +272,27 @@ impl DynamicTransportError {
}
}
pub(crate) fn is_authorization_required(&self) -> bool {
let mut error = Some(self.error.as_ref() as &(dyn std::error::Error + 'static));
while let Some(current) = error {
#[cfg(feature = "auth")]
if matches!(
current.downcast_ref::<auth::AuthError>(),
Some(auth::AuthError::AuthorizationRequired)
) {
return true;
}
#[cfg(feature = "transport-streamable-http-client")]
if current.is::<streamable_http_client::AuthRequiredError>() {
return true;
}
error = current.source();
}
false
}
pub fn downcast<T: Transport<R> + 'static, R: ServiceRole>(self) -> Result<T::Error, Self> {
if !self.is::<T, R>() {
Err(self)