MCP server exposing Enabot EBO robots to AI agents with vision-in-the-loop control. Runs inside the Home Assistant add-on, proxying the local data API at 127.0.0.1:8098. Implements a look→decide→move loop where moves are refused without a recent camera snapshot.
Strong tool naming (verb_noun pattern: ebo_list, ebo_state, ebo_move, ebo_stop, ebo_dock, ebo_wake, ebo_look, ebo_night_vision, ebo_laser, ebo_listen, ebo_say). All 11 tools have descriptions (avg ~120 chars, within 10-1024 range). Input schemas present with typed parameters and descriptions. Key strengths: clear action verbs, safety-aware descriptions (ebo_move enforces ebo_look prerequisite), enum constraints (direction, mode, vision). Gaps: output schemas not documented; no pagination/limits for list tools; error handling guidance minimal; no tool annotations (readOnlyHint/destructiveHint); descriptions could be more LLM-optimized (some lack 'when to use' context).
Send the robot back to its charging base (firmware homing; check ebo_state for docked).
Turn the pointer laser on/off.
List the EBO robots and their key state (battery, charging, docked, driving mode, obstacle avoidance, night vision). Call this first to learn the node name for the other tools.
Open or close the robot's microphone. With it on you can hear the room through the robot (the audio is carried inside the camera stream).
SEE what the robot sees: a fresh live snapshot (JPEG). ALWAYS call this right before ebo_move to check the path is clear. If the image is black, call ebo_wake and retry after ~2 s.
Drive a short step. direction ∈ {forward, back, left, right, forward_left, forward_right, back_left, back_right}. speed 1-100 (capped), seconds capped. SAFETY: you MUST have called ebo_look in the last few seconds — this refuses to move otherwise, to avoid driving blind.
Output schemas not documented. LLMs cannot infer what ebo_list, ebo_state, ebo_look return (field names, types, structure). This forces agents to guess at response structure and risks failed downstream chaining.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). ebo_move, ebo_stop, ebo_dock, ebo_wake, ebo_night_vision, ebo_laser, ebo_listen, ebo_say are WRITE operations but lack destructiveHint. ebo_list, ebo_state, ebo_look are READ-ONLY but lack readOnlyHint. Agents cannot distinguish safe from risky tools without explicit hints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 65 | 2026-07-28+ | v2 |
Set day/night vision: mode ∈ {Auto, Day, Night}.
Make the robot speak (text-to-speech through its speaker).
Full live state of one robot. node from ebo_list(); empty = the first robot.
Stop the robot immediately.
Wake the robot and start its camera (before looking/driving). Wait ~2-3 s, then ebo_look.
ebo_move description lacks error guidance. It states 'refuses to move otherwise' if ebo_look not called, but does not explain what error is returned or how the agent should recover. Should say: 'Returns error if ebo_look not called in last N seconds, call ebo_look first, wait 2s, then retry.'
Parameter 'node' in 9 tools accepts empty string to select 'first robot', but no description explains what happens if multiple robots exist and node is empty. Ambiguous behavior invites wrong tool selection when multiple robots are present.
ebo_move speed and seconds parameters lack explicit min/max constraints in descriptions. 'capped at MAX_SPEED, default 45' and 'capped at MAX_SECONDS, default 2.0' reference undefined constants. Should state: 'speed 1 - 100 (default 45)' and 'seconds 0.1 - 10.0 (default 2.0)' with actual bounds.