Current state
crates/redisctl-mcp/src/tools/cloud/account.rs defines 33 tools.
Current test coverage in cloud_tools.rs covers 11 of them (all read-only or task-related):
get_account, get_system_logs, get_session_logs, get_regions, get_modules,
list_account_users, list_tasks, get_task (happy path + failed), create_acl_user,
create_redis_rule, delete_acl_role.
The following 22 tools have zero coverage:
Read-only (no test — medium priority):
get_account_user — GET /users/{id}
list_acl_users — GET /acl/users
get_acl_user — GET /acl/users/{id}
list_acl_roles — GET /acl/roles
list_redis_rules — GET /acl/redisRules
download_cost_report — GET /reports/{report_id}
list_payment_methods — GET /payment-methods
wait_for_cloud_task — polling helper (special case)
list_cloud_accounts — GET /cloud-accounts
get_cloud_account — GET /cloud-accounts/{id}
Write tools (no test — high priority):
update_account_user — PUT /users/{id}
update_acl_user — PUT /acl/users/{id}
create_acl_role — POST /acl/roles
update_acl_role — PUT /acl/roles/{id}
update_redis_rule — PUT /acl/redisRules/{id}
generate_cost_report — POST /reports (complex request body with date ranges)
create_cloud_account — POST /cloud-accounts
update_cloud_account — PUT /cloud-accounts/{id}
Destructive tools (no test — high priority):
delete_account_user — DELETE /users/{id}
delete_acl_user — DELETE /acl/users/{id}
delete_acl_role — covered (test exists)
delete_redis_rule — DELETE /acl/redisRules/{id}
delete_cloud_account — DELETE /cloud-accounts/{id}
Desired state
Each of the 22 tools above has at least one test:
- Write tools:
body_partial_json matcher verifying camelCase field serialization.
- Destructive tools: path+method matcher + policy guard assertion.
- Read-only tools: path+method matcher verifying correct URL construction.
generate_cost_report is a particularly important, frequently-used tool — it takes
from_date/to_date parameters that must be serialized correctly to fromDate/toDate.
Code example
#[tokio::test]
async fn test_update_acl_role_request_shape() {
let server = MockCloudServer::start().await;
// AclRoleUpdateRequest: name -> "name", redis_rules -> "redisRules" (camelCase)
Mock::given(method("PUT"))
.and(path("/acl/roles/42"))
.and(body_partial_json(json!({
"name": "readonly-role",
"redisRules": [{"ruleName": "+@read"}]
})))
.respond_with(ResponseTemplate::new(202).set_body_json(json!({
"taskId": "task-update-role",
"status": "processing-in-progress"
})))
.mount(server.inner())
.await;
let client = server.client();
let state = full_policy_state(client);
let tool = cloud::update_acl_role(state);
let result = call_tool_text(&tool, json!({
"role_id": 42,
"name": "readonly-role",
"redis_rules": [{"rule_name": "+@read"}]
})).await;
assert!(result.contains("task-update-role") || result.contains("taskId"),
"Expected task response for update_acl_role, got: {result}");
}
Implementation notes
- File:
crates/redisctl-mcp/tests/cloud_tools.rs — add a new "Section: Account write tools"
- Inspect
account.rs create/update request structs to confirm camelCase field names
(the #[serde(rename_all = "camelCase")] annotation is the source of truth)
generate_cost_report returns a task response; verify taskId is present
wait_for_cloud_task wraps task polling — a negative-path test (task fails) would be useful
in addition to the already-covered get_task_failed pattern
- Priority ordering:
update_acl_role, create_acl_role, update_redis_rule (ACL write tools),
then generate_cost_report, then cloud account CRUD
Current state
crates/redisctl-mcp/src/tools/cloud/account.rsdefines 33 tools.Current test coverage in
cloud_tools.rscovers 11 of them (all read-only or task-related):get_account,get_system_logs,get_session_logs,get_regions,get_modules,list_account_users,list_tasks,get_task(happy path + failed),create_acl_user,create_redis_rule,delete_acl_role.The following 22 tools have zero coverage:
Read-only (no test — medium priority):
get_account_user— GET /users/{id}list_acl_users— GET /acl/usersget_acl_user— GET /acl/users/{id}list_acl_roles— GET /acl/roleslist_redis_rules— GET /acl/redisRulesdownload_cost_report— GET /reports/{report_id}list_payment_methods— GET /payment-methodswait_for_cloud_task— polling helper (special case)list_cloud_accounts— GET /cloud-accountsget_cloud_account— GET /cloud-accounts/{id}Write tools (no test — high priority):
update_account_user— PUT /users/{id}update_acl_user— PUT /acl/users/{id}create_acl_role— POST /acl/rolesupdate_acl_role— PUT /acl/roles/{id}update_redis_rule— PUT /acl/redisRules/{id}generate_cost_report— POST /reports (complex request body with date ranges)create_cloud_account— POST /cloud-accountsupdate_cloud_account— PUT /cloud-accounts/{id}Destructive tools (no test — high priority):
delete_account_user— DELETE /users/{id}delete_acl_user— DELETE /acl/users/{id}delete_acl_role— covered (test exists)delete_redis_rule— DELETE /acl/redisRules/{id}delete_cloud_account— DELETE /cloud-accounts/{id}Desired state
Each of the 22 tools above has at least one test:
body_partial_jsonmatcher verifying camelCase field serialization.generate_cost_reportis a particularly important, frequently-used tool — it takesfrom_date/to_dateparameters that must be serialized correctly tofromDate/toDate.Code example
Implementation notes
crates/redisctl-mcp/tests/cloud_tools.rs— add a new "Section: Account write tools"account.rscreate/update request structs to confirm camelCase field names(the
#[serde(rename_all = "camelCase")]annotation is the source of truth)generate_cost_reportreturns a task response; verifytaskIdis presentwait_for_cloud_taskwraps task polling — a negative-path test (task fails) would be usefulin addition to the already-covered
get_task_failedpatternupdate_acl_role,create_acl_role,update_redis_rule(ACL write tools),then
generate_cost_report, then cloud account CRUD