> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anonalabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Integration

> Connect Anona Memory to Claude Code, Claude Desktop, and other MCP clients, with no integration code.

Anona exposes memory over the Model Context Protocol, so an MCP-capable assistant can
record and recall context directly.

## Tools

| Tool | What it does | Transport |
| - | - | - |
| `record` | Stores a memory in a space. Optional `user_id` / `agent_id` / `session_id` scope it. | All |
| `retrieve` | Semantically searches memories in a space. Pass the same scope keys to see only that user's memories, and `tag_groups` for a [boolean tag filter](https://docs.anonalabs.com/memory/api-reference/retrieve.md#compound-tag-filters). With `route: "auto"` it picks the space, and `max_targets` caps how many it may search — when more than one is searched each memory is labelled with the space it came from. | All |
| `list_spaces` | Lists the available memory spaces. | All |
| `reason` | Synthesizes an answer from accumulated memories. Takes `depth: "thorough"` to read past the space's [memory models](https://docs.anonalabs.com/memory/api-reference/models.md) — see [Depth](https://docs.anonalabs.com/memory/api-reference/reason.md#depth). | All |
| `get_profile` | Reads a space's standing profile and the [memory models](https://docs.anonalabs.com/memory/api-reference/models.md) it keeps current. | Remote and `anona mcp` (not `anona-mcp`) |
| `get_model` | Reads one memory model, the space's current answer to a standing question, such as how this user prefers to be communicated with. | Remote and `anona mcp` (not `anona-mcp`) |
| `get_user_profile` | Reads what a space knows about one end user, by their `user_id`. | Remote and `anona mcp` (not `anona-mcp`) |

