Skip to main content
Glama

蒸留蔵 — distill-kura

Долговременная память для агентов, которая дистиллируется, а не накапливается. Воспоминание работает по смыслу, запись ограничена доказательствами, и один сервер может хранить несколько отдельных воспоминаний — по одному на режим агента — так что переключение режима меняет то, что агент помнит.

Поставляется как плагин DeepSeek Harness, MCP-сервер для любого другого хоста, HTTP-сервис и Python-библиотека. Только стандартная библиотека; никакой векторной базы данных, никаких эмбеддингов, никакого фреймворка.

        ┌── recall ──────────────────────────────────────────────┐
        │  question → whole index in one prompt → picked slugs   │
        │           → walk [[links]] → the neighbourhood         │  ~0.4 s
        └────────────────────────────────────────────────────────┘
        ┌── distil ──────────────────────────────────────────────┐
        │  journal → classed evidence → candidates → GATE        │
        │  → new? → composed → draft → judged → poured           │
        └────────────────────────────────────────────────────────┘

Зачем это существует

Два сбоя убивают долговременную память агента, и они убивают её с противоположных сторон.

Поиск по ключевым словам упускает то, что было нужно. Вопрос о «чипах для инференса SSD» не имеет ни одного общего слова с воспоминанием под названием «запуск модели 2.6T с SSD-уровня» — и всё же это одна и та же тема. Поиск по словам ничего не возвращает; агент отвечает из ниоткуда. Решение здесь — не эмбеддинги, а распознавание: весь индекс (одна строка на воспоминание, записанная как триггер распознавания) помещается в один промпт, и небольшая модель называет то, что относится к вопросу. Индекс из ~500 воспоминаний — это около 6k токенов — несколько процентов современного контекстного окна, и он лежит в кэше префикса.

Запись всего подряд отравляет хранилище. Агент делает утверждение; наивный дистиллятор записывает утверждение как факт; следующий агент читает его как истину и повторяет с большей уверенностью. Этот цикл самоподкрепляющийся, и инструкции в промпте его не останавливают — это измерено, а не предположено. Поэтому путь записи ограничен детерминированным Python: каждая кандидатная память должна содержать цитаты, которые существуют символ-в-символ в исходном материале, с указанием, откуда они взялись.

класс

что это

что это разрешает

[USER]

собственные слова человека

«они решили», «они попросили»

[TOOL]

вывод машины

числа — единственный источник

[ACT]

инструмент, который был вызван

«это было сделано»

[SELF]

собственная проза агента

суждение от первого лица, никогда не голый факт

Цитата, не найденная дословно, отбрасывается. Кандидат без выжившей цитаты выбрасывается. Число без подкрепляющего [TOOL] удаляется. Текст, приписывающий человеку решение, когда ни одна цитата [USER] не выжила, отклоняется на последнем рубеже. Идеи приветствуются — они идут в файл семян, никогда в хранилище, и получают статус только когда позднейшие доказательства их подтверждают.


Related MCP server: Synapto

Быстрый старт

git clone https://github.com/lna-lab/distill-kura && cd distill-kura
pip install -e .                       # or just run: python3 -m distill_kura.cli

cp kura.example.toml kura.toml         # edit: one model endpoint is enough to start
kura init main --path ~/kura/main      # create an empty store
kura serve                             # http://127.0.0.1:8085
curl -s -X POST localhost:8085/recall -H 'content-type: application/json' \
     -d '{"question":"what did we decide about the archive disk?","hops":1}'

Носите индекс, чтобы агент всегда знал, что известно:

kura weave                             # build the three-layer cloth
kura prefill                           # the block to put in the system prompt

Скармливайте ему транскрипты вашего агента:

kura distill run      # drink a batch → candidates → gate → drafts
kura distill drafts   # look at what it wants to write
kura distill drain    # the scribe re-reads each draft cold: pour / fix / toss
kura distill night    # stay resident and do it whenever things go quiet

Ничто не попадает в хранилище, пока не выполнен drain (или запущенный вручную pour). Черновики несут свои доказательства в HTML-комментарии, так что вы всегда можете видеть, почему существует память.


Карта резидента

