@@ -2073,6 +2073,45 @@ def get_actions() -> dict:
20732073 dict: Contains list of all active actions,
20742074 or a message string if no actions are found.
20752075 """
2076+ # Check if required service is available
2077+ required_services = ["/rosapi/action_servers" ]
2078+
2079+ with ws_manager :
2080+ # Get available services to check compatibility
2081+ services_message = {
2082+ "op" : "call_service" ,
2083+ "service" : "/rosapi/services" ,
2084+ "type" : "rosapi/Services" ,
2085+ "args" : {},
2086+ "id" : "check_services_for_get_actions" ,
2087+ }
2088+
2089+ services_response = ws_manager .request (services_message )
2090+ if not services_response or not isinstance (services_response , dict ):
2091+ return {
2092+ "warning" : "Cannot check service availability" ,
2093+ "compatibility" : {
2094+ "issue" : "Cannot determine available services" ,
2095+ "required_services" : required_services ,
2096+ "suggestion" : "Ensure rosbridge is running and rosapi is available" ,
2097+ },
2098+ }
2099+
2100+ available_services = services_response .get ("values" , {}).get ("services" , [])
2101+ missing_services = [svc for svc in required_services if svc not in available_services ]
2102+
2103+ if missing_services :
2104+ return {
2105+ "warning" : "Action listing not supported by this rosbridge/rosapi version" ,
2106+ "compatibility" : {
2107+ "issue" : "Required action services are not available" ,
2108+ "missing_services" : missing_services ,
2109+ "required_services" : required_services ,
2110+ "available_services" : [s for s in available_services if "action" in s ],
2111+ "suggestion" : "This rosbridge version doesn't support action listing services" ,
2112+ },
2113+ }
2114+
20762115 # rosbridge service call to get action list
20772116 message = {
20782117 "op" : "call_service" ,
@@ -2127,6 +2166,47 @@ def get_action_type(action: str) -> dict:
21272166 if not action or not action .strip ():
21282167 return {"error" : "Action name cannot be empty" }
21292168
2169+ # Check if required service is available
2170+ required_services = ["/rosapi/interfaces" ]
2171+
2172+ with ws_manager :
2173+ # Get available services to check compatibility
2174+ services_message = {
2175+ "op" : "call_service" ,
2176+ "service" : "/rosapi/services" ,
2177+ "type" : "rosapi/Services" ,
2178+ "args" : {},
2179+ "id" : "check_services_for_get_action_type" ,
2180+ }
2181+
2182+ services_response = ws_manager .request (services_message )
2183+ if not services_response or not isinstance (services_response , dict ):
2184+ return {
2185+ "warning" : "Cannot check service availability" ,
2186+ "action" : action ,
2187+ "compatibility" : {
2188+ "issue" : "Cannot determine available services" ,
2189+ "required_services" : required_services ,
2190+ "suggestion" : "Ensure rosbridge is running and rosapi is available" ,
2191+ },
2192+ }
2193+
2194+ available_services = services_response .get ("values" , {}).get ("services" , [])
2195+ missing_services = [svc for svc in required_services if svc not in available_services ]
2196+
2197+ if missing_services :
2198+ return {
2199+ "warning" : "Action type resolution not supported by this rosbridge/rosapi version" ,
2200+ "action" : action ,
2201+ "compatibility" : {
2202+ "issue" : "Required services are not available" ,
2203+ "missing_services" : missing_services ,
2204+ "required_services" : required_services ,
2205+ "available_services" : [s for s in available_services if "interface" in s ],
2206+ "suggestion" : "This rosbridge version doesn't support interface listing services" ,
2207+ },
2208+ }
2209+
21302210 # Since there's no direct action_type service, we'll derive it from known patterns
21312211 # or use a mapping approach for common actions
21322212
@@ -2173,7 +2253,16 @@ def get_action_type(action: str) -> dict:
21732253 "suggestion" : "This action might not be available or use a different naming pattern" ,
21742254 }
21752255
2176- return {"error" : f"Failed to get type for action { action } " }
2256+ return {
2257+ "error" : f"Failed to get type for action { action } " ,
2258+ "action" : action ,
2259+ "compatibility" : {
2260+ "issue" : "Failed to retrieve interfaces from rosapi" ,
2261+ "required_services" : ["/rosapi/interfaces" ],
2262+ "suggestion" : "Ensure rosbridge is running and rosapi is available" ,
2263+ "note" : "Action type resolution requires /rosapi/interfaces service" ,
2264+ },
2265+ }
21772266
21782267
21792268@mcp .tool (
@@ -2197,6 +2286,57 @@ def get_action_details(action_type: str) -> dict:
21972286 if not action_type or not action_type .strip ():
21982287 return {"error" : "Action type cannot be empty" }
21992288
2289+ # Check if required action detail services are available
2290+ required_services = [
2291+ "/rosapi/action_goal_details" ,
2292+ "/rosapi/action_result_details" ,
2293+ "/rosapi/action_feedback_details" ,
2294+ ]
2295+
2296+ with ws_manager :
2297+ # Get available services to check compatibility
2298+ services_message = {
2299+ "op" : "call_service" ,
2300+ "service" : "/rosapi/services" ,
2301+ "type" : "rosapi/Services" ,
2302+ "args" : {},
2303+ "id" : "check_services_for_action_details" ,
2304+ }
2305+
2306+ services_response = ws_manager .request (services_message )
2307+ if not services_response or not isinstance (services_response , dict ):
2308+ return {
2309+ "error" : "Failed to check service availability" ,
2310+ "action_type" : action_type ,
2311+ "compatibility" : {
2312+ "issue" : "Cannot determine available services" ,
2313+ "required_services" : required_services ,
2314+ "suggestion" : "Ensure rosbridge is running and rosapi is available" ,
2315+ },
2316+ }
2317+
2318+ available_services = services_response .get ("values" , {}).get ("services" , [])
2319+ missing_services = [svc for svc in required_services if svc not in available_services ]
2320+
2321+ if missing_services :
2322+ return {
2323+ "error" : f"Action details for { action_type } not found" ,
2324+ "action_type" : action_type ,
2325+ "compatibility" : {
2326+ "issue" : "Required action detail services are not available" ,
2327+ "missing_services" : missing_services ,
2328+ "required_services" : required_services ,
2329+ "available_services" : [s for s in available_services if "action" in s ],
2330+ "suggestions" : [
2331+ "Use get_actions() to list available actions" ,
2332+ "Use get_action_type() to get action type from action name" ,
2333+ "Action details may not be exposed by this rosbridge/rosapi version" ,
2334+ "Consider subscribing to action topics directly for live message inspection" ,
2335+ ],
2336+ "note" : "Action detail services (/rosapi/action_*_details) are not part of standard rosapi" ,
2337+ },
2338+ }
2339+
22002340 result = {"action_type" : action_type , "goal" : {}, "result" : {}, "feedback" : {}}
22012341
22022342 # Get goal, result, and feedback details in a single WebSocket context
@@ -2475,6 +2615,50 @@ def inspect_all_actions() -> dict:
24752615 dict: Contains detailed information about all actions,
24762616 including action names, types, and server information.
24772617 """
2618+ # Check if required action services are available
2619+ required_services = ["/rosapi/action_servers" ]
2620+
2621+ with ws_manager :
2622+ # Get available services to check compatibility
2623+ services_message = {
2624+ "op" : "call_service" ,
2625+ "service" : "/rosapi/services" ,
2626+ "type" : "rosapi/Services" ,
2627+ "args" : {},
2628+ "id" : "check_services_for_inspect_actions" ,
2629+ }
2630+
2631+ services_response = ws_manager .request (services_message )
2632+ if not services_response or not isinstance (services_response , dict ):
2633+ return {
2634+ "error" : "Failed to check service availability" ,
2635+ "compatibility" : {
2636+ "issue" : "Cannot determine available services" ,
2637+ "required_services" : required_services ,
2638+ "suggestion" : "Ensure rosbridge is running and rosapi is available" ,
2639+ },
2640+ }
2641+
2642+ available_services = services_response .get ("values" , {}).get ("services" , [])
2643+ missing_services = [svc for svc in required_services if svc not in available_services ]
2644+
2645+ if missing_services :
2646+ return {
2647+ "error" : "Action inspection not supported by this rosbridge/rosapi version" ,
2648+ "compatibility" : {
2649+ "issue" : "Required action services are not available" ,
2650+ "missing_services" : missing_services ,
2651+ "required_services" : required_services ,
2652+ "available_services" : [s for s in available_services if "action" in s ],
2653+ "suggestions" : [
2654+ "This rosbridge version doesn't support action inspection services" ,
2655+ "Use get_actions() to list available actions" ,
2656+ "Consider upgrading rosbridge or using a different implementation" ,
2657+ ],
2658+ "note" : "Action inspection requires /rosapi/action_servers service" ,
2659+ },
2660+ }
2661+
24782662 # First get all actions
24792663 actions_message = {
24802664 "op" : "call_service" ,
0 commit comments