There are three ways in: the remote `/mcp` endpoint, `anona mcp` (the local server in
the [CLI](https://docs.anonalabs.com/memory/cli/overview.md), in both the Python and npm packages), and `anona-mcp` (the
Python SDK's local server, under the Local tab below). `anona mcp` forwards every call
to the remote endpoint, so it exposes all seven tools. `anona-mcp` ships the first four.

### Parameters by transport

The two servers are not the same surface. The four shared tools take the same
*required* argument on both, but the hosted gateway accepts a good deal more besides.
`anona-mcp`, the Python SDK's local stdio server, declares only the arguments listed
here — one it does not declare is not passed on, so asking for it there is not a
slower version of the hosted behaviour, it is nothing at all.

| Tool | Argument | `anona-mcp` (stdio) | Remote `/mcp` |
| - | - | - | - |
| `record` | `content` (required) | Yes | Yes |
| | `space_id` | Yes | Yes |
| | `user_id`, `agent_id`, `session_id` | Yes | Yes |
| | `tags` | No | Yes |
| | `timestamp` | No | Yes |
| | `route: "auto"`, `fallback_space_id`, `max_targets` | No | Yes |
| | `org_id` | No | Yes |
| `retrieve` | `query` (required) | Yes | Yes |
| | `space_id` | Yes | Yes |
| | `limit` | Yes | Yes |
| | `user_id`, `agent_id`, `session_id` | Yes | Yes |
| | `mode: "fast"` | No | Yes |
| | `as_of`, `occurred_after`, `occurred_before` | No | Yes |
| | `tag_groups` | No | Yes |
| | `route: "auto"`, `fallback_space_id`, `max_targets` | No | Yes |
| | `org_id` | No | Yes |
| `list_spaces` | `org_id` | No | Yes |
| `reason` | `query` (required) | Yes | Yes |
| | `space_id` | Yes | Yes |
| | `model` | Yes | Yes |
| | `user_id`, `agent_id`, `session_id` | Yes | Yes |
| | `depth: "thorough"` | No | Yes |
| | `org_id` | No | Yes |

What the remote-only arguments do:

* `tags` and `tag_groups` — visibility-scope tags on a write, and a
  [boolean tag filter](https://docs.anonalabs.com/memory/api-reference/retrieve.md#compound-tag-filters) on a read.
* `timestamp`, `as_of`, `occurred_after`, `occurred_before` — event time, so a memory can
  be recorded after the fact and found by when it happened rather than when it was
  stored.
* `mode: "fast"` — skips the reranker for much lower latency, at a real cost in recall
  quality.
* `route: "auto"` — the gateway picks the space, on `record` and on `retrieve` alike.
  `fallback_space_id` says where to go when nothing fits, and on `retrieve`
  `max_targets` caps how many spaces may be searched; when more than one is searched,
  each memory is labelled with the space it came from. Note that a routed request sends
  text to a [third-party decision model](https://docs.anonalabs.com/memory/legal/subprocessors.md).
* `depth: "thorough"` — makes `reason` read past the space's
  [memory models](https://docs.anonalabs.com/memory/api-reference/models.md). See [Depth](https://docs.anonalabs.com/memory/api-reference/reason.md#depth).

**Organization argument.** On the hosted gateway every tool takes an optional `org_id`,
and the `/mcp` endpoint accepts the `X-Anona-Org` header. A signed-in (OAuth) client
starts in your personal organization; naming a shared organization selects your
membership there (`not_an_org_member` if you hold none). An API key belongs to one
organization, so naming another is `org_mismatch`. If both header and argument are sent
they must agree. See
[Choosing an organization](https://docs.anonalabs.com/memory/api-reference/organization.md#choosing-an-organization-per-request).
The `anona-mcp` stdio server has no `org_id` argument and no header: it acts in whichever
organization owns the `ANONA_API_KEY` it was given.

**Space argument.** On the hosted gateway, on a signed-in account, the tools that act on
a space need a `space_id` (or `route: "auto"` on `record` and `retrieve`), because an
account may hold several spaces. On a [temporary profile](https://docs.anonalabs.com/memory/agents/temp-profiles.md) they do
not: leave it out and the call uses the profile's only space, `default`. On `anona-mcp`
a space must always be named, either as `space_id` or through `ANONA_SPACE_ID`;
omitting both is an error that tells you to call `list_spaces`.

Per-tool failures, such as a denied space or exhausted credits, come back as structured
tool errors rather than broken connections. The MCP session stays alive.

## Choosing a transport

| | Local (stdio) | Remote (Streamable HTTP) |
| - | - | - |
| **Runs** | On your machine, via `uvx` | On the hosted gateway |
| **Install** | Python SDK required | Nothing to install |
| **Auth** | `ANONA_API_KEY` environment variable | API key header, or OAuth sign-in |
| **Best for** | Local development, scripted setups | Everyday use, and teams |

> [tab] Remote (recommended)
>
> Connect directly to the hosted gateway. There is no local process to run.
>
> ```bash theme={null}
> claude mcp add --transport http anona https://memory.anonalabs.com/mcp \
>   --header "Authorization: Bearer anona_live_YOUR_KEY"
> ```
>
> Authentication uses the same API key as the REST API, so there is no separate credential
> to manage.
>
> **Hermes Agent:** add a `mcp_servers` entry to `~/.hermes/config.yaml`:
>
> ```yaml theme={null}
> mcp_servers:
>   anona:
>     url: "https://memory.anonalabs.com/mcp"
>     headers:
>       Authorization: "Bearer ${env:ANONA_API_KEY}"
> ```
>
> Hermes also supports `auth: oauth` in place of a static header, the same OAuth flow
> described below for Claude Code.
>
> **OpenClaw:** add the server under `nodeHost.mcp.servers` in `openclaw.json` on the
> node machine. See [OpenClaw](#openclaw) below for the full block. That path takes an
> API key only, not OAuth.
>
> **Connecting without a key.** Leave off `--header` and an OAuth-capable client such as
> Claude Code, Claude Desktop, or Cursor signs you in instead.
>
> ```bash theme={null}
> claude mcp add --transport http anona-oauth https://memory.anonalabs.com/mcp
> ```
>
> > [!NOTE]
> >
> > `add` does not open a browser, and that is expected. It only writes the server to your
> > config file. OAuth sign-in does not run until the client actually connects, which
> > happens at session start or when you run `/mcp`. After `add` you are not signed in yet.
>
> > [!NOTE]
> >
> > **No API key is needed for this path.** An organization that has never created
> > one works from its first tool call: the gateway proves your tenancy to the
> > memory service itself. This was not true before 2026-10-01, when a keyless
> > organization got `403 No active API key for this organization` and had to
> > create a key once to work around it. If you still see that error, something is
> > wrong on our side rather than with your setup, so please report it instead of
> > minting a key.
> >
> > One deliberate exception: an organization that created keys and then revoked
> > all of them is refused, because revoking every key is how you cut off access.
> > Create a new key to restore it.
>
> To trigger sign-in:
>
> 1. Run `/mcp` in Claude Code, or restart it. This connects to the server for the first time.
> 2. Your browser opens the Anona consent screen. Sign in with email and password, or with Google, GitHub, or Microsoft, whichever your account uses.
> 3. Approve, and the client stores the token. No API key ever touches its config.
>
> Manage or revoke authorized apps at any time from the dashboard, under
> **MCP → Connected apps**. Tokens refresh automatically, and revoking cuts an app's
> access immediately.
>
> **Connecting with a temporary profile.** A token starting `anona_tmp_`, created by
> `anona start`, authenticates `/mcp` the same way an API key does, so no account or
> sign-in is needed. On such a profile no tool needs a `space_id`. See
> [Temporary profiles](https://docs.anonalabs.com/memory/agents/temp-profiles.md) for the limits and how to claim one.
>
> > [!WARNING]
> >
> > Opening `https://memory.anonalabs.com/mcp` in a browser returns `Method Not Allowed`.
> > That endpoint speaks the MCP protocol over POST and is not a web page. Point an MCP
> > client at it rather than visiting it.

> [tab] Local (stdio)
>
> Runs on your machine via `uvx`, and ships with the Python SDK.
>
> ```bash theme={null}
> uvx --from 'anona[mcp]' anona-mcp
> ```
>
> Set the environment before starting your client:
>
> ```bash theme={null}
> export ANONA_API_KEY="anona_live_YOUR_KEY"
> export ANONA_SPACE_ID="customer-support-bot"   # optional, scopes the server to one space
> ```
>
> Or install the extra explicitly:
>
> ```bash theme={null}
> pip install "anona[mcp]"
> ```
>
> **Register with Claude Code:**
>
> ```bash theme={null}
> claude mcp add --transport stdio anona -- uvx --from 'anona[mcp]' anona-mcp
> ```
>
> Set `ANONA_API_KEY`, and optionally `ANONA_SPACE_ID`, in your shell environment before
> starting Claude Code.

## Things worth knowing

| Behavior | Detail |
| - | - |
| **Tools only load at session start.** | Adding or changing an MCP server mid-session will not expose its tools until you restart the client. |
| **`ANONA_SPACE_ID` is the stdio server's default space.** | Set it and the local tools use it whenever a call leaves `space_id` out; leave it unset and such a call fails, telling you to run `list_spaces`. It is not read by the remote server. A temporary profile on the remote server is the one case where no space need ever be named: it has exactly one. |
| **Same quota, same billing.** | MCP calls consume credits and count against your usage exactly as REST calls do. |

## Example session

Once registered, talk naturally:

> Remember that the user prefers dark mode and uses VS Code.

> What do we know about this user's editor preferences?

Claude Code calls `record` and `retrieve` behind the scenes.

> [!NOTE]
>
> Serving several people through one MCP connection? Pass `user_id` on `record` and
> `retrieve` so each person's memories stay separate inside the shared space. See
> [Scoping](https://docs.anonalabs.com/memory/api-reference/retrieve.md#scoping-within-a-space).

## Client setup guides

### Claude Code

1. Get a key from the dashboard, under **API keys**.
2. Register the server:
   ```bash theme={null}
   claude mcp add --transport http anona https://memory.anonalabs.com/mcp \
     --header "Authorization: Bearer anona_live_YOUR_KEY"
   ```
3. Run `/mcp` in Claude Code, or restart it, to connect.
4. Try it: "Remember that I prefer dark mode and use VS Code."

### Hermes Agent

1. Get a key from the dashboard, under **API keys**.
2. Add to `~/.hermes/config.yaml`:
   ```yaml theme={null}
   mcp_servers:
     anona:
       url: "https://memory.anonalabs.com/mcp"
       headers:
         Authorization: "Bearer ${env:ANONA_API_KEY}"
   ```
3. Set `ANONA_API_KEY` in `~/.hermes/.env` or your shell environment.
4. If Hermes is already running, it auto-reloads the config within 30s, or run
   `/reload-mcp` in-session. Otherwise the server picks it up on next start.
5. Try it: "Remember that I prefer dark mode and use VS Code."

### OpenClaw

1. Get a key from the dashboard, under **API keys**.
2. On the node machine (not the OpenClaw gateway), add to `openclaw.json`.
   `openclaw config file` prints its path.
   ```json5 theme={null}
   {
     nodeHost: {
       mcp: {
         servers: {
           anona: {
             url: "https://memory.anonalabs.com/mcp",
             transport: "streamable-http",
             headers: { Authorization: "Bearer ${ANONA_API_KEY}" },
           },
         },
       },
     },
   }
   ```
3. Set `ANONA_API_KEY` in the node's environment, then `openclaw node restart`.
   The node host does not watch this file.
4. This path takes an API key only, not OAuth.
5. Try it: "Remember that I prefer dark mode and use VS Code."

Without the MCP server, the [Agent Skill](https://docs.anonalabs.com/memory/integrations/skills.md) still works in
OpenClaw: it calls the API with `curl` and the key in `~/.anona/config.env`.

## Next steps

> [card] [Agent Skills](https://docs.anonalabs.com/memory/integrations/skills.md)
>
> Make the client use these tools by itself, instead of waiting to be told.

> [card] [Python SDK](https://docs.anonalabs.com/memory/sdk/python.md)
>
> The programmatic client library.

> [card] [API overview](https://docs.anonalabs.com/memory/api-reference/overview.md)
>
> The full REST surface.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.