Skip to main content
Glama

memalyze

MCP-native, self-hosted memory for AI agents — with the governance an enterprise will actually ask for.

One static binary. Local embeddings. No cloud, no graph database, no Python stack. Redaction happens before anything is written; every read is audited.

Website · MCP Registry · v0.1.0

./memalyze          # MCP over stdio, for Claude Code / Cline / any harness

v0.1.0 is out — static binaries for linux/darwin/windows, checksums published alongside.

memalyze governance demo


The problem

Every agent framework ships its own memory: a vector table here, a JSON file there, a "notes" folder somewhere else. Three things follow, and all three hurt in production:

  1. You cannot audit it. "Which customer's data did the agent read last Tuesday?" has no answer, so security review stops the project.

  2. You cannot deploy it offline. Most options either call a cloud API or download model weights from HuggingFace at runtime — both fail inside a bank, a hospital, or a factory.

  3. You cannot keep it small. Twenty-three tools, a graph database, and a Python dependency tree later, the "memory feature" is a second product to operate.

memalyze is the middleware that fixes those three, and nothing else.

Related MCP server: Centralaizer

What is different

Cloud memory APIs

Framework built-ins

Personal note apps

memalyze

Where data lives

vendor cloud

inside the framework

local Markdown

your server / your laptop

How to connect

proprietary API

tied to one framework

MCP

MCP, any harness, stdio or HTTP

Redaction before write

❌

❌

❌

✅ 8 rule families, configurable, irreversible by default

Read audit

partial

❌

❌

✅ append-only*, per-actor, exportable

Offline

❌

partial

⚠️ model download needed

✅ local embeddings, no network

Deployment

SaaS

with the framework

173 Python packages

✅ one static binary / one compose file

Tool surface

—

—

23 tools

4 tools

* A database trigger rejects UPDATE on audit_log; DELETE is not blocked, so anyone with the database file can remove rows. It is append-only at the SQL level, not WORM — export to object-lock or syslog storage if deletions are inside your threat model (SECURITY.md).

Not another mem0, and not Basic Memory either: those are good at remembering. memalyze assumes remembering is becoming a commodity and competes on governance, offline operation, and a deliberately small surface.

30-second demo

No Ollama, no network, no MCP client:

./examples/demo/demo.sh
# or: go run ./cmd/memalyze demo

It writes a memory containing a phone number, an e-mail and a resident ID, then shows:

  • what is actually stored ([REDACTED:phone], not 13800138000);

  • that searching for the original number returns 0 hits;

  • that a business-word search still hits, returning the redacted text;

  • the audit rows for the two writes and the two reads.

Details and transcripts: docs/s15-redaction-audit.md.

Quick start

1. Binary + local embedding model

Prebuilt, checksum-verified (Linux/macOS; Windows: take the .exe from the release page):

curl -fsSL https://raw.githubusercontent.com/mahaoboy/memalyze/main/scripts/install.sh | sh
ollama pull qwen3-embedding:0.6b      # ~640 MB, 1024-dim, strong on Chinese
memalyze --version

From source (Go 1.27+): make build, then ./memalyze --version.

2. Wire it into a harness

Claude Code (project scope):

claude mcp add --scope project memalyze -- "$(pwd)/memalyze"
cp examples/claude-code/CLAUDE.md ./CLAUDE.md   # makes Claude search before answering

Cline: copy examples/cline/cline_mcp_settings.json and .clinerules. Generic harness: examples/custom-harness/ — one prompt contract plus pseudocode. All options: examples/README.md.

3. Or one-click in Claude Desktop (MCPB)

Download the bundle for your platform from the v0.1.0 release and open it. Claude Desktop shows an install sheet and asks where to keep memalyze.db.

Platform

File

macOS Apple Silicon

memalyze-0.1.0-darwin-arm64.mcpb

macOS Intel

memalyze-0.1.0-darwin-amd64.mcpb

Windows x64

memalyze-0.1.0-windows-amd64.mcpb

Linux x64

memalyze-0.1.0-linux-amd64.mcpb

The binary inside is the same v0.1.0 build as above. These bundles are new and have not been opened on a real macOS/Windows desktop yet — if the install sheet does not appear, use the plain binary. The server is also listed in the MCP Registry.

4. Or run it in Docker (memalyze + Ollama + model pull)

printf 'MEMALYZE_HTTP_TOKEN=%s\n' "$(openssl rand -hex 24)" > .env
docker compose up -d --build
curl -s http://127.0.0.1:8080/healthz     # {"status":"ok","version":"dev"}

Point a Streamable-HTTP MCP client at http://127.0.0.1:8080/mcp with Authorization: Bearer $MEMALYZE_HTTP_TOKEN. See docs/s16-docker.md.

