fix: allow MCP OAuth refresh_token to be absent from initial token exchanges
CI / All (macos-latest) (push) Waiting to run
CI / All (windows-latest) (push) Waiting to run
CI / All (ubuntu-latest) (push) Failing after 25s

This commit is contained in:
2026-07-07 14:15:39 -06:00
parent fa7eadd08a
commit 84ce094677
+11 -7
View File
@@ -70,7 +70,8 @@ pub trait OAuthProvider: Send + Sync {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OAuthTokens { pub struct OAuthTokens {
pub access_token: String, pub access_token: String,
pub refresh_token: String, #[serde(default)]
pub refresh_token: Option<String>,
pub expires_at: i64, pub expires_at: i64,
#[serde(default)] #[serde(default)]
pub account_id: Option<String>, pub account_id: Option<String>,
@@ -165,10 +166,7 @@ pub async fn run_oauth_flow(provider: &dyn OAuthProvider, client_name: &str) ->
.as_str() .as_str()
.ok_or_else(|| anyhow!("Missing access_token in response: {response}"))? .ok_or_else(|| anyhow!("Missing access_token in response: {response}"))?
.to_string(); .to_string();
let refresh_token = response["refresh_token"] let refresh_token = response["refresh_token"].as_str().map(|s| s.to_string());
.as_str()
.ok_or_else(|| anyhow!("Missing refresh_token in response: {response}"))?
.to_string();
let expires_in = response["expires_in"] let expires_in = response["expires_in"]
.as_i64() .as_i64()
.ok_or_else(|| anyhow!("Missing expires_in in response: {response}"))?; .ok_or_else(|| anyhow!("Missing expires_in in response: {response}"))?;
@@ -217,13 +215,19 @@ pub async fn refresh_oauth_token(
client_name: &str, client_name: &str,
tokens: &OAuthTokens, tokens: &OAuthTokens,
) -> Result<OAuthTokens> { ) -> Result<OAuthTokens> {
let refresh_token_val = tokens.refresh_token.as_deref().ok_or_else(|| {
anyhow!(
"No refresh token available for '{}'. Please re-authenticate.",
client_name
)
})?;
let request = build_token_request( let request = build_token_request(
client, client,
provider, provider,
&[ &[
("grant_type", "refresh_token"), ("grant_type", "refresh_token"),
("client_id", provider.client_id()), ("client_id", provider.client_id()),
("refresh_token", &tokens.refresh_token), ("refresh_token", refresh_token_val),
], ],
); );
@@ -236,7 +240,7 @@ pub async fn refresh_oauth_token(
let refresh_token = response["refresh_token"] let refresh_token = response["refresh_token"]
.as_str() .as_str()
.map(|s| s.to_string()) .map(|s| s.to_string())
.unwrap_or_else(|| tokens.refresh_token.clone()); .or_else(|| tokens.refresh_token.clone());
let expires_in = response["expires_in"] let expires_in = response["expires_in"]
.as_i64() .as_i64()
.ok_or_else(|| anyhow!("Missing expires_in in refresh response: {response}"))?; .ok_or_else(|| anyhow!("Missing expires_in in refresh response: {response}"))?;