FastMCP 3.4 MCP server for the Nori Robotics A3 bimanual home robot (nori-sdk WebRTC teleop, LeRobot-format recording, fleet virtual-twin/actuator guidance)
Six tools with detailed descriptions and operation-based dispatch. Naming is unconventional (nori_* prefix + operation param rather than verb_noun), which deviates from the 90% baseline of action-verb-first naming. Schemas are present but parameter descriptions are sparse, many params lack type info or usage context. Error handling is basic (success/message fields) but lacks recovery guidance. Output schemas are not documented. Tool composition is reasonable (session lifecycle isolated, control/recording/navigation separate), but the operation-dispatch pattern obscures individual tool intent from LLM perspective.
NORI_CONTROL — drive joints/gripper and manage the e-stop/reset safety latch. Requires an open session (nori_session(operation='connect')). Every op here maps 1:1 onto a nori_sdk.RemoteTeleop method — this tool does not reinterpret or clamp targets beyond what the SDK/robot firmware already does (calibration clamping + stall detection + thermal cutoff live in the robot's own protection stack, not here). Operations (motion — require `wait_ready` state): jog, set_jog, clear_jog, action, pose. Operations (safety — always available once connected): estop, estop_confirmed, reset_latch, reset_arm. Operations (policy/leader streaming — new in nori-sdk 1.1.0, 2026-09-01): policy_stream, policy_stream_status, set_leader_action.
NORI_INFO — Nori A3 hero specs, SDK links, hardware lineage, HN community reaction, fleet map. Single read-only entry point for 'what is this robot and where does it come from' — kept separate from nori_session/nori_control/nori_recording so an agent can answer these questions without ever opening a live robot session (real or mock). Operations: info, specs, sdk_links, predecessor, community, actuator_upgrade, fleet_peers, skills_marketplace.
NORI_NAVIGATION — named waypoint navigation (Nav2 goals under the hood). Requires an open session. Waypoints are saved against the robot's ACTIVE map — `remember_waypoint` captures the robot's current localized pose under a name; `navigate_to_waypoint` starts one Nav2 goal to a previously saved destination. This is a fresh SDK 1.1.0 capability (2026-09-01) verified against the real installed package. Operations: remember_waypoint, delete_waypoint, list_waypoints, navigate_to_waypoint, goto_pose, cancel_navigation, await_navigation, status.
Naming violates verb_noun convention. All six tools use nori_<domain> + operation param dispatch instead of action-verb-first (e.g., get_robot_info, start_navigation, jog_arm). This obscures intent from LLM perspective and forces the model to reason about operation strings rather than tool selection.
Parameter descriptions are inconsistent and sparse. Many params (e.g., 'payload', 'targets', 'extra') lack detail on expected structure, valid values, or constraints. 'payload' and 'targets' are generic object types with no schema guidance. Violates pattern:tool-description baseline of 100% param annotation.
Output schemas are not documented. Tool descriptions state what they return (e.g., 'success/message fields') but do not specify the full response structure, field types, or nested objects. LLMs cannot plan downstream calls without knowing response shape.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 48 | <=2025-11-25 | v2 |
NORI_PERCEPTION — opt-in LiDAR/IMU streams and the vision-stack world-state snapshot. Requires an open session. These feeds are opt-in and off by default — `configure_sensor_streams` must enable them before `lidar_scan`/`imu_sample`/`perceive` return real data; until then (or against the mock, which never publishes sensor frames) they correctly return None. This is a fresh SDK 1.1.0 capability verified against the real installed package. Operations: lidar_scan, imu_sample, perceive, configure_sensor_streams, status.
NORI_RECORDING — control episode/session recording state, video snapshot/bitrate. Requires an open session (nori_session(operation='connect')). `operation` for the record-verb group maps 1:1 onto nori_sdk's own RecordVerb literal — not a fleet-invented 'start/stop a named task' abstraction, because the SDK already distinguishes a *session* (the whole capture run) from an *episode* (one demonstration within it). Operations (record verbs): session_start, episode_start, episode_stop, episode_discard, session_end, session_discard, start, stop, discard, discard_last, status. Operations (video): snapshot, frames, set_bitrate, set_paused.
NORI_SESSION — open/close/inspect the live Nori A3 control session, and manage the multi-bot profile registry (Virtual Twin plus any number of named physical A3s, e.g. one per real owner/site). Every motion, safety, and recording operation needs an open session first. Isolating lifecycle here keeps nori_control/nori_recording free of connection bookkeeping and makes the mock-vs-real distinction visible in exactly one place. Operations: connect, disconnect, status, wait_ready, list_profiles, add_profile, switch_profile, remove_profile.
Error handling lacks recovery guidance. Error responses return {success: false, message, error_type} but do not suggest next steps (e.g., 'Call nori_session(operation=connect) first' when session is not open). Violates pattern:recovery-guide.
Credentials exposed as parameters. nori_session(operation='add_profile') accepts supabase_url, supabase_anon_key, user_email, user_password as parameters. These should be injected server-side via environment or vault, not exposed in tool params where they enter logs and traces.