Tools

Four, on purpose. Every extra tool is a decision the model has to make.

Tool

What it does

Notable semantics

memory_add

store a memory

duplicates return the existing id; embedding failure keeps the memory (embedding_failed=true); returns redacted + rule names

memory_search

retrieve

vector first, keyword backfill, degraded + degrade_reason when the vector path is unavailable; empty query lists recent

memory_delete

soft delete

idempotent for already-deleted ids; unknown id returns a tool error

echo

wiring check

proves the MCP link works; no business logic

There is no memory_context tool: memory_search already returns text you can paste into a prompt, and two overlapping tools make model choice worse (D-017).

Governance

Redaction (write path). Rules run in memory.Service.Add before dedup, FTS and embedding — so plaintext never reaches the main table, the full-text index or a vector.

Rule

Example input

Stored as

private_key_block

-----BEGIN RSA PRIVATE KEY-----…

[REDACTED:private_key]

id_card_cn

110101199003071234

[REDACTED:id_card]

bank_card

6222021234567890123

[REDACTED:bank_card]

jwt

eyJhbGciOi…

[REDACTED:jwt]

api_key_known_prefix

sk-…, ghp_…, AKIA…

[REDACTED:api_key]

credential_assignment

api_key=abcdef123456

api_key=[REDACTED:credential]

email

a@b.com

[REDACTED:email]

phone_cn

+86 13800138000

[REDACTED:phone]

Modes: enforce (default), dry-run (count only, for tuning), off (debugging). Custom rule packs are JSON: examples/redaction-rules.json.

Audit (read path). Append-only audit_log (a database trigger rejects UPDATE): actor, tenant, scope, action, memory id, timestamp, result count, degraded, redaction count. The search text itself is stored as SHA-256 + length unless you explicitly set MEMALYZE_AUDIT_QUERY_PLAIN=1.

memalyze audit export --from 2026-10-01 --to 2026-10-31 --format csv --out audit.csv
memalyze audit export --tenant acme --format json

What is not here yet: per-user authentication (one token per process, actor from env), audit retention/purge, reversible redaction, audit UI.

Retrieval, measured

Numbers from S8 on a 60-memory Chinese corpus, 16 queries, measured not assumed (docs/s8-retrieval-report.md):

Approach

recall@3

MRR

qwen3-embedding:0.6b (default)

0.94

0.92

CJK bigram FTS5 (keyword backfill)

0.88

—

nomic-embed-text

0.47

—

Two counter-intuitive findings that shaped the design: SQLite FTS5's default tokenizer cannot search Chinese at all (0.19 recall until we stored bigram text), and RRF fusion scored worse than vector-only, so v0.1 does not fuse. See D-012.

Latency (S14, cold start fixed): warmup 37.8 s in background, then search 1.14 s with degraded=false; after five idle minutes a fresh process answers in 1.52 s. If the vector path is unavailable, search degrades to keyword in ≤3 s instead of hanging (D-015/D-018).

How it works

harness (Claude Code / Cline / your agent)
   │  MCP: stdio or Streamable HTTP
   ▼
internal/mcp     4 tools, argument conversion only
   ▼
internal/memory  redact → dedup → store → embed; search: vector → keyword → degraded
   ├── internal/govern     rule engine (8 families, JSON configurable)
   ├── internal/store      interface; sqlite impl (memories, embeddings, audit_log)
   ├── internal/embed      float32 BLOB codec, cosine; Ollama client
   └── internal/search     CJK bigram tokenizer + FTS5 MATCH builder
  • SQLite (WAL) with ULID ids, partial unique index for dedup, soft delete, TTL.

  • Vectors are float32 little-endian BLOBs; search is brute-force cosine (fine under ~10k memories, and the honest limit of a single-binary design).

  • Schema migrations are versioned via PRAGMA user_version (v1 → v2 adds the audit table).

Operations

memalyze audit export --from 2026-10-01 --format csv --out audit.csv   # who read what
memalyze backup --out /var/backups/memalyze-$(date +%F).db             # consistent snapshot
memalyze health --url http://127.0.0.1:8080/healthz                    # probe

Configuration

All through environment variables; defaults work out of the box.

Variable

Default

Meaning

MEMALYZE_DB

./memalyze.db

SQLite path

MEMALYZE_TENANT

default

default tenant for tool calls

MEMALYZE_OLLAMA_URL

http://127.0.0.1:11434

local embedding endpoint

MEMALYZE_EMBED_MODEL

qwen3-embedding:0.6b

embedding model

MEMALYZE_QUERY_TIMEOUT

3s

vector-path budget before degrading

