Store your first memory
This tutorial stores one memory and gets it back, using any profile from the quick start or installation. There is no REST memory API — every memory operation is an MCP tool call (JSON-RPC), so you talk to the server through an MCP client. Two options below: the MCP Inspector UI, or raw curl against the Streamable HTTP transport.
Option A — MCP Inspector
Section titled “Option A — MCP Inspector”Start the server (any profile), then launch the Inspector from a second terminal:
pnpm inspectorIn the Inspector, connect to your server (for a locally spawned stdio server,
point it at node apps/mcp-server/dist/main.js; for a Streamable HTTP server,
use http://localhost:3000/mcp), open the Tools tab, and run the calls
below.
1. Create a memory
Section titled “1. Create a memory”Call create_memory:
{ "userId": "qp", "content": "ENGRAM uses Postgres as the source of truth; the vector store is a derived index.", "type": "long-term", "tags": ["architecture"]}The response includes the new memory’s id and its version (used later for
updates).
2. Recall it semantically
Section titled “2. Recall it semantically”Call recall:
{ "userId": "qp", "query": "what is the source of truth for memories?"}The stored memory comes back with a relevance score. When embeddings are
unavailable (no reachable provider) or the vector store is down, recall
degrades gracefully and returns { "results": [] } rather than erroring.
With the default ollama provider — an Ollama server running with
nomic-embed-text pulled — you get real hybrid matches with no API key;
openai (with OPENAI_API_KEY) and the deterministic local provider work
too.
3. Inspect it
Section titled “3. Inspect it”Call get_memory with the id from step 1:
{ "userId": "qp", "memoryId": "<id from create_memory>"}4. Update it (optimistic concurrency)
Section titled “4. Update it (optimistic concurrency)”update_memory requires expectedVersion — pass the version you read in
step 3. Blind updates are rejected, and a stale version fails with a
CONFLICT error; re-read the memory and retry with the fresh version:
{ "userId": "qp", "memoryId": "<id from create_memory>", "content": "ENGRAM uses Postgres as the source of truth; vector stores are derived and rebuildable.", "expectedVersion": 1}See the concurrent-writer policy for why this is enforced.
Option B — curl (Streamable HTTP)
Section titled “Option B — curl (Streamable HTTP)”Start the server with the HTTP transport:
DEPLOYMENT_PROFILE=lite \MCP_TRANSPORT=streamable-http \ pnpm --filter mcp-server devThe MCP endpoint is a single route, http://localhost:3000/mcp, keyed by a
per-session mcp-session-id header. First perform the initialize handshake
and capture the session id:
SID=$(curl -sS -D - -o /dev/null \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -X POST http://localhost:3000/mcp \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}' \ | tr -d '\r' | awk -F': ' 'tolower($1)=="mcp-session-id"{print $2; exit}')echo "session: $SID"
curl -sS -o /dev/null \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H "mcp-session-id: $SID" \ -X POST http://localhost:3000/mcp \ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'Then call the tools with tools/call:
curl -sS \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H "mcp-session-id: $SID" \ -X POST http://localhost:3000/mcp \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_memory","arguments":{"userId":"qp","content":"ENGRAM uses Postgres as the source of truth.","type":"long-term"}}}'
curl -sS \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H "mcp-session-id: $SID" \ -X POST http://localhost:3000/mcp \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"recall","arguments":{"userId":"qp","query":"what is the source of truth?"}}}'The
liteprofile is single-user, so it serves HTTP without an auth gate. A multi-tenant (standard) Streamable HTTP server refuses to start withoutAUTH_REQUIRED=true(or an explicitALLOW_UNAUTHENTICATED_HTTP=true); on an authenticated server, add anAuthorization: Bearer <api-key>header to every request — see Provision agent API keys.
Higher-level alternative: remember
Section titled “Higher-level alternative: remember”For agents, the preferred write path is the higher-level remember tool
instead of raw create_memory: it auto-routes short-term vs long-term and
deduplicates, so re-storing the same fact is a safe no-op. See the
MCP tools reference for every tool’s schema.
Next steps
Section titled “Next steps”- MCP client setup — let Claude Desktop or Claude Code make these calls for you.
- Agent memory contract — the conventions agents follow for scopes, tags, and what is memory-worthy.