use raps_kernel::auth::AuthClient;
use raps_kernel::config::Config;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AuthRequirement {
TwoLegged,
ThreeLegged,
Either,
}
#[derive(Debug, Clone)]
pub struct AuthState {
pub has_client_id: bool,
pub has_client_secret: bool,
pub two_legged_valid: bool,
pub three_legged_valid: bool,
pub three_legged_expired: bool,
}
impl AuthState {
pub fn has_any_credentials(&self) -> bool {
self.has_client_id || self.has_client_secret
}
pub fn has_complete_2leg_credentials(&self) -> bool {
self.has_client_id && self.has_client_secret
}
}
pub const SETUP_INSTRUCTIONS: &str = r#"
To set up authentication for RAPS MCP Server:
1. Go to https://aps.autodesk.com/ (Autodesk Platform Services)
2. Sign in or create an Autodesk account
3. Create a new application or select an existing one
4. Copy your Client ID and Client Secret
5. Set environment variables before starting the MCP server:
For Unix/macOS:
export APS_CLIENT_ID="your_client_id"
export APS_CLIENT_SECRET="your_client_secret"
For Windows (PowerShell):
$env:APS_CLIENT_ID="your_client_id"
$env:APS_CLIENT_SECRET="your_client_secret"
Or add to your MCP server configuration (claude_desktop_config.json):
{
"mcpServers": {
"raps": {
"command": "raps",
"args": ["serve"],
"env": {
"APS_CLIENT_ID": "your_client_id",
"APS_CLIENT_SECRET": "your_client_secret"
}
}
}
}
For more information: https://rapscli.xyz/docs/auth
"#;
pub const MISSING_CLIENT_ID: &str = r#"
Missing: APS_CLIENT_ID environment variable
The Client ID is required for all APS operations. To get your Client ID:
1. Go to https://aps.autodesk.com/
2. Navigate to your application's settings
3. Copy the "Client ID" value
4. Set APS_CLIENT_ID environment variable
"#;
pub const MISSING_CLIENT_SECRET: &str = r#"
Missing: APS_CLIENT_SECRET environment variable
The Client Secret is required for authentication. To get your Client Secret:
1. Go to https://aps.autodesk.com/
2. Navigate to your application's settings
3. Copy or regenerate the "Client Secret" value
4. Set APS_CLIENT_SECRET environment variable
Note: Keep your Client Secret secure and never share it publicly.
"#;
pub const THREE_LEGGED_PROMPT: &str = r#"
To access BIM 360/ACC data (hubs, projects, folders, files, issues, RFIs), you need to log in with your Autodesk account.
Use the `auth_login` tool to start the authentication process, or run:
raps auth login
This will open a browser window for you to sign in with your Autodesk credentials.
"#;
pub const TOOL_AVAILABILITY_HEADER: &str = "\nTool Availability:\n";
pub fn get_tool_auth_requirement(tool_name: &str) -> AuthRequirement {
match tool_name {
"auth_test" | "auth_status" | "auth_login" | "auth_logout" => AuthRequirement::Either,
"bucket_list"
| "bucket_create"
| "bucket_get"
| "bucket_delete"
| "object_list"
| "object_delete"
| "object_signed_url"
| "object_urn"
| "object_upload"
| "object_upload_batch"
| "object_download"
| "object_info"
| "object_copy"
| "object_delete_batch" => AuthRequirement::TwoLegged,
"translate_start" | "translate_status" => AuthRequirement::TwoLegged,
"admin_project_list"
| "admin_operation_list"
| "admin_operation_status"
| "admin_operation_resume"
| "admin_operation_cancel" => AuthRequirement::TwoLegged,
"admin_user_add"
| "admin_user_remove"
| "admin_user_update_role"
| "admin_folder_rights" => AuthRequirement::TwoLegged,
"hub_list" | "project_list" | "folder_list" | "folder_create" | "item_info"
| "item_versions" => AuthRequirement::ThreeLegged,
"project_info" | "project_users_list" | "folder_contents" => AuthRequirement::ThreeLegged,
"project_create" | "project_user_add" | "project_users_import" => {
AuthRequirement::ThreeLegged
}
"item_create" | "item_delete" | "item_rename" => AuthRequirement::ThreeLegged,
"issue_list"
| "issue_get"
| "issue_create"
| "issue_update"
| "rfi_list"
| "rfi_get"
| "rfi_create"
| "rfi_update"
| "acc_assets_list"
| "asset_create"
| "asset_update"
| "asset_delete"
| "acc_submittals_list"
| "submittal_create"
| "submittal_update"
| "acc_checklists_list"
| "checklist_create"
| "checklist_update" => AuthRequirement::ThreeLegged,
_ => AuthRequirement::TwoLegged,
}
}
pub async fn get_auth_state(config: &Config, auth_client: &AuthClient) -> AuthState {
let has_client_id = !config.client_id.is_empty();
let has_client_secret = !config.client_secret.is_empty();
let two_legged_valid = if has_client_id && has_client_secret {
auth_client.get_token().await.is_ok()
} else {
false
};
let (three_legged_valid, three_legged_expired) = match auth_client.get_3leg_token().await {
Ok(_) => (true, false),
Err(e) => {
let err_msg = e.to_string().to_lowercase();
if err_msg.contains("expired") || err_msg.contains("refresh") {
(false, true)
} else {
(false, false)
}
}
};
AuthState {
has_client_id,
has_client_secret,
two_legged_valid,
three_legged_valid,
three_legged_expired,
}
}
pub fn format_error_guidance(error: &str) -> String {
let error_lower = error.to_lowercase();
if error_lower.contains("client_id") || error_lower.contains("aps_client_id") {
return format!(
"Authentication Error: Missing Client ID\n{}",
MISSING_CLIENT_ID
);
}
if error_lower.contains("client_secret") || error_lower.contains("aps_client_secret") {
return format!(
"Authentication Error: Missing Client Secret\n{}",
MISSING_CLIENT_SECRET
);
}
if error_lower.contains("401") || error_lower.contains("unauthorized") {
return format!(
r#"Authentication Error: Invalid Credentials
Your credentials were rejected by Autodesk. Troubleshooting steps:
1. Verify APS_CLIENT_ID is correct (typically 32 characters)
2. Verify APS_CLIENT_SECRET is correct (typically 64 characters)
3. Check that your app is active at https://aps.autodesk.com/
4. Ensure credentials are for the correct environment (production vs sandbox)
Error details: {}
"#,
error
);
}
if error_lower.contains("network")
|| error_lower.contains("connection")
|| error_lower.contains("timeout")
{
return format!(
r#"Authentication Error: Network Issue
Unable to reach Autodesk authentication servers. Troubleshooting steps:
1. Check your internet connection
2. Verify firewall settings allow access to *.autodesk.com
3. Try again in a few moments
Error details: {}
"#,
error
);
}
if error_lower.contains("expired") || error_lower.contains("refresh") {
return format!(
r#"Authentication Error: Token Expired
Your 3-legged authentication token has expired. To re-authenticate:
1. Use the `auth_login` tool, or
2. Run `raps auth login` in your terminal
Error details: {}
"#,
error
);
}
format!(
r#"Authentication Error
An error occurred during authentication. Please check your setup:
1. Verify APS_CLIENT_ID and APS_CLIENT_SECRET are set correctly
2. Check your network connection
3. Visit https://rapscli.xyz/docs/troubleshooting for more help
Error details: {}
"#,
error
)
}
pub fn get_tool_availability_summary(state: &AuthState) -> String {
let mut summary = String::from(TOOL_AVAILABILITY_HEADER);
if state.two_legged_valid {
summary.push_str(" ✓ OSS (bucket_*, object_*) - available\n");
} else {
summary.push_str(" ✗ OSS (bucket_*, object_*) - requires 2-legged auth\n");
}
if state.two_legged_valid {
summary.push_str(" ✓ Derivative (translate_*) - available\n");
} else {
summary.push_str(" ✗ Derivative (translate_*) - requires 2-legged auth\n");
}
if state.two_legged_valid {
summary.push_str(" ✓ Admin (admin_*) - available\n");
} else {
summary.push_str(" ✗ Admin (admin_*) - requires 2-legged auth\n");
}
if state.three_legged_valid {
summary.push_str(" ✓ Data Management (hub_*, project_*, folder_*, item_*) - available\n");
} else {
summary.push_str(
" ✗ Data Management (hub_*, project_*, folder_*, item_*) - requires 3-legged auth\n",
);
}
if state.three_legged_valid {
summary.push_str(" ✓ ACC (issue_*, rfi_*, acc_*) - available\n");
} else {
summary.push_str(" ✗ ACC (issue_*, rfi_*, acc_*) - requires 3-legged auth\n");
}
summary
}