One URL for every MCP client.
Point Claude Code, Cursor, VS Code, Windsurf or Claude Desktop at the hosted server with your key and an end-user header, or add it to claude.ai or ChatGPT and sign in. The model gets 8 memory tools and asks for what it needs.
- URL
- https://api.twinmemory.dev/v1/mcp
- Transport
- Streamable HTTP, JSON responses
- Auth
- Authorization: Bearer <key>, or sign-in (OAuth)
- End user
- X-Twin-Account: <your user's id>, or chosen at sign-in
- Tools
- 8 read; memory_add with a write key or Read and save
Connect in one step
A key from the console and the id of the user whose memory the agent should read. Nothing to install: the server is hosted, and speaks MCP over Streamable HTTP.
Keep the key in an environment variable. Cursor reads ${env:TWIN_MEMORY_API_KEY} from yours.
claude mcp add --transport http twin-memory \
https://api.twinmemory.dev/v1/mcp \
--header "Authorization: Bearer $TWIN_MEMORY_API_KEY" \
--header "X-Twin-Account: user_42"The tools
The same tools the REST API publishes, under the names a model calls them by. Only memory_search ranks and counts as a retrieval; everything that reads by address is free.
| Tool | What it answers | Arguments | Metered |
|---|---|---|---|
| Find | |||
| memory_search | One ranked search: dated facts read from what was added, then whole passages | query, before?, after?, scope? | 1 retrieval |
| memory_grep | Exact substring match, for a quoted phrase similarity would blur | pattern, scope?, limit? | free |
| Read by address | |||
| memory_overview | What this memory holds: its shape, counts and index | none | free |
| memory_ls | The children of one directory, before reading | path | free |
| memory_read | One file by exact path; a wrong path answers with its siblings | path | free |
| memory_around | The passages either side of one, in its own thread | passage_id, width? | free |
| memory_latest | The most recent passages, newest first | k?, place?, after?, before? | free |
| Change over time | |||
| memory_history | What was true of one subject, and when it stopped being | subject, attribute? | free |
| Write, with a write key or a Read and save connection | |||
| memory_add | Saves anything new the person says, on its own, every turn; never secrets | items, wait? | 1 event per item |
The account is never a tool argument
Which memory a call reads comes from the key and the X-Twin-Account header, set once in the client's config, or from the signed sign-in token of a claude.ai or ChatGPT connection. No tool has a field that could name another user.
A model that could name an account could name somebody else's.
POST /v1/mcp
Authorization: Bearer tm_AbC1234…
X-Twin-Account: user_42
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "memory_search",
"arguments": { "query": "Where does Alice live?" }
}
}{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{
"type": "text",
"text": "{\"query\": \"Where does Alice live?\", \"found\": 2, …}"
}],
"isError": false
}
}Writes need a key that writes
A read key lists only the read tools, so an agent handed one cannot change memory. Mint a write key when the agent should save what it learns, and memory_add appears in its tool list.
| Key | Tools |
|---|---|
| Read key | 8 |
| Write key | 9 |
Give your agent a memory in one command.
10,000 events and 1,000 retrievals a month on Free. No card needed.