Skip to main content
Glama
thecodacus

OKF Knowledge Agent MCP Server

by thecodacus

understory 🌱

Память, которая растёт.

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

Бандлы соответствуют спецификации Open Knowledge Format (OKF) v0.1 — обычные markdown-файлы с YAML-frontmatter, читаемые людьми, диффабельные в git, переносимые между инструментами.

Три способа доступа — один агент:

  • MCP-сервер — инструменты memory_query / memory_add / memory_update / memory_status / memory_maintain через stdio или streamable HTTP. Каждый вызов управляет внутренним LLM-агентом со спецификацией OKF в системном промпте.

  • Веб-интерфейс — просматривайте бандл (дерево, просмотрщик концепций, журнал обновлений, значок соответствия), видите память как силовой граф в стиле Obsidian (перетаскивание/панорамирование/масштабирование, цвет по типу, размер по связям, осиротевшие обведены красным, клик открывает) и общайтесь с тем же агентом, чтобы протестировать его. Вызовы инструментов отображаются инлайн, так что вы можете наблюдать за работой.

  • Воспроизведение пути запроса — каждый запуск агента (запрос/мутация/чат) записывает свой обход (поиски → чтения → записи) в компактной нотации, сохраняемой в <bundle>/.traces/. В представлении графа перечислены недавние запуски; выбор одного воспроизводит путь в виде нумерованных направленных переходов по графу — посещённые концепции обведены кольцом, результаты поиска пунктиром, всё остальное затемнено.

  • CLI — проверочные команды pnpm agent:query "..." / pnpm agent:mutate "...".

Правило проектирования: соответствие обеспечивается кодом, а не промптами. Детерминированный слой бандла проверяет frontmatter (обязателен type), перегенерирует файлы index.md, добавляет записи в log.md (сначала новые, спецификация §7) и изолирует все пути в корне бандла. LLM решает, что изменить; код гарантирует, что результат — соответствующий спецификации бандл.

Быстрый старт (Docker)

Клонировать не нужно — образ публичный. Сохраните это как docker-compose.yml:

services:
  understory:
    image: ghcr.io/thecodacus/understory:latest
    ports:
      - "3800:3800"
    # Lets the container reach a llama.cpp server running on the host via
    # http://host.docker.internal:8080/v1 (see "Local llama.cpp" below).
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      # Your memory lives here as plain markdown — a named volume, or point
      # a bind mount (e.g. ./my-memory:/bundle) at any OKF bundle.
      - understory-memory:/bundle
    environment:
      BUNDLE_ROOT: /bundle
      LLM_API_BASE_URL: ${LLM_API_BASE_URL}
      LLM_API_KEY: ${LLM_API_KEY}
      LLM_API_FORMAT: openai
      LLM_MODEL: ${LLM_MODEL:-}
      # Optional fallback
      LLM_FALLBACK_API_BASE_URL: ${LLM_FALLBACK_API_BASE_URL:-}
      LLM_FALLBACK_API_KEY: ${LLM_FALLBACK_API_KEY:-}
      LLM_FALLBACK_API_FORMAT: ${LLM_FALLBACK_API_FORMAT:-openai}
      LLM_FALLBACK_MODEL: ${LLM_FALLBACK_MODEL:-}
    restart: unless-stopped

volumes:
  understory-memory:
docker compose up -d

Выбор провайдера

Универсальная система провайдеров поддерживает любой API, совместимый с OpenAI или Anthropic. Задайте LLM_API_BASE_URL + LLM_API_KEY + LLM_MODEL и оставьте LLM_PROVIDER незаданным.

DeepSeek:

LLM_API_BASE_URL=https://api.deepseek.com/v1 LLM_API_KEY=sk-... LLM_MODEL=deepseek-chat

OpenAI:

LLM_API_BASE_URL=https://api.openai.com/v1 LLM_API_KEY=sk-... LLM_MODEL=gpt-4o

Anthropic (Claude):

LLM_API_BASE_URL=https://api.anthropic.com/v1 LLM_API_KEY=sk-ant-... LLM_API_FORMAT=anthropic LLM_MODEL=claude-sonnet-5

Groq:

LLM_API_BASE_URL=https://api.groq.com/openai/v1 LLM_API_KEY=gsk_... LLM_MODEL=llama-3.3-70b-versatile

