Skip to content

About

A transparent, Markdown-backed, L0-L3 tiered hybrid memory system for AI agents with CBT safety and enterprise multi-tenancy support. Powered by MCP. 中文:为 AI Agent 打造的透明 Markdown 白盒与 L0-L3 分层混合记忆系统,兼顾 CBT 心理安全与企业级多租户支持,由 MCP 驱动。

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

strata-memory

strata-memory

License MCP

English · 简体中文

It remembers why you decided.

When a fact changes, strata does not overwrite the row. The previous memory is archived and linked (supersedes_id / superseded_by). A decision_record keeps the choice, the date, and what it replaced, so a later session can explain why the current fact is the current fact.

{
  "user_id": "user_001",
  "memory_type": "decision_record",
  "fact_claim": "On 2026-08-10 the team decided SQLite is the memory source of truth, replacing the Markdown drawers.",
  "confidence_score": 0.95
}

Recall returns a short card. expand_memory_detail loads the chain: the new claim, supersedes_id, and the archived predecessor.


Quickstart

Python 3.11+ and uv. No API key. Text stays on the machine.

uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp

PyPI install (uvx strata-memory-mcp) is coming soon; it does not work until the first release is published. The PyPI project name will be strata-memory-mcp. strata-memory on PyPI is a different package. Do not install that name.

That starts the MCP server on stdio. Data lives in STRATA_PALACE (default ~/.strata/palace). A new palace defaults to the local embedder. A config.json that already names a provider is left alone. Host snippets do not set STRATA_EMBEDDING_PROVIDER, because an environment value overrides the saved palace.

Print a snippet for your host and merge it into the existing config. Do not replace the rest of the file.

uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp setup --host cursor
uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp setup --host claude-code
uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp setup --host claude-desktop
Host Config
Cursor ~/.cursor/mcp.json or .cursor/mcp.json
Claude Code .mcp.json or mcpServers in ~/.claude.json
Claude Desktop Settings → Developer → Edit Config
Hermes ~/.hermes/config.yaml — see skills/strata-memory/references/hermes-config.yaml

Cursor example (setup --host cursor):

{
  "mcpServers": {
    "strata-memory": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/SherryLi-vc/strata-memory", "strata-memory-mcp"],
      "env": {
        "STRATA_PALACE": "${userHome}/.strata/palace"
      }
    }
  }
}

Claude Desktop's snippet is the same shape and is valid JSON. Desktop does not expand ${VAR}; edit the palace path in that file if you need to. Once the package is on PyPI (coming soon), args can shrink to ["strata-memory-mcp"].

Then call strata_init once and strata_doctor. Both report the effective embedding provider, model, and backend. With the default provider, summary.api_key.usable is true because no key is required.

Examples

Commit a preference:

{
  "user_id": "user_001",
  "memory_type": "user_preference",
  "fact_claim": "User prefers the Monokai Pro theme with dark mode in VS Code.",
  "confidence_score": 0.92
}

Recall cards. limit applies to L0, scratch, and every other tier. include_l0 defaults to true.

{
  "user_id": "user_001",
  "query": "Monokai Pro theme dark mode",
  "limit": 3,
  "include_l0": true
}

Expand one id:

{ "user_id": "user_001", "memory_id": "<id from hits>" }

Forget one memory, or a filtered set. A filter does nothing until confirm is true. The row is removed from SQLite and from the vector index, so strata_rebuild_index cannot bring it back.

{ "user_id": "user_001", "memory_id": "<id>" }
{ "user_id": "user_001", "memory_type": "episodic_event", "confirm": true }

Export JSON (MCP export_memories, or the CLI):

uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp export --user user_001 --out memories.json

What the default embedder is

local tries fastembed, then sentence-transformers. If neither is installed, it uses a deterministic hashing embedder: offline, no download, no key. Hashing matches shared words. It does not match paraphrases. scripts/recall_benchmark.py reports literal-overlap and paraphrase scores separately, and it runs the semantic backend only when fastembed is installed.

For a semantic model:

uvx --from 'strata-memory-mcp[local] @ git+https://github.com/SherryLi-vc/strata-memory' strata-memory-mcp

That pulls the optional local extra (fastembed / ONNX). The first run downloads sentence-transformers/all-MiniLM-L6-v2 and needs a network. Offline, that download fails quickly and tells you to set STRATA_LOCAL_EMBED_BACKEND=hash (or STRATA_EMBEDDING_HASH_FALLBACK=1) instead of hanging. After a successful download the weights stay on the machine. The index stores the embedder identity. A provider or model change refuses vector reads and writes until strata_rebuild_index(confirm=true).

Cloud endpoints are opt-in. They receive memory text and recall queries.

Variable Role
STRATA_EMBEDDING_PROVIDER local (default), siliconflow, openai, openai_compatible
STRATA_EMBEDDING_BASE_URL OpenAI-compatible POST /embeddings root. SiliconFlow is https://api.siliconflow.cn/v1
STRATA_EMBEDDING_MODEL Model id
STRATA_EMBEDDING_DIMENSION Vector length. Default 384
STRATA_EMBEDDING_API_KEY or STRATA_API_KEY Required for non-loopback HTTP providers

A config.json that already names siliconflow keeps that provider. Set STRATA_EMBEDDING_PROVIDER=local to switch, then rebuild.

