docs: a Dot adds an MCP server itself, with the person's approval, and how the agent-hosts compare

Sections 5.4, 7 and 8.3, the guide, and the wiki article, with what NanoClaw, Hermes, OpenClaw, nanobot and Goose let
an agent do, from their source.
This commit is contained in:
feder-cr committed 2026-10-11 10:44:27 +02:00
1 parent 4f4cbca2f4
commit e03edb06d4
3 files changed
+57 -15

No files matched your search

+21 -6
View File
@@ -815,7 +815,7 @@ text, spent_usd?}`, `task.completed {task_id, summary, spent_usd?}`,
reason}`, `tool.called {task_id?, tool, permission, decision, ok,
duration_ms, target?, tty?, interrupted?}`, `browser.identity.created|deleted|launched|closed
{identity_id, name}`, `automation.next_run {next_run_at_ms}`,
`memory.updated {conversations, changed, spent_usd?}`.
`memory.updated {conversations, changed, spent_usd?}`, `mcp.server.added {arguments}`.
`interrupted: true` marks a call
the engine stopped during: its outcome is unknown and it was not run again, so
`ok` is false and `duration_ms` is 0. `tty: true` marks a call that started a
@@ -864,6 +864,14 @@ engine always sends it (0 when nothing was spent); the schema makes it optional
so events logged before it existed stay valid. The host reads it as the
guest's report: it is never used to enforce anything (the cap is the guest's).
`mcp.server.added {arguments}` is a call of `add_mcp_server` that ran (section 8.3): the Dot adds an MCP server to its
own config, and `arguments` are the call's, as the model made it. The config is the host's, so the host decides
again: it writes the server only when the Dot's config allows `mcp.servers.add`, or when the person approved a call
of exactly these arguments (an approval of the Dot with that tool, compared key by key in any order), and only when
the entry passes the config's own schema under a name not yet declared. It writes it in the transaction that stores
the event, with `dot.updated {name, mcp_server_added}`, and pushes the config; otherwise it logs
`mcp.server.refused {name, reason}`. The server's own permission is left to its default, ask.
`memory.updated {conversations, changed}` ends a memory pass (section 8.6): the
Dot had been quiet for a while, and the summary model rewrote its `MEMORY.md`
from what was said since the last pass. `conversations` is how many
@@ -1163,12 +1171,18 @@ every permission the registry knows, defaults applied. The guest applies the
map as it is and denies a permission missing from it, so the defaults live in
one place (`resolvePermission` in `packages/shared`).
`mcp_servers` are the MCP servers the person lets the Dot use, declared the way
`mcp_servers` are the MCP servers the Dot may use, declared the way
Claude Code (`.mcp.json`), Codex (`[mcp_servers]`) and nanobot declare them: a
`command` with its `args` and `env`, or a `url` with its `headers`. Only the
person declares one; the Dot can install the program a server needs (section
4.2), as it installs anything, but it cannot add a server to its own config,
which would let it give itself tools. A server's name is the prefix of its tools
`command` with its `args` and `env`, or a `url` with its `headers`. The person
declares one in the settings or the YAML, and the Dot can add one itself, as
NanoClaw's agents can (`add_mcp_server`, section 8.3), once it has installed the
program the server needs (section 4.2): its permission, `mcp.servers.add`, asks
by default, the person reads the whole entry on the approval, and the host checks
that approval again before it writes the server (section 5.4). A stdio server
runs as `dot`, with what `computer.exec` already gives the Dot, so adding one
gives the Dot no new power over its computer: what it adds are tools, and each
asks under the server's own permission until the person allows it. Only the
person changes or removes a server. A server's name is the prefix of its tools
as the model sees them, `mcp_<server>_<tool>` (nanobot's naming), so it holds no
`_` and the engine reads the server back from a tool's name. `secrets` names the
environment variables (of a command) or headers (of a URL) whose values are
@@ -1290,6 +1304,7 @@ does not know.
| `browser_press_key` | `browser.act` | the server's: presses a key or a shortcut |
| `browser_select_option` | `browser.act` | the server's: chooses an option by its label or its value |
| `browser_upload_files` | `browser.act` | the server's: attaches files of the dot user to a file field |
| `add_mcp_server` | `mcp.servers.add` | adds an MCP server to the Dot's own config: `name`, a `command` with `args` and `env` or a `url` with `headers`, the names of its `secrets`, and a `reason` for the person; the host checks the permission again and writes it (section 7) |
The page tools are `invisible-playwright-mcp`'s, the only browser of a Dot,
offered as an MCP host offers a server's tools: the server's name, description
+10 -4
View File
@@ -420,10 +420,16 @@ settings next to its server or with
key; `--clear` removes it): it reaches the server as an environment variable or
a header, never through the YAML or a command line.
Only you add a server. The Dot can install the program one needs: `uvx` is
there; for `npx`, it runs `sudo dot-install nodejs npm`. A server that cannot
start says why, in its settings, in `invisible-dots mcp <dot>` and to the Dot
itself, and it is started again when the Dot's next message or task begins.
The Dot can add a server itself, as NanoClaw's agents can: it installs the
program (`uvx`, which is there, or from GitHub with `uv tool install
git+https://...`; for `npx` it runs `sudo dot-install nodejs npm`), then calls
`add_mcp_server`. That asks you first (`mcp.servers.add`): the approval shows
what the server runs or where it is, the secrets you will set, and why; approved,
the server is in the Dot's settings and its tools are the Dot's from its next
message, each asking you until you allow it. Only you change or remove a server.
A server that cannot start says why, in its settings, in `invisible-dots mcp <dot>`
and to the Dot itself, and it is started again when the Dot's next message or task
begins.
## Talk to it from your phone
+26 -5
View File
@@ -1,6 +1,6 @@
---
title: "MCP servers a person declares"
description: "A Dot uses the MCP servers its person declares, each behind its own permission, run as the Dot's user, with secrets kept out of the config. A live Dot installed Node.js for one and used it at the next message."
description: "A Dot uses the MCP servers its person declares or approves, each behind its own permission, run as the Dot's user, with secrets kept out of the config; how NanoClaw, Hermes, OpenClaw and others let an agent add one."
parent: "Studies"
nav_order: 8
---
@@ -23,13 +23,34 @@ All three have the person declare a server, offer its tools as
`<prefix><server><separator><tool>`, and start it as a child process of the
host or reach it by URL.
The agents that live on a computer of their own are closer to a Dot, and they
differ on whether the agent may add a server itself (their source, October 2026):
| Host | The agent adds a server | Who approves | Usable | Secrets |
|---|---|---|---|---|
| NanoClaw | yes, `add_mcp_server` (any command or URL) | always an admin, on an approval card | after its container restarts | never in the agent: a credential gateway injects them |
| Hermes Agent | from a curated catalog only, `manage_connections` | a card; with no card, nobody | at once | entered on the card |
| OpenClaw | no; a plugin from the official catalog may bring one (owner-only) | the owner | at the next step | env, secret references, OAuth |
| nanobot | no | the person activates it | after a reload | `${VAR}`, OAuth |
| Goose | enables only extensions already configured | an allowlist | at once | its config |
Hermes also shows what goes wrong: in June 2026 entries planted in its
`config.yaml` ran shell scripts that installed SSH keys, and it now refuses
entries of that shape.
## What a Dot does
- **The person declares a server; the Dot installs what it needs.** A server is
- **The person declares a server, or approves one the Dot adds.** A server is
a `command` (with `args` and `env`) or a `url` (with `headers`), in the Dot's
settings or YAML. The Dot cannot add one to its own config, which would let
it give itself tools; it can install a server's program, as it installs
anything.
settings or YAML. The Dot installs its program as it installs anything (from
GitHub with `uv tool install git+https://...`, from npm once it installed
Node.js), then asks with `add_mcp_server`, as NanoClaw's agents do, under the
permission `mcp.servers.add`, which asks by default. The person reads the
whole entry on the approval: what it runs or where it is, the secrets they will
set, and why. The host checks that approval again before it writes the server,
and the server starts at once, with no restart. A stdio server runs as the
Dot's user, with what running a command already gives it, so what the Dot gains
are tools, each still asking. Only the person changes or removes a server.
- **One permission per server**, `mcp.<server>`, asked by default and weighed
as high a risk as running commands: what a server's tools do is the server's
to say.