Skip to main content
Glama
thecodacus

OKF Knowledge Agent MCP Server

by thecodacus

understory 🌱

成長するメモリ。

エージェントの下層に位置する、自己配線型のプレーンマークダウンメモリ。エージェントが学んだすべての事実はマークダウンのコンセプトとしてファイル化され、生きたナレッジグラフに相互リンクされ、エージェント自身によって健全に保たれます。検索可能で、差分も取れ、完全にあなたのもの。ローカルモデルでも問題なく動作します。

バンドルは Open Knowledge Format (OKF) v0.1 spec に従います。YAMLフロントマター付きのプレーンマークダウンファイルで、人間が読め、gitで差分を管理でき、ツール間で移植可能です。

3つの入り口、1つのエージェント:

  • MCP server — stdioまたはストリーマブルHTTP上で memory_query / memory_add / memory_update / memory_status / memory_maintain ツールを提供します。各呼び出しは、システムプロンプトにOKF仕様を持つ内部LLMエージェントを駆動します。

  • Web UI — バンドルを閲覧(ツリー、コンセプトビューア、更新ログ、適合バッジ)、Obsidianスタイルのフォース指向グラフとしてメモリを表示(ドラッグ/パン/ズーム、タイプ別に色分け、接続数でサイズ調整、孤立ノードは赤いリング、クリックで開く)、同じエージェントとチャットしてテストできます。ツール呼び出しはインラインで表示されるので、動作を確認できます。

  • クエリパス再生 — すべてのエージェント実行(クエリ/ミューテーション/チャット)は、そのトラバーサル(検索→読み取り→書き込み)をコンパクトな表記で記録し、<bundle>/.traces/ の下に永続化します。グラフビューには最近の実行が一覧表示され、1つ選択すると、パスが番号付きの有向ホップとしてグラフ上で再生されます。訪問したコンセプトはリング、検索ヒットは点線、それ以外はフェードアウトします。

  • CLI — pnpm agent:query "..." / pnpm agent:mutate "..." スモークエントリ。

設計ルール: 適合性はプロンプトではなくコードで強制されます。 決定的なバンドル層は、フロントマター(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

プロバイダの選択

汎用プロバイダシステムは、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-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

ローカル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 を使用してください。

DeepSeekフォールバック付きローカルllama.cpp:

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(ストリーマブル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モノレポ:

パッケージ

説明

packages/core

OKFバンドル層(LLMなし)+ エージェント(Vercel AI SDKツールループ: search/read/list/write/patch/delete)+ プロバイダレジストリ

packages/server

Express: /mcp でのMCPストリーマブルHTTP、stdioバイナリ、/api/* でのRESTブラウズAPI、/api/chat でのストリーミングチャット、Webビルドを配信

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や信頼できるLANでは問題ありません。他の場所に公開する前に、AUTH_TOKEN を設定してください:

AUTH_TOKEN=$(openssl rand -hex 24)

これを設定すると、/mcp と /api は Authorization: Bearer <token> を要求します(Web UIは引き続きアクセス可能で、トークンの入力を求められます)。認証付きMCPクライアントをヘッダー付きで登録:

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

stdioトランスポートはトークンを必要としません。クライアントが生成するローカルプロセスだからです。

シードメモリ

4つの裸のツール名だけを見るクライアントLLMは、メモリを確認するという本能を持ちません。そこで、セッション開始時にサーバーは、ナレッジベースの内容(ディレクトリ、タイプと説明付きのコンセプト、最近のアクティビティ)のコンパクトな概要を、モデルに届く両方のチャネルを通じて注入します:

  1. MCP initialize の instructions フィールド(Claudeのようなクライアントはこれをシステムプロンプトに含めます)、および

  2. memory_query ツールの説明 — すべてのツール呼び出しクライアントが読み込む普遍的なフォールバック。

シードは新しいセッションごとに新しく再生成されます。長期間続く(stdio)セッションで memory_add / memory_update を行った後、ツールの説明は tools/list_changed を介して更新され、セッションは自身の書き込みを確認できます。帯域外の編集(手動編集、他のクライアント)は次のセッションで反映されます。

グラフの健全性とメンテナンス

メモリはグラフであり、ノートの山ではありません。そしてグラフは腐敗します。コンセプトは孤立し(何もリンクしない)、リンクは壊れます。2つのメカニズムが健全性を保ちます:

  • 書き込み時リンク — 新しい知識は、それが属するコンセプトを豊かにするか(既存エンティティの属性は別ファイルではなくパッチとして取り込まれる)、または、それが別個のエンティティである場合は、作成されかつ関連コンセプトからバックリンクされます。矛盾はその場で置き換えられ、古い値と並んで残ることはありません。

  • memory_maintain — 決定的なlint(孤立と壊れたリンク。memory_status の graph の下に表示されます)が内部エージェントを駆動し、孤立を関連コンセプトに配線し、ぶら下がったリンクを修正します。ドリフトに対抗するために定期的に実行してください。グラフがすでに健全な場合は何もしません。

この設計は、Karpathyの LLM Wiki のパターンを反映しています(index.md + log.md、作成対拡張、孤立のlint)。スケールが必要になるまで先送りされているもの: 明示的なページタイプスキーマと、ハイブリッドFTS5+埋め込み検索(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 はすべてのミューテーションをコミットします。

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
    15
    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
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP 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.
    -