Tools (13)

Tool Use
strata_init Create the palace and SQLite store
commit_memory Write one vetted fact
promote_session Promote that session's scratch rows
recall_context Ranked cards. limit covers every tier. include_l0 controls L0
expand_memory_detail Full text for one id
forget_memory Delete by id, or by filter with confirm=true
export_memories JSON for one user and tenant
strata_doctor SQLite vs index, and whether a key is required
strata_rebuild_index Rebuild vectors from SQLite. confirm=true
strata_stats Layer counts
strata_project Read-only Markdown view
strata_digest Demote or archive. Default dry-run
strata_hygiene Expired rows, hash duplicates, secret scan

memory_type is factual_truth, user_preference, procedure_rule, episodic_event, or decision_record. The first three default to L0.

FAQ

Where do memories live?
SQLite under STRATA_PALACE (default ~/.strata/palace) stores the source of truth and rebuildable vector index. Markdown from strata_project is a read-only view.

Does this phone home?
Not with the default local provider. A cloud provider or a non-loopback STRATA_EMBEDDING_BASE_URL receives memory text and queries.

Why is a fact different from last month?
Look at decision_record rows and at supersedes_id / superseded_by on the expanded card. The old row is archived, not destroyed, unless you forget_memory.

Can I delete something?
Yes. forget_memory by id, or by memory_type / layer / session_id / query with confirm=true. Deletion is scoped to user_id and tenant_id. A rebuild will not restore deleted rows.

How do I back up?
export_memories or strata-memory export --user USER --out memories.json. strata_project is the Markdown view of the same store.

Does recall dump the whole palace?
No. You pass a query and a limit (1–20). L0 facts, preferences, and procedures are ranked against that query. They are not pinned to the front of the list with a score of 1.

Will it store a password or an API key?
No. By default commit_memory masks a detected secret before anything is stored, embedded or audited: key AKIA… becomes key [redacted:aws_access_key_id], and the response lists what was masked in secrets_redacted. Set "on_secret": "reject" in the palace config.json (or STRATA_ON_SECRET=reject) to refuse such writes with SECRET_DETECTED instead. Detection is pattern-based (cloud and API keys, tokens, private keys, JWTs, passwords, credentials in URLs), so it can miss a secret with no recognizable shape. The quality kernel also rejects emotion-only text, fuzzy times (yesterday, 刚才), and speculation stored as factual_truth. Other memory tools also block or redact secrets; this is a write-time check, not a claim that the feature is unique.

The doctor says the key is missing.
You selected a cloud provider. Set the key in the host environment, not in chat. Or switch STRATA_EMBEDDING_PROVIDER back to local.

Breaking changes in 2.2

  • New installs default to STRATA_EMBEDDING_PROVIDER=local. A saved config.json that names siliconflow (or another provider) is unchanged. A palace file with no embedding block stays on SiliconFlow, which was the historical default.
  • recall_context ranks L0 and scratch with everything else and applies limit to that list. Scores are no longer a constant 1.0. include_l0 is on the MCP tool (default true). current_turn_only still leaves L0 out.
  • The distribution name is strata-memory-mcp. uvx strata-memory installs a different project.

Upgrading from an older version

Indexes built before 2.2.1 have no embedder stamp (l2_vector/embedder.json). After upgrading:

  1. recall_context keeps working, but on the lexical path only. The reply carries fusion.vector_skipped = "EMBEDDER_UNSTAMPED" and a warning. commit_memory still writes to SQLite; it skips the vector until the index is stamped.
  2. Run strata_rebuild_index with confirm=true once. It re-embeds every active memory from SQLite and writes the stamp. With a cloud provider this re-embeds every row, which costs API calls.
  3. Run strata_doctor. embedder_stamp and vector_coverage should both be ok.

strata_rebuild_index without tenant_id rebuilds every tenant. With tenant_id it deletes and re-adds only that tenant's vectors; other tenants are untouched. If the index is unstamped or was built by another embedder, a tenant-scoped call rebuilds all tenants instead (scope: "all", escalated_from_tenant), because the other vectors are unusable anyway. Changing the embedding provider or model still requires a rebuild before vector recall resumes (EMBEDDER_MISMATCH).

Known issues

  • The default install embeds with an offline hashing fallback, which matches shared words, not meaning. Install the local extra (fastembed) for semantic recall.

Develop

git clone https://github.com/SherryLi-vc/strata-memory.git
cd strata-memory
uv sync --extra dev
uv run pytest -v
uv run python scripts/recall_benchmark.py

Packaging check: uv build and uvx twine check dist/*. Publishing is a maintainer action through PyPI Trusted Publishing (see DEVELOPMENT.md, "Releasing"). This repo does not contain a PyPI token.

Architecture: docs/architecture.md · Tools: docs/tools.md · Security: SECURITY.md · 中文: README.zh-CN.md

License

MIT — see LICENSE

About

A transparent, Markdown-backed, L0-L3 tiered hybrid memory system for AI agents with CBT safety and enterprise multi-tenancy support. Powered by MCP. 中文:为 AI Agent 打造的透明 Markdown 白盒与 L0-L3 分层混合记忆系统,兼顾 CBT 心理安全与企业级多租户支持,由 MCP 驱动。

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages