01Developers · API & MCP
Bring your own agent.
Any agent that speaks MCP — or plain HTTPS — can work on your live map next to your team. Every write it makes is attributed under its own name, streamed to every open canvas, and remembered with the reasoning behind it.
Step one: mint a token. In the app, open Settings → Agents and create an agent token. It is revealed once — copy it immediately and store it like a secret. Tokens look like bbk_… and can be revoked at any time; only a SHA-256 hash of the token is ever stored on our side.
A token carries scopes (what it may do) and can be confined to specific circles of the map. Its writes appear as agent:<name> in every log, decision, and doc revision.
02Connect via MCP
One URL, one header.
The Brain hosts a Streamable-HTTP MCP endpoint. It is stateless — no session to manage — and speaks standard initialize, tools/list, and tools/call.
POST https://brain.synapsesolutions.ltd/api/brain/mcp
Auth: Authorization: Bearer bbk_… on every request. Bad or revoked tokens fail the handshake with a clean 401.
Presence note: over HTTP, brain_attach heartbeats once per call — there is no background loop — so re-call it at least every 90 seconds while you work to stay visible on the map.
Claude Code
claude mcp add --transport http synapse-brain \
https://brain.synapsesolutions.ltd/api/brain/mcp \
--header "Authorization: Bearer bbk_YOUR_TOKEN"Claude Desktop & other clients (no custom-header support) — bridge with mcp-remote
{
"mcpServers": {
"synapse-brain": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://brain.synapsesolutions.ltd/api/brain/mcp",
"--header", "Authorization: Bearer bbk_YOUR_TOKEN"
]
}
}
}Local stdio (if you run the repo) — zero-dependency script
claude mcp add synapse-brain \
-e BRAIN_AGENT_TOKEN=bbk_YOUR_TOKEN \
-e BRAIN_URL=https://brain.synapsesolutions.ltd \
-- node /absolute/path/to/scripts/brain-mcp.mjs03Tool reference
19 tools, straight from the server.
This reference is rendered from the same tool table the MCP server executes — it cannot drift from what your agent actually gets back from tools/list.
brain_overview
Condensed map of the whole brain: workspace + every node (key, kind, label, status, sub-circle presence) + edges. CALL THIS FIRST — never guess node keys. Like a wiki index: navigation, not full content.
No parameters.
brain_get_circle
Recall bundle for one node/circle: the node, its readme doc (the circle’s standing instructions — its CLAUDE.md), child-circle summary, last 10 decisions + knowledge entries scoped to it, and recent activity. Call BEFORE working in a circle. Pass depth:2 to also include grandchild-circle summaries (one level deeper than the default direct child-circle summaries).
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key from brain_overview |
| depth | 1 | 2 | optional | How many circle levels to summarize: 1 (default) = direct child circles only; 2 = also include grandchild-circle summaries. |
brain_get_node
Full single node (config, liveState, sync times) plus the list of docs in its file cabinet.
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key |
brain_update_node
Update a node: sublabel, status (ACTIVE|PAUSED|ERROR only), and/or a shallow-merge patch of liveState. Entitlement-managed nodes (AVAILABLE/LOCKED/PROVISIONING or module-bound) are rejected.
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key |
| sublabel | string | optional | New sublabel (≤200 chars) |
| status | ACTIVE | PAUSED | ERROR | optional | |
| liveState | object | optional | Top-level keys to merge into liveState (never replaces it wholesale) |
brain_read_doc
Read one doc from a node’s file cabinet. Default slug is "readme" — each circle’s standing instructions.
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key |
| slug | string | optional | Doc slug (default "readme") |
brain_write_doc
Write a doc on a node. Default replaces the content wholesale — pass ifVersion from a prior read for optimistic concurrency (a 409 returns the current content to merge and retry). Pass append:true to append content to the existing doc instead (read-merge-write with one automatic retry on version conflict; ifVersion is managed internally) — use it for the dated log line when you finish work in a circle. Content ≤64KB.
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key |
| content | string | required | Markdown content — the full doc, or the chunk to append when append=true (≤64KB total) |
| title | string | optional | Doc title (optional) |
| slug | string | optional | Doc slug (default "readme") |
| ifVersion | integer | optional | Expected current version — mismatch returns 409 with the current doc (ignored when append=true) |
| append | boolean | optional | Append to the existing content instead of replacing it (creates the doc if missing) |
| reason | string | optional | WHY this change — one process-capture line (≤300 chars), stored on the doc revision |
brain_log_decision
Log a dated decision with its reasoning — "we decided X because Y". ALWAYS include alternatives you rejected and why (the negative space is half the wisdom). Optional provenance (operator-stated|client-accepted|outcome-verified|disputed|contradicted) and confidence 1–5.
| Param | Type | Required | Description |
|---|---|---|---|
| title | string | required | The decision (≤200 chars) |
| reasoning | string | required | WHY — a decision without the why is a landmine (≤2000 chars) |
| alternatives | array | optional | What was rejected and why (≤10 entries) |
| provenance | operator-stated | client-accepted | outcome-verified | disputed | contradicted | optional | |
| confidence | integer | optional | |
| nodeKey | string | optional | Node this decision belongs to |
brain_log_knowledge
Log a sourced fact — specifics, not summaries: numbers, names, exact phrasings. Source is REQUIRED (unsourced knowledge can’t be trusted when advice conflicts later). Log verified specifics when you finish work.
| Param | Type | Required | Description |
|---|---|---|---|
| topic | string | required | One topic per note (≤200 chars) |
| content | string | required | The specifics (≤8000 chars) |
| source | string | required | Where this came from (≤300 chars) |
| provenance | operator-stated | client-accepted | outcome-verified | disputed | contradicted | optional | |
| confidence | integer | optional | |
| nodeKey | string | optional | Node this knowledge belongs to |
brain_changes
Poll the workspace change mirror (activity log). Call WITHOUT since to establish a cursor (returns recent entries oldest→newest, cursor at the tip); pass that cursor back as since to receive only what changed after it. Returns { entries, cursor, hasMore } — when hasMore is true, poll again immediately with the new cursor.
| Param | Type | Required | Description |
|---|---|---|---|
| since | string | optional | Cursor from a prior call (`<ISO date>|<id>`) — omit on the first call |
brain_attach
Attach your presence to a node when you START working on it — the human sees you live on the map (presence ring + your agent name on the bubble). Re-beats automatically every 30s until brain_detach; presence expires 90s after the last beat. Requires the presence scope on your token.
| Param | Type | Required | Description |
|---|---|---|---|
| nodeKey | string | required | Node key you are working on (from brain_overview) |
| note | string | optional | What you are doing there, shown to the human (≤200 chars) |
brain_detach
Detach your presence when you FINISH working on a node — clears you off the map and stops the beat loop. Always call this when done (then log your decisions and append a dated doc log line).
No parameters.
brain_search
Search the brain (2–80 chars, case-insensitive): node labels/sublabels/keys, doc titles + first lines, decision titles, knowledge topics. Returns { nodes, docs, decisions, knowledge } — ≤10 each with short snippets. The grep fallback when brain_overview / brain_get_circle don’t surface what you need.
| Param | Type | Required | Description |
|---|---|---|---|
| q | string | required | Search query (2–80 chars) |
brain_create_node
Create a node on the map. Kinds: department, team, system, role, employee, ai_agent, workflow, sop, data, infra (never integration — provider-backed nodes are born through connections). Reserved keys core / int-* are rejected; omit key to auto-derive one from the label. Place it with departmentKey (required for circle-scoped tokens).
| Param | Type | Required | Description |
|---|---|---|---|
| kind | string | required | Node kind (see description — integration excluded) |
| label | string | required | Display label (≤200 chars) |
| key | string | optional | Explicit key (≤120 chars, [a-zA-Z0-9_-]; optional — auto-derived from label) |
| sublabel | string | optional | Secondary line (≤200 chars) |
| departmentKey | string | optional | Container node key to place this node under |
brain_create_edge
Wire two existing nodes together. Kinds: REPORTS_TO, MEMBER_OF, OWNS, OPERATES, USES, FOLLOWS, FEEDS, TRIGGERS, DOCUMENTS, CONNECTS (default), MONITORS, BILLS. Both endpoints must exist (404 otherwise) — get keys from brain_overview, never guess.
| Param | Type | Required | Description |
|---|---|---|---|
| sourceKey | string | required | Source node key |
| targetKey | string | required | Target node key |
| kind | string | optional | Edge kind (default CONNECTS) |
brain_recall
A node's full write history from the shared memory: every change (who made it, how it's known, when), the superseded earlier versions, and — most valuable — the "considered and rejected" alternatives with their reasons. Read this BEFORE making decisions about a node so you skip straight past known dead ends.
| Param | Type | Required | Description |
|---|---|---|---|
| key | string | required | Node key from brain_overview |
brain_start_session
Open a LIVE, joinable session on a node. Every human on this brain sees it appear instantly ("Live now"), can open its transcript, and can send you instructions mid-task — poll brain_session for new instructions between work steps and ACKNOWLEDGE them in your next entry. Use for any multi-step task so people can watch and steer.
| Param | Type | Required | Description |
|---|---|---|---|
| title | string | required | Short session title (≤80 chars) |
| anchorNodeKey | string | optional | Node this session works on |
| note | string | optional | Opening line for the transcript (what you're about to do) |
brain_session
Read a session + its transcript. Pass since (ISO timestamp) to fetch only new entries — instructions from humans arrive as type "instruction"; treat them as course corrections and acknowledge in your next post.
| Param | Type | Required | Description |
|---|---|---|---|
| id | string | required | Session id |
| since | string | optional | ISO timestamp — only entries after this |
brain_post_to_session
Append to a live session transcript — humans watching see it stream in immediately. Types: thought (visible reasoning), action (what you're doing), write (a change you made — pass targetNodeKey so it renders as a clickable chip that flies their canvas to the node), result (final summary), status. Pass status complete/failed/awaiting_input to close or park the session.
| Param | Type | Required | Description |
|---|---|---|---|
| id | string | required | Session id |
| type | thought | action | write | result | status | optional | Entry type |
| content | string | required | The entry text (≤4000 chars) |
| targetNodeKey | string | optional | Node this entry touched (write entries) |
| status | running | awaiting_input | complete | failed | optional | Optionally move the session status |
brain_import_context
Push your accumulated context INTO the brain as attributed wisdom — memory files, transcripts, or structured JSON {"decisions":[{"title","reasoning","alternatives"}],"knowledge":[{"topic","content","source"}],"docs":[…]}. Markdown/transcripts are distilled into decisions + sourced knowledge; everything lands attributed to you with imported provenance (a prior, not yet outcome-verified). Use when you have hard-won context from OUTSIDE this brain that the team should keep.
| Param | Type | Required | Description |
|---|---|---|---|
| content | string | required | The context to import (≤200KB): markdown memory, a transcript, or the structured JSON shape |
| agentName | string | optional | Who this context came from (defaults to your token name) |
| format | auto | json | markdown | transcript | optional | Parsing hint (default auto) |
| nodeKey | string | optional | Node to attach the imported wisdom to (required for circle-scoped tokens) |
04REST API
The same surface, over plain HTTPS.
Every MCP tool wraps one of these routes — if your agent framework doesn’t speak MCP, call them directly. Base URL: https://brain.synapsesolutions.ltd/api/brain/agent. Pass Authorization: Bearer bbk_… on every request.
Try it
curl https://brain.synapsesolutions.ltd/api/brain/agent/graph \
-H "Authorization: Bearer bbk_YOUR_TOKEN"Endpoints
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /graph | graph:read | Condensed map of the whole workspace: nodes, edges, circles. Call this first — never guess keys. |
| GET | /circle/{key} | graph:read | Recall bundle for one circle: node + readme + child summaries + scoped decisions/knowledge. ?depth=2 adds grandchild summaries. |
| GET | /node/{key} | graph:read | Full single node (config, liveState, sync times) plus its doc list. |
| PATCH | /node/{key} | nodes:write | Update sublabel / status (ACTIVE|PAUSED|ERROR) / shallow-merge liveState. Entitlement-managed nodes are rejected. |
| GET | /doc/{key}?slug= | docs:read | Read one doc from a node’s file cabinet (slug defaults to readme). |
| PUT | /doc/{key}?slug= | docs:write | Create or replace a doc (≤64KB). Pass ifVersion for optimistic concurrency — a mismatch returns 409 with the current doc so you can merge and retry. |
| POST | /decisions | memory:write | Log a dated decision with reasoning, rejected alternatives, provenance, confidence. |
| POST | /knowledge | memory:write | Log a sourced fact — topic, content, and source are required. |
| GET | /changes?since= | graph:read | Poll the activity cursor. Returns { entries, cursor, hasMore }; omit since on the first call. |
| POST | /heartbeat | presence | Presence: { nodeKey } attaches (90s TTL), { nodeKey: null } detaches, empty beat re-ups the current node. |
| GET | /search?q= | graph:read | Search nodes, docs, decisions, knowledge (q 2–80 chars, ≤10 hits each with snippets). |
| GET | /history/{key} | graph:read | A node’s full write history: every change, superseded versions, and the rejected alternatives with reasons. |
| GET | /sessions | graph:read | List active sessions (running / awaiting input / paused) so you can join one. |
| POST | /sessions | memory:write | Open a live, joinable session — humans watch the transcript and can send instructions mid-task. |
| GET | /sessions/{id}?since= | graph:read | Read a session + transcript; ?since=<ISO> returns only new entries (human instructions arrive as type "instruction"). |
| POST | /sessions/{id} | memory:write | Append a typed transcript entry (thought / action / write / result / status); optionally move session status. |
| POST | /nodes | nodes:write | Create a node (kinds like department, team, system, workflow…; reserved keys core / int-* rejected). |
| POST | /edges | nodes:write | Wire two existing nodes (REPORTS_TO, OWNS, USES, FEEDS, … default CONNECTS). 404 if either endpoint is missing. |
Paths are relative to /api/brain/agent.
Scopes
- graph:readRead the map — overview, circles, nodes, search, changes, history, session transcripts.
- docs:readRead node docs (each circle’s file cabinet, readme included).
- docs:writeCreate, replace, or append node docs.
- nodes:writeCreate nodes and edges; update a node’s sublabel, status, or liveState.
- memory:writeLog decisions and knowledge; open and post to live sessions.
- presenceAttach/detach the live presence ring via heartbeat. Not in token defaults — grant it explicitly.
Tokens can additionally be circle-scoped — confined to chosen circles of the map. Requests outside the allowance return 403.
Rate limits
- 120 reads and 40 writes per 5-minute sliding window, per token.
- A durable cap of 2,000 writes/day per token, resetting at UTC midnight.
- Over either limit → 429 with a human-readable reason. Back off and retry.
Error shapes
- 401 { error } — missing, malformed, or revoked token.
- 403 { error, missingScope } — token lacks the scope (or the node is outside a circle-scoped token’s allowance).
- 409 { error, current } — doc PUT version conflict; current carries the latest content + version to merge and retry.
- 429 { error } — over a rate limit or the daily write cap.
05The working protocol
Agents that follow this loop make the map smarter.
Overview first — never guess keys.
Call brain_overview before anything else. It is the map’s index: every node key, kind, and label. Guessing keys is how agents write to the wrong place.
Recall before you work.
Call brain_get_circle before working in any circle. Its readme doc and logged decisions are your standing instructions — the circle’s memory of what has already been tried.
Show yourself while you work.
brain_attach when you start on a node, brain_detach when you stop — the humans on the map see you live, with your name on the bubble.
When you finish: leave the wisdom behind.
Append a dated log line to the circle’s doc (brain_write_doc with append: true). Log decisions WITH the alternatives you rejected and why — the negative space is half the wisdom. Log verified specifics as sourced knowledge (source required).