A native ROS 2 MCP server for AI-assisted robotics
Server has 21 well-named tools with consistent verb_noun patterns (detect_, list_, send_, get_, navigate_, subscribe_, publish_). All tools have descriptions (avg ~120 chars, within baseline 34-392). Input schemas are present and typed for all tools. However, descriptions lack LLM-optimized guidance on WHEN to use each tool vs. alternatives, and several parameter descriptions are generic. Output schemas are not documented. Error handling is minimal, no recovery guidance or actionable error messages visible in code. Safety config exists but not exposed to LLM. Risk annotations (READ_ONLY, WRITE, DESTRUCTIVE) are declared but not integrated into tool definitions as toolAnnotations.
Call a ROS 2 service with request data. Example: call_service('/rosapi/topics', 'rosapi/srv/Topics', {})
Cancel the current navigation task.
Clear navigation costmaps ('global', 'local', or 'all').
Detect the installed ROS 2 distribution and version.
Navigate through a sequence of waypoints. Example: follow_waypoints('[[0,0],[2,0],[2,2]]')
Get the Goal, Result, and Feedback structure of a specific ROS 2 action.
Subscribe to a ROS 2 image topic and return the image. By default returns base64-encoded JPEG. Optionally saves to disk. Example: get_camera_image('/camera/image_raw')
Output schemas not documented. Tools return data but LLM cannot predict field structure, forcing trial-and-error parsing and wasting tokens.
Descriptions lack WHEN-to-use guidance. E.g., 'List all active ROS 2 nodes' does not explain when to call this vs. get_node_info, or what the LLM should do with the result.
No error recovery guidance. Tools declare risk levels (DESTRUCTIVE, WRITE) but provide no actionable error messages or recovery paths if a call fails.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | <=2025-11-25 | v2 |
Get detailed info about a specific ROS 2 node — publishers, subscribers, services, clients.
Get parameter values from a ROS 2 node. Example: get_parameters('/amcl', ['robot_model_type'])
Get the request and response structure of a specific ROS 2 service.
Get the message structure of a specific ROS 2 topic.
List all available ROS 2 action servers.
List all active ROS 2 nodes with their namespaces.
List all parameters of a specific ROS 2 node. Example: list_parameters('/teleop_keyboard')
List all active ROS 2 services with their types.
List all active ROS 2 topics with their message types.
Navigate robot to a specific pose in the map frame. Example: navigate_to_pose(2.0, 3.0, 1.57)
Publish a message to a ROS 2 topic. Example: publish_to_topic('/cmd_vel', 'geometry_msgs/msg/Twist', {'linear': {'x': 0.5}})
Send a goal to a ROS 2 action server. Example: send_action_goal('/navigate_to_pose', 'nav2_msgs/action/NavigateToPose', {'pose': {...}})
Spin the robot in place by a specified angle in radians.
Subscribe to a ROS 2 topic and get one message. Example: subscribe_to_topic('/scan', 'sensor_msgs/msg/LaserScan')
Risk annotations (READ_ONLY, WRITE, DESTRUCTIVE) declared in metadata but not integrated into tool definitions as readOnlyHint/destructiveHint/idempotentHint per MCP spec.
Parameter descriptions are generic. E.g., 'Timeout in seconds' does not explain what happens on timeout, whether retry is safe, or what the default behavior is.