Local llama.cpp:

LLM_API_BASE_URL=http://host.docker.internal:8080/v1 LLM_MODEL=

Когда understory работает в Docker, localhost — это сам контейнер, а не хост, поэтому llama-server на хосте доступен по адресу host.docker.internal (файлы compose выше уже пробрасывают его через extra_hosts). При запуске из исходников на той же машине, где работает llama-server, используйте http://localhost:8080/v1.

Local llama.cpp с запасным вариантом DeepSeek:

LLM_API_BASE_URL=http://host.docker.internal:8080/v1 LLM_MODEL= \
LLM_FALLBACK_API_BASE_URL=https://api.deepseek.com/v1 LLM_FALLBACK_API_KEY=sk-... LLM_FALLBACK_MODEL=deepseek-chat

Старые переменные окружения LLM_PROVIDER + ключи для каждого провайдера по-прежнему работают (обратная совместимость), но устарели.

Затем:

  • Веб-интерфейсhttp://localhost:3800 — просматривайте память, наблюдайте за графом, общайтесь с агентом

  • MCP-эндпоинтhttp://localhost:3800/mcp (streamable HTTP) — зарегистрируйте его в любом MCP-клиенте:

    claude mcp add --transport http ustory http://localhost:3800/mcp
  • Теперь ваш агент имеет memory_query / memory_add / memory_update / memory_status / memory_maintain и получает сид-обзор памяти при каждом старте сессии.

Научите его чему-нибудь (memory_add: «Мы выкатываемся по пятницам, никогда по понедельникам»), затем откройте граф и наблюдайте, как концепция встраивается сама. Разворачиваете через Portainer? Используйте docker-compose.portainer.yml как стек репозитория.

Related MCP server: Kremis

Стек

pnpm монорепозиторий:

Package

Что

packages/core

Слой бандла OKF (без LLM) + агент (цикл инструментов Vercel AI SDK: search/read/list/write/patch/delete) + реестр провайдеров

packages/server