Вызов-по-инструменту отвечает на вопрос «что ты знаешь об X?» — но только после того, как агент решил спросить. Он никогда не отвечает на вопрос, который агент не догадывается задать: есть ли здесь вообще что-нибудь? Агент, который не видит карту, не знает, чего ему не хватает, поэтому он догадывается, а уверенная догадка о вашем хозяйстве — это именно тот сбой, который этот проект призван предотвратить.

Поэтому индекс также носится: постоянный блок в системном промпте, на каждом ходу.

kura weave      # re-weave the index into the three-layer cloth
kura prefill    # print the block a host should inject

Три слоя, потому что детализация окупается только для недавнего

Слепой A/B-тест — 20 вопросов, полный индекс против урезанного, оценка без знания того, какой был какой — определил форму:

диапазон

полный

урезанный

в целом

9

11

недавние события

4

1

доктрина

1

4

кросс-доменные скачки

1

4

Строки доктрины были побайтово идентичны в обоих индексах, и урезанный индекс всё равно выиграл этот диапазон: более лёгкое окружение заставляет постоянные строки работать лучше. Детализация — не источник понимания. Она оправдывает своё место только там, где вещи ещё движутся.

слой

правило

строка

закреплённый

frontmatter type в pinned_types

сохраняется полностью

свежий

изменён в пределах fresh_days

сохраняется полностью

триггер

всё остальное

сжимается до ~trigger_tokens

Строки триггеров пишутся моделью scribe и кэшируются в журнале с ключом по описанию и бюджету, так что повторное плетение в стабильном состоянии ничего не стоит. Если модель недоступна, ткацкий станок обрезает механически — система памяти не должна глохнуть из-за того, что GPU лежит.

Возраст — это не mtime. cp -r, восстановление или checkout сбрасывают все временные метки, весь индекс становится «свежим», ничего не обрезается, и механизм молча отключает сам себя. Поэтому ткацкий станок предпочитает дату, записанную внутри памяти, и не доверяет любому mtime, который пятая часть хранилища делит с одним календарным днём.

Куда это идёт, и почему это решение о кэше

- id: kura
  name: distill-kura
  config: { store: eq, promptOrder: -50 }   # before the persona

Кэш префикса теряется с первого изменённого байта — измерено на одном локальном сервере: идентичный преамбул из 4 029 токенов переоценивается с 0,68 с до 0,14 с, добавление в конец остаётся 0,14 с, а одно слово, добавленное в начало, стоит всего кэша (0,66 с). Персона обычно несёт часы, так что она меняется каждую минуту; карта — это самый большой блок в промпте и меняется несколько раз в день. Большой стабильный блок идёт перед тем, что тикает.

Поэтому сам блок не содержит ни даты, ни часов, ни счётчика — и build() отказывает заголовку, который их содержит, во время сборки, а не через таинственно медленные ходы три недели спустя.

Она никогда не отдаёт полкарты

ситуация

что получает агент

всё в порядке

карту, между маркерами <<<KURA-MAP>>>

свыше budget_fraction

всю карту и предупреждение в JSON (никогда в тексте — баннер — это изменчивое содержимое)

свыше hard_fraction

заглушку без строк индекса, говорящую, что карта отсутствует, а не пуста

kura недоступен

явное примечание, что карта отсутствует, никогда не пустую строку

Усечённая карта — худший из доступных артефактов: она выглядит полной, и каждое воспоминание ниже среза выглядит несуществующим. weave сократит окно свежести, чтобы вписаться, но никогда не отбросит строку — и если ни одна настройка не достигает бюджета, он сообщает об этом, сохраняет лучшую карту и показывает вам, где вес.

Как доставить её в хост

хост

механизм

DSH

нативный плагин — systemPrompt.section, обновляется в фоне

Claude Code, VS Code, Goose

MCP instructions несёт короткий указатель (лимит 2KB); сама карта приходит из инструмента kura_map или хука сессии, запускающего kura prefill

Claude Desktop, claude.ai

игнорируют instructions полностью — используйте kura_map

что угодно ещё

GET /prefill?format=text, или kura prefill в шелл-хуке

Поле MCP instructions — это MAY в спецификации, и индекс на 9 000 токенов не может пройти через лимит 2KB в любом случае, так что этот проект не притворяется иначе.


Режимы: больше одной куры

