Skip to content
Pilotoo
v0.1

Use it from an agent

Brain serves one MCP endpoint, POST /mcp, over Streamable HTTP. An agent holding a Brain token gets six memory tools, and six workflow tools more when the token holds the connectors grant. The token carries grants per memory, and an agent never reaches more than the person who owns the token.

Open the web app, or call POST /api/tokens while signed in, and name the token with one grant per memory:

POST /api/tokens
{
"name": "Claude Code",
"grants": [
{ "memoryId": "<graph memory id>", "access": "read" },
{ "memoryId": "<collection memory id>", "access": "write" },
{ "memoryId": "<personal memory id>", "access": "remember" }
]
}

The response includes secret once, starting with pb_. Only its SHA-256 is stored, so a lost secret cannot be recovered; create another and delete the old one with DELETE /api/tokens/:id.

Access Allows Memory kinds
read memory_list, memory_search, memory_get any
write also memory_add_source graph, collection
remember memory_remember, memory_forget personal only
connectors the six workflow_* tools, for connectors that write into this memory graph, collection
Terminal window
claude mcp add --transport http brain https://brain.example.com/mcp \
--header "Authorization: Bearer pb_..."

Any MCP client that speaks Streamable HTTP and sends an Authorization: Bearer header works the same way. The endpoint is stateless: every request is its own session, and GET and DELETE on /mcp answer 405.

A pb_ token is accepted only on /mcp. Every other route needs a signed-in session.

Tool Input Returns
memory_list none {memories: [{slug, kind, name, description, access}]} for the memories the token may use. Call it first.
memory_search memory (slug), query, limit (1 to 50, default 8) {passages: [{text, sourceId, sourceTitle, locator, score}]}. In a personal memory it searches the facts.
memory_get memory (slug), id of a page, source or fact from a search The whole document: a page, a source with its text, or a fact.
memory_remember text, one standalone sentence The fact, with operation: add, update, delete or noop. Needs remember.
memory_forget id of a fact {forgotten: true}. Needs remember.
memory_add_source memory (slug), title, text, labels?, externalId? The created source. Needs write on that memory.

A failed call returns an MCP result with isError: true and a JSON body {error: {code, message}}, where code is invalid, not_found, forbidden or conflict.

With the connectors grant the endpoint also lists workflow_list, workflow_run, workflow_kinds, workflow_get, workflow_validate and workflow_save. They have the same names, inputs and answers as the workflow tools of the desktop app, so the desktop’s workflow skill describes them as they are. Any MCP client can use them, such as Claude Desktop, Claude Code or Cursor, and so can the Pilotoo desktop app: two settings in its .env give its agents these tools as brain_workflow_save and the rest (Brain from the desktop app). Without the grant the tools are not listed and a call is refused with forbidden.

The token acts as its owner, and every connector it touches belongs to that owner. It sees, reads, saves, turns on and runs only the connectors whose steps all write to memories the token holds connectors on. A connector that writes anywhere else is invisible to it, and saving one that does, or one whose step names no memory or picks it at run time, is refused with the issue. workflow_kinds offers only the granted memories for a Brain step.

Tool In Brain
workflow_list The connectors, with enabled.
workflow_get One connector: nodes, edges and enabled.
workflow_kinds The kinds Brain offers to connectors, and the memories the token may write to.
workflow_validate The engine’s issues plus Brain’s, and memory_not_granted for a memory outside the grants.
workflow_save Creates a connector, or replaces id. It starts off; pass enabled: true to turn it on, which needs a valid workflow.
workflow_run Runs it now and answers {output: {added, unchanged, skipped, items}, nodes}; a failed run answers Not done: with the failed step.

The registry of each memory shows what the agent changed, under the token name.

A personal memory has a write policy, set with PUT /api/memories/:mid/write-policy:

  • auto: facts agents send are saved at once (the default).
  • ask: facts wait for the owner to keep them; they come back with pending: true.
  • off: memory_remember is refused.

Brain compares each new fact with the ones it already has. operation tells the agent what happened: add saved a new fact, update rewrote an older one, delete retired an older fact the new one contradicts, and noop means it was already known. Under ask, an update or delete also waits until the owner keeps the fact.

An agent can add a source to a graph memory, and that source goes through the memory’s review like any other.

Give memory_add_source an externalId, your own stable id for the document, and send it again whenever it changes. The same id with the same text does nothing; with new text it becomes the next version of that source and only what differs is recompiled.

The desktop app reaches Brain the way it reaches Pilotoo Connect. Create a token under Agents & tokens with write on the memories agents may fill, and the connectors grant to let them manage connectors. Add it to ~/.pilotoo/.env and restart the app:

~/.pilotoo/.env
BRAIN_REMOTE_URL=https://brain.example.com
BRAIN_REMOTE_TOKEN=pb_...

Every tool the token is offered arrives with the prefix brain_: brain_memory_search, brain_memory_add_source, brain_workflow_save and the rest. They are opt-in, as the Connect tools are: an agent gets one only by listing it in its tools.

tools: [brain_memory_search, brain_memory_add_source]

With only one of the two settings the app warns at start and offers no Brain tool. When Brain cannot be reached at start, or refuses the token, the app starts anyway and the warning names the cause; the only tool is then brain_status, which tries again and, once Brain answers, registers the others (list them in an agent, or restart the app). A call that fails comes back to the agent as an error naming Brain.