Kirok Memory

io.github.TadFujiPublished by GitHub account TadFujiv1.4.2Updated Oct 24, 2026

Persistent memory for AI agents - hybrid semantic + keyword recall with autonomous consolidation

The publisher's own server: Memory.fit

VerifiedSTDIODesktop onlyKnowledge & MemoryAI & ML

Overview

AI-generated overview

Gives an AI assistant a persistent, searchable memory store with hybrid semantic and keyword recall, plus autonomous consolidation into insights.

What you can do
Kirok is a local MCP server that stores memories in a SQLite database and retrieves them with hybrid search: semantic KNN and FTS5 BM25 fused by Reciprocal Rank Fusion, with a calibrated similarity floor. Core tools include retain, recall, reflect, smart_retain and consolidate, alongside memory CRUD, mental-model management, bank management and per-bank configuration. A background loop periodically synthesises raw memories into higher-level observations, and startup auto-snapshots plus soft deletes with an audit trail aim to keep data recoverable.
When to use it
Use it when an assistant needs durable memory across sessions rather than re-reading notes each turn, and when you want keyword and semantic recall combined instead of a plain vector store. It suits self-hosted setups where a local SQLite file is acceptable but embedding and LLM inference may go to a cloud API.
Requirements
Local process run via uvx or uv from the PyPI package kirok-mcp; Python 3.12+ and uv. Requires a Google Gemini API key supplied as GEMINI_API_KEY, either in ~/.kirok/.env or in the client's env block. Storage is a local SQLite file at ~/.kirok/memory.db by default; network access is needed for Gemini embeddings and inference. Desktop MCP clients only.
Before you install
Embedding and LLM inference are sent to Google's Gemini API, so memory content leaves the machine even though storage is local; the README states it is not local-first. GEMINI_API_KEY is required and should be kept out of shared configs. Destructive tools exist: forget, delete_mental_model, clear_bank and delete_bank are irreversible, though bank clearing and deletion require confirm=true and otherwise preview. Consolidation lets an LLM decide to remove observations, mitigated by soft deletes…

Installation

In SourceWeft

  1. Open Kirok Memory in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

Kirok

English | 日本語

[tests] [License: MIT] [Python 3.12+] [Version 1.4.2]

Persistent memory for AI agents, over MCP. Kirok (記録, "record") is a Model Context Protocol server that gives an agent a durable, searchable memory: Retain what matters, Recall it with hybrid semantic + keyword search, and Reflect to distil accumulated memories into reusable insights. A background consolidation loop turns raw memories into higher-level observations on its own.

[Kirok demo: retain a memory, then recall it later with hybrid search — consolidated observations shown first]

Why Kirok

Most "agent memory" is either a flat vector store (recall is a bare cosine top-k, no keyword grounding, no forgetting) or a pile of markdown the agent has to re-read every turn. Kirok is a small, self-hostable server that does the retrieval engineering properly:

  • Hybrid retrieval, not just vectors. Semantic KNN and FTS5 BM25 are fused with Reciprocal Rank Fusion, so an exact keyword match and a semantic match reinforce each other instead of competing.
  • A calibrated relevance floor. Naive cosine thresholds don't work on real embedding distributions (see Search quality); Kirok's floor is measured against live data, and there's an evaluation harness to keep it honest.
  • Autonomous consolidation. Memories are periodically synthesised into observations, and destructive LLM decisions are soft-deleted with an audit trail rather than executed blindly.
  • Reliability first. Atomic writes, soft deletes, startup auto-snapshots, and a fail-open background pipeline that never loses a retain.

Not local-first: storage is a local SQLite file you own, but embedding and LLM inference are sent to Google's Gemini API. If everything must stay on-device, Kirok is not for you (yet).

Architecture

mermaid
flowchart TB    client["MCP Client<br/>(Claude Desktop / Claude Code / Cursor / …)"]    subgraph server["Kirok MCP Server (FastMCP)"]        direction TB        tools["19 MCP tools<br/>Retain · Recall · Reflect · consolidate · CRUD"]        pipeline["Hybrid search (RRF) · Smart dedup<br/>Consolidation · Auto-refresh"]    end    subgraph storage["Local SQLite (WAL)"]        direction LR        fts["FTS5 trigram<br/>(BM25 keyword)"]        vec["sqlite-vec<br/>(KNN, brute-force fallback)"]        tables["memories · observations<br/>mental_models · banks · system_events"]    end    gemini["Google Gemini API<br/>gemini-embedding-001 (3072-d)<br/>gemini-2.5-flash-lite"]
    client <-->|"stdio (JSON-RPC 2.0)"| tools    tools --> pipeline    pipeline <--> storage    pipeline <-->|embeddings · entity extraction<br/>reflection · consolidation| gemini

Storage is a single SQLite database at ~/.kirok/memory.db. sqlite-vec provides per-bank vector KNN; if the native extension can't load, Kirok falls back to a NumPy brute-force scan with identical results. See docs/architecture.md for the full design.

