Add hermes_mcp, the bridge between Hermes and the ROS graph
The MCP server is now a ROS node and the only way in or out, per the owner's decision that ROS never leaves the robot. It serves MCP on the USB address only with a bearer token, keeps the stable tool name look() (which waits for the next camera frame, so it is never stale, and passes the camera's JPEG through), and registers turn_head/head_position only when a head is fitted, which today it is not. While an authenticated client is connected it republishes the agent heartbeat on /hermes/state, so the face wakes on connect and sleeps about 40 s after the client leaves; look() also makes the face squint. The token is generated on the Pi into /etc/robot-mcp.env (root:hermes, 640) and never printed. Verified end to end from talos with a real MCP client over the USB link: tools listed, a 157 KB JPEG back in 0.08 s, a wrong token refused, the Wi-Fi path dropped by the firewall. Host config snippets now point at 10.55.0.2. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFN8nRRCiDiMN7ChBpHJhs
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
#!/bin/bash
|
||||
# One unit runs the whole robot (face, camera, vision, audio) via the hermes_bringup launch file, so
|
||||
# One unit runs the whole robot (face, camera, vision, audio, MCP bridge) via the hermes_bringup launch file, so
|
||||
# the face is up whenever the robot is powered, and everything is ROS. Each node is its own process
|
||||
# and is respawned by the launch file, so one crash cannot take the others down.
|
||||
# Replaces the earlier standalone robot-face.service. Run as root from this directory. Re-runnable.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
# The MCP bridge's bearer token: created once, readable only by root and the service user, and never
|
||||
# printed (read it yourself with `sudo cat /etc/robot-mcp.env` when configuring the host).
|
||||
if [ ! -s /etc/robot-mcp.env ]; then
|
||||
(umask 077; printf 'ROBOT_MCP_TOKEN=%s\n' "$(openssl rand -hex 32)" > /etc/robot-mcp.env)
|
||||
fi
|
||||
chown root:hermes /etc/robot-mcp.env
|
||||
chmod 640 /etc/robot-mcp.env
|
||||
install -m 644 robot-cpu-performance.service robot.service /etc/systemd/system/
|
||||
systemctl disable --now robot-face.service 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/robot-face.service
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Robot (hermes_bringup): face, camera, face detection, audio levels
|
||||
Description=Robot (hermes_bringup): face, camera, face detection, audio levels, MCP bridge
|
||||
# Nothing here needs the user session: audio_state retries until the user's PipeWire is up.
|
||||
After=local-fs.target robot-cpu-performance.service robot-firewall.service
|
||||
|
||||
@@ -9,6 +9,8 @@ User=hermes
|
||||
# be writable: systemd's default, /, is not.
|
||||
RuntimeDirectory=robot
|
||||
WorkingDirectory=/run/robot
|
||||
# hermes_mcp reads its bearer token from here (root:hermes, mode 640); it is never in a parameter
|
||||
EnvironmentFile=-/etc/robot-mcp.env
|
||||
# audio_state reaches the user's PipeWire through this
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/1000
|
||||
ExecStart=/bin/bash -c 'source /home/hermes/robot-env.sh && exec ros2 launch hermes_bringup robot.launch.py'
|
||||
|
||||
Reference in New Issue
Block a user