Settings
Keeps 4 promises
Settings has an MCP page per node. Off, it says what MCP is and offers Turn on for an agent. That one action, after one confirmation:
- turns the service on;
- makes a client: a name (Claude Code, Codex, or one you type) and a key the node holds for it;
- writes the default grants to that key, signed by the device you're on:
| grant | scope | answer |
|---|---|---|
| read | the folders this node keeps (files.md, Open, keep, hold) |
allow |
| write | the same folders | ask |
No shell, no other node, no internet and no folder outside what's kept, until you add them on the same page, each a grant like these. The confirmation lists them before anything is written. When the node keeps no folders yet, the page asks for one, since a client that can read nothing is useless.
Each client is a row: its name, its grants, when it was last used, and
its audit (access/audited). Remove ungrants everything it holds and
forgets its key. Turning MCP off stops the service and leaves the clients
listed, unable to call until it is on again.
The line for your agent
Keeps 2 promises
A local client starts its servers as commands and talks to them over
stdin and stdout, so the door is a command: youros-node mcp <client>. It
is not a way to set anything up (that is the settings page); it is a pipe
from the client's stdio to the MCP service's local socket, readable only
by the node's user, and naming the client. The page shows the line for
each agent it knows, such as:
claude mcp add youros -- youros-node mcp <client>
codex mcp add youros -- youros-node mcp <client>
and the command and arguments for any other client's settings file. Clients change their syntax, so the lines live in a table beside the page that a release can update, and the end-to-end test runs each one.
No HTTP on localhost: any page in any browser on the machine can try a
port there (DNS rebinding), and so can another user. Any process running
as you could start the command with another client's name, but such a
process can already read the node's key file (access.md, Where it
breaks), so the command gives it nothing new.
Tools
Keeps 2 promises
The service lists a client's tools from its grants: each verb its grants
allow, by the manifests of the services on the nodes they cover, with the
node and path in the arguments. A few tools stand for the common path
(read, write, list, search a folder); the rest are found by one search
tool and run through one call tool, so the tool list stays small however
many services and nodes there are.
A call to another node goes through this node's session with it, as the
client's key, with a chain from this node to the client (access/node-holds-keys).
The far machine checks it against its own log and audits it under the
client's name.
Waiting for an answer
A call the holder parks (access.md, An ask, from call to answer) is
held open for up to 30 seconds, sending MCP progress notifications. If no
answer comes, it returns pending with the ask's id and what to tell the
person, and the client calls wait(ask) when it wants the result; once
answered, the result is kept for a day. MCP elicitation is never used for
an ask: the client draws that prompt, and the client is the one asking.
Later: a door for agents in the cloud
An agent that isn't on one of your machines (claude.ai, or an agent on
someone else's server) needs an HTTPS address and OAuth. The same service
would serve it, OAuth's authorize page showing a pairing link that a
device of yours opens to make the client and its grants. Two things are
open: where it is reached (a node of yours, through the relay passing TLS
through unread, or a hosted door that sees what the agent reads), and
whether a hosted door is offered at all. Whatever hosts the door sees
everything the agent reads, as the agent's provider does; the relay still
sees nothing. It is a node facing outward (access.md): its
grants are the most an agent can get through it, and its OAuth decides
which agents those are.