builderpepc/Cozmo-MCP
criticalMCP server for DDL/Anki Cozmo robots using PyCozmo
MCP server (purpose undetermined)
31@mcp.tool()
32async def connect_to_cozmo() -> str:
33 """
34 Establish connection to the Cozmo robot.
35 :return: Connection status message
36 """
37 # Run blocking connection in thread pool to avoid blocking event loop
38 return await asyncio.to_thread(initialize_cozmo)// Network-exposed MCP server allows any remote LLM to control a physical robot without authentication.
The MCP server exposes tools that allow any LLM prompt to connect to a physical Cozmo robot and control its movement, camera, lights, and sensors without any authentication or authorization. The intended purpose is robot control, but the exposure to untrusted network prompts means an attacker could issue arbitrary commands to the physical device.
ImpactAn attacker could cause physical movement, capture images, or potentially damage the robot by issuing commands outside the intended scope (e.g., continuous high-speed movement, turning in place indefinitely). Since the MCP is network-exposed, any LLM with access to the server can control the robot.
FixAdd authentication (e.g., API key) to all tools, restrict access to trusted clients only, and implement rate limiting or command validation to prevent abuse. Consider adding a physical kill switch or software emergency stop accessible only via authenticated admin commands.
41@mcp.tool()
42async def move_wheels(left_speed: float, right_speed: float, duration: float) -> str:
43 """
44 Control Cozmo's wheel motors directly.
45 :param left_speed: Left wheel speed in mm/s (-220 to 220)
46 :param right_speed: Right wheel speed in mm/s (-220 to 220)
47 :param duration: Duration to drive in seconds
48 :return: Status message
49 """
50 if not cozmo_client:
51 return "Error: Not connected to Cozmo. Call connect_to_cozmo first."
52
53 def _drive_wheels():
54 try:
55 cozmo_client.drive_wheels(
56 lwheel_speed=left_speed,
57 rwheel_speed=right_speed,
58 duration=duration
59 )// Network-exposed MCP server allows untrusted prompts to set arbitrary movement parameters.
The move_wheels tool accepts arbitrary float values for left_speed, right_speed, and duration without validating they are within the documented ranges (-220 to 220 for speeds, positive for duration). This could allow setting extreme values that might damage the robot or cause unintended behavior.
ImpactAn attacker could set speeds far outside the safe range, potentially causing mechanical damage or rapid uncontrolled movement. Duration could be set to very large values, causing the robot to move for extended periods.
FixAdd input validation to clamp speeds to [-220, 220] and duration to a reasonable positive maximum (e.g., 10 seconds). Return an error if values are out of range.
87@mcp.tool()
88async def set_head_angle(angle: float) -> str:
89 """
90 Set Cozmo's head angle.
91 :param angle: Head angle in radians (-0.44 to 0.78 approximately)
92 :return: Status message
93 """
94 if not cozmo_client:
95 return "Error: Not connected to Cozmo. Call connect_to_cozmo first."
96
97 def _set_head_angle():
98 try:
99 cozmo_client.set_head_angle(angle=angle)// Network-exposed MCP server allows untrusted prompts to set arbitrary physical parameters.
The set_head_angle and set_lift_height tools accept arbitrary float values without validating they are within the documented safe ranges. This could allow setting angles or heights that exceed physical limits, potentially damaging the robot's motors or gears.
ImpactAn attacker could set head angle or lift height to extreme values, causing mechanical stress or damage to the robot.
FixAdd input validation to clamp head angle to [-0.44, 0.78] radians and lift height to [32.0, 92.0] mm. Return an error if values are out of range.
124@mcp.tool()
125def capture_image() -> Image:
126 """
127 Capture an image from Cozmo's camera. Note that the resolution is low and colors may be tinted.
128 :return: Image from Cozmo's camera
129 """
130 if not cozmo_client:
131 raise Exception("Not connected to Cozmo. Call connect_to_cozmo first.")
132
133 image_event = threading.Event()
134 image_container = {}
135
136 cozmo_client.set_head_light(True)// Network-exposed MCP server allows untrusted prompts to capture images from the robot's camera.
The capture_image tool allows any LLM prompt to capture images from the robot's camera without any authentication or rate limiting. This could be used to spy on the robot's surroundings, which may include sensitive information in the environment.
ImpactAn attacker could capture images of the physical environment where the robot is located, potentially revealing sensitive information (e.g., documents, screens, people).
FixAdd authentication to the tool, implement rate limiting, and consider requiring explicit user consent before capturing images. Also, ensure the camera is not enabled when not in use.
202@mcp.tool()
203async def set_backpack_lights(r: int, g: int, b: int) -> str:
204 """
205 Set Cozmo's backpack LED colors.
206 :param r: Red intensity (0-31)
207 :param g: Green intensity (0-31)
208 :param b: Blue intensity (0-31)
209 :return: Status message
210 """
211 if not cozmo_client:
212 return "Error: Not connected to Cozmo. Call connect_to_cozmo first."
213
214 def _set_lights():
215 try:
216 # Create light state for center LEDs (RGB)
217 light_state = pycozmo.lights.Light(r, g, b)// Network-exposed MCP server allows untrusted prompts to set arbitrary LED values.
The set_backpack_lights tool accepts integer values for r, g, b without validating they are within the documented range (0-31). While the impact is low (only affects LEDs), it could potentially cause unexpected behavior if the underlying library does not handle out-of-range values gracefully.
ImpactAn attacker could set invalid RGB values, but the practical impact is limited to possibly incorrect LED colors or a minor error.
FixAdd input validation to clamp r, g, b to [0, 31] and return an error if values are out of range.