🚀 Quick start

Requirements: Python 3.12+, uv (for uvx), and a Gemini API key (free tier is plenty).

Kirok ships on PyPI — nothing to clone. Put your key in ~/.kirok/.env (one line: GEMINI_API_KEY=AIza...), then verify the setup:

bash
uvx --from kirok-mcp kirok-doctor   # offline sanity check

Connect an MCP client

Claude Code CLI:

bash
claude mcp add kirok -s user -- uvx kirok-mcp

Claude Desktop — edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):

json
{  "mcpServers": {    "kirok": { "command": "uvx", "args": ["kirok-mcp"] }  }}

Then restart the client. The server reads GEMINI_API_KEY from ~/.kirok/.env; an env block in the client config also works and takes precedence.

From source (development)

bash
git clone https://github.com/TadFuji/kirok-mcp.gitcd kirok-mcpuv sync                       # installs deps, including sqlite-veccp .env.example .env          # then put your key in it: GEMINI_API_KEY=AIza...uv run kirok-doctor           # offline sanity check of the whole setup

Point your MCP client at the checkout with uv run --directory /absolute/path/to/kirok-mcp kirok-mcp instead of uvx kirok-mcp.

[!TIP] If uv run fails to launch the server (common on Windows or cloud-synced folders — uv run re-syncs on every launch and can hit locked .venv files or an in-use entry-point .exe), invoke the venv's Python directly to skip the sync entirely:

json
{  "mcpServers": {    "kirok": {      "command": "/absolute/path/to/kirok-mcp/.venv/bin/python",      "args": ["-m", "kirok_mcp.server"],      "env": { "PYTHONPATH": "/absolute/path/to/kirok-mcp/src" }    }  }}

On Windows use .venv\\Scripts\\python.exe and double-backslash paths in JSON.

A bundled agent skill in skills/kirok/ teaches the agent when and how to use the memory tools on its own — point your client at skills/kirok/SKILL.md to enable it.

🛠️ Tools

19 MCP tools. One-line summaries below; full parameter tables in docs/tools-reference.md.

Core

ToolPurpose
KIROK_retainStore a memory: entity/keyword extraction + embedding + smart ADD/UPDATE/NOOP dedup
KIROK_recallHybrid semantic + keyword search (RRF), observations shown first
KIROK_reflectSynthesise memories into a mental model (insight), optionally auto-refreshing
KIROK_smart_retainScore importance (1–10) first, then retain only if it clears a threshold
KIROK_consolidateManually run observation consolidation for a bank

Memory management

ToolPurpose
KIROK_get_memory / KIROK_list_memoriesFetch one memory / browse a bank with pagination
KIROK_update_memoryEdit content or context (re-extracts and re-embeds on content change)
KIROK_forgetDelete a single memory (irreversible)

Mental models

ToolPurpose
KIROK_list_mental_models / KIROK_get_mental_modelList / inspect insights from Reflect
KIROK_refresh_mental_modelRe-analyse against current memories
KIROK_delete_mental_modelDelete a mental model (irreversible)

Banks

ToolPurpose
KIROK_list_banks / KIROK_statsList banks with counts / detailed per-bank stats incl. background failures
KIROK_clear_bankDelete a bank's memories + observations (requires confirm=true; previews otherwise)
KIROK_delete_bankDelete a bank entirely (requires confirm=true; previews otherwise)

Config

ToolPurpose
KIROK_set_bank_config / KIROK_get_bank_configSet / view a bank's retain & observation "missions" (what to focus on)

⚙️ Configuration

Everything is set via environment variables (typically in .env). Only GEMINI_API_KEY is required.

VariableDefaultDescription
GEMINI_API_KEY—Required. Google Gemini API key.
KIROK_DB_PATH~/.kirok/memory.dbSQLite database location.
KIROK_DEDUP_THRESHOLD0.85Cosine similarity above which retain invokes the LLM dedup (ADD/UPDATE/NOOP) decision.
KIROK_RECALL_MIN_SIMILARITY0.62Similarity floor for semantic memory hits in recall. Keyword/FTS hits are exempt.
KIROK_OBS_MIN_SIMILARITY0.62Similarity floor for observation hits in recall.
KIROK_CONSOLIDATION_BATCH_SIZE5Run auto-consolidation only once this many memories are pending (1 = every retain).
KIROK_CONSOLIDATION_TIMEOUT120Consolidation timeout, seconds.
KIROK_REFLECT_TIMEOUT300Reflect timeout, seconds.
KIROK_AUTO_SNAPSHOT_HOURS24Min hours between startup auto-snapshots (0 disables).
KIROK_SNAPSHOT_KEEP5Auto-snapshot generations to keep before rotating out the oldest.

🔍 Search quality