Одна память, которая служит и «помоги мне это построить», и «помоги мне это обдумать», не служит ни тому, ни другому хорошо: воспоминание, которое помогает вам отлаживать, — это шум в разговоре о том, что делать дальше. Поэтому хранилище — это каталог, а режим сопоставляется с хранилищем.

[stores.maker]
path = "~/kura/maker"
label = "maker mode — building things"

[stores.eq]
path = "~/kura/eq"
label = "EQ mode — talking things through"

[modes]
maker = "maker"
eq    = "eq"

Каждый маршрут принимает селектор, так что один процесс обслуживает их все:

curl -s -X POST localhost:8085/recall -d '{"question":"...","mode":"eq"}'
curl -s localhost:8085/index?store=maker
curl -s localhost:8085/s/eq/doctor          # path form, for clients that only vary a base URL

Хранилища не разделяют воспоминания, индекс и водяной знак дистиллятора. Переключение режима действительно меняет то, что запоминается, — а не ту же память другим голосом.

Независимость как маршрутизация, а не как конфиденциальность. У сервера нет аутентификации, так что любой процесс, который может достичь его порта, может назвать любое хранилище, которое он держит. Привязка агента удерживает модель в её полосе; она не удерживает процесс снаружи. Один уровень доверия на процесс — docs/TRUST.md короткий, и его стоит прочитать, прежде чем в хранилище попадёт приватное. Он также покрывает две границы, которые легко упустить: два хранилища, пьющие из одного корня журнала, и два хранилища за одной конечной точкой модели.

С DeepSeek Harness

DSH переключает персону и инструменты по пресету агента. distill-kura переключает память по хранилищу. Свяжите их, и одно изменение пресета сдвигает всё «я» целиком:

# .agent-presets/eq/agent.cordis.yml
- id: kura-eq
  name: distill-kura
  config:
    url: http://127.0.0.1:8085
    store: eq            # this preset's memory
    readonly: true       # the CLIENT's own switch: do not even offer a write tool
    # (the store's own `write_policy` is the authority; this just keeps the tool
    #  out of the model's hands. Naming a store already binds the preset.)

Оставьте allowSwitch по умолчанию, и агент также получит kura_use, так что он сможет перемещаться между курами в середине разговора без смены пресета. Инструменты: kura_recall, kura_read, kura_doctor, kura_list, kura_use и kura_remember (только когда хранилище доступно для записи). Полная схема подключения, включая MCP-мост и правило области isolate для сервисных строк, — в examples/dsh-presets/.

Персона — дело хоста, не наше. Этот проект никогда не рендерит и не внедряет персону; он только записывает, по хранилищу, какой файл персоны принадлежит ему, доступный по GET /profile?store=eq, чтобы две половины можно было держать в шаге тому, кто владеет пресетом. Инструкции агента также остаются с механизмом AGENTS.md хоста — см. AGENTS.md в этом репозитории для соглашений, которым должен следовать агент, работающий над этой кодовой базой.

С любым MCP-хостом

{ "mcpServers": { "kura": {
    "command": "python3", "args": ["-m", "distill_kura.mcp"],
    "env": { "KURA_URL": "http://127.0.0.1:8085", "KURA_STORE": "eq", "KURA_READONLY": "1" }
}}}

Оставьте KURA_STORE неустановленным для свободного режима: инструменты принимают необязательный аргумент store, и kura_use переключает для сессии.


Модели: одна по умолчанию, обновляйте роль за раз

Три роли, а не три машины:

роль

когда запускается

требования

thinker

каждый вызов воспоминания

маленькая и быстрая; должна судить о релевантности по смыслу

brain

дистилляция: читает целую партию журнала

длина контекста и терпение

scribe

дистилляция: пишет память, затем оценивает черновики

хорошая проза на вашем языке, суждение

Объявите только [models.thinker], и одна модель делает всё три. Обновите любую из остальных независимо — более крупную локальную модель или онлайн-API (любой OpenAI-совместимый /chat/completions; ключ читается из переменной окружения, которую вы называете, и никогда не хранится в конфиге):

[models.thinker]                       # always-on, local, small
url = "http://127.0.0.1:8000/v1"
model = "local-small"

