[MCP] Add support for specifying scopes for MCP oauth (#5487)

```
codex mcp login server_name --scopes=scope1,scope2,scope3
```

Fixes #5480
This commit is contained in:
Gabriel Peal
2025-10-22 09:37:33 -07:00
committed by GitHub
parent f522aafb7f
commit 34c5a9eaa9
2 changed files with 10 additions and 2 deletions

View File

@@ -150,6 +150,10 @@ pub struct RemoveArgs {
pub struct LoginArgs { pub struct LoginArgs {
/// Name of the MCP server to authenticate with oauth. /// Name of the MCP server to authenticate with oauth.
pub name: String, pub name: String,
/// Comma-separated list of OAuth scopes to request.
#[arg(long, value_delimiter = ',', value_name = "SCOPE,SCOPE")]
pub scopes: Vec<String>,
} }
#[derive(Debug, clap::Parser)] #[derive(Debug, clap::Parser)]
@@ -279,6 +283,7 @@ async fn run_add(config_overrides: &CliConfigOverrides, add_args: AddArgs) -> Re
config.mcp_oauth_credentials_store_mode, config.mcp_oauth_credentials_store_mode,
http_headers.clone(), http_headers.clone(),
env_http_headers.clone(), env_http_headers.clone(),
&Vec::new(),
) )
.await?; .await?;
println!("Successfully logged in."); println!("Successfully logged in.");
@@ -327,7 +332,7 @@ async fn run_login(config_overrides: &CliConfigOverrides, login_args: LoginArgs)
); );
} }
let LoginArgs { name } = login_args; let LoginArgs { name, scopes } = login_args;
let Some(server) = config.mcp_servers.get(&name) else { let Some(server) = config.mcp_servers.get(&name) else {
bail!("No MCP server named '{name}' found."); bail!("No MCP server named '{name}' found.");
@@ -349,6 +354,7 @@ async fn run_login(config_overrides: &CliConfigOverrides, login_args: LoginArgs)
config.mcp_oauth_credentials_store_mode, config.mcp_oauth_credentials_store_mode,
http_headers, http_headers,
env_http_headers, env_http_headers,
&scopes,
) )
.await?; .await?;
println!("Successfully logged in to MCP server '{name}'."); println!("Successfully logged in to MCP server '{name}'.");

View File

@@ -37,6 +37,7 @@ pub async fn perform_oauth_login(
store_mode: OAuthCredentialsStoreMode, store_mode: OAuthCredentialsStoreMode,
http_headers: Option<HashMap<String, String>>, http_headers: Option<HashMap<String, String>>,
env_http_headers: Option<HashMap<String, String>>, env_http_headers: Option<HashMap<String, String>>,
scopes: &[String],
) -> Result<()> { ) -> Result<()> {
let server = Arc::new(Server::http("127.0.0.1:0").map_err(|err| anyhow!(err))?); let server = Arc::new(Server::http("127.0.0.1:0").map_err(|err| anyhow!(err))?);
let guard = CallbackServerGuard { let guard = CallbackServerGuard {
@@ -61,8 +62,9 @@ pub async fn perform_oauth_login(
let http_client = apply_default_headers(ClientBuilder::new(), &default_headers).build()?; let http_client = apply_default_headers(ClientBuilder::new(), &default_headers).build()?;
let mut oauth_state = OAuthState::new(server_url, Some(http_client)).await?; let mut oauth_state = OAuthState::new(server_url, Some(http_client)).await?;
let scope_refs: Vec<&str> = scopes.iter().map(String::as_str).collect();
oauth_state oauth_state
.start_authorization(&[], &redirect_uri, Some("Codex")) .start_authorization(&scope_refs, &redirect_uri, Some("Codex"))
.await?; .await?;
let auth_url = oauth_state.get_authorization_url().await?; let auth_url = oauth_state.get_authorization_url().await?;