#[cfg(feature = "mcp")]
use scim_server::{
mcp_integration::ScimMcpServer,
multi_tenant::ScimOperation,
providers::StandardResourceProvider,
resource_handlers::{create_group_resource_handler, create_user_resource_handler},
scim_server::ScimServer,
storage::InMemoryStorage,
};
#[cfg(feature = "mcp")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
env_logger::init();
eprintln!("🚀 Starting SCIM MCP Stdio Server");
eprintln!("==================================\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("Failed to get user schema")
.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,
],
)?;
eprintln!("✅ Registered User resource type with operations:");
eprintln!(" • Create (scim_create_user)");
eprintln!(" • Read (scim_get_user)");
eprintln!(" • Update (scim_update_user)");
eprintln!(" • Delete (scim_delete_user)");
eprintln!(" • Search (scim_search_users, scim_list_users)");
eprintln!(" • Existence Check (scim_user_exists)");
eprintln!();
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,
],
)?;
eprintln!("✅ Registered Group resource type with operations:");
eprintln!(" • Create, Read, Update, Delete");
eprintln!(" • List, Search operations");
eprintln!(" (Note: Group-specific MCP tools not yet implemented)");
eprintln!();
}
let mcp_server = ScimMcpServer::new(scim_server);
let tools = mcp_server.get_tools();
eprintln!("🔧 Available MCP Tools ({} total):", tools.len());
eprintln!("=====================================");
for (i, tool) in tools.iter().enumerate() {
let name = tool
.get("name")
.and_then(|n| n.as_str())
.unwrap_or("Unknown");
let description = tool
.get("description")
.and_then(|d| d.as_str())
.unwrap_or("No description");
eprintln!("{}. {} - {}", i + 1, name, description);
}
eprintln!();
eprintln!("🎯 Server Capabilities:");
eprintln!("=======================");
eprintln!("• JSON-RPC 2.0 protocol support");
eprintln!("• SCIM 2.0 compliant operations");
eprintln!("• Multi-tenant isolation");
eprintln!("• ETag-based optimistic locking");
eprintln!("• Comprehensive error handling");
eprintln!("• Async/non-blocking operations");
eprintln!();
eprintln!("📡 Starting MCP stdio communication...");
eprintln!("Listening for JSON-RPC messages on stdin");
eprintln!("Send MCP protocol messages to interact with the server");
eprintln!("Use Ctrl+C or send EOF to stop the server");
eprintln!("==========================================\n");
mcp_server.run_stdio().await?;
eprintln!("\n✅ SCIM MCP Server shutdown complete");
Ok(())
}
#[cfg(not(feature = "mcp"))]
fn main() {
eprintln!("This example requires the 'mcp' feature to be enabled.");
eprintln!("Run with: cargo run --example mcp_stdio_server --features mcp");
std::process::exit(1);
}