[models.scribe]                        # upgrade just the writing
url = "https://api.example.com/v1"
model = "big-model"
api_key_env = "EXAMPLE_API_KEY"

Две вещи, которые это обрабатывает за вас: диалекты усилия рассуждения различаются по семействам моделей (reasoning_effort, thinking_effort, enable_thinking), поэтому отправляются все из них — неизвестная игнорируется шаблоном, а модель, оставленная на глубоком мышлении по умолчанию, может потратить весь свой бюджет на рассуждение и ничего не вернуть. И текст устава размещается побайтово идентично в начале промпта каждой роли, так что на медленной локальной модели три роли разделяют один кэшированный префикс вместо трёх префиллов.

Если мыслитель недоступен, recall не замолкает — он откатывается к пересечению слов и помечает ответ how=words, который инструменты отображают как ⚠ degraded. Тихая деградация хуже деградации.


Как выглядит память

Один файл — один факт.

---
name: archive-on-slow-disk
description: the archive lives on the slow disk; the fast one stays scratch
metadata:
  type: project          # user | feedback | project | reference
---

The archive goes on the slow disk. The fast disk is scratch space.

**Why:** the other way round burns write endurance for nothing.
**How to apply:** check which disk a target directory is on before writing there.
Related: [[disk-layout]]

И одна строка в MEMORY.md:

- [Archive on the slow disk](archive-on-slow-disk.md) — the archive lives on the slow disk; the fast one stays scratch

Эта строка — единственное, что читается каждый раз. Это триггер распознавания, а не сводка: имена собственные, числа, ⚠️ мины, сделанный вывод. Если строку можно поменять местами со строкой другого воспоминания, и она по-прежнему будет читаться нормально, она не выполняет свою работу — kura distill tidy находит механически обнаруживаемые случаи и переписывает их.

kura doctor сообщает о количестве, битых ссылках, островах (воспоминаниях, на которые ничто не ссылается) и дрейфе индекса. Это глаз, необходимый метаболизму.


HTTP-поверхность

route

что делает

POST /recall

{question, hops, top, chars, total_chars, store|mode} → выбрано, пройдено, контекст. chars — на одно воспоминание; total_chars — жёсткий потолок для всего контекста

POST /remember

{slug, description, body, type, title} — ПРЯМАЯ запись, отклоняется, если write_policy = "direct-allowed" не установлено

GET /index

необработанный индекс

GET /prefill

резидентный блок, готовый к внедрению (&format=text для хука)

GET /memory/<slug>

одно воспоминание полностью

GET /doctor

здоровье одного хранилища (?all=1 для всех хранилищ)

GET /stores

хранилища, режимы и какая модель выполняет какую роль

GET /profile

устав хранилища и указатель на его персону (здесь никогда не отображается)

GET /health

живость

Любой маршрут принимает ?store= / ?mode=, поле store/mode в теле или префикс пути /s/<name>/…. Без аутентификации: привяжитесь к loopback или поставьте что-то перед ним.


Заметки по дизайну, которые стоит прочитать перед изменениями

  • docs/DESIGN.md — почему распознавание лучше поиска, что даёт шлюз и какой сбой мотивировал каждый механизм.

  • docs/OPERATING.md — запуск в резидентном режиме, планировщики и коды выхода, резервное копирование, за чем следить.

  • docs/TRUST.md — что такое граница хранилища, а что нет, политики записи и две границы, которые легко упустить (общие журналы, общие модели). Прочтите, прежде чем создавать приватное хранилище.

Несколько решений, которые выглядят странно, пока не столкнёшься с тем, от чего они защищают:

  • Резервируй, прежде чем пить. Дистиллятор резервирует участок журнала до его чтения, под блокировкой, и водяные знаки движутся только вперёд. Два дистиллятора, каждый из которых записывал свой снимок, стирали прогресс друг друга и по дюжине раз перепивали одну и ту же воду.

  • Водяные знаки — это единицы на адаптер. Байтовые смещения для журналов с добавлением, порядковые номера для архивов, которые перезаписываются (байтовое смещение в пережатом файле — это ложь).

  • Подавление эха. Цитата, которая уже есть в хранилище, — это не новый материал; это хранилище читает само себя через результат инструмента. Без этого система памяти вечно переоткрывает и перезаписывает собственное содержимое.

  • Последний шлюз — это модель, а не человек. Если человек должен утверждать каждый черновик, система тихо делает этого человека своим узким местом, и черновики копятся вечно. Ничто в цикле не должно требовать того, кого нет рядом.

  • kura distill run завершается с кодом 2, когда делать было нечего. Планировщик должен отличать «сделал работу» от «ничего не нашёл», иначе сторожевой пёс крутится в пустой очереди и морит голодом шаги, которым нужно время простоя.