MEMALYZE_KEEP_ALIVE

30m

Ollama model residency

MEMALYZE_REDACT_MODE

enforce

enforce / dry-run / off

MEMALYZE_REDACT_RULES

(built-in)

path to a JSON rule pack

MEMALYZE_AUDIT

on

append audit rows

MEMALYZE_ACTOR

local

actor recorded in audit

MEMALYZE_AUDIT_QUERY_PLAIN

off

store query text (default: hash only)

MEMALYZE_HTTP_ADDR

(empty = stdio)

e.g. :8080 for Streamable HTTP

MEMALYZE_HTTP_TOKEN

(empty)

Bearer token; required when binding off-loopback

Status

Honest snapshot — this is an early-stage project, not a 1.0.

Milestone

State

M0 立项与定位 (S1–S4)

✅

M1 备料与技术验证 (S5–S8)

✅

M2 核心链路 (S9–S14)

✅

M3 打磨与文档 (S15–S19)

✅ S15 governance, S16 Docker, S17 docs, S18 tests+CI, S19 examples

M4 发布 (S20–S23)

🟡 S20 ✅, S21 ✅ (v0.1.0 public), S22 GitHub ✅ / HN·Reddit·V2EX pending, S23 ⬜

M5 复盘 (S24)

⬜ needs real users

M5 复盘 (S24)

⬜

Known gaps: no per-user auth, no audit retention, the Docker image has not been built in CI (no daemon in the dev environment), brute-force vector scan, Chinese-first defaults (English works, but the tokenizer is tuned for CJK).

Docs

Doc

What it covers

docs/s15-redaction-audit.md

rules, modes, audit schema, demo transcript

docs/s16-docker.md

compose stack, token policy, verification status

docs/s16-systemd.md

hardened systemd unit, env file, backup/restore

docs/s8-retrieval-report.md

the 11 retrieval approaches and why this one won

docs/s13-context-injection.md

the prompt contract that makes models search

docs/s14-end-to-end.md

real harness, two sessions, cold-start numbers

docs/s21-distribution.md

release artifacts, channels, post-release checklist

docs/s21-submissions.md

copy-paste entries for MCP directories and ClawHub

docs/s23-feedback-log.md

live feedback log (currently empty, honestly)

docs/s24-review.md

the milestone review template (not yet filled)

SECURITY.md

threat model: what is defended, what is out of scope

Pilot

Two-week pilot: we install memalyze in your environment, tune the redaction rules to your data, review the audit export with you, and write down the threat-model gaps we find. No fee; you keep the deployment and the notes.

Request a pilot · Integration notes

Non-goals

  • Not a SaaS: you self-host, we do not hold your data.

  • Not an agent framework: it never takes over the harness.

  • Not a knowledge graph: no entity extraction pipeline, no graph database.

  • Not feature-maximal: four tools, one binary, and a hard "no" to anything that needs an operator.

License

AGPL-3.0-or-later (LICENSE). Commercial licensing for embedding in closed products: open an issue titled commercial license.

Contributions: see CONTRIBUTING.md. Security reports: see SECURITY.md.

Available Tools

4 tools
echoA

Echo the given text back unchanged. Used to verify the MCP wiring.

NameRequiredDescriptionDefault
textYesthe text to echo back

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does state the key behavioral fact: the input is returned unchanged, so the tool is side-effect free and deterministic. It doesn't discuss failure modes or payload limits, but for a trivial echo this covers the essential contract.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the behavior stated first and the diagnostic purpose second. Nothing could be removed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, no-side-effect tool with no annotations and no output schema, the description supplies everything an agent needs: what it returns and why it exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter with 100% schema description coverage ("the text to echo back"), so the schema already fully documents it. The description adds nothing beyond that — "the given text" merely restates it — so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (echo) and resource (the given text) plus the exact transformation — returned unchanged — and adds that it exists to verify MCP wiring, which separates it completely from the memory_* siblings. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Used to verify the MCP wiring" gives a clear triggering context: call this to test connectivity/plumbing. It doesn't explicitly exclude other uses or name alternatives, but for a single-purpose diagnostic tool the guidance is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_addA

Store a memory for later retrieval. Returns duplicate=true when identical content already exists (no new record), and embedding_failed=true when the memory was saved but vectorization failed (keyword search still works).

NameRequiredDescriptionDefault
kindNooptional kind: fact, preference, episode, or note; defaults to note
scopeNooptional scope, for example project:opc; defaults to 'default'
contentYesthe memory text to store
ttl_hoursNooptional time-to-live in hours; 0 means the memory never expires

Output Schema

