Connected in 60 seconds.
Smara is MCP-native: one config block gives any MCP-compatible agent — Claude Code, Claude.ai, Cursor, your own — durable memory that follows it across tools and sessions. It is a plain REST API underneath: same key, same memory, whichever way you call it — and it scores 74.7% on the LoCoMo long-term-memory benchmark, measured on this live service.
Quickstart
Three steps. No SDK, nothing to run.
Get a key
Sign up (email or Google) — your first sign-in creates a tenant. Mint an API key in the portal; it is shown exactly once.
Sign up freeAdd one block to your agent's MCP config
Hosted and stateless — nothing to install, nothing to run locally. Your agent discovers seven memory tools on connect.
{
"mcpServers": {
"smara": {
"type": "http",
"url": "https://api.smara.dev/mcp",
"headers": { "Authorization": "Bearer smara_live_…" }
}
}
}Teach your assistant the memory discipline
In Claude, install the smara-memory Skill — it carries the full discipline: recall-first, honest importance calibration, corrections via supersession, per-assistant session prefixes, and domain-scoped recall. The /claude page walks through connector, Skill, and first phrase as one flow. Anywhere Skills aren't supported, paste this condensed version into the system prompt or custom instructions instead.
The 3-step Claude setupYou have long-term memory via the Smara tools.
At the start of a conversation, call get_context with the user's
first message as the query. Trust what comes back: it is what you
already know.
As you work, record what happens with capture_event -- decisions,
stated preferences, tasks completed, problems hit. Write it when it
happens, not at the end. Rate importance honestly (0.8+ identity
facts, ~0.5 preferences, ~0.2 details) and set session_end=true on
a session's final event.
When you learn a durable fact outright, store it with remember_fact.
When you need something specific, use search_facts. Don't announce
any of this; just use your memory naturally.MCP
One config block, seven tools.
The MCP endpoint lives at https://api.smara.dev/mcp — hosted and stateless, nothing to run locally. It authenticates with the same smara_live_… key as the REST API, sent as a bearer token.
Tools are thin wrappers over the same handlers the REST routes use, so the two surfaces cannot drift apart: what a tool writes, a REST call reads, and vice versa.
get_contextThe per-turn read: everything relevant, packed to a token budget.capture_eventRecord what happened to the durable episodic log.append_turnAdd a turn to the ephemeral recent-turns window.remember_factWrite a durable fact directly; supersede to correct one.search_factsVector search over what is true now.search_eventsSearch what happened, by vector or keyword.patch_scratchpadMerge into the session's short-term working state.
{
"mcpServers": {
"smara": {
"type": "http",
"url": "https://api.smara.dev/mcp",
"headers": { "Authorization": "Bearer smara_live_…" }
}
}
}Try it
A chat agent with memory, in one call.
The fastest way to feel what Smara does: a terminal chat agent where Claude connects to your memory tenant through the Anthropic API's server-side MCP connector. No local MCP client, no tool loop — the API dials api.smara.dev/mcp itself, using your Smara key as the bearer token.
Tell it a few things about yourself, quit, start a fresh session and ask what it knows about you. That round trip exercises capture, consolidation, vector recall and reinforcement — then watch the facts (and their access counts) in the portal.
A fuller version — streaming, tool-call tracing, pause/resume handling — ships in the repo as examples/memory_chat.py.
# pip install anthropic
# export ANTHROPIC_API_KEY=… SMARA_API_KEY=smara_live_…
import anthropic, os
client = anthropic.Anthropic()
messages = []
while (user_input := input("you> ")):
messages.append({"role": "user", "content": user_input})
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=16000,
system="You have long-term memory via the Smara tools. "
"Recall with get_context; store durable facts "
"with remember_fact.",
messages=messages,
betas=["mcp-client-2025-11-20"],
mcp_servers=[{
"type": "url",
"name": "smara",
"url": "https://api.smara.dev/mcp",
"authorization_token": os.environ["SMARA_API_KEY"],
}],
tools=[{"type": "mcp_toolset", "mcp_server_name": "smara"}],
)
messages.append({"role": "assistant", "content": response.content})
print(next(b.text for b in response.content if b.type == "text"))REST
The three calls you actually need.
Every MCP tool exists as a REST endpoint, but a working integration is three of them: read context in, write events out, and search what you know. The rest is in the API reference.
Read context
Everything relevant to this turn, packed to a token budget.
export SMARA_API_KEY="smara_live_…"
curl -G "https://api.smara.dev/v1/context" \
-H "Authorization: Bearer $SMARA_API_KEY" \
--data-urlencode "session_id=sess_9f21" \
--data-urlencode "query=hello" \
--data-urlencode "agent_id=support-copilot" \
--data-urlencode "token_budget=1000"Write what happens
Consolidation turns events into facts and graph structure.
curl "https://api.smara.dev/v1/sessions/sess_9f21/events" \
-H "Authorization: Bearer $SMARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "tool_call",
"content": "Looked up the CRM record for org acme.",
"agent_id": "support-copilot",
"importance": 0.6
}'Search your facts
Vector search over what is true now, ranked by use.
curl -G "https://api.smara.dev/v1/semantic/search" \
-H "Authorization: Bearer $SMARA_API_KEY" \
--data-urlencode "q=what stack does acme use" \
--data-urlencode "limit=5"Multi-agent
Shared pools and change webhooks.
Two primitives turn single-agent memory into team memory: pools let agents share memory deliberately, and webhooks tell them when it changes.
Memory pools
Create a pool in the portal, grant it to keys at creation (grants become pool:<id>:read|write scopes). Reads stay private by default — pass pools= to include a pool; write into one with pool_id, and facts consolidated from that session inherit it. A pool fact can never supersede a private one, or vice versa.
# read: private memory + the shared pool
curl -G "https://api.smara.dev/v1/context" \
-H "Authorization: Bearer $SMARA_API_KEY" \
--data-urlencode "session_id=sess_9f21" \
--data-urlencode "query=what do we know about acme" \
--data-urlencode "pools=support-fleet"
# write: capture into the pool (needs pool:support-fleet:write)
curl -X POST "https://api.smara.dev/v1/sessions/sess_9f21/events" \
-H "Authorization: Bearer $SMARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "user_statement",
"content": "Acme upgraded to the scale plan",
"pool_id": "support-fleet"}'Memory-change webhooks
Register an HTTPS endpoint and Smara POSTs signed events — fact.created, fact.superseded, fact.expired, consolidation.completed. Payloads carry ids and counts, never memory content; delivery is at-least-once, so dedupe on the event id. Emission is best-effort: treat webhooks as a wake-up signal, not a ledger.
import hmac, hashlib, time
def verify(secret: str, body: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False # stale: possible replay
expected = hmac.new(
secret.encode(),
f"{parts['t']}.".encode() + body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
# header: request.headers["X-Smara-Signature"] -> "t=...,v1=..."Chat apps
Connect from any chat app.
Every major chat app can use Smara as a custom connector — they just differ in how much you have to paste. Either way, the server URL is the same: https://api.smara.dev/mcp.
Claude & Grok — zero config
Paste https://api.smara.dev/mcp as the connector or MCP URL and you are done. Both apps speak OAuth client discovery (CIMD): they register themselves, run the PKCE flow, and send you to Smara's consent screen automatically. No client ID, no secret, nothing to mint.
Gemini & ChatGPT — one credential
Their connector forms ask for a pre-registered OAuth client ID and secret. Mint one under Portal → Connectors — the app preset pre-fills that app's callback URLs — then paste all three values into the form. The secret is shown once at creation; revoking the client stops new sign-ins and token refreshes.
Server / MCP URL: https://api.smara.dev/mcp
Client ID: (from Portal -> Connectors)
Client secret: (shown once at creation)Portability
Arrive with two years of memory, not zero.
Your ChatGPT, Claude, and Gemini history is memory raw material. Download the official data export from each provider, run smara-import, and consolidation distills years of conversations into durable facts and a knowledge graph — dated when they actually happened, not when you imported them.
No export file handy? The smara-migrate Skill takes a different route: it has Claude recall everything durable it already knows about you and save it to Smara through the connector — the assistant itself is the migration tool, one conversation, no files.
Imports are idempotent server-side: re-running the same export is a no-op, and a fresher export ingests only what is new. Behind it is POST /v1/conversations — a provider-neutral upsert any client can use for live capture. The matching GET /v1/export streams everything back out — facts, graph, events, the full revision audit trail (dream edits included), your import registry, pools, and skills: memory that travels with you, in both directions.
# get the CLI (stdlib-only, no pip installs)
curl -LO https://smara.dev/downloads/smara-import.zip
unzip smara-import.zip && cd smara-import
export SMARA_API_KEY=smara_live_…
# preview what would be imported (writes nothing)
python3 -m smara_import chatgpt ~/Downloads/chatgpt-export.zip \
--user-id curioso --dry-run
# import for real — safe to re-run any time
python3 -m smara_import chatgpt ~/Downloads/chatgpt-export.zip --user-id curioso
python3 -m smara_import claude ~/Downloads/claude-export.zip --user-id curioso
python3 -m smara_import gemini ~/Downloads/Takeout.zip --user-id curiosoAuthentication
Two callers, two credentials.
Agents call the data plane with a per-tenant API key: Authorization: Bearer smara_live_…. A key resolves to exactly one tenant and carries scopes such as memory:read and memory:write.
People call the control plane — tenants, members, keys — with a Firebase ID token from the portal session. Control-plane endpoints will not accept an API key, and data-plane endpoints will not accept an ID token.
Secrets are shown once at creation and stored only as a SHA-256 hash. There is no endpoint that returns a key secret, including to the person who created it. Lose it and you revoke and reissue.
The quickest sanity check that a key works: any of the three calls above returns 200 with it and 401 without. The same key connects over MCP and REST — one credential, both surfaces.
What is here today
The interactive API reference is live and generated from the service itself. Long-form guides — consolidation tuning, graph modelling, retention policy — are still being written. Until they land, the reference plus the architecture page are the complete picture.