Измеряем, а не заявляем

На два вопроса отвечают одним числом, и не следовало бы.

Насколько меньше? store_ratio = токены в воспоминаниях и индексе / токены реально потреблённого сырого журнала. Что потеряно? Это другое измерение, и хранилище, которое хранит одно воспоминание из ста, прекрасно набирает баллы по первому, оставаясь бесполезным.

kura bench compress                       # what this store cost, from the distiller's own metrics
kura bench compress --tokenizer-command "./count-tokens"   # exact, not estimated
kura bench retention --questions bench/fixtures/questions.json

Измерено здесь, с поставляемыми фикстурами и встроенным оценщиком:

корпус

store_ratio

scripts/demo-clean-room.sh (обычный чат, в основном вода)

0.18

bench/fixtures/corpus.jsonl (плотный: каждая строка — сигнал)

1.14

Второе — не баг. На материале, где нет воды, дистилляция не сжимает — каждое воспоминание добавляет своё зачем и как применить, и хранилище получается чуть больше стенограммы. Коэффициент — свойство корпуса, а не этого инструмента, поэтому здесь нет ключевой цифры и поэтому команда сообщает, с чем она считала.

Удержание оценивается без модели: каждый посаженный факт несёт маркер, который должен появиться в том, что возвращает recall, поэтому оценка воспроизводима на чужой машине. Дистракторы инвертируются: факт, помеченный must_not_store, стоит очко, если хранилище его сохранило, потому что систему памяти судят и по тому, что она отклоняет, и по тому, что сохраняет.

score 1.0 (10/10)   decision 1/1  number 2/2  negation 1/1  reversal 1/1
                    conditional 1/1  landmine 1/1  returning 1/1  distractor 2/2

Это десять посаженных фактов в синтетической фикстуре, дистиллированных локальной Qwen3.8-27B (NVFP4) в роли мозга и писца с max_items = 8, coverage_passes = 2 и оценённых той же моделью в роли мыслителя. Другая модель даст другой балл: оценка измеряет конвейер-плюс-модель, и фикстура существует, чтобы модель была единственной переменной. Она измеряет, находим ли факт, а не хорошо ли читается ответ, — оценка прозы требует модели, и тогда бенчмарк перестаёт быть воспроизводимым.

kura distill run пишет по одной строке на пакет в _still/metrics.jsonl, откуда берётся сырая сторона. Каноническая сторона считает только те воспоминания, чей манифест свидетельств указывает на записанный пакет — делить всё хранилище на сырьё нескольких пакетов — это число не в ту сторону на порядок, и первая версия этой команды делала именно так. Воспоминания, предшествующие манифестам, помечаются как unattributed, а не молча включаются. Сырая сторона — это всегда оценка дистиллятора на момент питья, поэтому с --tokenizer-command коэффициент помечается как mixed.

С чем это работает

требование

Python

3.11+ (без зависимостей; pip install -e ".[dev]" добавляет только pytest)

Node

20+, только для плагина DSH

zstd

только для чтения архивов сессий DSH

модельная конечная точка

всё, что отвечает на POST <url>/chat/completions в формате OpenAI

«Совместимость с OpenAI» уже, чем «любой провайдер». Собственному API вендора нужен совместимый с OpenAI шлюз перед ним; собственный URL не подойдёт. Строгий сервис также отклоняет неизвестные поля верхнего уровня, поэтому установите dialect = "openai" (или "generic") — по умолчанию "vllm" отправляет chat_template_kwargs, которые нужны локальным серверам, а строгий отвечает 400. Клиент повторяет попытку один раз с простым телом и записывает, почему вызов не удался, а не схлопывает все причины в молчаливый None.

Тесты

python3 -m pytest tests -q                              # 145 tests, no model required
cd dsh-plugin && npm test                               # 24 more for the plugin