NameRequiredDescription
idYesthe id of the stored (or already existing) memory
dry_runYestrue when redaction ran in dry-run mode and the content was stored unchanged
embeddedYestrue when a vector was written for this memory
redactedYestrue when the content hit redaction rules before being stored
duplicateYestrue when identical content already exists in the same tenant/scope; no new record was written
redactionsYesnames of the redaction rules that matched; never contains the original text
embedding_errorNothe vectorization error, present only when embedding_failed is true
embedding_failedYestrue when the memory was saved but vectorization failed; keyword search still works

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose genuinely useful behavior beyond the schema: duplicate detection yields duplicate=true with no new record, and partial failure yields embedding_failed=true while keyword search still works. What's missing is dedup semantics (is identity based on content alone or content+scope?), whether the call is idempotent, and any permission or rate-limit expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the core purpose front-loaded and the return-flag caveats following. Every clause conveys actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so explaining return values isn't strictly required (though the flags provided are useful). For a mutation tool with no annotations, the description adequately conveys the failure model, but it stops short of stating whether writes are irreversible, how duplicates are keyed, or how expiration behaves — gaps an agent would want before writing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so kind, scope, content, and ttl_hours are already documented in the schema. The description adds no additional meaning about parameter behavior — notably nothing on how scope interacts with duplicate detection or on ttl_hours expiry semantics. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Store a memory for later retrieval." It's immediately distinguishable from memory_search and memory_delete by name and verb. However, it never explicitly contrasts itself with those siblings or clarifies boundaries (e.g., add vs. update semantics).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"for later retrieval" implies the write-then-search workflow with memory_search, but there is no explicit when-to-use/when-not, no naming of alternatives, and no guidance on prerequisites such as whether a matching memory should be searched for first. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_deleteA

Soft-delete a memory by id. Already-deleted ids are idempotent; an unknown id returns an error instead of pretending to succeed.

NameRequiredDescriptionDefault
idYesthe id of the memory to delete

Output Schema

NameRequiredDescription
deletedYestrue when the memory is deleted (already-deleted ids are idempotent)

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses that deletion is soft (recoverable), that repeated calls on an already-deleted id are idempotent, and that an unknown id raises an error rather than silently succeeding. What's missing is auth/permission requirements and whether the memory can be restored and how.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with the core action front-loaded and the edge-case semantics immediately after. No filler, no restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values need no explanation, and the description covers the two failure modes an agent must anticipate (idempotent re-delete, unknown-id error). For an unannotated mutation tool, the only real gap is permission/authorization context and recoverability.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter is already documented as "the id of the memory to delete", so the schema does the work. The description only echoes "by id" without adding format, source, or example values, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and qualifier ("Soft-delete") plus the resource ("a memory") and the lookup key ("by id"). This is immediately distinguishable from siblings memory_add and memory_search, and the soft-delete qualifier alone tells an agent this is not a hard purge.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the verb — an agent knows to call this when removing a memory — but there is no explicit statement of when to prefer it, no prerequisites, and no mention of alternatives or how to recover a soft-deleted memory. The idempotency note is behavioral rather than usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updates
    • First observedecho
    • First observedmemory_add
    • First observedmemory_delete
    • First observedmemory_search

TDQS

A4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: echo is a wiring check, while memory_add, memory_delete, and memory_search map to separate lifecycle operations on a single resource. Descriptions reinforce the boundaries (e.g., soft-delete vs. store vs. hybrid search).

Naming Consistency4/5

The three core tools follow a clean memory_verb snake_case pattern. echo is the only deviation, but as a conventional diagnostic utility it does not create confusion.

Tool Count4/5

Four tools is slim but reasonable for a focused memory store; each earns its place except arguably echo, which is a wiring diagnostic rather than a memory operation. Not thin enough to be a mismatch.

Completeness4/5

Add, search (with list-recent fallback), and delete cover the core lifecycle, but there is no get-by-id or update/edit operation, so an agent cannot correct or inspect a specific memory without going through search. These are minor workaround-able gaps assuming memories are effectively immutable.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Self-hosted semantic memory for AI agents. Save worklogs, decisions, and notes via MCP, then recall them across sessions by meaning rather than keyword. Backed by Postgres + pgvector with local embeddings (multilingual-e5-base).
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Embedded memory and retrieval engine for AI agents, providing local-first memory with MCP support for multi-agent access control.
    3
    16 PyPI
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An offline-first, governed memory and knowledge server for AI agents that provides Remember, Search, Update, and Forget operations with hybrid retrieval, semantic embeddings, and NID-based authentication. It can be used as an MCP server via stdio or Streamable HTTP, enabling agents to persist and query memories and wiki knowledge.
    Apache 2.0