MCP server + manager CLI for the Reachy Mini robot. Provides tools to control the robot's head, antennas, camera, and more through a repository-based dynamic tool system.
The Reachy Mini MCP server exposes only a single tool, 'operate_robot', which is a meta-dispatcher that accepts arbitrary tool_name strings and parameters. This violates fundamental tool design principles. The tool has a generic name that does not follow verb_noun conventions. The description exists but is vague ('Meta-tool that dispatches to individual robot operations by name') and does not clearly explain WHEN to use it, WHAT operations are supported, or what the expected return structure is. The input schema is present but severely underspecified: 'tool_name' is a free-form string with no enum constraint, 'parameters' is an object with no shape documentation, and 'commands' is an array with no item schema. No output schema is documented. The tool is designed to hide actual robot operations behind a string dispatcher, forcing LLMs to reason about opaque tool names and parameter structures without any discovery mechanism or validation. This pattern (single meta-tool dispatcher) is actively harmful to agent reasoning and violates the single-responsibility principle.
Meta-tool that dispatches to individual robot operations by name. Supports both single commands and command sequences.
Single meta-dispatcher tool violates single-responsibility principle. 'operate_robot' accepts arbitrary tool_name strings instead of exposing concrete, named tools. LLMs cannot infer intent from the tool name and must guess what 'tool_name' strings are valid. This forces the LLM into trial-and-error behavior and breaks tool discovery.
'operate_robot' tool name does not follow verb_noun convention. It is generic ('operate') and does not clearly signal a specific action. A name like 'operate_robot' or 'dispatch_command' gives the LLM no clarity on what happens when invoked.
'tool_name' parameter is an unconstrained string with no enum, no description of valid values, and no validation. The code contains logic to load tool definitions from a repository (tools_repository/*.json), but these concrete tool definitions are NOT exposed as individual MCP tools, they are hidden behind the dispatcher. LLMs cannot discover what tool_name values are valid without trial-and-error.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 37 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 42 | - | v1 |
'parameters' input field is an untyped object with no schema, no description of expected structure, and no per-field constraints. Different robot operations likely require different parameters, but the tool provides no guidance on what object shape to pass for each operation.
No output schema documented. The tool description does not explain what fields are returned, their types, or what the successful response looks like. LLMs cannot plan downstream operations or extract required data from the response.
Tool description is under 50 characters and lacks essential context. It does not explain WHEN to use the tool, what prerequisites are needed, whether it modifies state (risk: WRITE suggests it does), or what happens on error. When to use it? What does it return?
Tool is marked as WRITE risk, indicating it modifies state, but the description does NOT explicitly state that operations are irreversible. Per pattern:command-tool, tools that create/update/delete/send MUST declare their side effects in the description so agents understand retry semantics and consequences.
No error handling guidance in the tool definition. Tool code is partially visible in server.py but error recovery paths are not documented. LLMs cannot know what to do if a robot operation fails (retry? ask user? fatal?). Per pattern:recovery-guide, errors must tell the LLM what to do next.
Actual robot tool definitions live in tools_repository/*.json (referenced in server.py code: 'load_tool_definition(definition_file)'), but these are NOT registered as individual MCP tools. The server loads them dynamically but only exposes the 'operate_robot' dispatcher. This breaks tool discovery and forces composition inside a single opaque tool.