Шлюз тестируется состязательно: каждый случай — это способ, которым реальная модель пыталась что-то протащить. test_containment.py написан так же — каждый случай это попытка побега, а не счастливый путь, — потому что он закрывает реальную дыру: хранилище отвечало за любой файл, путь к которому можно было произнести. Сквозной тест прогоняет полный цикл distil→drain против скриптованного модельного сервера на реальном сокете.

Лицензия

MIT.

Available Tools

6 tools
kura_doctorA

Health check of the kura: how many memories, resolved and dead [[links]], islands (memories nothing links to), index drift. Call when recall behaves oddly, or when asked about the memory system itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeNoWhich kura. Omit for the current one.

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It does well by naming the diagnostic nature ('health check'), the categories of data inspected, and the symptom-triggered use case. It does not explicitly state whether the tool is read-only or whether any repair/reindexing occurs, but 'health check' strongly implies diagnostic rather than mutating behavior.

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?

The description is compact: two sentences, front-loaded with the core purpose, followed by a concise list of diagnostic metrics and explicit usage triggers. Every clause earns its place, with no filler or redundancy.

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?

For a simple tool with zero required parameters and a fully documented optional parameter, the description provides enough context to select and invoke the tool correctly. It explains what will be inspected and when to use it. The only gap is that it does not describe the return format or explicitly confirm the absence of side effects, but neither is critical for a diagnostic health-check tool.

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 description provides no additional parameter-level meaning beyond what the schema already states. The optional 'store' parameter is fully documented in the schema, so the baseline of 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?

The description uses a specific verb-resource pairing: 'Health check of the kura', and enumerates concrete diagnostic outputs (memory counts, resolved/dead links, islands, index drift). This clearly differentiates it from the sibling tools like kura_read or kura_recall, which focus on reading or retrieving memories rather than diagnosing system health.

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?

The description explicitly states when to use the tool: 'Call when recall behaves oddly, or when asked about the memory system itself.' This provides clear invocation context. However, it does not explicitly mention alternatives or when not to use it, so it stops just short of full routing guidance.

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

kura_listA

List the kura this server holds and which agent mode each one belongs to. Call it when you are unsure which memory you are speaking from, or before switching.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It states the operation (list) and the output (kura and agent modes) but does not mention side effects, read-only nature, performance, or any edge cases. Adequate but not rich for a tool without annotation safety signals.

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 wasted words. The first sentence states the core function; the second provides immediate usage context. Information is front-loaded and every word serves a purpose.

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?

For a no-parameter list tool with no output schema, the description explains what is listed and exactly when to invoke it. It could mention what 'kura' refers to or if results are ordered, but the definition is sufficient for an agent to decide and call it correctly.

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

Parameters4/5

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

The tool has zero parameters, and the schema coverage is trivially 100%. Per the rubric, 0 params earns a baseline of 4. The description does not need to add parameter details since none exist.

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?

The description clearly states the verb 'list', the resource 'kura', and what is listed (which agent mode each belongs to). It implies a distinction from siblings like kura_read or kura_recall by focusing on the server's collection and mode mapping, though it does not explicitly name alternatives.

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?

The description gives explicit when-to-use guidance: 'Call it when you are unsure which memory you are speaking from, or before switching.' It lacks explicit when-not-to-use or named alternative tools, but the usage context is concrete and helpful.

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

kura_mapA

Show the whole index of the kura — every memory's one-line recognition trigger, in one answer. Use it when you need to see WHAT EXISTS rather than look something up: before claiming a topic was never discussed, when choosing which memory to open, or right after switching kura. It is a map, not the contents: open a memory with kura_read for the detail.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeNoWhich kura. Omit for the current one.

TDQS

A4.5/5.0
Behavior4/5

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

No annotations are present, so the description carries the full burden. It clearly frames a display operation ('Show the whole index... in one answer') and sets output expectations ('map, not the contents'). It does not discuss permissions or exact formatting, but for a non-mutating index tool the core behavioral disclosure is present.

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?

