raps_cli/mcp/
auth_guidance.rs1use raps_kernel::auth::AuthClient;
12use raps_kernel::config::Config;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum AuthRequirement {
17 TwoLegged,
19 ThreeLegged,
21 Either,
23}
24
25#[derive(Debug, Clone)]
27pub struct AuthState {
28 pub has_client_id: bool,
30 pub has_client_secret: bool,
32 pub two_legged_valid: bool,
34 pub three_legged_valid: bool,
36 pub three_legged_expired: bool,
38}
39
40impl AuthState {
41 pub fn has_any_credentials(&self) -> bool {
43 self.has_client_id || self.has_client_secret
44 }
45
46 pub fn has_complete_2leg_credentials(&self) -> bool {
48 self.has_client_id && self.has_client_secret
49 }
50}
51
52pub const SETUP_INSTRUCTIONS: &str = r#"
58To set up authentication for RAPS MCP Server:
59
601. Go to https://aps.autodesk.com/ (Autodesk Platform Services)
612. Sign in or create an Autodesk account
623. Create a new application or select an existing one
634. Copy your Client ID and Client Secret
645. Set environment variables before starting the MCP server:
65
66 For Unix/macOS:
67 export APS_CLIENT_ID="your_client_id"
68 export APS_CLIENT_SECRET="your_client_secret"
69
70 For Windows (PowerShell):
71 $env:APS_CLIENT_ID="your_client_id"
72 $env:APS_CLIENT_SECRET="your_client_secret"
73
74 Or add to your MCP server configuration (claude_desktop_config.json):
75 {
76 "mcpServers": {
77 "raps": {
78 "command": "raps",
79 "args": ["serve"],
80 "env": {
81 "APS_CLIENT_ID": "your_client_id",
82 "APS_CLIENT_SECRET": "your_client_secret"
83 }
84 }
85 }
86 }
87
88For more information: https://rapscli.xyz/docs/auth
89"#;
90
91pub const MISSING_CLIENT_ID: &str = r#"
93Missing: APS_CLIENT_ID environment variable
94
95The Client ID is required for all APS operations. To get your Client ID:
961. Go to https://aps.autodesk.com/
972. Navigate to your application's settings
983. Copy the "Client ID" value
994. Set APS_CLIENT_ID environment variable
100"#;
101
102pub const MISSING_CLIENT_SECRET: &str = r#"
104Missing: APS_CLIENT_SECRET environment variable
105
106The Client Secret is required for authentication. To get your Client Secret:
1071. Go to https://aps.autodesk.com/
1082. Navigate to your application's settings
1093. Copy or regenerate the "Client Secret" value
1104. Set APS_CLIENT_SECRET environment variable
111
112Note: Keep your Client Secret secure and never share it publicly.
113"#;
114
115pub const THREE_LEGGED_PROMPT: &str = r#"
117To access BIM 360/ACC data (hubs, projects, folders, files, issues, RFIs), you need to log in with your Autodesk account.
118
119Use the `auth_login` tool to start the authentication process, or run:
120 raps auth login
121
122This will open a browser window for you to sign in with your Autodesk credentials.
123"#;
124
125pub const TOOL_AVAILABILITY_HEADER: &str = "\nTool Availability:\n";
127
128pub fn get_tool_auth_requirement(tool_name: &str) -> AuthRequirement {
134 match tool_name {
135 "auth_test" | "auth_status" | "auth_login" | "auth_logout" => AuthRequirement::Either,
137
138 "bucket_list"
140 | "bucket_create"
141 | "bucket_get"
142 | "bucket_delete"
143 | "object_list"
144 | "object_delete"
145 | "object_signed_url"
146 | "object_urn"
147 | "object_upload"
148 | "object_upload_batch"
149 | "object_download"
150 | "object_info"
151 | "object_copy"
152 | "object_delete_batch" => AuthRequirement::TwoLegged,
153
154 "translate_start" | "translate_status" => AuthRequirement::TwoLegged,
156
157 "admin_project_list"
159 | "admin_operation_list"
160 | "admin_operation_status"
161 | "admin_operation_resume"
162 | "admin_operation_cancel" => AuthRequirement::TwoLegged,
163
164 "admin_user_add"
166 | "admin_user_remove"
167 | "admin_user_update_role"
168 | "admin_folder_rights" => AuthRequirement::TwoLegged,
169
170 "hub_list" | "project_list" | "folder_list" | "folder_create" | "item_info"
172 | "item_versions" => AuthRequirement::ThreeLegged,
173
174 "project_info" | "project_users_list" | "folder_contents" => AuthRequirement::ThreeLegged,
176
177 "project_create" | "project_user_add" | "project_users_import" => {
179 AuthRequirement::ThreeLegged
180 }
181
182 "item_create" | "item_delete" | "item_rename" => AuthRequirement::ThreeLegged,
184
185 "issue_list"
187 | "issue_get"
188 | "issue_create"
189 | "issue_update"
190 | "rfi_list"
191 | "rfi_get"
192 | "rfi_create"
193 | "rfi_update"
194 | "acc_assets_list"
195 | "asset_create"
196 | "asset_update"
197 | "asset_delete"
198 | "acc_submittals_list"
199 | "submittal_create"
200 | "submittal_update"
201 | "acc_checklists_list"
202 | "checklist_create"
203 | "checklist_update" => AuthRequirement::ThreeLegged,
204
205 _ => AuthRequirement::TwoLegged,
207 }
208}
209
210pub async fn get_auth_state(config: &Config, auth_client: &AuthClient) -> AuthState {
216 let has_client_id = !config.client_id.is_empty();
217 let has_client_secret = !config.client_secret.is_empty();
218
219 let two_legged_valid = if has_client_id && has_client_secret {
221 auth_client.get_token().await.is_ok()
222 } else {
223 false
224 };
225
226 let (three_legged_valid, three_legged_expired) = match auth_client.get_3leg_token().await {
228 Ok(_) => (true, false),
229 Err(e) => {
230 let err_msg = e.to_string().to_lowercase();
231 if err_msg.contains("expired") || err_msg.contains("refresh") {
232 (false, true)
233 } else {
234 (false, false)
235 }
236 }
237 };
238
239 AuthState {
240 has_client_id,
241 has_client_secret,
242 two_legged_valid,
243 three_legged_valid,
244 three_legged_expired,
245 }
246}
247
248pub fn format_error_guidance(error: &str) -> String {
254 let error_lower = error.to_lowercase();
255
256 if error_lower.contains("client_id") || error_lower.contains("aps_client_id") {
257 return format!(
258 "Authentication Error: Missing Client ID\n{}",
259 MISSING_CLIENT_ID
260 );
261 }
262
263 if error_lower.contains("client_secret") || error_lower.contains("aps_client_secret") {
264 return format!(
265 "Authentication Error: Missing Client Secret\n{}",
266 MISSING_CLIENT_SECRET
267 );
268 }
269
270 if error_lower.contains("401") || error_lower.contains("unauthorized") {
271 return format!(
272 r#"Authentication Error: Invalid Credentials
273
274Your credentials were rejected by Autodesk. Troubleshooting steps:
2751. Verify APS_CLIENT_ID is correct (typically 32 characters)
2762. Verify APS_CLIENT_SECRET is correct (typically 64 characters)
2773. Check that your app is active at https://aps.autodesk.com/
2784. Ensure credentials are for the correct environment (production vs sandbox)
279
280Error details: {}
281"#,
282 error
283 );
284 }
285
286 if error_lower.contains("network")
287 || error_lower.contains("connection")
288 || error_lower.contains("timeout")
289 {
290 return format!(
291 r#"Authentication Error: Network Issue
292
293Unable to reach Autodesk authentication servers. Troubleshooting steps:
2941. Check your internet connection
2952. Verify firewall settings allow access to *.autodesk.com
2963. Try again in a few moments
297
298Error details: {}
299"#,
300 error
301 );
302 }
303
304 if error_lower.contains("expired") || error_lower.contains("refresh") {
305 return format!(
306 r#"Authentication Error: Token Expired
307
308Your 3-legged authentication token has expired. To re-authenticate:
3091. Use the `auth_login` tool, or
3102. Run `raps auth login` in your terminal
311
312Error details: {}
313"#,
314 error
315 );
316 }
317
318 format!(
320 r#"Authentication Error
321
322An error occurred during authentication. Please check your setup:
3231. Verify APS_CLIENT_ID and APS_CLIENT_SECRET are set correctly
3242. Check your network connection
3253. Visit https://rapscli.xyz/docs/troubleshooting for more help
326
327Error details: {}
328"#,
329 error
330 )
331}
332
333pub fn get_tool_availability_summary(state: &AuthState) -> String {
339 let mut summary = String::from(TOOL_AVAILABILITY_HEADER);
340
341 if state.two_legged_valid {
343 summary.push_str(" ✓ OSS (bucket_*, object_*) - available\n");
344 } else {
345 summary.push_str(" ✗ OSS (bucket_*, object_*) - requires 2-legged auth\n");
346 }
347
348 if state.two_legged_valid {
350 summary.push_str(" ✓ Derivative (translate_*) - available\n");
351 } else {
352 summary.push_str(" ✗ Derivative (translate_*) - requires 2-legged auth\n");
353 }
354
355 if state.two_legged_valid {
357 summary.push_str(" ✓ Admin (admin_*) - available\n");
358 } else {
359 summary.push_str(" ✗ Admin (admin_*) - requires 2-legged auth\n");
360 }
361
362 if state.three_legged_valid {
364 summary.push_str(" ✓ Data Management (hub_*, project_*, folder_*, item_*) - available\n");
365 } else {
366 summary.push_str(
367 " ✗ Data Management (hub_*, project_*, folder_*, item_*) - requires 3-legged auth\n",
368 );
369 }
370
371 if state.three_legged_valid {
373 summary.push_str(" ✓ ACC (issue_*, rfi_*, acc_*) - available\n");
374 } else {
375 summary.push_str(" ✗ ACC (issue_*, rfi_*, acc_*) - requires 3-legged auth\n");
376 }
377
378 summary
379}