#[cfg(feature = "mcp")]
use scim_server::{
ScimServer,
mcp_integration::{McpServerInfo, ScimMcpServer},
multi_tenant::ScimOperation,
providers::StandardResourceProvider,
resource_handlers::{create_group_resource_handler, create_user_resource_handler},
storage::InMemoryStorage,
};
#[cfg(feature = "mcp")]
use serde_json::json;
#[cfg(feature = "mcp")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.format_timestamp_secs()
.init();
println!("๐ Group MCP Operations Test");
println!("============================\n");
let storage = InMemoryStorage::new();
let provider = StandardResourceProvider::new(storage);
let mut scim_server = ScimServer::new(provider)?;
let user_schema = scim_server
.get_schema_by_id("urn:ietf:params:scim:schemas:core:2.0:User")
.expect("User schema should be available")
.clone();
let user_handler = create_user_resource_handler(user_schema);
scim_server.register_resource_type(
"User",
user_handler,
vec![
ScimOperation::Create,
ScimOperation::Read,
ScimOperation::Update,
ScimOperation::Delete,
ScimOperation::List,
ScimOperation::Search,
],
)?;
if let Some(group_schema) =
scim_server.get_schema_by_id("urn:ietf:params:scim:schemas:core:2.0:Group")
{
let group_handler = create_group_resource_handler(group_schema.clone());
scim_server.register_resource_type(
"Group",
group_handler,
vec![
ScimOperation::Create,
ScimOperation::Read,
ScimOperation::Update,
ScimOperation::Delete,
ScimOperation::List,
ScimOperation::Search,
],
)?;
println!("โ
Registered Group resource type");
}
let server_info = McpServerInfo {
name: "SCIM Group Test Server".to_string(),
version: "1.0.0".to_string(),
description: "Testing Group operations in MCP integration".to_string(),
supported_resource_types: scim_server
.get_supported_resource_types()
.into_iter()
.map(|s| s.to_string())
.collect(),
};
let mcp_server = ScimMcpServer::with_info(scim_server, server_info);
println!("๐ฅ Creating test users...");
let alice_result = mcp_server
.execute_tool(
"scim_create_user",
json!({
"user_data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "alice@company.com",
"name": {
"givenName": "Alice",
"familyName": "Smith"
},
"active": true
}
}),
)
.await;
let alice_id = if alice_result.success {
alice_result.metadata.unwrap()["resource_id"].as_str().unwrap().to_string()
} else {
panic!("Failed to create Alice user");
};
let bob_result = mcp_server
.execute_tool(
"scim_create_user",
json!({
"user_data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "bob@company.com",
"name": {
"givenName": "Bob",
"familyName": "Johnson"
},
"active": true
}
}),
)
.await;
let bob_id = if bob_result.success {
bob_result.metadata.unwrap()["resource_id"].as_str().unwrap().to_string()
} else {
panic!("Failed to create Bob user");
};
println!(" โ
Created users Alice and Bob\n");
println!("๐ Testing Group CRUD operations:");
println!("=================================");
println!("1. Creating a new group...");
let create_group_result = mcp_server
.execute_tool(
"scim_create_group",
json!({
"group_data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Engineering Team",
"members": [
{
"value": alice_id,
"$ref": format!("https://example.com/v2/Users/{}", alice_id),
"type": "User"
},
{
"value": bob_id,
"$ref": format!("https://example.com/v2/Users/{}", bob_id),
"type": "User"
}
],
"externalId": "eng-team-001"
}
}),
)
.await;
let group_id = if create_group_result.success {
let group_id = create_group_result.metadata.as_ref().unwrap()["resource_id"]
.as_str()
.unwrap()
.to_string();
println!(" โ
Group created successfully with ID: {}", group_id);
group_id
} else {
println!(" โ Group creation failed: {:?}", create_group_result.content);
return Ok(());
};
println!("\n2. Retrieving the group...");
let get_group_result = mcp_server
.execute_tool(
"scim_get_group",
json!({
"group_id": group_id
}),
)
.await;
if get_group_result.success {
println!(" โ
Group retrieved successfully");
let group_data = &get_group_result.content;
println!(" ๐ Group name: {}",
group_data.get("displayName").and_then(|d| d.as_str()).unwrap_or("Unknown"));
println!(" ๐ฅ Members count: {}",
group_data.get("members").and_then(|m| m.as_array()).map(|a| a.len()).unwrap_or(0));
if group_data.get("_version").is_some() {
println!(" WARNING: _version field found in content - this should not exist");
}
} else {
println!(" โ Group retrieval failed: {:?}", get_group_result.content);
}
println!("\n3. Updating the group...");
let update_group_result = mcp_server
.execute_tool(
"scim_update_group",
json!({
"group_id": group_id,
"group_data": {
"id": group_id,
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Senior Engineering Team",
"members": [
{
"value": alice_id,
"$ref": format!("https://example.com/v2/Users/{}", alice_id),
"type": "User"
}
],
"externalId": "senior-eng-team-001"
}
}),
)
.await;
if update_group_result.success {
println!(" โ
Group updated successfully");
println!(" ๐ Updated name and removed Bob from members");
} else {
println!(" โ Group update failed: {:?}", update_group_result.content);
}
println!("\n๐ Testing Group query operations:");
println!("==================================");
let create_group2_result = mcp_server
.execute_tool(
"scim_create_group",
json!({
"group_data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Marketing Team",
"members": [
{
"value": bob_id,
"$ref": format!("https://example.com/v2/Users/{}", bob_id),
"type": "User"
}
],
"externalId": "marketing-001"
}
}),
)
.await;
let group2_id = if create_group2_result.success {
create_group2_result.metadata.as_ref().unwrap()["resource_id"]
.as_str()
.unwrap()
.to_string()
} else {
println!("Failed to create second group");
return Ok(());
};
println!("\n1. Listing all groups...");
let list_groups_result = mcp_server.execute_tool("scim_list_groups", json!({})).await;
if list_groups_result.success {
let empty_vec = vec![];
let groups = list_groups_result.content
.get("Resources")
.and_then(|r| r.as_array())
.unwrap_or(&empty_vec);
println!(" โ
Groups list retrieved");
println!(" ๐ Total groups: {}", groups.len());
for group in groups {
if let Some(name) = group.get("displayName").and_then(|n| n.as_str()) {
println!(" โข {}", name);
}
}
} else {
println!(" โ Groups listing failed: {:?}", list_groups_result.content);
}
println!("\n2. Searching for groups by displayName...");
let search_groups_result = mcp_server
.execute_tool(
"scim_search_groups",
json!({
"attribute": "displayName",
"value": "Marketing Team"
}),
)
.await;
if search_groups_result.success {
let empty_vec = vec![];
let found_groups = search_groups_result.content
.get("Resources")
.and_then(|r| r.as_array())
.unwrap_or(&empty_vec);
println!(" โ
Group search completed");
println!(" ๐ Found {} matching groups", found_groups.len());
} else {
println!(" โ Group search failed: {:?}", search_groups_result.content);
}
println!("\n3. Checking if group exists...");
let group_exists_result = mcp_server
.execute_tool(
"scim_group_exists",
json!({
"group_id": group_id
}),
)
.await;
if group_exists_result.success {
let exists = group_exists_result.content
.get("exists")
.and_then(|e| e.as_bool())
.unwrap_or(false);
println!(" โ
Group existence check: {}", if exists { "EXISTS" } else { "NOT FOUND" });
} else {
println!(" โ Group existence check failed: {:?}", group_exists_result.content);
}
println!("\n๐ข Testing multi-tenant Group operations:");
println!("=========================================");
let tenant_group_result = mcp_server
.execute_tool(
"scim_create_group",
json!({
"group_data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Tenant A Admin Group",
"externalId": "tenant-a-admins"
},
"tenant_id": "tenant-a"
}),
)
.await;
if tenant_group_result.success {
println!(" โ
Tenant-specific group created");
if let Some(metadata) = tenant_group_result.metadata {
if let Some(tenant_id) = metadata.get("tenant_id") {
println!(" ๐ข Tenant context preserved: {}", tenant_id);
}
}
} else {
println!(" โ Tenant-specific group creation failed");
}
println!("\nโ ๏ธ Testing Group error handling:");
println!("=================================");
let error_test_result = mcp_server
.execute_tool(
"scim_get_group",
json!({
"group_id": "non-existent-group-id"
}),
)
.await;
if !error_test_result.success {
println!(" โ
Error handling working correctly for non-existent groups");
let error_code = error_test_result.content
.get("error_code")
.and_then(|e| e.as_str())
.unwrap_or("UNKNOWN");
println!(" ๐ Error code: {}", error_code);
}
println!("\n๐งน Cleaning up test data:");
println!("=========================");
for (name, id) in [("Engineering Group", &group_id), ("Marketing Group", &group2_id)] {
let delete_result = mcp_server
.execute_tool(
"scim_delete_group",
json!({
"group_id": id
}),
)
.await;
if delete_result.success {
println!(" โ
{} deleted", name);
} else {
println!(" โ Failed to delete {}", name);
}
}
for (name, id) in [("Alice", &alice_id), ("Bob", &bob_id)] {
let delete_result = mcp_server
.execute_tool(
"scim_delete_user",
json!({
"user_id": id
}),
)
.await;
if delete_result.success {
println!(" โ
User {} deleted", name);
} else {
println!(" โ Failed to delete user {}", name);
}
}
println!("\n๐ Group MCP Operations Test Complete!");
println!("======================================");
let final_tools = mcp_server.get_tools();
let group_tools: Vec<_> = final_tools
.iter()
.filter(|tool| tool.get("name")
.and_then(|n| n.as_str())
.map_or(false, |name| name.contains("group")))
.collect();
println!("โ
Group operations successfully integrated into MCP server");
println!("โ
Total Group tools available: {}", group_tools.len());
println!("โ
All CRUD operations tested and working");
println!("โ
Query operations tested and working");
println!("โ
Multi-tenant support verified");
println!("โ
Error handling confirmed");
println!("\n๐ Available Group Tools:");
for tool in group_tools {
if let Some(name) = tool.get("name").and_then(|n| n.as_str()) {
if let Some(desc) = tool.get("description").and_then(|d| d.as_str()) {
println!(" โข {} - {}", name, desc);
}
}
}
println!("\n๐ Group MCP Integration Ready for Production!");
Ok(())
}
#[cfg(not(feature = "mcp"))]
fn main() {
eprintln!("This example requires the 'mcp' feature to be enabled.");
eprintln!("Please run with: cargo run --example test_group_mcp --features mcp");
std::process::exit(1);
}