Three sentences, each earning its place: the first states the action and scope, the second gives concrete use cases, and the third clarifies depth and names the sibling for details. It is front-loaded and free of filler.

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 low-complexity tool with one optional parameter and no output schema, the description provides the essential context: what it returns, when to use it, what it is not, and where to go for detail. Nothing needed to call it correctly is missing.

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 the single 'store' parameter is already documented as 'Which kura. Omit for the current one.' The description adds no parameter-level detail beyond that, so it meets the baseline but does not exceed it.

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?

The description opens with a specific verb and resource: 'Show the whole index of the kura - every memory's one-line recognition trigger.' It also distinguishes itself from siblings by saying it is 'a map, not the contents' and explicitly directs details to kura_read, so an agent can tell it apart from the other tools.

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

Usage Guidelines5/5

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

It gives explicit when-to-use conditions ('when you need to see WHAT EXISTS... before claiming a topic was never discussed, when choosing which memory to open, or right after switching kura') and an explicit alternative ('open a memory with kura_read for the detail'). This is clear routing guidance rather than leaving usage to inference.

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

kura_readA

Read one whole memory from the kura by its slug (e.g. 'storage-doctrine'). Use after kura_recall when a summary is not enough and you need the full text.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugYesMemory slug, without .md
storeNoWhich kura. Omit for the current one.

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations available, the description carries the burden of behavior. It clearly indicates a read operation fetching the full memory text, which is sufficient for this simple tool. It could add detail about return format or failure behavior, but the core behavior is transparent enough.

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 with no filler. The primary behavior is front-loaded, and the usage guidance, alternative, and selection condition are packed efficiently into the second sentence.

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 simple read-by-slug tool with only two parameters, no output schema, and full schema coverage, the description is complete. It tells the agent what it does, when to use it, and provides an example. Nothing essential is missing.

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 the baseline is 3. The description adds a useful example slug ('storage-doctrine') but otherwise does not need to add much beyond what the schema already documents for 'slug' and 'store'.

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?

The description clearly states the action ('Read'), the resource ('one whole memory'), and the retrieval key ('by its slug'), with a concrete example. It also names the sibling tool it complements, distinguishing it from kura_recall without needing to inspect 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 Guidelines5/5

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

It explicitly states when to use this tool: 'Use after kura_recall when a summary is not enough and you need the full text.' This directly routes the agent to the appropriate alternative and gives a clear selection condition.

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

kura_recallA

Recall from the kura — long-term memory retrieved by MEANING rather than keyword, then following [[links]] between memories. Call it whenever the question touches past decisions, measurements, people, machines, or anything done before — prefer it over guessing. An empty result means it is simply not remembered yet: say so plainly and never fill the gap with invention. Pass store to reach a different kura, or call kura_use to switch for the session.

ParametersJSON Schema
NameRequiredDescriptionDefault
hopsNoHow many [[link]] hops to walk (default 1)
storeNoWhich kura to ask (store or mode name). Omit for the current one.
questionYesWhat you want to remember, as a natural question

TDQS

A4.3/5.0
Behavior3/5

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

Annotations are absent, so the description carries the full burden of behavioral disclosure. It does reveal important behavior: it retrieves by meaning, follows links, and emphasizes not to fabricate when no result is found. However, it does not disclose potential side effects, rate limits, or what happens with the hops parameter (e.g., how deep the search goes and whether more hops affect latency). It also doesn't specify if the tool is read-only, though recall implies reading. Overall, it gives useful context but leaves some behavioral aspects unmentioned.

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

Conciseness4/5

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

The description is a single, dense paragraph but contains no filler. It front-loads the core purpose and usage guidance, then addresses edge cases and parameter use. It is appropriately sized for a tool with multiple interconnected behaviors (meaning-based recall, link-following, empty result handling). It could be slightly more structured (e.g., bullet points for handling empty results or parameter variants), but it is efficient and every sentence earns its place.

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?

Given the tool has 3 parameters (1 required), no output schema, and moderate complexity due to link-following and alternate stores, the description covers the essential aspects: what it does, when to use it, how to handle empty results, and how to use parameters. It does not explicitly describe return format (e.g., whether it returns text or a list of memories), but with no output schema, it could have provided more on that. Missing details on hops behavior and potential limitations are minor gaps. Overall, it is fairly complete for an agent to use it correctly.

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

Parameters4/5

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

