OKF Knowledge Agent MCP Server
understory 🌱
不断生长的记忆。
位于你的智能体之下的一层:一种自连线的纯 Markdown 记忆。你的智能体学到的每一条事实都会被整理为一个 Markdown 概念,交叉链接进一个活的知识图谱,并由智能体自身维护其健康——可搜索、可 diff、完全归你所有。在本地模型上运行效果很好。
Bundle 遵循 Open Knowledge Format (OKF) v0.1 spec —— 带 YAML frontmatter 的纯 Markdown 文件,人类可读、可在 git 中 diff、可跨工具移植。
三种接入方式,同一个智能体:
MCP server —— 通过 stdio 或 streamable HTTP 提供
memory_query/memory_add/memory_update/memory_status/memory_maintain工具。每次调用都会驱动一个内部 LLM 智能体,其系统提示词中包含 OKF 规范。Web UI —— 浏览 bundle(目录树、概念查看器、更新日志、一致性徽章),以 Obsidian 风格的力导向图查看记忆(拖拽/平移/缩放,按类型着色,按连接数决定大小,孤立概念以红色圆环标出,点击打开),并与同一个智能体聊天来测试它。工具调用会内联渲染,让你能观察它的工作过程。
查询路径回放 —— 每次智能体运行(查询/变更/聊天)都会将其遍历过程(搜索 → 读取 → 写入)以紧凑记法记录下来,持久化在
<bundle>/.traces/下。图视图会列出最近的运行;选中一次运行后,会以编号的有向跳转在图上回放路径——已访问的概念带圆环,搜索命中用点线标出,其余全部淡化。CLI ——
pnpm agent:query "..."/pnpm agent:mutate "..."冒烟测试入口。
设计原则:一致性由代码强制保证,而非提示词。 确定性的 bundle 层会校验 frontmatter(type 必填)、重新生成 index.md 文件、追加 log.md 条目(最新的在前,规范 §7),并将所有路径沙箱化到 bundle 根目录。LLM 决定要改什么;代码保证结果是一个符合规范的 bundle。
快速开始(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选择提供商
通用提供商系统支持任何兼容 OpenAI 或兼容 Anthropic 的 API。
设置 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-chatOpenAI:
LLM_API_BASE_URL=https://api.openai.com/v1 LLM_API_KEY=sk-... LLM_MODEL=gpt-4oAnthropic (Claude):
LLM_API_BASE_URL=https://api.anthropic.com/v1 LLM_API_KEY=sk-ant-... LLM_API_FORMAT=anthropic LLM_MODEL=claude-sonnet-5Groq:
LLM_API_BASE_URL=https://api.groq.com/openai/v1 LLM_API_KEY=gsk_... LLM_MODEL=llama-3.3-70b-versatile本地 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。
本地 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 以及各提供商专属的密钥环境变量仍然有效(向后兼容),但已弃用。
然后:
Web UI → 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 monorepo:
Package | 说明 |
| OKF bundle 层(零 LLM)+ 智能体(Vercel AI SDK 工具循环:search/read/list/write/patch/delete)+ 提供商注册表 |
| Express:MCP streamable-HTTP 位于 |
| Vite + React + TS + Tailwind:bundle 浏览器 + 智能体聊天( |
提供商通过 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 devMCP 注册(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 或可信 LAN 上没问题。在将其暴露到任何其他地方之前,请设置 AUTH_TOKEN:
AUTH_TOKEN=$(openssl rand -hex 24)设置后,/mcp 和 /api 需要 Authorization: Bearer <token>(Web UI 仍然可访问,并会提示输入 token)。使用请求头注册已认证的 MCP 客户端:
claude mcp add --transport http ustory http://host:3800/mcp \
--header "Authorization: Bearer <token>"stdio 传输不需要 token——它是由客户端生成的本地进程。
种子记忆
一个只看到四个光秃秃的工具名称的客户端 LLM 永远不会产生检查记忆的本能。因此,在会话开始时,服务器会通过两条到达模型的通道注入知识库内容的紧凑概览(目录、带类型和描述的概念、近期活动):
MCP initialize 的
instructions字段(像 Claude 这样的客户端会将其放入系统提示词),以及memory_query工具描述 —— 每个工具调用客户端都会加载的通用回退。
种子会在每个新会话中重新生成。在长生命周期(stdio)会话中执行 memory_add / memory_update 后,工具描述会通过 tools/list_changed 刷新,因此会话能看到自己的写入。带外编辑(手动编辑、其他客户端)会在下一个会话中被捕获。
图谱健康与维护
记忆是一个图谱,而不是一堆笔记,而图谱会腐烂:概念会变成孤立(没有任何链接指向它们),链接会断裂。有两种机制保持其健康:
写入时链接 —— 新知识要么丰富它所属的概念(现有实体的属性被修补进去,而不是单独归档),要么在它是一个独立实体时被创建并从相关概念反向链接。矛盾会在原地被取代,绝不会与旧值并存。
memory_maintain—— 一个确定性的 lint(孤立概念 + 断裂链接,在memory_status的graph下显示)驱动内部智能体将孤立概念接入相关概念并修复悬空链接。定期运行它以对抗漂移;当图谱已经健康时,它是一个空操作。
这一设计借鉴了 Karpathy 的 LLM Wiki 中的模式(index.md + log.md、创建与丰富之争、针对孤立的 lint)。在规模需要之前,暂缓实现该模式中的:显式页面类型 schema,以及混合 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 会为每次变更提交。
This server cannot be deployed
Maintenance
Related MCP Connectors
Knowledge base MCP for AI agents on iknow.dev. Search, read, and maintain via OAuth.
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Knowledge base for AI agents: search, read, tasks; write, correct, report outcomes via /mcp/write.
Persistent memory, hybrid search and a goal graph for AI agents, over stdio or remote HTTP.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceA 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.-
- AlicenseAqualityAmaintenanceMCP 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).1015Apache 2.0
- FlicenseNot gradedqualityDmaintenanceMCP server exposing a RAG knowledge base as read-only tools (search_knowledge_base, ask_knowledge_base, kb_stats, kb_diagnostic) for AI clients like Claude Desktop and Cursor, enabling token-efficient document retrieval and Q&A.-
- AlicenseBqualityCmaintenanceLocal-first knowledge system for reasoning agents, exposing facts, evidence, documents, retrieval, and audit history through a thin stdio MCP server.14MIT