Running in Simulation Mode
Relevant source files
The following files were used as context for generating this wiki page:The reachy-mini-mcp project allows AI systems to control a Pollen Robotics' Reachy Mini robot. A key feature is the ability to run the entire system in a simulated environment without requiring physical hardware. This is accomplished using the MuJoCo physics engine, which provides a virtual representation of the robot.
Running in simulation mode is ideal for development, testing, and demonstration purposes. It allows developers to interact with all the robot's functionalities—such as movement, emotion expression, and vision—through the same MCP server and tools used for the real robot. The architecture is designed to be transparent, with the MCP server communicating with a daemon process that abstracts away the difference between the physical robot and the simulator.
Sources: README.md:3-6, README.md:83-84, src/server.py:3-15
Architecture
The system architecture in simulation mode follows a clear, layered path from the AI system to the virtual robot. The MCP server acts as the central hub, translating high-level tool calls into commands for the Reachy Mini SDK, which then communicates with a daemon process controlling the MuJoCo simulator.
Sources: README.md:46-48
This diagram illustrates the data flow from an AI's tool call to the simulator's response.
Sources: README.md:46-48, src/server.py:183-199
Setup and Execution
To run in simulation mode, you must first install the necessary dependencies and then launch the simulator daemon and the MCP server in the correct order.
Sources: README.md:37-44
Prerequisites
The project requires Python 3.10+ and several key packages. The reachy-mini SDK with the mujoco extra is essential for simulation.
| Requirement | Installation | Purpose |
|---|---|---|
| Python | 3.10+ | Core language |
| Poetry | pip install poetry | Dependency management |
| Project Dependencies | poetry install | Installs fastmcp, reachy-mini[mujoco], etc. |
| MuJoCo | (See SDK docs) | Physics simulator for the virtual robot |
The poetry install command reads the pyproject.toml file to install all required libraries.
Sources: README.md:38-39, README.md:82-84, pyproject.toml:10-13
Execution Flow
The simulation environment requires two main processes to be running: the simulator daemon and the MCP server.
This sequence diagram shows the steps a user must take to start the system.
1. Start the Simulator Daemon
The daemon is the bridge between the SDK and the simulator. It must be started with the --sim flag.
# On macOS, mjpython is required for visualization
mjpython -m reachy_mini.daemon.app.main --sim --scene minimal
This command launches the Reachy Mini application daemon, instructing it to connect to a MuJoCo simulation instance instead of physical hardware. The daemon exposes an API, by default at http://localhost:8321/api.
Sources: README.md:42-43, src/server.py:870-872
2. Run the MCP Server
With the simulator running, the MCP server can be started. It will connect to the daemon on the first tool call.
poetry run python src/server.py
This command executes the main server script, which initializes the FastMCP instance and exposes the robot control tools to compatible AI systems.
Sources: README.md:44, src/server.py:978-984
Simulation-Specific Configuration
Media Backend
When running in simulation, the ReachyMini instance within the MCP server must be configured correctly to avoid trying to access physical hardware like cameras or microphones that don't exist. This is handled by the REACHY_MEDIA_BACKEND environment variable.
| Backend Value | Description | Use Case |
|---|---|---|
default_no_video | Audio only. | Default for simulation. Allows speak() and listen() but not snap(). |
no_media | Headless. No audio or camera. | Useful for CI/CD or environments without audio/visual dependencies. |
default | Full media (audio + camera). | Requires real hardware. |
The get_robot() function in src/server.py reads this variable to initialize the ReachyMini object appropriately. If not set, it defaults to default_no_video.
# src/server.py:183-185
def get_robot():
# ...
backend = os.environ.get("REACHY_MEDIA_BACKEND", "default_no_video")
_robot_instance = ReachyMini(media_backend=backend)
# ...
Sources: src/server.py:181-189
Connection Management
The connection to the robot (or simulator) is managed lazily. The ReachyMini object is not instantiated until the first tool call that requires it. This is handled by the get_robot() function.
This diagram shows the lazy initialization process.
Sources: src/server.py:173-189
Upon server shutdown, the cleanup_robot function is called to properly close the connection to the robot/daemon.
# src/server.py:981-983
def main():
import atexit
atexit.register(cleanup_robot)
mcp.run()
Sources: src/server.py:192-200, src/server.py:981-983