Skip to main content
store_memory is an MCP tool, exposed by @sovseal/mcp-server. It is built around a single operational principle: no tool call ever blocks on I/O. It redacts, embeds, encrypts, writes to the local LanceDB index, and returns — without waiting for the replication endpoint.
store_memory is exposed as an MCP tool by @sovseal/mcp-server. @sovseal/sdk (v1.0.0+) and sovseal-sdk (v1.1.0+) also expose store(content) via framed IPC to the local native host (~/.sovseal/native-host/run.sh). If the native host is absent, version-mismatched (protocolVersion: 1), or times out, SDK calls throw/raise EngineUnavailableError (reason: "not-installed" | "version-mismatch" | "timeout") with zero cloud fallback. See Quickstart.

The write contract

Reproduce these numbers: pnpm --filter @sovseal/mcp-server test bench-v2.

Arguments

That is the entire input schema — a single non-empty content string, length-capped by STORE_MEMORY_MAX_CHARS. There is no path, no metadata, and no parent argument.

Return value

  • id — the local record identifier.
  • reinforcedtrue when the content matched an existing memory closely enough to increment reinforce_count instead of inserting a new row.
  • redacted / redactedRules — how many high-risk PII matches were masked before embedding, and which rules fired. The matched values are never returned or logged.

The write pipeline

1

Redact high-risk PII

Content passes through the redaction chokepoint before anything else. The always-on trio — SSN, Luhn-validated credit cards, and provider API keys — is masked to [REDACTED:…] tokens. The secret therefore never reaches the vector, the stored row, or the sync envelope.
2

Embed on-device

The cleaned text runs through the local Xenova/all-MiniLM-L6-v2 ONNX model (quantized, ~22 MB, auto-downloaded to ~/.sovseal/models/ and SHA-256 pinned), producing a 384-dimensional vector. The embedding is stored locally and is never sent to the server.
The MCP server and the browser extension currently run different embedders (Xenova/all-MiniLM-L6-v2 vs. intfloat/multilingual-e5-small) — a same-day integrity-pinning fix reverted a brief mid-development unification. The two surfaces do not currently share one vector space. See logs/escalation/EMBEDDER-minilm-e5-prefix-mismatch.md.
3

Encrypt at rest

The text field is sealed with AES-256-GCM under k_rest — envelope format sgcm1: + base64(IV‖ciphertext‖tag), with a per-row 96-bit IV and AAD = utf8(id|schema_version). The key is an HKDF subkey of a master that lives in your OS keychain.
4

Write to LanceDB, or reinforce

If an identical fact already exists, reinforce_count and last_reinforced are updated instead of inserting a duplicate. Otherwise a new Schema-v2 row is written.
5

Enqueue replication and return

The record enters the write-behind outbox and the call returns. A background SyncWorker seals the snapshot under k_sync and pushes ciphertext to the edge endpoint.
Embedding vectors remain in the clear on the local disk. Only text is encrypted at rest. This is a documented residual, not an oversight — see Zero-Knowledge.

Calling it


Failure modes

The design invariant: replication failures can never lose or block a local write.

What reaches the server

Only what is needed to store and later restore an opaque blob:
  • agent_idsha256(project_id ‖ ":" ‖ key). The server never learns the raw key name.
  • ciphertext — AES-256-GCM sealed under k_sync.
  • client_payload_hashsha256(canonicalize(payload)), the integrity anchor for Verified Semantic Recall.
  • sequence_number, parent_snapshot, timestamp — lineage metadata.
Never sent: the plaintext, the encryption key, or the embedding vector.

Next steps

recall_memory

How stored records become ranked query results — locally, with zero RTTs.

Verified Semantic Recall

What prevents a malicious server from substituting your ciphertext on restore.