[MCP] Add the ability to explicitly specify a credentials store (#4857)

This lets users/companies explicitly choose whether to force/disallow
the keyring/fallback file storage for mcp credentials.

People who develop with Codex will want to use this until we sign
binaries or else each ad-hoc debug builds will require keychain access
on every build. I don't love this and am open to other ideas for how to
handle that.


```toml
mcp_oauth_credentials_store = "auto"
mcp_oauth_credentials_store = "file"
mcp_oauth_credentials_store = "keyrung"
```
Defaults to `auto`
This commit is contained in:
Gabriel Peal
2025-10-07 19:39:32 -07:00
committed by GitHub
parent abd517091f
commit 496cb801e1
8 changed files with 313 additions and 56 deletions

View File

@@ -35,6 +35,7 @@ use tracing::warn;
use crate::load_oauth_tokens;
use crate::logging_client_handler::LoggingClientHandler;
use crate::oauth::OAuthCredentialsStoreMode;
use crate::oauth::OAuthPersistor;
use crate::oauth::StoredOAuthTokens;
use crate::utils::convert_call_tool_result;
@@ -119,10 +120,11 @@ impl RmcpClient {
server_name: &str,
url: &str,
bearer_token: Option<String>,
store_mode: OAuthCredentialsStoreMode,
) -> Result<Self> {
let initial_oauth_tokens = match bearer_token {
Some(_) => None,
None => match load_oauth_tokens(server_name, url) {
None => match load_oauth_tokens(server_name, url, store_mode) {
Ok(tokens) => tokens,
Err(err) => {
warn!("failed to read tokens for server `{server_name}`: {err}");
@@ -132,7 +134,8 @@ impl RmcpClient {
};
let transport = if let Some(initial_tokens) = initial_oauth_tokens.clone() {
let (transport, oauth_persistor) =
create_oauth_transport_and_runtime(server_name, url, initial_tokens).await?;
create_oauth_transport_and_runtime(server_name, url, initial_tokens, store_mode)
.await?;
PendingTransport::StreamableHttpWithOAuth {
transport,
oauth_persistor,
@@ -286,6 +289,7 @@ async fn create_oauth_transport_and_runtime(
server_name: &str,
url: &str,
initial_tokens: StoredOAuthTokens,
credentials_store: OAuthCredentialsStoreMode,
) -> Result<(
StreamableHttpClientTransport<AuthClient<reqwest::Client>>,
OAuthPersistor,
@@ -320,6 +324,7 @@ async fn create_oauth_transport_and_runtime(
server_name.to_string(),
url.to_string(),
auth_manager,
credentials_store,
Some(initial_tokens),
);