Recall runs semantic KNN and FTS5 BM25 in parallel and fuses them with Reciprocal Rank Fusion (k=60). Short Japanese keyword queries get special handling: 1–2 character kanji/katakana tokens fall below the trigram tokenizer's 3-char window and can never MATCH, so they're rescued by an exact-substring LIKE supplement appended after the BM25 hits (hiragana-only short tokens stay excluded — function words would substring-match half a bank; tokens are OR-joined, matching the MATCH side).

Three details keep the hybrid honest: each source is fetched deeper than the final page (max(limit*3, 30)) so RRF can promote an item ranked just outside the cut in both lists; all FTS text is NFKC-normalized on both the index and query side, so width variants (MCP vs MCP, バグ vs バグ) actually match; and observations get the same hybrid treatment as memories — semantic hits floored, keyword hits floor-exempt — instead of being reachable only through the semantic floor.

The similarity floor is calibrated on real data. A naive cosine threshold doesn't work here: on live gemini-embedding-001 vectors the distribution is narrow — off-topic queries score 0.55–0.62 against unrelated banks while true hits score 0.66–0.73. So the usable floor sits just above the off-topic ceiling, at 0.62. Without it, an unrelated query still returns a full page of memories from any non-empty bank (context pollution); much lower and the floor filters nothing (the old hardcoded 0.4 sat below even off-topic scores). FTS keyword hits bypass the floor entirely — a literal term match is independent evidence, not a weak vector score.

Search parameters aren't tuned by vibes. scripts/search_eval.py runs a golden query set through the exact recall pipeline the server uses (extracted as hybrid_search_memories, so the harness can't drift from production) and reports hit@1/hit@5/hit@k and MRR:

bash
cp scripts/search_eval.example.json my_golden.json   # add 30–50 real casesuv run python scripts/search_eval.py my_golden.json --limit 10

🛡️ Reliability

  • Atomic consolidation. Every create/update embedding is generated before any DB write; all observation changes plus the "consolidated" mark commit in a single transaction. A failure at any step leaves the database exactly as it was, with the source memories still pending for a later retry — never a half-applied batch.
  • Failures surface, never fake success. A consolidation LLM failure raises and is recorded to system_events — the batch stays pending for a later retry, instead of being silently marked consolidated with nothing produced. Runs are serialized per bank, so two retains landing together cannot double-process the same batch into duplicate observations.
  • Soft deletes with audit trail. An observation the consolidation LLM decides to remove is stamped deprecated_at (excluded from search/list/stats) instead of destroyed, and a dedup UPDATE records the pre-merge content in the same transaction as the merge itself — both logged to system_events so a bad LLM decision is recoverable, not silent data loss.
  • Startup auto-snapshot. On launch, if the newest auto-snapshot is older than KIROK_AUTO_SNAPSHOT_HOURS, a VACUUM INTO + integrity_check snapshot is written under ~/.kirok/backups/, keeping the newest KIROK_SNAPSHOT_KEEP generations. A snapshot that fails partway leaves no broken file behind, and manual backups are never rotated.
  • Concurrency. Connections set PRAGMA busy_timeout=30000, so a second MCP client waits out a busy writer instead of failing with database is locked.
  • Fail-open background work. Auto-consolidation and mental-model refresh run behind retain and can never fail it — errors are swallowed, recorded to system_events, and surfaced via KIROK_stats so silent degradation stays visible.

💾 Backup & restore

All state is one SQLite file. The offline kirok-backup CLI needs no API key:

bash
uv run kirok-backup snapshot        # byte-level DB copy (safe while server runs)uv run kirok-backup export          # portable JSON of all banks + memories + observations + modelsuv run kirok-backup import ~/.kirok/backups/kirok-export-YYYYMMDD-HHMMSS.json

snapshot and export write timestamped files under ~/.kirok/backups/ and refuse to overwrite. import runs in one transaction (all-or-nothing), skips existing IDs rather than overwriting, and rebuilds the FTS + vector indexes so search works immediately. Use --db to target a different database file.

🩺 Diagnostics

bash
uv run kirok-doctor            # offline: Python version, .env, key presence (never printed),                               # required modules, FTS5, sqlite-vec, DB writabilityuv run kirok-doctor --json     # machine-readable, for automationuv run kirok-doctor --online   # adds one live embedding call to verify Gemini connectivity

🧑‍💻 Development

bash
uv syncuv run --no-sync pytest        # 164 offline tests; no API key or network needed

The suite is fully offline — importing kirok_mcp.server is side-effect-free (the API key is checked at startup, not import) and tests swap in fake Gemini clients. CI runs the same suite on Ubuntu and Windows on every push (.github/workflows/test.yml). See CONTRIBUTING.md before opening a PR.

📚 Documentation

📄 License

MIT — see LICENSE.

Acknowledgements

Source: README.md at commit 4c03352

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v1.4.2LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

Other Memory integrations