Compare commits

...

3 Commits

Author SHA1 Message Date
Javier Soto
214ac14b60 Remove import 2025-11-04 11:31:41 -08:00
Javier Soto
24535c5922 Implement proper fix: also set the token expiration time when it's expired
The old load path in codex-rs/rmcp-client/src/oauth.rs only set expires_in when the stored expiry was in the future:

  // codex-rs/rmcp-client/src/oauth.rs:369-374 (original)
  if let Some(expires_at) = entry.expires_at
      && let Some(seconds) = expires_in_from_timestamp(expires_at)
  {
      let duration = Duration::from_secs(seconds);
      token_response.set_expires_in(Some(&duration));
  }

  And expires_in_from_timestamp returned None for expired tokens:

  // codex-rs/rmcp-client/src/oauth.rs:444-453 (original)
  if expires_at <= now_ms {
      None
  } else {
      Some((expires_at - now_ms) / 1000)
  }

  So when the stored token was already expired, set_expires_in was never called, RMCP saw “no expiry,” and it didn’t auto-refresh on handshake.
2025-11-04 11:31:41 -08:00
Javier Soto
bc90844a63 fix: refresh expired MCP OAuth tokens
Repro:

- Set up an HTTP MCP server with OAuth expiring tokens like Datadog
- Use it for a bit until the token expires
- Start a new codex session

Expected results:
- The token gets transparently refreshed and the MCP server continues to
work

Actual results:
- You start getting 401s and need to do `codex mcp logout` and log back 
  in.
2025-11-04 11:31:41 -08:00

View File

@@ -366,9 +366,8 @@ fn load_oauth_tokens_from_file(server_name: &str, url: &str) -> Result<Option<St
token_response.set_scopes(Some(scopes.into_iter().map(Scope::new).collect()));
}
if let Some(expires_at) = entry.expires_at
&& let Some(seconds) = expires_in_from_timestamp(expires_at)
{
if let Some(expires_at) = entry.expires_at {
let seconds = expires_in_from_timestamp(expires_at).unwrap_or(0);
let duration = Duration::from_secs(seconds);
token_response.set_expires_in(Some(&duration));
}