Express: MCP streamable-HTTP на /mcp, stdio-бинарь, REST API просмотра на /api/*, стриминг-чат на /api/chat, раздаёт веб-сборку

packages/web

Vite + React + TS + Tailwind: браузер бандла + чат с агентом (useChat)

Провайдеры настраиваются через LLM_API_BASE_URL, LLM_API_KEY, LLM_API_FORMAT (openai или anthropic) и LLM_MODEL. Любой OpenAI-совместимый эндпоинт (DeepSeek, OpenAI, Groq, OpenRouter, llama.cpp и т.д.) работает с LLM_API_FORMAT=openai; Anthropic-совместимые эндпоинты используют LLM_API_FORMAT=anthropic. Опциональный запасной вариант использует соответствующие переменные LLM_FALLBACK_*.

llama.cpp

# on the inference box — --jinja enables OpenAI-style tool calling
llama-server -m model.gguf --jinja --host 0.0.0.0 --port 8080

# here — no model id needed, it's discovered for llama-server-like local endpoints
LLM_API_BASE_URL=http://inference-box:8080/v1 LLM_API_FORMAT=openai LLM_MODEL= \
BUNDLE_ROOT=./sample-bundle node packages/server/dist/index.js

Также работает за llama-swap: при обнаружении предпочитается текущая загруженная модель, чтобы запрос не вызывал многоминутную смену модели. Зафиксируйте конкретную модель с помощью LLM_MODEL=.

Из исходников

pnpm install
pnpm build
cp .env.example .env   # add your API key

BUNDLE_ROOT=./sample-bundle \
LLM_API_BASE_URL=https://api.deepseek.com/v1 \
LLM_API_KEY=sk-... \
LLM_API_FORMAT=openai \
LLM_MODEL=deepseek-chat \
node packages/server/dist/index.js
# → http://localhost:3800  (web UI + /api + /mcp)

Или соберите контейнер сами: docker compose up --build (docker-compose.yml из репозитория собирает из исходников и монтирует ./sample-bundle).

Режим разработки (сервер на :3800, Vite HMR на :5180 с прокси):

BUNDLE_ROOT=./sample-bundle pnpm --filter @understory/server dev
pnpm --filter @understory/web dev

Регистрация MCP (Claude Code / Desktop)

claude mcp add ustory \
  -e BUNDLE_ROOT=/path/to/your/bundle \
  -e LLM_API_BASE_URL=https://api.deepseek.com/v1 \
  -e LLM_API_KEY=sk-... \
  -e LLM_API_FORMAT=openai \
  -e LLM_MODEL=deepseek-chat \
  -- node /path/to/understory/packages/server/dist/mcp/stdio.js

Или укажите HTTP MCP-клиенту адрес http://host:3800/mcp.

Аутентификация

По умолчанию сервер открыт — это нормально для localhost или доверенной локальной сети. Прежде чем открывать его где-либо ещё, задайте AUTH_TOKEN:

AUTH_TOKEN=$(openssl rand -hex 24)

Когда он задан, /mcp и /api требуют Authorization: Bearer <token> (веб-интерфейс остаётся доступным и запрашивает токен). Регистрируйте аутентифицированные MCP-клиенты с заголовком:

claude mcp add --transport http ustory http://host:3800/mcp \
  --header "Authorization: Bearer <token>"

Транспорт stdio не требует токена — это локальный процесс, запускаемый клиентом.

Сид памяти

Клиентская LLM, которая видит только четыре голых имени инструментов, никогда не получит инстинкт проверять память. Поэтому при старте сессии сервер внедряет компактный обзор того, что содержит база знаний (каталоги, концепции с типами + описаниями, недавняя активность), через оба канала, которые достигают модели:

  1. поле instructions инициализации MCP (такие клиенты, как Claude, помещают его в системный промпт), и

  2. описание инструмента memory_query — универсальный запасной вариант, который загружает каждый клиент, вызывающий инструменты.

Сид перегенерируется заново для каждой новой сессии. После memory_add / memory_update в долгоживущей (stdio) сессии описание инструмента обновляется через tools/list_changed, так что сессия видит свои собственные записи. Внеполосные изменения (ручные правки, другие клиенты) подхватываются в следующей сессии.

Здоровье графа и обслуживание

Память — это граф, а не куча заметок, а графы портятся: концепции становятся осиротевшими (ничто на них не ссылается), а ссылки — битыми. Два механизма поддерживают его в порядке:

  • Связывание при записи — новое знание либо обогащает концепцию, к которой оно относится (атрибут существующей сущности вносится патчем, а не заводится отдельно), либо, если это отдельная сущность, создаётся и связывается обратными ссылками из связанных концепций. Противоречия замещаются на месте и никогда не остаются рядом со старым значением.

  • memory_maintain — детерминированный линт (осиротевшие + битые ссылки, отображаемые в memory_status в разделе graph) управляет внутренним агентом, чтобы встроить осиротевшие концепции в связанные и исправить висячие ссылки. Запускайте его периодически для противодействия дрейфу; когда граф уже здоров, он ничего не делает.

Эта конструкция повторяет паттерн из LLM Wiki Карпати (index.md + log.md, create-vs-enrich, линт для осиротевших). Отложено из этого паттерна до тех пор, пока масштаб не потребует: явная схема типов страниц и гибридный поиск FTS5+embedding (наивный скан в search.ts нормально работает до нескольких тысяч концепций).

Тесты

pnpm test                                  # core: 18 tests (spec §5/§6/§7/§9, sandbox, search, concurrency)
pnpm --filter @understory/server exec tsx scripts/mcp-smoke.mts   # MCP stdio round-trip (needs SMOKE_BUNDLE + an API key)

Окружение

Смотрите .env.example. BUNDLE_ROOT обязателен; GIT_AUTOCOMMIT=true коммитит каждую мутацию.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    A Knowledge Graph MCP server optimized for LLM context efficiency through compact JSON and SQLite persistence. It enables full graph management including node/edge CRUD operations, full-text search, and subgraph traversal.
  • A
    license
    A
    quality
    A
    maintenance
    MCP server exposing a deterministic, local knowledge graph over stdio. Zero LLM calls in the bridge; answers are classified as Fact, Inference, or Unknown and persisted in redb (ACID, BLAKE3-hashed).
    10
    14
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    A local OKF-compatible knowledge engine for AI agents. Enables capturing agent conversations, hybrid semantic+keyword search, MCP serving to agents, interactive graph visualization, and OKF bundle export.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides LLM agents with a structured, queryable, local-first knowledge base with typed documents and full-text search via MCP.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thecodacus/understory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server