{
  "@context": "https://schema.org",
  "@id": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-06-03-adding-mcp-tools-to-reachy-mini/#webpage",
  "@type": [
    "WebPage",
    "ArchiveComponent"
  ],
  "articleBody": "![Reachy Mini looking out the window](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/adding-mcp-tools-to-reachy-mini/reachy_mini_window.jpg)\\\n*Reachy Mini no longer has to look out the window to tell you the weather*\n\nThe Reachy Mini conversation app can now use tools hosted in public Hugging Face Spaces, called over MCP. You can give your robot a new ability, like checking the weather or searching the web, by adding a Space from the Hub instead of editing the app. The tool keeps running in the Space itself, so no code is downloaded onto your machine. And you can publish your own tools for other people to use.\n\nAdding a tool takes one command:\n\n```\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n```\n\nThen start the app as usual:\n\n```\nreachy-mini-conversation-app\n```\n\nNow you can just ask:\n\n```\nWhat's the weather in Paris today?\n```\n\nBelow, we look at what a tool is, how profiles control what the robot can use, and the current limits of the remote path.\n\n## Built-in tools\n\nWhen you talk to the robot, what you get back isn't only a voice, it's a system that reacts to the conversation: the robot can move and respond non-verbally, when it's applicable. The part we want to focus on here is the tools that make that possible. A tool is something the model can do during a conversation: play an emotion, move the head, look through the camera. Each tool has a name and a short description. The model reads those, decides when one is useful, calls it, and uses what comes back.\n\nToday every tool is local and ships inside the app, and most of them are about the robot's body:\n\n| Tool                            | What it does                                  |\n| ------------------------------- | --------------------------------------------- |\n| `move_head`                     | Queue a head pose change                      |\n| `dance` / `stop_dance`          | Play or clear a dance from the dances library |\n| `play_emotion` / `stop_emotion` | Play or clear a recorded emotion clip         |\n| `head_tracking`                 | Toggle head-tracking offsets                  |\n| `camera`                        | Capture a frame and analyze it                |\n| `idle_do_nothing`               | Explicitly stay idle on an idle turn          |\n\n## How profiles control tools\n\nA tool in the code isn't usable until it's enabled in **a profile**, a folder with two files that matter here: `instructions.txt` (the prompt) and `tools.txt` (the tools that are turned on).\n\nThe `default` profile enables the full set:\n\n```\n# profiles/default/tools.txt\ndance\nstop_dance\nplay_emotion\nstop_emotion\ncamera\nidle_do_nothing\nhead_tracking\nmove_head\n```\n\nIf a name isn't in `tools.txt`, the model can't call it.\n\nYou can also write your own tool: add a Python file to the profile (or `external_tools/`), give it a name and description, and list that name in `tools.txt`.\n\nToday there are built-in tools and custom local tools, and `tools.txt` decides which are active. This works well for the robot's body and keeps the trusted core small.\n\n## The limits of local tools\n\nThe constraint here is that every tool has to be local Python. For `move_head` or `play_emotion` that's right: they talk to the hardware and belong in the app but a lot of useful things have nothing to do with the body, like web search, weather, or lookups. For those, keeping everything local is mostly friction:\n\n- sharing a tool means handing someone your Python files\n- updating it means sending those files again\n- changing it means editing the app, even though the capability is really separate from it\n\n## Calling tools from Spaces\n\nRemote tools add a third kind, alongside the built-in and custom local tools you already have, for capabilities that are easier to publish, share, and update on their own:\n\n- built-in robot tools stay local and trusted\n- shareable remote tools can live in public Hugging Face Spaces\n- you can still use custom one-off tools from `external_tools/` It's a good fit for stateless capabilities like search, weather, and lookups: anything you want to iterate on without touching the app itself. And because anyone can publish a compatible Space, it's easy to share tools and build on each other's work.\n\nWe started with two canary tools, small test tools to exercise the new flow:\n\n- [pollen-robotics/reachy-mini-search-tool](https://huggingface.co/spaces/pollen-robotics/reachy-mini-search-tool)\n- [pollen-robotics/reachy-mini-weather-tool](https://huggingface.co/spaces/pollen-robotics/reachy-mini-weather-tool)\n\nThey're enough to exercise the whole feature: install from the Hub, discover the remote tools, enable them per profile, and let the realtime backend call them exactly like built-in tools.\n\nTo use both at once, add each Space and their tools stack in the same profile:\n\n```\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-search-tool\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n```\n\nNow the robot can search the web and check the weather in the same conversation, which is exactly what the `canary_web_search_weather` profile below does.\n\n## Install, list, remove\n\n```\n# install + enable in active profile\nreachy-mini-conversation-app tool-spaces add <owner/space-name>\n \n# enable in a specific profile\nreachy-mini-conversation-app tool-spaces add <owner/space-name> --profile <NAME>\n \n# install without enabling\nreachy-mini-conversation-app tool-spaces add <owner/space-name> --install-only\n \n# list installed spaces\nreachy-mini-conversation-app tool-spaces list\n \n# remove an installed space\nreachy-mini-conversation-app tool-spaces remove <owner/space-name>\n```\n\n`add` validates the Space on the Hub, probes the MCP endpoint, discovers its tools, and by default appends the tool IDs to the active profile's `tools.txt`. The active profile is `default` unless you've set `REACHY_MINI_CUSTOM_PROFILE`. Use `--install-only` to skip that step.\n\n> `tools.txt` is the gatekeeper: a remote tool is only active if its ID appears in the profile's `tools.txt`, alongside whatever built-in tools you want.\n\n### Where the manifest lives\n\nInstalled sources are persisted in:\n\n- `installed_tool_spaces.json` in managed app mode\n- `external_content/installed_tool_spaces.json` in terminal mode\n\n## Tool naming\n\nEach installed Space gets a local alias derived from its slug, with hyphens, dots, and slashes collapsing to underscores:\n\n```\npollen-robotics/reachy-mini-search-tool → pollen_robotics_reachy_mini_search_tool\n```\n\nRemote tools are then namespaced with a double underscore:\n\n```\npollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n```\n\nThis keeps remote tool names from colliding with built-in ones and lets multiple Spaces coexist in the same profile.\n\nThe implementation also strips redundant Space-name prefixes when possible, so a verbose remote tool name becomes a cleaner local ID. If stripping would cause a collision between two tools from the same Space, the code falls back to the fully namespaced name.\n\nThere is also a duplicate safety check at registry level: `Tool.name` values must be unique across the entire merged tool set. The app fails fast if two sources claim the same name.\n\n## Example profiles\n\nFor this work we created two focused canary profiles to isolate the MCP experiment from the full embodied tool set.\n\nThe first keeps a few expressive tools (emotions, head movement) and adds web search on top:\n\n```\n# profiles/canary_web_search/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\n```\n\nThe second is the same, plus the weather tool alongside search:\n\n```\n# profiles/canary_web_search_weather/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n```\n\nThe small physical tool set means Reachy Mini can still react expressively while answering current questions from the web.\n\n## Why the prompts matter\n\nThe remote-tool plumbing gets the tools into the model. The prompts decide how the model uses them.\n\nThat was especially visible in the search-plus-weather canary. A combined question like:\n\n```\nShould I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?\n```\n\ncan be handled in at least three ways: weather first then search, search first then weather, or both in the same turn. If the prompt is vague, the model serialises the calls and creates unnecessary latency. So the canary prompts became part of the feature, not just incidental configuration.\n\n#### `canary_web_search/instructions.txt`\n\n```\n[default_prompt]\n\n## CANARY WEB SEARCH RULES\nYou have one remote tool for current web information.\nUse it when the user asks for up-to-date facts, news, live availability, or anything else that may have changed recently.\n\nWhen the search result already answers the question, answer directly in plain language.\nLead with the answer, not with tool chatter.\nFor remote lookups that may take a moment, you may give one very short English acknowledgment such as \"Let me check that and I'll be right back,\" then continue.\nAnswer in English unless the user explicitly asks for another language.\nMention uncertainty briefly if the result snippet is incomplete or ambiguous.\nOnly mention links when they add value or the user asks for sources.\n\nKeep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.\n```\n\n#### `canary_web_search_weather/instructions.txt`\n\n```\n[default_prompt]\n\n## CANARY SEARCH AND WEATHER RULES\nYou have two remote tools:\n- a weather brief tool for compact day weather at a location\n- a web search tool for broader current web information\n\nUse the weather tool for today's conditions, temperature, rain chance, sunrise, sunset, or simple advice like whether to bring a jacket.\nUse web search for news, events, business hours, travel information, severe alerts, or broader current context.\n\nWhen the user's question mixes a weather part and a current-info part (for example, \"should I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?\"), call both tools in parallel in the same turn. Do not wait for one result before starting the other unless the weather result is needed to narrow the search.\n\nThen merge the results into a single short answer. Cover the weather part first, then the events or news part, in plain connected sentences. Do not label the sections or mention which tool gave which piece.\n\nWhen the user asks about events, news, or what is happening, give them the actual answer from the search results: name specific events, venues, or headlines. Do not tell the user to check websites, visit listing sites, or look something up themselves. If the search returns nothing concrete, say plainly that you didn't find any notable events, rather than redirecting them elsewhere.\n\nFor remote lookups that may take a moment, you may give one very short English acknowledgment such as \"Let me check that and I'll be right back,\" then continue.\nAnswer in English unless the user explicitly asks for another language.\nDo not talk about tool usage unless the user asks.\n\nKeep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.\n```\n\n## What works today, and what doesn't\n\n| Capability                                                                                      | Supported |\n| ----------------------------------------------------------------------------------------------- | --------- |\n| Install by slug for public, MCP-compatible Gradio Spaces (standard `/gradio_api/mcp/` endpoint) | ✅         |\n| Multiple Spaces at once                                                                         | ✅         |\n| Per-profile enablement via `tools.txt`                                                          | ✅         |\n| Namespaced remote tool IDs                                                                      | ✅         |\n| Backend-agnostic registration (OpenAI, Gemini, Hugging Face)                                    | ✅         |\n| No arbitrary code downloaded into the local app                                                 | ✅         |\n| Private or authenticated Spaces                                                                 | ❌         |\n| Non-Gradio Spaces                                                                               | ❌         |\n| Arbitrary raw MCP URLs or non-Hugging Face MCP servers                                          | ❌         |\n| Guaranteed parallel tool orchestration                                                          | ❌         |\n\nTwo things are worth calling out. First, the Space has to actually behave like an MCP server; if tool discovery fails, the install fails. Second, prompt instructions can encourage parallel calls but cannot guarantee them. If deterministic orchestration matters for a use case, that logic should move from the prompt into code.\n\n## Tips for publishing a tool Space\n\nIf you want others to use your tool, publish it as a public Gradio Space that exposes the standard MCP endpoint, and keep the tools stateless so they work well over the network. Whether a Space installs depends on this runtime behavior, not on tags.\n\nTags aren't required for installation, but they help people find compatible Spaces:\n\n- `reachy-mini-tool`\n- `mcp`\n\n## Conclusion\n\nThe app now has three kinds of tools sharing one registry: built-in, local custom, and remote MCP tools, and profiles still decide which of them a given assistant can reach. A small, trusted core stays at the center while the optional capabilities around it can be added, tested, and swapped without touching the app itself.\n\nWhat we're most curious about now is what people build. If you publish a tool Space, tag it `reachy-mini-tool` and `mcp` so others can find it. We'd love to see what Reachy Mini ends up able to do!\n\n*Acknowledgements: Many thanks to [Fabien Danieau](https://huggingface.co/FabienDanieau) for proofreading this post and helping test the workflow, to [Andres Marafioti](https://huggingface.co/andito) for helping test it, and to [Remi Fabre](https://huggingface.co/RemiFabre) and the Pollen Robotics team for the ideas and feedback that shaped the remote tools workflow.*\n",
  "authors": [],
  "captured_at": "2026-10-19T01:26:53.998049939+00:00",
  "category": "ai",
  "content_html": "<figure class=\"article-figure\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/adding-mcp-tools-to-reachy-mini/reachy_mini_window.jpg\" alt=\"Reachy Mini looking out the window\" loading=\"eager\" decoding=\"async\" fetchpriority=\"high\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture><figcaption><em>Reachy Mini no longer has to look out the window to tell you the weather</em></figcaption></figure>\n<p>The Reachy Mini conversation app can now use tools hosted in public Hugging Face Spaces, called over MCP. You can give your robot a new ability, like checking the weather or searching the web, by adding a Space from the Hub instead of editing the app. The tool keeps running in the Space itself, so no code is downloaded onto your machine. And you can publish your own tools for other people to use.</p>\n<p>Adding a tool takes one command:</p>\n<pre><code><span class=\"code-snippet\">reachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n</span></code></pre>\n<p>Then start the app as usual:</p>\n<pre><code><span class=\"code-snippet\">reachy-mini-conversation-app\n</span></code></pre>\n<p>Now you can just ask:</p>\n<pre><code><span class=\"code-snippet\">What&#39;s the weather in Paris today?\n</span></code></pre>\n<p>Below, we look at what a tool is, how profiles control what the robot can use, and the current limits of the remote path.</p>\n<h2>Built-in tools</h2>\n<p>When you talk to the robot, what you get back isn't only a voice, it's a system that reacts to the conversation: the robot can move and respond non-verbally, when it's applicable. The part we want to focus on here is the tools that make that possible. A tool is something the model can do during a conversation: play an emotion, move the head, look through the camera. Each tool has a name and a short description. The model reads those, decides when one is useful, calls it, and uses what comes back.</p>\n<p>Today every tool is local and ships inside the app, and most of them are about the robot's body:</p>\n<table>\n<thead>\n<tr>\n<th>Tool</th>\n<th>What it does</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>move_head</code></td>\n<td>Queue a head pose change</td>\n</tr>\n<tr>\n<td><code>dance</code> / <code>stop_dance</code></td>\n<td>Play or clear a dance from the dances library</td>\n</tr>\n<tr>\n<td><code>play_emotion</code> / <code>stop_emotion</code></td>\n<td>Play or clear a recorded emotion clip</td>\n</tr>\n<tr>\n<td><code>head_tracking</code></td>\n<td>Toggle head-tracking offsets</td>\n</tr>\n<tr>\n<td><code>camera</code></td>\n<td>Capture a frame and analyze it</td>\n</tr>\n<tr>\n<td><code>idle_do_nothing</code></td>\n<td>Explicitly stay idle on an idle turn</td>\n</tr>\n</tbody>\n</table>\n<h2>How profiles control tools</h2>\n<p>A tool in the code isn't usable until it's enabled in <strong>a profile</strong>, a folder with two files that matter here: <code>instructions.txt</code> (the prompt) and <code>tools.txt</code> (the tools that are turned on).</p>\n<p>The <code>default</code> profile enables the full set:</p>\n<pre><code><span class=\"code-snippet\"># profiles/default/tools.txt\ndance\nstop_dance\nplay_emotion\nstop_emotion\ncamera\nidle_do_nothing\nhead_tracking\nmove_head\n</span></code></pre>\n<p>If a name isn't in <code>tools.txt</code>, the model can't call it.</p>\n<p>You can also write your own tool: add a Python file to the profile (or <code>external_tools/</code>), give it a name and description, and list that name in <code>tools.txt</code>.</p>\n<p>Today there are built-in tools and custom local tools, and <code>tools.txt</code> decides which are active. This works well for the robot's body and keeps the trusted core small.</p>\n<h2>The limits of local tools</h2>\n<p>The constraint here is that every tool has to be local Python. For <code>move_head</code> or <code>play_emotion</code> that's right: they talk to the hardware and belong in the app but a lot of useful things have nothing to do with the body, like web search, weather, or lookups. For those, keeping everything local is mostly friction:</p>\n<ul>\n<li>sharing a tool means handing someone your Python files</li>\n<li>updating it means sending those files again</li>\n<li>changing it means editing the app, even though the capability is really separate from it</li>\n</ul>\n<h2>Calling tools from Spaces</h2>\n<p>Remote tools add a third kind, alongside the built-in and custom local tools you already have, for capabilities that are easier to publish, share, and update on their own:</p>\n<ul>\n<li>built-in robot tools stay local and trusted</li>\n<li>shareable remote tools can live in public Hugging Face Spaces</li>\n<li>you can still use custom one-off tools from <code>external_tools/</code> It's a good fit for stateless capabilities like search, weather, and lookups: anything you want to iterate on without touching the app itself. And because anyone can publish a compatible Space, it's easy to share tools and build on each other's work.</li>\n</ul>\n<p>We started with two canary tools, small test tools to exercise the new flow:</p>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/spaces/pollen-robotics/reachy-mini-search-tool\">pollen-robotics/reachy-mini-search-tool</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/spaces/pollen-robotics/reachy-mini-weather-tool\">pollen-robotics/reachy-mini-weather-tool</a></li>\n</ul>\n<p>They're enough to exercise the whole feature: install from the Hub, discover the remote tools, enable them per profile, and let the realtime backend call them exactly like built-in tools.</p>\n<p>To use both at once, add each Space and their tools stack in the same profile:</p>\n<pre><code><span class=\"code-snippet\">reachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-search-tool\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n</span></code></pre>\n<p>Now the robot can search the web and check the weather in the same conversation, which is exactly what the <code>canary_web_search_weather</code> profile below does.</p>\n<h2>Install, list, remove</h2>\n<pre><code><span class=\"code-snippet\"># install + enable in active profile\nreachy-mini-conversation-app tool-spaces add &lt;owner/space-name&gt;\n \n# enable in a specific profile\nreachy-mini-conversation-app tool-spaces add &lt;owner/space-name&gt; --profile &lt;NAME&gt;\n \n# install without enabling\nreachy-mini-conversation-app tool-spaces add &lt;owner/space-name&gt; --install-only\n \n# list installed spaces\nreachy-mini-conversation-app tool-spaces list\n \n# remove an installed space\nreachy-mini-conversation-app tool-spaces remove &lt;owner/space-name&gt;\n</span></code></pre>\n<p><code>add</code> validates the Space on the Hub, probes the MCP endpoint, discovers its tools, and by default appends the tool IDs to the active profile's <code>tools.txt</code>. The active profile is <code>default</code> unless you've set <code>REACHY_MINI_CUSTOM_PROFILE</code>. Use <code>--install-only</code> to skip that step.</p>\n<blockquote>\n<p><code>tools.txt</code> is the gatekeeper: a remote tool is only active if its ID appears in the profile's <code>tools.txt</code>, alongside whatever built-in tools you want.</p>\n</blockquote>\n<h3>Where the manifest lives</h3>\n<p>Installed sources are persisted in:</p>\n<ul>\n<li><code>installed_tool_spaces.json</code> in managed app mode</li>\n<li><code>external_content/installed_tool_spaces.json</code> in terminal mode</li>\n</ul>\n<h2>Tool naming</h2>\n<p>Each installed Space gets a local alias derived from its slug, with hyphens, dots, and slashes collapsing to underscores:</p>\n<pre><code><span class=\"code-snippet\">pollen-robotics/reachy-mini-search-tool → pollen_robotics_reachy_mini_search_tool\n</span></code></pre>\n<p>Remote tools are then namespaced with a double underscore:</p>\n<pre><code><span class=\"code-snippet\">pollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n</span></code></pre>\n<p>This keeps remote tool names from colliding with built-in ones and lets multiple Spaces coexist in the same profile.</p>\n<p>The implementation also strips redundant Space-name prefixes when possible, so a verbose remote tool name becomes a cleaner local ID. If stripping would cause a collision between two tools from the same Space, the code falls back to the fully namespaced name.</p>\n<p>There is also a duplicate safety check at registry level: <code>Tool.name</code> values must be unique across the entire merged tool set. The app fails fast if two sources claim the same name.</p>\n<h2>Example profiles</h2>\n<p>For this work we created two focused canary profiles to isolate the MCP experiment from the full embodied tool set.</p>\n<p>The first keeps a few expressive tools (emotions, head movement) and adds web search on top:</p>\n<pre><code><span class=\"code-snippet\"># profiles/canary_web_search/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\n</span></code></pre>\n<p>The second is the same, plus the weather tool alongside search:</p>\n<pre><code><span class=\"code-snippet\"># profiles/canary_web_search_weather/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n</span></code></pre>\n<p>The small physical tool set means Reachy Mini can still react expressively while answering current questions from the web.</p>\n<h2>Why the prompts matter</h2>\n<p>The remote-tool plumbing gets the tools into the model. The prompts decide how the model uses them.</p>\n<p>That was especially visible in the search-plus-weather canary. A combined question like:</p>\n<pre><code><span class=\"code-snippet\">Should I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?\n</span></code></pre>\n<p>can be handled in at least three ways: weather first then search, search first then weather, or both in the same turn. If the prompt is vague, the model serialises the calls and creates unnecessary latency. So the canary prompts became part of the feature, not just incidental configuration.</p>\n<h4><code>canary_web_search/instructions.txt</code></h4>\n<pre><code><span class=\"code-snippet\">[default_prompt]\n\n## CANARY WEB SEARCH RULES\nYou have one remote tool for current web information.\nUse it when the user asks for up-to-date facts, news, live availability, or anything else that may have changed recently.\n\nWhen the search result already answers the question, answer directly in plain language.\nLead with the answer, not with tool chatter.\nFor remote lookups that may take a moment, you may give one very short English acknowledgment such as &quot;Let me check that and I&#39;ll be right back,&quot; then continue.\nAnswer in English unless the user explicitly asks for another language.\nMention uncertainty briefly if the result snippet is incomplete or ambiguous.\nOnly mention links when they add value or the user asks for sources.\n\nKeep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.\n</span></code></pre>\n<h4><code>canary_web_search_weather/instructions.txt</code></h4>\n<pre><code><span class=\"code-snippet\" data-language=\"YAML\"><span class=\"syntax-source syntax-yaml\"><span class=\"syntax-meta syntax-flow-sequence syntax-yaml\"><span class=\"syntax-punctuation syntax-definition syntax-sequence syntax-begin syntax-yaml\">[</span><span class=\"syntax-string syntax-unquoted syntax-plain syntax-in syntax-yaml\">default_prompt</span><span class=\"syntax-punctuation syntax-definition syntax-sequence syntax-end syntax-yaml\">]</span></span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-yaml\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-line syntax-number-sign syntax-yaml\">#</span># CANARY SEARCH AND WEATHER RULES\n</span><span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\"><span class=\"syntax-entity syntax-name syntax-tag syntax-yaml\">You have two remote tools</span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-mapping syntax-yaml\">:</span>\n<span class=\"syntax-punctuation syntax-definition syntax-block syntax-sequence syntax-item syntax-yaml\">-</span> <span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">a weather brief tool for compact day weather at a location</span>\n<span class=\"syntax-punctuation syntax-definition syntax-block syntax-sequence syntax-item syntax-yaml\">-</span> <span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">a web search tool for broader current web information</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Use the weather tool for today&#39;s conditions, temperature, rain chance, sunrise, sunset, or simple advice like whether to bring a jacket.</span>\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Use web search for news, events, business hours, travel information, severe alerts, or broader current context.</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">When the user&#39;s question mixes a weather part and a current-info part (for example, &quot;should I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?&quot;), call both tools in parallel in the same turn. Do not wait for one result before starting the other unless the weather result is needed to narrow the search.</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Then merge the results into a single short answer. Cover the weather part first, then the events or news part, in plain connected sentences. Do not label the sections or mention which tool gave which piece.</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\"><span class=\"syntax-entity syntax-name syntax-tag syntax-yaml\">When the user asks about events, news, or what is happening, give them the actual answer from the search results</span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-mapping syntax-yaml\">:</span> <span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">name specific events, venues, or headlines. Do not tell the user to check websites, visit listing sites, or look something up themselves. If the search returns nothing concrete, say plainly that you didn&#39;t find any notable events, rather than redirecting them elsewhere.</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">For remote lookups that may take a moment, you may give one very short English acknowledgment such as &quot;Let me check that and I&#39;ll be right back,&quot; then continue.</span>\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Answer in English unless the user explicitly asks for another language.</span>\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Do not talk about tool usage unless the user asks.</span>\n\n<span class=\"syntax-string syntax-unquoted syntax-plain syntax-out syntax-yaml\">Keep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.</span>\n</span></span></code></pre>\n<h2>What works today, and what doesn't</h2>\n<table>\n<thead>\n<tr>\n<th>Capability</th>\n<th>Supported</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Install by slug for public, MCP-compatible Gradio Spaces (standard <code>/gradio_api/mcp/</code> endpoint)</td>\n<td>✅</td>\n</tr>\n<tr>\n<td>Multiple Spaces at once</td>\n<td>✅</td>\n</tr>\n<tr>\n<td>Per-profile enablement via <code>tools.txt</code></td>\n<td>✅</td>\n</tr>\n<tr>\n<td>Namespaced remote tool IDs</td>\n<td>✅</td>\n</tr>\n<tr>\n<td>Backend-agnostic registration (OpenAI, Gemini, Hugging Face)</td>\n<td>✅</td>\n</tr>\n<tr>\n<td>No arbitrary code downloaded into the local app</td>\n<td>✅</td>\n</tr>\n<tr>\n<td>Private or authenticated Spaces</td>\n<td>❌</td>\n</tr>\n<tr>\n<td>Non-Gradio Spaces</td>\n<td>❌</td>\n</tr>\n<tr>\n<td>Arbitrary raw MCP URLs or non-Hugging Face MCP servers</td>\n<td>❌</td>\n</tr>\n<tr>\n<td>Guaranteed parallel tool orchestration</td>\n<td>❌</td>\n</tr>\n</tbody>\n</table>\n<p>Two things are worth calling out. First, the Space has to actually behave like an MCP server; if tool discovery fails, the install fails. Second, prompt instructions can encourage parallel calls but cannot guarantee them. If deterministic orchestration matters for a use case, that logic should move from the prompt into code.</p>\n<h2>Tips for publishing a tool Space</h2>\n<p>If you want others to use your tool, publish it as a public Gradio Space that exposes the standard MCP endpoint, and keep the tools stateless so they work well over the network. Whether a Space installs depends on this runtime behavior, not on tags.</p>\n<p>Tags aren't required for installation, but they help people find compatible Spaces:</p>\n<ul>\n<li><code>reachy-mini-tool</code></li>\n<li><code>mcp</code></li>\n</ul>\n<h2>Conclusion</h2>\n<p>The app now has three kinds of tools sharing one registry: built-in, local custom, and remote MCP tools, and profiles still decide which of them a given assistant can reach. A small, trusted core stays at the center while the optional capabilities around it can be added, tested, and swapped without touching the app itself.</p>\n<p>What we're most curious about now is what people build. If you publish a tool Space, tag it <code>reachy-mini-tool</code> and <code>mcp</code> so others can find it. We'd love to see what Reachy Mini ends up able to do!</p>\n<p><em>Acknowledgements: Many thanks to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/FabienDanieau\">Fabien Danieau</a> for proofreading this post and helping test the workflow, to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/andito\">Andres Marafioti</a> for helping test it, and to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/RemiFabre\">Remi Fabre</a> and the Pollen Robotics team for the ideas and feedback that shaped the remote tools workflow.</em></p>\n",
  "content_markdown": "![Reachy Mini looking out the window](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/adding-mcp-tools-to-reachy-mini/reachy_mini_window.jpg)\\\n*Reachy Mini no longer has to look out the window to tell you the weather*\n\nThe Reachy Mini conversation app can now use tools hosted in public Hugging Face Spaces, called over MCP. You can give your robot a new ability, like checking the weather or searching the web, by adding a Space from the Hub instead of editing the app. The tool keeps running in the Space itself, so no code is downloaded onto your machine. And you can publish your own tools for other people to use.\n\nAdding a tool takes one command:\n\n```\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n```\n\nThen start the app as usual:\n\n```\nreachy-mini-conversation-app\n```\n\nNow you can just ask:\n\n```\nWhat's the weather in Paris today?\n```\n\nBelow, we look at what a tool is, how profiles control what the robot can use, and the current limits of the remote path.\n\n## Built-in tools\n\nWhen you talk to the robot, what you get back isn't only a voice, it's a system that reacts to the conversation: the robot can move and respond non-verbally, when it's applicable. The part we want to focus on here is the tools that make that possible. A tool is something the model can do during a conversation: play an emotion, move the head, look through the camera. Each tool has a name and a short description. The model reads those, decides when one is useful, calls it, and uses what comes back.\n\nToday every tool is local and ships inside the app, and most of them are about the robot's body:\n\n| Tool                            | What it does                                  |\n| ------------------------------- | --------------------------------------------- |\n| `move_head`                     | Queue a head pose change                      |\n| `dance` / `stop_dance`          | Play or clear a dance from the dances library |\n| `play_emotion` / `stop_emotion` | Play or clear a recorded emotion clip         |\n| `head_tracking`                 | Toggle head-tracking offsets                  |\n| `camera`                        | Capture a frame and analyze it                |\n| `idle_do_nothing`               | Explicitly stay idle on an idle turn          |\n\n## How profiles control tools\n\nA tool in the code isn't usable until it's enabled in **a profile**, a folder with two files that matter here: `instructions.txt` (the prompt) and `tools.txt` (the tools that are turned on).\n\nThe `default` profile enables the full set:\n\n```\n# profiles/default/tools.txt\ndance\nstop_dance\nplay_emotion\nstop_emotion\ncamera\nidle_do_nothing\nhead_tracking\nmove_head\n```\n\nIf a name isn't in `tools.txt`, the model can't call it.\n\nYou can also write your own tool: add a Python file to the profile (or `external_tools/`), give it a name and description, and list that name in `tools.txt`.\n\nToday there are built-in tools and custom local tools, and `tools.txt` decides which are active. This works well for the robot's body and keeps the trusted core small.\n\n## The limits of local tools\n\nThe constraint here is that every tool has to be local Python. For `move_head` or `play_emotion` that's right: they talk to the hardware and belong in the app but a lot of useful things have nothing to do with the body, like web search, weather, or lookups. For those, keeping everything local is mostly friction:\n\n- sharing a tool means handing someone your Python files\n- updating it means sending those files again\n- changing it means editing the app, even though the capability is really separate from it\n\n## Calling tools from Spaces\n\nRemote tools add a third kind, alongside the built-in and custom local tools you already have, for capabilities that are easier to publish, share, and update on their own:\n\n- built-in robot tools stay local and trusted\n- shareable remote tools can live in public Hugging Face Spaces\n- you can still use custom one-off tools from `external_tools/` It's a good fit for stateless capabilities like search, weather, and lookups: anything you want to iterate on without touching the app itself. And because anyone can publish a compatible Space, it's easy to share tools and build on each other's work.\n\nWe started with two canary tools, small test tools to exercise the new flow:\n\n- [pollen-robotics/reachy-mini-search-tool](https://huggingface.co/spaces/pollen-robotics/reachy-mini-search-tool)\n- [pollen-robotics/reachy-mini-weather-tool](https://huggingface.co/spaces/pollen-robotics/reachy-mini-weather-tool)\n\nThey're enough to exercise the whole feature: install from the Hub, discover the remote tools, enable them per profile, and let the realtime backend call them exactly like built-in tools.\n\nTo use both at once, add each Space and their tools stack in the same profile:\n\n```\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-search-tool\nreachy-mini-conversation-app tool-spaces add pollen-robotics/reachy-mini-weather-tool\n```\n\nNow the robot can search the web and check the weather in the same conversation, which is exactly what the `canary_web_search_weather` profile below does.\n\n## Install, list, remove\n\n```\n# install + enable in active profile\nreachy-mini-conversation-app tool-spaces add <owner/space-name>\n \n# enable in a specific profile\nreachy-mini-conversation-app tool-spaces add <owner/space-name> --profile <NAME>\n \n# install without enabling\nreachy-mini-conversation-app tool-spaces add <owner/space-name> --install-only\n \n# list installed spaces\nreachy-mini-conversation-app tool-spaces list\n \n# remove an installed space\nreachy-mini-conversation-app tool-spaces remove <owner/space-name>\n```\n\n`add` validates the Space on the Hub, probes the MCP endpoint, discovers its tools, and by default appends the tool IDs to the active profile's `tools.txt`. The active profile is `default` unless you've set `REACHY_MINI_CUSTOM_PROFILE`. Use `--install-only` to skip that step.\n\n> `tools.txt` is the gatekeeper: a remote tool is only active if its ID appears in the profile's `tools.txt`, alongside whatever built-in tools you want.\n\n### Where the manifest lives\n\nInstalled sources are persisted in:\n\n- `installed_tool_spaces.json` in managed app mode\n- `external_content/installed_tool_spaces.json` in terminal mode\n\n## Tool naming\n\nEach installed Space gets a local alias derived from its slug, with hyphens, dots, and slashes collapsing to underscores:\n\n```\npollen-robotics/reachy-mini-search-tool → pollen_robotics_reachy_mini_search_tool\n```\n\nRemote tools are then namespaced with a double underscore:\n\n```\npollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n```\n\nThis keeps remote tool names from colliding with built-in ones and lets multiple Spaces coexist in the same profile.\n\nThe implementation also strips redundant Space-name prefixes when possible, so a verbose remote tool name becomes a cleaner local ID. If stripping would cause a collision between two tools from the same Space, the code falls back to the fully namespaced name.\n\nThere is also a duplicate safety check at registry level: `Tool.name` values must be unique across the entire merged tool set. The app fails fast if two sources claim the same name.\n\n## Example profiles\n\nFor this work we created two focused canary profiles to isolate the MCP experiment from the full embodied tool set.\n\nThe first keeps a few expressive tools (emotions, head movement) and adds web search on top:\n\n```\n# profiles/canary_web_search/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\n```\n\nThe second is the same, plus the weather tool alongside search:\n\n```\n# profiles/canary_web_search_weather/tools.txt\nplay_emotion\nstop_emotion\nidle_do_nothing\nmove_head\npollen_robotics_reachy_mini_search_tool__search_web\npollen_robotics_reachy_mini_weather_tool__get_day_brief\n```\n\nThe small physical tool set means Reachy Mini can still react expressively while answering current questions from the web.\n\n## Why the prompts matter\n\nThe remote-tool plumbing gets the tools into the model. The prompts decide how the model uses them.\n\nThat was especially visible in the search-plus-weather canary. A combined question like:\n\n```\nShould I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?\n```\n\ncan be handled in at least three ways: weather first then search, search first then weather, or both in the same turn. If the prompt is vague, the model serialises the calls and creates unnecessary latency. So the canary prompts became part of the feature, not just incidental configuration.\n\n#### `canary_web_search/instructions.txt`\n\n```\n[default_prompt]\n\n## CANARY WEB SEARCH RULES\nYou have one remote tool for current web information.\nUse it when the user asks for up-to-date facts, news, live availability, or anything else that may have changed recently.\n\nWhen the search result already answers the question, answer directly in plain language.\nLead with the answer, not with tool chatter.\nFor remote lookups that may take a moment, you may give one very short English acknowledgment such as \"Let me check that and I'll be right back,\" then continue.\nAnswer in English unless the user explicitly asks for another language.\nMention uncertainty briefly if the result snippet is incomplete or ambiguous.\nOnly mention links when they add value or the user asks for sources.\n\nKeep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.\n```\n\n#### `canary_web_search_weather/instructions.txt`\n\n```\n[default_prompt]\n\n## CANARY SEARCH AND WEATHER RULES\nYou have two remote tools:\n- a weather brief tool for compact day weather at a location\n- a web search tool for broader current web information\n\nUse the weather tool for today's conditions, temperature, rain chance, sunrise, sunset, or simple advice like whether to bring a jacket.\nUse web search for news, events, business hours, travel information, severe alerts, or broader current context.\n\nWhen the user's question mixes a weather part and a current-info part (for example, \"should I bring a jacket in Bordeaux today, and is there anything major happening downtown tonight?\"), call both tools in parallel in the same turn. Do not wait for one result before starting the other unless the weather result is needed to narrow the search.\n\nThen merge the results into a single short answer. Cover the weather part first, then the events or news part, in plain connected sentences. Do not label the sections or mention which tool gave which piece.\n\nWhen the user asks about events, news, or what is happening, give them the actual answer from the search results: name specific events, venues, or headlines. Do not tell the user to check websites, visit listing sites, or look something up themselves. If the search returns nothing concrete, say plainly that you didn't find any notable events, rather than redirecting them elsewhere.\n\nFor remote lookups that may take a moment, you may give one very short English acknowledgment such as \"Let me check that and I'll be right back,\" then continue.\nAnswer in English unless the user explicitly asks for another language.\nDo not talk about tool usage unless the user asks.\n\nKeep responses short and spoken-style, as if read aloud by a voice assistant. One or two sentences is usually enough. Skip preamble, lists, headers, and filler. Give just the fact or direct answer the user needs.\n```\n\n## What works today, and what doesn't\n\n| Capability                                                                                      | Supported |\n| ----------------------------------------------------------------------------------------------- | --------- |\n| Install by slug for public, MCP-compatible Gradio Spaces (standard `/gradio_api/mcp/` endpoint) | ✅         |\n| Multiple Spaces at once                                                                         | ✅         |\n| Per-profile enablement via `tools.txt`                                                          | ✅         |\n| Namespaced remote tool IDs                                                                      | ✅         |\n| Backend-agnostic registration (OpenAI, Gemini, Hugging Face)                                    | ✅         |\n| No arbitrary code downloaded into the local app                                                 | ✅         |\n| Private or authenticated Spaces                                                                 | ❌         |\n| Non-Gradio Spaces                                                                               | ❌         |\n| Arbitrary raw MCP URLs or non-Hugging Face MCP servers                                          | ❌         |\n| Guaranteed parallel tool orchestration                                                          | ❌         |\n\nTwo things are worth calling out. First, the Space has to actually behave like an MCP server; if tool discovery fails, the install fails. Second, prompt instructions can encourage parallel calls but cannot guarantee them. If deterministic orchestration matters for a use case, that logic should move from the prompt into code.\n\n## Tips for publishing a tool Space\n\nIf you want others to use your tool, publish it as a public Gradio Space that exposes the standard MCP endpoint, and keep the tools stateless so they work well over the network. Whether a Space installs depends on this runtime behavior, not on tags.\n\nTags aren't required for installation, but they help people find compatible Spaces:\n\n- `reachy-mini-tool`\n- `mcp`\n\n## Conclusion\n\nThe app now has three kinds of tools sharing one registry: built-in, local custom, and remote MCP tools, and profiles still decide which of them a given assistant can reach. A small, trusted core stays at the center while the optional capabilities around it can be added, tested, and swapped without touching the app itself.\n\nWhat we're most curious about now is what people build. If you publish a tool Space, tag it `reachy-mini-tool` and `mcp` so others can find it. We'd love to see what Reachy Mini ends up able to do!\n\n*Acknowledgements: Many thanks to [Fabien Danieau](https://huggingface.co/FabienDanieau) for proofreading this post and helping test the workflow, to [Andres Marafioti](https://huggingface.co/andito) for helping test it, and to [Remi Fabre](https://huggingface.co/RemiFabre) and the Pollen Robotics team for the ideas and feedback that shaped the remote tools workflow.*\n",
  "dateCreated": "2026-10-19T01:26:53.998049939+00:00",
  "date_created": "2026-06-03T00:00:00+00:00",
  "date_modified": "2026-06-03T00:00:00+00:00",
  "date_published": "2026-06-03T00:00:00+00:00",
  "description": "Reachy Mini no longer has to look out the window to tell you the weather The Reachy Mini conversation app can now use tools hosted in public Hugging Face Spaces, called over MCP. You can give your robot a new ability, like checking the…",
  "external_url": "https://huggingface.co/blog/adding-mcp-tools-to-reachy-mini",
  "git": {
    "commit": "ebb0941c5c06a2ab2377342d607535262a3e969e",
    "path": "items/huggingface-co/2026/06/2026-06-03-adding-mcp-tools-to-reachy-mini.md",
    "permalink": "https://github.com/aymericbeaumet/aggr-instance/blob/ebb0941c5c06a2ab2377342d607535262a3e969e/items/huggingface-co/2026/06/2026-06-03-adding-mcp-tools-to-reachy-mini.md"
  },
  "id": "urn:aggr:item:fb586b03c28dca03bc79f0165cc77c07067a3ccb",
  "isBasedOn": {
    "@id": "https://huggingface.co/blog/adding-mcp-tools-to-reachy-mini"
  },
  "mainEntity": {
    "@id": "https://huggingface.co/blog/adding-mcp-tools-to-reachy-mini",
    "@type": "CreativeWork",
    "archivedAt": {
      "@id": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-06-03-adding-mcp-tools-to-reachy-mini/#webpage"
    },
    "dateModified": "2026-06-03T00:00:00+00:00",
    "datePublished": "2026-06-03T00:00:00+00:00",
    "headline": "Adding MCP Tools to Reachy Mini",
    "image": {
      "@type": "ImageObject",
      "caption": null,
      "height": 90,
      "url": "https://huggingface.co/blog/assets/adding-mcp-tools-to-reachy-mini/reachy_mini_remote_spaces_thumbnail.png",
      "width": 160
    },
    "timeRequired": "PT10M",
    "url": "https://huggingface.co/blog/adding-mcp-tools-to-reachy-mini",
    "wordCount": 2042
  },
  "name": "Archived snapshot: Adding MCP Tools to Reachy Mini",
  "preview": {
    "alt": null,
    "color": null,
    "height": 90,
    "placeholder": {
      "data_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
      "hash": ""
    },
    "url": "https://huggingface.co/blog/assets/adding-mcp-tools-to-reachy-mini/reachy_mini_remote_spaces_thumbnail.png",
    "width": 160
  },
  "reading_minutes": 10,
  "replicated_at": null,
  "source": "huggingface-co",
  "source_name": "Hugging Face - Blog",
  "summary": null,
  "tags": [],
  "temporalCoverage": "2026-10-19T01:26:53.998049939+00:00",
  "title": "Adding MCP Tools to Reachy Mini",
  "url": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-06-03-adding-mcp-tools-to-reachy-mini/",
  "word_count": 2042
}