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
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.reinforced—truewhen the content matched an existing memory closely enough to incrementreinforce_countinstead 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_id—sha256(project_id ‖ ":" ‖ key). The server never learns the raw key name.ciphertext— AES-256-GCM sealed underk_sync.client_payload_hash—sha256(canonicalize(payload)), the integrity anchor for Verified Semantic Recall.sequence_number,parent_snapshot,timestamp— lineage metadata.
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.