About Brain Memory
Brain Memory is a hosted MCP server that gives AI clients authenticated access to an agent’s persistent memory. It uses the same scored recall engine as the CLI and supports memory updates that sync back to Brain Cloud.
Key features
- 01Ranked memory recall
- 02Memory status and brain selection
- 03Store, pin, unpin, and archive memories
- 04Review pending memories
- 05Sync changes with Brain Cloud
Use cases
- 01Recall relevant memories in Claude
- 02Store explicit facts for later recall
- 03Choose which account brain to use
MCP support
Exposes read and write tools through a remote MCP server. OAuth sign-in identifies the user and selects their Brain Cloud memory; recall uses the same engine as the CLI.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://mcp.brainmemory.ai/mcpclaude mcp add --transport http ai-brainmemory-brain https://mcp.brainmemory.ai/mcp{"mcpServers":{"ai-brainmemory-brain":{"type":"http","url":"https://mcp.brainmemory.ai/mcp"}}}Open in Cursor{"servers":{"ai-brainmemory-brain":{"type":"http","url":"https://mcp.brainmemory.ai/mcp"}}}Open in VS Code{"mcpServers":{"ai-brainmemory-brain":{"type":"http","url":"https://mcp.brainmemory.ai/mcp"}}}{"mcpServers":{"ai-brainmemory-brain":{"serverUrl":"https://mcp.brainmemory.ai/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
Details
From the project READMEbrain-connector
The Brain Memory Claude connector — a remote MCP server that exposes the brain's
scored recall to Claude (web / desktop / iOS / Cowork). Built with the official
@modelcontextprotocol/sdk per Anthropic's
build-mcp-server guidance. Design rationale lives in
brain-cloud/docs/connector-architecture.md.
It lives in this repo (not the npm package — excluded from package.json files, like
website/) so it reuses the real recall engine in ../src directly. One brain, one
engine, two faces.
Status: 🟢 LIVE IN PRODUCTION — Phase 1 + 2 (read + write)
Deployed at https://mcp.brainmemory.ai/mcp (Node service on the VPS beside brain-cloud;
systemd + nginx + certbot — see deploy/). Added at claude.ai and verified on Claude web +
iPhone. Tools: brain_recall, brain_status (read) + brain_memorize, brain_pin,
brain_unpin, brain_forget, brain_verify (write — writes sync back to brain-cloud; hosts gate
them behind confirmation) + brain_use (switch between the account's brains).
Two things to know in production:
- One brain ↔ one Google account — the connector serves the brain of whatever Firebase (Google) identity signs in, so the brain must be pushed to that brain-cloud account. See Identity & accounts below for how the connector now surfaces a wrong / empty / multi-brain account instead of silently serving a phantom brain.
- Sessions renew silently for ~a month — access tokens live 1 h, but the token endpoint issues
rotating refresh tokens (OAuth 2.1: single-use, family-revoked on reuse) with a sliding
30-day window (
CONNECTOR_REFRESH_TTL_MS), so an active user never sees the login page. Each refresh also renews the Firebase credential server-side (securetoken API, from the refresh token captured at login) — so sync-back and TTL re-pulls keep working far past the old ~1 h Firebase ID-token window. Grants + the DCR client registry persist underCONNECTOR_STATE_DIR(systemdStateDirectory; Firebase refresh tokens encrypted at rest viaCONNECTOR_STATE_KEY, our tokens stored hashed), so deploys/restarts no longer log users out. Local CLI memories (brain cloud push) reach an active session automatically via a TTL re-pull (CONNECTOR_REPULL_TTL_MS, default 120s) — it re-pulls only when the cloud checksum changed and never over an unsynced local write.
npm test typechecks and proves the whole path end-to-end in one server — the
complete OAuth 2.1 handshake through to real scored recall (token request is form-urlencoded,
matching real clients):
① unauthenticated MCP call → 401 + WWW-Authenticate (RFC 9728)
② discovery → AS metadata (RFC 8414), PKCE S256
③ Dynamic Client Registration (RFC 7591)
④ authorize → code (iss + state validated, RFC 9207)
⑤ token → audience-bound Bearer (PKCE verified, RFC 8707)
⑥ MCP initialize + tools/list → [brain_recall, brain_status, brain_use, brain_memorize, brain_pin, brain_unpin, brain_forget, brain_verify] (official SDK)
⑦ brain_recall(query) → the brain's REAL scored results (relevance + decayed
strength + spreading activation), identical to the CLI
How recall stays identical to the CLI
The engine bridge (src/engine.ts) runs the repo's bin/recall.js with BRAIN_DIR
pointed at the authenticated user's brain working copy — so the connector's scoring is
byte-for-byte the CLI's, with zero reimplementation. (BRAIN_DIR is the same override
the CLI ships.)
Run / test
npm install
npm test # end-to-end Phase 1 proof
npm start # serve MCP on http://localhost:8788
Tools
| Tool | Kind | Description |
|---|---|---|
brain_recall | read (readOnlyHint) | Ranked recall for a query, scored by the brain engine. |
brain_status | read (readOnlyHint) | Memory count + last-updated for the user's brain, and the account's brains with the one in use marked active. |
brain_use | write (idempotentHint) | Switch which of the account's brains the connector serves, by name or id. Remembered across sessions; copies nothing between brains. |
brain_memorize | write (destructiveHint) | Store the explicit content provided (never the conversation); immediately recallable. |
brain_pin / brain_unpin | write (destructiveHint, idempotentHint) | Move a memory into or out of the always-present tier. |
brain_forget | write (destructiveHint) | Archive a memory (recoverable — moved to _archived/, not hard-deleted). |
brain_verify | write (destructiveHint) | List memories pending verification; approve them, or reject them into the archive. |
Writes reuse the deterministic CLIs (memorize.js / pin.js / unpin.js / forget.js) and then
syncBack() to brain-cloud.
Identity & accounts
One brain ↔ one Google account. The connector has no idea which laptop you're on — it serves the
brain belonging to whatever Firebase (Google) identity completes the sign-in. The verified uid maps
deterministically to a brain user (resolveBrainUserId), and that user's canonical brain is pulled
from brain-cloud: the brain the user chose with brain_use, or else the account's oldest. So the
rule is simple: connect with the same Google account your CLI's brain cloud syncs to, and use
the same brain (brain cloud brains shows which one the CLI is linked to).
To keep that rule from failing silently, ensureUserBrain returns an identity signal that the
tools surface to you:
| Situation | identity.status | What you see |
|---|---|---|
| Account has no brain in Brain Cloud | no-cloud-brain | A note (in brain_status, and in brain_recall when it finds nothing) telling you this account is empty — most likely you signed in with the wrong Google account, or you're brand new. |
| Account has exactly one brain | ok | Nothing — the common, unambiguous case. |
| Account has several brains | multiple-brains | A note naming the brain in use. brain_status lists them all; brain_use switches, and the choice (kept with the OAuth state, per user) holds for later sessions. A chosen brain that is later deleted falls back to the oldest. |
This is guidance, not enforcement — a genuinely new user with no brain yet still gets a usable
empty brain. Account-linking (letting one Google identity span several brains at once) is
deliberately deferred; choosing one brain at a time is brain_use.
Auth
Two layers — both real now:
- OAuth 2.1 between Claude and the connector (
src/oauth.ts): authorize / token / register / metadata, PKCE S256, RFC 8707 audience binding, RFC 9207iss. Tokens mint intosrc/auth.ts's store; the/mcpguard validates them (incl. audience). - Who is the human (
src/firebase.ts):/authorizebounces the user through Firebase login (the same project brain-cloud uses). The connector verifies the ID token server-side and secret-free — RS256 against Google's public certs, checkingaud/iss/exp— so it needs only the public project config, no service-account key. The verifieduidmaps to the brain user, then the OAuth code is minted.
If FIREBASE_* env is not set, /authorize falls back to a fixed dev user
(STUB:FIREBASE) so the headless test runs without a browser.
See the Firebase login work (demo)
cp .env.example .env # fill in FIREBASE_API_KEY / AUTH_DOMAIN / PROJECT_ID
npm start # http://localhost:8788
# then connect an MCP client (e.g. Claude) to http://localhost:8788/mcp —
# the OAuth flow opens the branded Google sign-in page from /authorize
Signing in through /authorize shows the branded consent/login page and, on success, resolves
your verified firebase_uid → brain_user_id → brain_dir — which is how the connector picks
whose brain to serve. (localhost is an authorized Firebase domain by default, so popup sign-in
works locally.)
Per-user store (src/store.ts)
ensureUserBrain({ userId, brainDir, idToken }) populates the user's brain working copy from a
pluggable provider, then the engine recalls over it. Providers (via CONNECTOR_STORE, else
inferred):
brain-cloud(production) — pulls the user's{brainID}.tar.gzfromBRAIN_CLOUD_API_URL(defaulthttps://api.brainmemory.ai) using their Firebase ID token (brain-cloud's middleware accepts it directly), thentar xzfintobrainDir. Refreshed at each login.local(dev) — symlinksbrainDir→$DEV_LOCAL_BRAIN(your live~/.brain), so your machine serves your real brain through the connector.none— assume pre-provisioned (tests).
Always graceful: if the brain is still missing, it empty-inits a valid (recall-safe) brain.
The brain-cloud provider speaks the store contract, so it works
against any store that implements it, including a self-hosted
brain-store. Sync-back is conditional (If-Match): if another
device pushed first, the connector discards its working copy, starts again from the store's
brain, re-applies the write and pushes again, so nobody's memories are overwritten.
Identity providers (src/identity.ts)
Who is logging in, and what the connector presents to the store for them, sits behind one
interface. Select with CONNECTOR_IDP:
-
firebase(the default whenFIREBASE_*is set) — Google sign-in. The store credential is the Firebase ID token, renewed from the Firebase refresh token. -
static— for a self-hosted store. The sign-in page takes the token the store's operator issued (brain-store user add); the store decides who the user is. RequiresBRAIN_CLOUD_API_URLto be set explicitly, so a token can never be sent to the hosted default by accident. Rotating or removing the user at the store ends their sessions at the next silent renewal. -
oidc— for a self-hosted store that accepts your organisation's OpenID Connect issuer (Entra, Google Workspace, Keycloak, Okta)./authorizesends the browser to the issuer (authorization code + PKCE + nonce) and the issuer returns it to/oidc/callback. The ID token is the store credential, renewed from the issuer's refresh token. NeedsOIDC_ISSUER,OIDC_CLIENT_IDand an explicitBRAIN_CLOUD_API_URL. Token verification is the store's own (store/lib/oidc.js), so the two can never disagree about what a valid token is. An issuer outage answers503and keeps the login; a revocation ends it.
With no provider configured the connector refuses to start in production. When the reverse
proxy is not on loopback (another container, say), name it with CONNECTOR_TRUST_PROXY, for
example uniquelocal; true is refused.
Next
- Account-linking — let one user span several brains at once (recall across them), rather than serving one chosen brain at a time. See Identity & accounts.
- Directory submission — remaining manual steps (test account, MCPB packaging, launch post); see
the submission checklist in
brain-cloud/docs/connector-architecture.md§7.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.