fix: respect account selection in MCP server and CLI --account flag (#223)
* fix: respect account selection in MCP server and CLI --account flag (#221, #181) MCP server now reads GOOGLE_WORKSPACE_CLI_ACCOUNT env var and passes it to get_token instead of always using None (default account). CLI filter_args_for_subcommand now dynamically locates the service name instead of hardcoding skip(2), fixing --account before service name causing unrecognized subcommand errors. * fix: skip --api-version in first_arg detection The first_arg loop only skipped --account but not --api-version, so `gws --api-version v3 drive ...` would misidentify --api-version as the service name. Now both global flags are consistently skipped.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@googleworkspace/cli": patch
|
||||
---
|
||||
|
||||
Fix multi-account selection: MCP server now respects `GOOGLE_WORKSPACE_CLI_ACCOUNT` env var (#221), and `--account` flag before service name no longer causes parse errors (#181)
|
||||
+45
-12
@@ -71,7 +71,7 @@ async fn run() -> Result<(), GwsError> {
|
||||
));
|
||||
}
|
||||
|
||||
// Find the first non-flag arg (skip --account and its value)
|
||||
// Find the first non-flag arg (skip --account/--api-version and their values)
|
||||
let mut first_arg: Option<String> = None;
|
||||
{
|
||||
let mut skip_next = false;
|
||||
@@ -80,11 +80,11 @@ async fn run() -> Result<(), GwsError> {
|
||||
skip_next = false;
|
||||
continue;
|
||||
}
|
||||
if a == "--account" {
|
||||
if a == "--account" || a == "--api-version" {
|
||||
skip_next = true;
|
||||
continue;
|
||||
}
|
||||
if a.starts_with("--account=") {
|
||||
if a.starts_with("--account=") || a.starts_with("--api-version=") {
|
||||
continue;
|
||||
}
|
||||
if !a.starts_with("--") || a.as_str() == "--help" || a.as_str() == "--version" {
|
||||
@@ -165,7 +165,7 @@ async fn run() -> Result<(), GwsError> {
|
||||
// Re-parse args (skip argv[0] which is the binary, and argv[1] which is the service name)
|
||||
// Filter out --api-version and its value
|
||||
// Prepend "gws" as the program name since try_get_matches_from expects argv[0]
|
||||
let sub_args = filter_args_for_subcommand(&args);
|
||||
let sub_args = filter_args_for_subcommand(&args, &first_arg);
|
||||
|
||||
let matches = cli.try_get_matches_from(&sub_args).map_err(|e| {
|
||||
// If it's a help or version display, print it and exit cleanly
|
||||
@@ -321,10 +321,11 @@ pub fn parse_service_and_version(
|
||||
Ok((api_name, version))
|
||||
}
|
||||
|
||||
pub fn filter_args_for_subcommand(args: &[String]) -> Vec<String> {
|
||||
pub fn filter_args_for_subcommand(args: &[String], service_name: &str) -> Vec<String> {
|
||||
let mut sub_args: Vec<String> = vec!["gws".to_string()];
|
||||
let mut skip_next = false;
|
||||
for arg in args.iter().skip(2) {
|
||||
let mut service_skipped = false;
|
||||
for arg in args.iter().skip(1) {
|
||||
if skip_next {
|
||||
skip_next = false;
|
||||
continue;
|
||||
@@ -336,6 +337,10 @@ pub fn filter_args_for_subcommand(args: &[String]) -> Vec<String> {
|
||||
if arg.starts_with("--account=") || arg.starts_with("--api-version=") {
|
||||
continue;
|
||||
}
|
||||
if !service_skipped && arg == service_name {
|
||||
service_skipped = true;
|
||||
continue;
|
||||
}
|
||||
sub_args.push(arg.clone());
|
||||
}
|
||||
sub_args
|
||||
@@ -698,7 +703,7 @@ mod tests {
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
assert!(!filtered.contains(&"--account".to_string()));
|
||||
assert!(!filtered.contains(&"user@corp.com".to_string()));
|
||||
@@ -714,7 +719,7 @@ mod tests {
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
}
|
||||
|
||||
@@ -730,7 +735,7 @@ mod tests {
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
}
|
||||
|
||||
@@ -744,7 +749,7 @@ mod tests {
|
||||
"--format".into(),
|
||||
"table".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list", "--format", "table"]);
|
||||
}
|
||||
|
||||
@@ -777,7 +782,7 @@ mod tests {
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert!(!filtered.contains(&"--account".to_string()));
|
||||
assert!(!filtered.contains(&"work@corp.com".to_string()));
|
||||
assert!(filtered.contains(&"files".to_string()));
|
||||
@@ -796,6 +801,34 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_args_account_before_service() {
|
||||
// --account appears BEFORE the service name (issue #181)
|
||||
let args: Vec<String> = vec![
|
||||
"gws".into(),
|
||||
"--account".into(),
|
||||
"work@corp.com".into(),
|
||||
"drive".into(),
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_args_account_equals_before_service() {
|
||||
let args: Vec<String> = vec![
|
||||
"gws".into(),
|
||||
"--account=work@corp.com".into(),
|
||||
"drive".into(),
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_args_strips_account_equals() {
|
||||
let args: Vec<String> = vec![
|
||||
@@ -805,7 +838,7 @@ mod tests {
|
||||
"files".into(),
|
||||
"list".into(),
|
||||
];
|
||||
let filtered = filter_args_for_subcommand(&args);
|
||||
let filtered = filter_args_for_subcommand(&args, "drive");
|
||||
assert!(!filtered.iter().any(|a| a.contains("account")));
|
||||
assert_eq!(filtered, vec!["gws", "files", "list"]);
|
||||
}
|
||||
|
||||
+2
-1
@@ -814,7 +814,8 @@ async fn execute_mcp_method(
|
||||
};
|
||||
|
||||
let scopes: Vec<&str> = crate::select_scope(&method.scopes).into_iter().collect();
|
||||
let (token, auth_method) = match crate::auth::get_token(&scopes, None).await {
|
||||
let account = std::env::var("GOOGLE_WORKSPACE_CLI_ACCOUNT").ok();
|
||||
let (token, auth_method) = match crate::auth::get_token(&scopes, account.as_deref()).await {
|
||||
Ok(t) => (Some(t), crate::executor::AuthMethod::OAuth),
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
|
||||
Reference in New Issue
Block a user