mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
Route MCP OAuth through configured HTTP clients (#35806)
## What changed - Pass resolved, route-aware HTTP clients through MCP OAuth discovery and login so CLI commands, plugin installation, and skill dependency setup honor configured proxies and execution environments. - Apply per-plugin MCP server configuration and requirements before starting OAuth during installation, and skip disabled servers or servers assigned to unowned environments. - Preserve configured MCP server policies when merging remotely installed plugin metadata. ## Testing - Cover proxy-routed OAuth for `codex mcp add`, `codex mcp login`, plugin installation, and skill MCP dependencies. - Cover plugin-install OAuth filtering for disabled servers, plugin requirements, and unowned environments. GitOrigin-RevId: f84c88820e24a627faa78d6bed1b371682ecdc2f
This commit is contained in:
+40
-10
@@ -19,16 +19,19 @@ use codex_core::config::find_codex_home;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_exec_server::EnvironmentManager;
|
||||
use codex_exec_server::HttpClient;
|
||||
use codex_exec_server::RouteAwareHttpClient;
|
||||
use codex_login::AuthManager;
|
||||
use codex_mcp::McpOAuthLoginSupport;
|
||||
use codex_mcp::McpRuntimeContext;
|
||||
use codex_mcp::ResolvedMcpOAuthScopes;
|
||||
use codex_mcp::compute_auth_statuses;
|
||||
use codex_mcp::discover_supported_scopes;
|
||||
use codex_mcp::oauth_login_support;
|
||||
use codex_mcp::discover_supported_scopes_with_http_client;
|
||||
use codex_mcp::oauth_login_support_with_http_client;
|
||||
use codex_mcp::resolve_oauth_scopes;
|
||||
use codex_mcp::should_retry_without_scopes;
|
||||
use codex_protocol::protocol::McpAuthStatus;
|
||||
use codex_rmcp_client::OAuthDiscoveryTimeout;
|
||||
use codex_rmcp_client::delete_oauth_tokens;
|
||||
use codex_rmcp_client::perform_oauth_login;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
@@ -224,6 +227,7 @@ async fn perform_oauth_login_retry_without_scopes(
|
||||
oauth_resource: Option<&str>,
|
||||
callback_port: Option<u16>,
|
||||
callback_url: Option<&str>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
) -> Result<()> {
|
||||
match perform_oauth_login(
|
||||
name,
|
||||
@@ -237,6 +241,7 @@ async fn perform_oauth_login_retry_without_scopes(
|
||||
oauth_resource,
|
||||
callback_port,
|
||||
callback_url,
|
||||
Arc::clone(&http_client),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -255,6 +260,7 @@ async fn perform_oauth_login_retry_without_scopes(
|
||||
oauth_resource,
|
||||
callback_port,
|
||||
callback_url,
|
||||
http_client,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -381,7 +387,17 @@ async fn run_add(config_overrides: &CliConfigOverrides, add_args: AddArgs) -> Re
|
||||
|
||||
println!("Added global MCP server '{name}'.");
|
||||
|
||||
match oauth_login_support(&transport).await {
|
||||
// `mcp add` assigns new servers to the local environment, so its immediate
|
||||
// OAuth discovery uses the local route-aware HTTP client.
|
||||
let http_client: Arc<dyn HttpClient> =
|
||||
Arc::new(RouteAwareHttpClient::new(config.http_client_factory()));
|
||||
let login_support = oauth_login_support_with_http_client(
|
||||
&transport,
|
||||
Arc::clone(&http_client),
|
||||
OAuthDiscoveryTimeout::LOCAL,
|
||||
)
|
||||
.await;
|
||||
match login_support {
|
||||
McpOAuthLoginSupport::Supported(oauth_config) => {
|
||||
println!("Detected OAuth support. Starting OAuth flow…");
|
||||
let resolved_scopes = resolve_oauth_scopes(
|
||||
@@ -401,6 +417,7 @@ async fn run_add(config_overrides: &CliConfigOverrides, add_args: AddArgs) -> Re
|
||||
oauth_resource.as_deref(),
|
||||
config.mcp_oauth_callback_port,
|
||||
config.mcp_oauth_callback_url.as_deref(),
|
||||
http_client,
|
||||
)
|
||||
.await?;
|
||||
println!("Successfully logged in.");
|
||||
@@ -479,9 +496,18 @@ async fn run_login(config_overrides: &CliConfigOverrides, login_args: LoginArgs)
|
||||
_ => bail!("OAuth login is only supported for streamable HTTP servers."),
|
||||
};
|
||||
|
||||
// Standalone `mcp login` runs OAuth from the local CLI process; execution
|
||||
// environment routing belongs to app-server and session MCP flows.
|
||||
let http_client: Arc<dyn HttpClient> =
|
||||
Arc::new(RouteAwareHttpClient::new(config.http_client_factory()));
|
||||
let explicit_scopes = (!scopes.is_empty()).then_some(scopes);
|
||||
let discovered_scopes = if explicit_scopes.is_none() && server.scopes.is_none() {
|
||||
discover_supported_scopes(&server.transport).await
|
||||
discover_supported_scopes_with_http_client(
|
||||
&server.transport,
|
||||
Arc::clone(&http_client),
|
||||
OAuthDiscoveryTimeout::LOCAL,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -500,6 +526,7 @@ async fn run_login(config_overrides: &CliConfigOverrides, login_args: LoginArgs)
|
||||
server.oauth_resource.as_deref(),
|
||||
config.mcp_oauth_callback_port,
|
||||
config.mcp_oauth_callback_url.as_deref(),
|
||||
http_client,
|
||||
)
|
||||
.await?;
|
||||
println!("Successfully logged in to MCP server '{name}'.");
|
||||
@@ -557,17 +584,20 @@ async fn run_list(config_overrides: &CliConfigOverrides, list_args: ListArgs) ->
|
||||
|
||||
let mut entries: Vec<_> = mcp_servers.iter().collect();
|
||||
entries.sort_by_key(|(name, _)| *name);
|
||||
// Standalone `mcp list` only discovers auth through local HTTP; it has
|
||||
// never initialized or routed through remote execution environments.
|
||||
let runtime_context = McpRuntimeContext::new(
|
||||
Arc::new(EnvironmentManager::without_environments(
|
||||
config.http_client_factory(),
|
||||
)),
|
||||
config.cwd.to_path_buf(),
|
||||
);
|
||||
let auth_statuses = compute_auth_statuses(
|
||||
effective_mcp_servers.iter(),
|
||||
config.mcp_oauth_credentials_store_mode,
|
||||
config.auth_keyring_backend_kind(),
|
||||
auth.as_ref(),
|
||||
&McpRuntimeContext::new(
|
||||
Arc::new(EnvironmentManager::without_environments(
|
||||
config.http_client_factory(),
|
||||
)),
|
||||
config.cwd.to_path_buf(),
|
||||
),
|
||||
&runtime_context,
|
||||
)
|
||||
.await;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user