The schema already documents all three parameters (question, hops, store) with descriptions, and coverage is 100%, so the baseline for parameter semantics is 3. The description adds value by explaining the semantics of 'store' ('reach a different kura') and hints that 'question' should be phrased as a natural question. It also implies the meaning of 'hops' (following [[links]]). It doesn't detail the format or constraints beyond the schema, but it enriches the meaning of each parameter sufficiently.

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?

The description clearly states the tool's purpose: 'Recall from the kura — long-term memory retrieved by MEANING rather than keyword, then following [[links]] between memories.' It differentiates itself from siblings by emphasizing meaning-based retrieval over keyword, which distinguishes it from tools like kura_read or kura_list. It also mentions specific use cases, making it easy for an agent to understand what it does.

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

Usage Guidelines5/5

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

The description explicitly tells the agent when to use this tool: 'Call it whenever the question touches past decisions, measurements, people, machines, or anything done before — prefer it over guessing.' It also explains what to do on empty results ('An empty result means it is simply not remembered yet: say so plainly and never fill the gap with invention') and mentions alternatives or related actions ('Pass store to reach a different kura, or call kura_use to switch for the session'). This provides clear guidance on selection and behavior.

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

kura_useA

Switch which kura the following calls read from, for the rest of this session. Use when the conversation moves to a different mode of work (for example from building things to talking things through). Has no effect on a bridge that was bound to a single kura at startup — it will say so.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeYesStore or mode name

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 burden of behavioral disclosure. It does this well by revealing that the switch persists for the session, affects subsequent calls, and has no effect on a single-kura bridge (and that it will say so). It does not cover every possible error or side effect, but the key stateful behavior is disclosed.

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?

The description is three sentences with no wasted words. The main effect and scope are front-loaded, the usage condition follows, and the edge case is placed last. Every sentence earns its place.

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 simple one-parameter state-switching tool with no annotations and no output schema, this description is complete enough. It explains what the tool does, when to invoke it, how long the effect lasts, and the one major exception an agent needs to know about.

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 coverage is 100% — 'store' is already described as 'Store or mode name.' The description adds some context by suggesting that stores correspond to modes of work, but it does not enumerate valid values or add meaningful parameter detail beyond the schema. This is the baseline for high schema coverage.

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?

The description uses a specific verb ('Switch') and names both the resource ('which kura the following calls read from') and the scope ('rest of this session'). This clearly distinguishes it from the sibling read/analysis tools like kura_read and kura_map, which retrieve data rather than change the active context.

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?

It explicitly says when to use it: 'Use when the conversation moves to a different mode of work,' with a concrete example. It also discloses a limitation about bridges bound to a single kura. It does not explicitly name sibling alternatives or state when not to use it, but the intended context is clear.

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. 6 tool updatesv0.1.0
    • First observedkura_doctor
    • First observedkura_list
    • First observedkura_map
    • First observedkura_read
    • First observedkura_recall
    • First observedkura_use

TDQS

A4.3/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a distinct purpose: recall for meaning-based search, read for slug-based retrieval, map for index views, doctor for health checks, list for enumerating kuras, and use for switching. No overlap in functionality.

Naming Consistency5/5

All tools follow the same `kura_` prefix with a verb-based second part (recall, read, map, doctor, list, use), creating a consistent and predictable naming scheme.

Tool Count5/5

Six tools is a well-scoped number for a memory-management server, covering retrieval, inspection, maintenance, and context switching without excess or deficiency.

Completeness4/5

The set covers all read and management operations (recall, read, map, health, list, switch), but lacks an explicit write or delete capability, which is a minor gap for a full memory system. Agents can work around this by relying on existing memories.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents with persistent, searchable memory that survives across conversations using semantic search, temporal versioning, and smart organization. Enables long-term context retention and cross-session continuity for AI assistants.
    14
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides persistent, searchable memory for MCP-compatible agents, enabling recall by meaning, automatic decay, trust scoring, and cross-agent handoffs.
    5
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides long-term memory and a temporal knowledge graph for AI agents, enabling persistent memory and reasoning across sessions.
    33
    101 PyPI
    2
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Provides persistent memory for AI agents, including context storage, facts, plans, RAG search, code snippets, and conversation compaction, enabling state to survive across sessions and processes.
    14
    14 npm
    2
    MIT