> **Development instance.** Same memory, same tools, separate data: use it to try changes before production (memory.adecubed.com).

# ADE Brain — agent memory over MCP

ADE Brain is a long-term memory for an agent: it keeps facts, replaces a fact when a
newer one contradicts it, keeps episodes with their dates, and forgets on request. It
has run as one person's daily memory since 2025. This page is everything an agent
needs to use it.

## Connect

The memory is an MCP server over Streamable HTTP. No installation.

| | |
|---|---|
| Endpoint | `https://dev.memory.adecubed.com/mcp` |
| Auth | `Authorization: Bearer <token>` — the token you were given |
| Transport | Streamable HTTP (MCP 2025-06-18) |

Claude Code:

```bash
claude mcp add --transport http ade-brain https://dev.memory.adecubed.com/mcp \
  --header "Authorization: Bearer <token>"
```

Any other MCP client: point it at the endpoint with that header. `tools/list` returns
four tools; there is nothing else to configure.

Before wiring up a client, check the token from a shell. One request, no session needed:

```bash
curl -s -X POST https://dev.memory.adecubed.com/mcp \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
```

| You get | It means |
|---|---|
| `event: message` and a JSON result with `"serverInfo":{"name":"ade-brain"...}` | the token works; connect your client |
| `{"error":"unauthorized"}`, HTTP 401 | the header is wrong: it must be exactly `Authorization: Bearer <token>`, the token as given, no quotes around it |
| HTTP 406 `Not Acceptable` | the `Accept` header is missing: Streamable HTTP wants both `application/json` and `text/event-stream` |

Check it works:

```
health()  →  {"ok": true, "version": "...", "facts": 0}
```

## The tools

### `remember(text, date=None, kind="fact")`

Store one memory.

- `text`: one self-contained sentence with the names in it. *"Priya Sharma's desk is
  on floor 3."* *"The Meridian weekly call moved to Friday."* One fact per call.
- `date`: `YYYY-MM-DD`, when the fact became true, if it matters and is not today.
- `kind`: `"fact"` (default) for something durable; `"event"` for something that
  happened (a meeting, a decision, a request), kept as a dated episode.

Returns `{ok, key, replaced}` for a fact (`replaced` is the key of the older fact this
one superseded, or `null`), and `{ok, id}` for an event. To forget that exact memory
later, pass `fact:<key>` or `episode:<id>` in `forget(items=...)`.

**Updates are just new facts.** Store *"Priya Sharma's desk is on floor 5."* and the
floor-3 fact stops being served. You never say which fact is replaced: the memory
finds it. A sentence about someone else (*"Ravi Kumar's desk is on floor 3."*) is a
different fact and both stay.

### `recall(question)`

Ask in natural language. Returns `{text, items}`.

- `text` is what the memory delivers for that question: entity cards first, then
  facts, each with its date (`[since 2026-05-10]`), then episodes and recent
  conversations. **Read the dates: when two facts disagree, the newer one is current.**
- If `text` opens with `TERMS THE BRAIN DOES NOT KNOW: ...`, no stored memory contains
  those words. The note under the line tells you which case you are in. When the unknown
  word is a name, the thing you asked about does not exist in memory: say you do not know.
  When it is an ordinary word (`mileage`, `current`), the memories that follow match the
  rest of the question and usually hold the answer in other words: use them if they do.
  Never fill the gap from general knowledge.
- `items` are identifiers (`fact:<key>`, `episode:<id>`) you can pass to `forget`.

### `forget(text=None, items=None)`

When the user asks to forget something, everything that carries it goes: the fact,
every older value it had replaced, the episodes and conversation turns that contain
it. Nothing comes back in its place.

- `text`: the thing to forget, as the user said it or as stored, at least 4 characters.
  A phone number, a name plus what is known about it, a sentence. Case does not matter.
- `items`: identifiers of exactly which memories to remove: `fact:<key>` and
  `episode:<id>`, as `recall` returns them, or built from what `remember` returned
  (`episode:` followed by the event's `id`).

Returns `{ok, facts, episodes, turns}`: what was removed. `ok: false` with empty lists
means nothing matched; try `recall` first and pass the `items`.

### `health()`

`{ok, version, facts}`. If `ok` is false, the memory is down; do not answer from
memory.

### `reset(confirm)` — evaluation instances only

Empties the whole memory: every fact, with every older value it replaced, and every
event. It exists only on an instance set up for evaluation, so that each test sequence
can start from nothing; a person's own memory never offers it. It cannot be undone.

- `confirm`: must be exactly `"erase everything"`; anything else removes nothing.

Returns `{ok, facts, episodes, left_facts, left_episodes}`: how many were removed and
what is left, `0` and `0` when the memory is empty.

## How to work with it

- **Store as you go.** After anything worth keeping — a fact stated, a decision, a
  preference, a change — call `remember` once per fact, in one sentence with the names
  spelled out. "It" and "they" do not survive a week.
- **Preferences are facts.** *"Dana prefers the weekly report as a bullet list, no
  intro."* Store them like that, and `recall` them before you act.
- **Explicit negatives are facts too.** *"Nordmed claimed no penalty for the late
  delivery."* *"The Q4 budget is not set yet; it will be set in October."* A later
  question about them has nothing to find otherwise.
- **Ask before you answer.** `recall` first, then answer from the text it returned, with
  its dates. If the answer is not in the text, say so.
- **Times.** Give `date` when a fact is about a time (*"since"*, *"on"*, *"until"*), and
  use `kind="event"` for things that happened, so the memory can tell you when.
- **Forgetting.** On *"forget X"*, call `forget` with X as the user said it. If it
  removed nothing, `recall` X and pass its `items`. Then confirm to the user what was
  removed, and do not repeat what X was.

## What it does on its own

- A new fact that contradicts an older one **about the same subject** replaces it. The
  old value is retired: it is not served again, not even next to the new one.
- A sentence that only says something is unknown (*"I have no record of that"*) is not
  stored as a fact.
- A write is readable on the next `recall`. There is no indexing delay.
- Cards: once an entity has enough facts, the memory writes a short card about it and
  serves it first when the entity is asked about.

## Limits

- One fact per `remember`. A paragraph is stored as one memory and updates nothing.
- `recall` returns at most a few thousand characters: the cards, the best facts, the
  latest episodes. It is a door, not a dump.
- `forget` by text is literal: it removes what contains that text. It does not infer.

## Behind the endpoint

The MCP server (`memory_mcp.py`, four tools) forwards to the Brain's HTTP service:
`POST /memory/semantic/learn`, `POST /sofia/ask`, `POST /memory/forget`,
`GET /brain/health`. This instance runs with an empty memory, in English
(`BRAIN_LANG=en`), on its own server; nothing of the author's memory is in it.

Contact: Founder@adecubed.com
