Skip to content

Quickstart

The reference implementation (@universalmemoryprotocol/core) ships the UMP record format, server ops, MCP/HTTP/file bindings, conformance runner, and store adapters. Endpoints report the highest level they actually prove: the default persistent server is L2 until capability-token enforcement is enabled at the binding boundary.

Add persistent, portable memory to Claude Code, Cursor, Codex, or any MCP host in one line. Add to your MCP client config:

{
"mcpServers": {
"ump": { "command": "npx", "args": ["-y", "@universalmemoryprotocol/core", "ump-memory"] }
}
}

The agent gets ump.remember / ump.recall (plus get / revise / forget / feedback). Memory persists to ~/.ump/memory.ump.json as a portable, signed file with a stable operator identity. Point another tool at the same store - or its export - and your agent keeps everything it learned. Set UMP_HTTP=4000 to also expose the HTTP binding; set UMP_DIR to change the data directory.

Prefer a command line? Install once and drive everything from ump:

Terminal window
npm install -g @universalmemoryprotocol/core
Terminal window
ump memory # persistent MCP memory server (~/.ump)
ump memory --http 4000 # also expose the HTTP binding
ump memory --store markdown # human-editable *.ump.md records
ump serve --http 4000 # ephemeral in-memory reference server
ump import --owner did:key:z... AGENTS.md CLAUDE.md
ump conformance http://localhost:4000
ump demo # the cross-vendor round-trip
ump --help

Don’t want a global install? npx -y @universalmemoryprotocol/core ump <command> works the same.

Terminal window
git clone https://github.com/<org>/universal-memory-protocol
cd universal-memory-protocol
pnpm install
pnpm test # conformance + binding tests
pnpm typecheck

A memory written by one agent, recalled by another, exported to a portable file, re-imported into a third server - signature intact across “vendors”.

Terminal window
node --experimental-strip-types examples/round-trip.ts
import { UmpServer, InMemoryStore, generateKeyPair, rehydrate, file } from "@universalmemoryprotocol/core";
const owner = generateKeyPair();
// Agent A (e.g. Claude Code) writes a correction - signed, content-addressed.
const a = new UmpServer({ name: "claude-code", version: "1", store: new InMemoryStore(), key: owner });
const { id } = await a.remember({
kind: "procedural",
body: { text: "Always run `pnpm gate` before handoff in this repo." },
scope: { owner: owner.did, project: "example/project", agent: "claude-code", visibility: "private" },
provenance: { actor: owner.did, actor_kind: "user", method: "user_correction" },
});
// Export to the portable file format and import into Agent B (e.g. Codex).
const exported = file.exportRecords((await a.recall({ query: "handoff", scope: { owner: owner.did } })).results.map(r => r.record));
const b = new UmpServer({ name: "codex", version: "1", store: new InMemoryStore() });
for (const rec of file.fromJson(file.toJson(exported))) await b.remember(rec);
// B recalls it and rehydrates into context - safely framed as untrusted data.
const hit = await b.recall({ query: "what should I do before I hand off?", scope: { owner: owner.did } });
const { text } = rehydrate(hit.results);
console.log(text);
Terminal window
# MCP over stdio (any MCP host can attach):
node --experimental-strip-types src/bin/serve.ts
# Add the HTTP binding too:
UMP_HTTP=4000 node --experimental-strip-types src/bin/serve.ts

ump-memory keeps a stable operator key and persists records under ~/.ump. Use JSON for a compact portable export, or Markdown for human-editable records.

~/.ump/memory.ump.json
node --experimental-strip-types src/bin/memory.ts
# Markdown directory store: ~/.ump/memory.d/*.ump.md
UMP_STORE=markdown node --experimental-strip-types src/bin/memory.ts

UMP does not require Claude, AGENTS.md, Recall, or Obsidian formats. It can translate them into UMP records so people can try the protocol with memory they already have.

Terminal window
# Import CLAUDE.md, AGENTS.md, or any Markdown file/folder.
node --experimental-strip-types src/bin/import.ts \
--owner did:key:zYourOwner \
--project github.com/you/repo \
--out .ump/import.ump.json \
CLAUDE.md AGENTS.md ~/Documents/main

The import layer currently recognizes:

SourceWhat it becomes
AGENTS.mdprocedural candidate memory
CLAUDE.mdprocedural candidate memory
.recall/context.md and Recall-style exportsimported Recall memory drafts
Obsidian / Markdown folderssemantic candidate memories split by headings
generic Markdown filesportable UMP drafts with filesystem provenance

Every imported record includes provenance.method such as filesystem:claude, so consumers can distinguish imported memory from native UMP writes.

All stores implement the same MemoryStore interface, so UMP stays independent from any one database. JsonFileStore is the default - it benchmarks as the fastest and most faithful baseline. Reach for a vector store (with embeddings enabled) when you need semantic retrieval at scale.

StoreBest fit
JsonFileStoreDefault - portable, signed, fast local persistence
InMemoryStoretests and ephemeral demos
MarkdownDirectoryStorerepo/vault workflows with human-editable files
PostgresStoreproduction SQL with a pg-compatible client
SqliteStoreembedded/local database with a SQLite-compatible client
RedisStoreshared cache / simple server-side persistence
VectorStoreBYO embedding + vector DB client (e.g. sqlite-vec) for semantic recall
QdrantStore, PineconeStore, WeaviateStorehosted vector engines over the same client contract
RecallStoreopt-in: Recall as a richer engine (enable embeddings for semantic recall)

The MCP binding exposes the operations as reserved tools - ump.capabilities, ump.recall, ump.remember, ump.get, ump.revise, ump.forget, ump.feedback. Point any MCP host at the server and the agent can recall on SessionStart / per-turn and remember on corrections.

// example MCP client config
{
"mcpServers": {
"ump": {
"command": "node",
"args": ["--experimental-strip-types", "src/bin/serve.ts"]
}
}
}