mcpField
I
IHMT Memory

IHMT Memory

ローカル
github.com/gonzaromanメモリ・ナレッジ372 週間前に更新

IHMT Memory について

IHMT Memoryは、AIコーディングエージェント向けのローカル長期記憶MCPサーバーです。読みやすいファイルをツリー状に保存し、セッションやエージェント間で共有できます。古い情報を履歴として残し、全件走査を避けて検索します。

主な機能

  1. 01決定事項や好みをセッション間で保存
  2. 02複数エージェント間で記憶を共有
  3. 03ツリー形式のファイル保存と検索
  4. 04古い情報に印を付け履歴を保持
  5. 05クラウド不要のローカルテキスト保存

活用シーン

  1. 01新しいセッションでの背景説明を省く
  2. 02複数のコーディングエージェントで設定を共有
  3. 03決定事項と変更履歴を検索

MCP 対応

標準的なstdio MCPサーバーとして、長期記憶、プロジェクトインデックス、セッション用一時記憶のツールを公開します。READMEでは3種類、計9個のツールが説明されています。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"gonzaroman-ihmt-memory": {
"command": "uvx",
"args": [
"ihmt-memory"
],
"env": {
"IHMT_HOME": "<IHMT_HOME>"
}
}
}
}
起動コマンドuvx ihmt-memory
設定が必要な環境変数
IHMT_HOMEFolder that holds the memory (created on first use). Defaults to ~/.ihmt.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypiihmt-memory1.2.1

ツール

9

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
clueanyいいえ
querystringはい
detailstringいいえ

詳細

IHMT — 無限階層メモリーツリー

mcpservers.org に掲載 IHMT-MEMORY MCP サーバー – Glama の品質・メンテナンススコア

AI コーディングエージェントの長期記憶です。 エージェントに決定事項、セットアップの仕組み、修正点などを一度伝えるだけで、今後のすべてのセッション、あらゆるプロジェクトで、どのエージェントを使っていても覚えています。

IHMT の機能

  • セッションをまたいで記憶します。 決定事項とその理由、環境、好み、人やプロジェクト、修正点を記憶します。エージェントは回答前にメモリーを検索し、長く役立つ情報を保存するため、同じことを繰り返し伝える必要がなくなります。
  • すべてのエージェントとモデルで、ひとつのメモリーを共有できます。 Claude Code、Codex、opencodeで同じメモリーを共有でき、ひとつが保存した内容を、ほかのエージェントも見つけられます。Anthropic、OpenAI、Google、Metaのモデルでテスト済みです。
  • トークンを節約します。 毎回メモを貼り付けたり、背景情報を説明し直したりする代わりに、エージェントは質問に必要な情報だけを取得します。通常は200~900トークンで、メモリーに50件あっても50,000件あっても変わりません。すべてを読むのではなく、ツリーをたどって検索するためです。節約できないケースも含む正直な数値をご覧ください。
  • 時間の経過を理解します。 何かが変わると(「バレンシアに引っ越しました」「ステージング環境は現在 PostgreSQL 17 です」)、古いメモリーは履歴として保持され、OUTDATEDのフラグが付きます。検索結果では、現在の情報が先に表示されます。居住地、勤務先、技術スタックは自動的に追跡されます。それ以外の修正点は、エージェントがreplacesを付けて保存すると関連付けられます。質問が曖昧なとき(「Luis」―どちらの人でしょうか?)は、推測せずに確認します。
  • 持ち運びできます。 メモリーはプレーンテキストファイルのフォルダーひとつです。別のコンピューターにコピーしたり、バックアップしたり、バージョン管理下に置いたりできます。どこに置いても動作します。
  • ローカルでプライベート、読みやすい設計です。 クラウド、データベース、アカウントは不要です。IHMTはすべてをディスクに保存し、外部には何も送信しません。(エージェントが取得したメモリーは、ほかのコンテキストと同様にモデルへ渡されます。)すべてのメモリーは開いて読めるテキストファイルです。IHMTをインストールした人は、それぞれ空のメモリーから始めます。

互換性。 公式サポート対象はClaude Codeです。Codex(CLIとChatGPTデスクトップアプリ — セットアップ)とopencode(セットアップ)でもテスト済みです。IHMTは標準的なstdio MCP サーバーのため、ローカルMCP サーバーに対応するエージェントであれば、GitHub Copilot、Antigravity、Cursor、Windsurf、Gemini CLI、Claude Desktopなどでも動作するはずです。INSTALL.mdにはそれらの設定方法が記載されていますが、まだテストはしていません。どのエージェントでも、ひとつのメモリーを共有できます。

インストール

始める前に
必要なもの理由
Python 3.10 以降IHMT は Python で書かれています
gitIHMT をダウンロードして最新の状態に保つため
コマンドを実行できる AI エージェント(Claude Code、Codex、opencode、エージェントモードの Copilot など)IHMT をインストールし、その後メモリを使用します
インストール中のインターネット接続コードと MCP パッケージのダウンロードに必要です。インストール後は不要です

Python または git がありませんか? AI エージェントがインストールします(最初に確認するよう指示されています)。 Python は管理者パスワードなしでユーザーフォルダーにインストールされるため、システム全体には変更を加えません。購入したばかりの Mac では、git のインストール時にワンクリックが必要になる場合があります。 Apple がコマンドラインツールのインストールを求めるウィンドウを表示します。

Mac では、macOS に付属する python3 はバージョン 3.9 で古すぎることに注意してください。そのため、python3 が存在していても、エージェントが Python は見つからないと言う場合があります。

管理者権限、データベース、アカウント、エージェント以外の有料サービスは必要ありません。 macOS と Linux(Ubuntu)でテスト済みです。Windows については手順を記載していますが、まだテストされていません。 詳細:GUIDE.md §3。

AI エージェントにインストールしてもらう

メモリを使わせたい AI エージェントに、これを貼り付けてください。Claude Code、Codex、 opencodeで動作を確認済みです。GitHub Copilot、Antigravity、Cursor、Windsurf、Gemini CLI、 Claude Desktopやその他の MCP クライアントでも動作するはずです。

Install the IHMT memory MCP server for me from https://github.com/gonzaroman/IHMT-MEMORY — follow the instructions in its INSTALL.md.

エージェントはINSTALL.mdに従って、IHMT を~/IHMT-MEMORYにダウンロードし、 メモリを~/.ihmtに保存して、サーバーをそのエージェントだけに登録し、使い方の説明を追加して、 実行した内容を知らせます。その後、新しいセッションを開始してメモリツールを読み込んでください。

**複数のエージェントを使っていますか?**必要なときに、同じプロンプトをそれぞれに貼り付けてください。 IHMT がすでにインストールされている場合(たとえば Claude で何か月も使っていて、今度は Codex でも使いたい場合)、 エージェントはそのインストールを見つけ、安全に可能であれば更新し、同じメモリに接続します。 そのため、最初から他のエージェントに伝えた内容も把握できます。

ターミナルコマンドを実行するか、ファイルを編集できるエージェントが必要です。ブラウザー上でチャットするだけの アシスタントでは、インストールできません。

手動インストール

必要なもの:Python 3.10+、git、エージェントの CLI。

git clone https://github.com/gonzaroman/IHMT-MEMORY.git ~/IHMT-MEMORY
cd ~/IHMT-MEMORY
python3 -m venv .venv
.venv/bin/pip install -r requirements-mcp.txt
mkdir -p ~/.ihmt

Claude Code

claude mcp add ihmt-memory -s user -e IHMT_HOME="$HOME/.ihmt" -- "$PWD/.venv/bin/python" "$PWD/mcp_server.py"
claude mcp list                     # ihmt-memory … ✔ Connected

サーバー名は-eより前に指定する必要があります。続いて、 templates/memory-instructions.mdを~/.claude/CLAUDE.mdに追記します。

Codex — codex mcp add ihmt-memory --env IHMT_HOME="$HOME/.ihmt" -- "$PWD/.venv/bin/python" "$PWD/mcp_server.py"を実行し、 ~/.codex/config.tomlの[mcp_servers.ihmt-memory]テーブル(envテーブルの上)に default_tools_approval_mode = "approve"を追加して、テンプレートを~/.codex/AGENTS.mdに追記します。 詳細。

opencode — ~/.config/opencode/opencode.jsonの"mcp"オブジェクトに "ihmt-memory"エントリー("type": "local"、"command": [<python>, <mcp_server.py>]、 "environment": {"IHMT_HOME": <memory folder>})を追加し、テンプレートを~/.config/opencode/AGENTS.mdに追記します。 詳細。

Windows、プロジェクトスコープ、グラフィカルなセットアップ、トラブルシューティングについては、 ガイドをご覧ください。

PyPI からインストール(uvx)

クローンも仮想環境も不要です。uvが ihmt-memoryパッケージをダウンロードして実行します。メモリは~/.ihmtに保存されます。 別のフォルダーを使う場合(たとえば、すでにあるメモリを使う場合)は、IHMT_HOMEを設定してください。

Claude Code

claude mcp add ihmt-memory -s user -- uvx ihmt-memory
claude mcp list                     # ihmt-memory … ✔ Connected
uvx ihmt-memory --instructions >> ~/.claude/CLAUDE.md

Codex — codex mcp add ihmt-memory -- uvx ihmt-memoryを実行し、 ~/.codex/config.tomlの[mcp_servers.ihmt-memory]テーブルに default_tools_approval_mode = "approve"を追加して、uvx ihmt-memory --instructions >> ~/.codex/AGENTS.mdを実行します。

opencode — ~/.config/opencode/opencode.jsonの"mcp"オブジェクトに "ihmt-memory"エントリー("type": "local"、"command": ["uvx", "ihmt-memory"])を追加し、 uvx ihmt-memory --instructions >> ~/.config/opencode/AGENTS.mdを実行します。

最後の手順は、どのインストール方法でも重要です。この説明があることで、エージェントは回答前に検索し、 修正内容を保存するようになります。pipx install ihmt-memoryも使用できます。その場合は、 uvx ihmt-memoryの代わりにihmt-memoryを使ってください。

初めての方は、GUIDE.mdをご覧ください — 日常的な使い方を、実際の出力とともに順を追って説明しています。 README の残りは技術リファレンスです。


仕組み

LLM 向けの、特定の分野に依存しない汎用的な長期メモリです。ローカルディスク上に、プレーンファイルの再帰的なツリーとして保存されます。ベクトルデータベースもサーバーも、サードパーティ製の依存関係も不要です。必要なのは Python 3.10 以降と標準ライブラリだけです。

すべてを 1 つのフラットなインデックスに埋め込んでスキャンするのではなく、IHMT は知識をツリーに整理します。最下層には生のテキストのリーフ、その上には再帰的な JSON サマリー、最上部には単一の root.json の幹があります。クエリはこのツリーを、ルート → ブランチ → ブランチ → リーフの順にたどります。そのため、開かれるファイル数は保存量ではなくツリーの 深さ に応じて増加します(≈ beam × log_B(n))。

フラット RAGIHMT
検索コストすべての n 個のチャンクをスキャン/ANNbeam × log_B(n) 回のファイル読み取り
構造なし — ベクトルの寄せ集め明示的な階層構造で、確認可能
チャンク分割固定文字数のウィンドウ構文、シーン、日付を考慮
古くなった事実何も通知せずに提供古い情報として置き換えられ、日付とフラグを付与
曖昧さもっともらしい推測を返す手掛かりを尋ねる
ストレージバイナリインデックス読み取り可能な UTF-8 .txt + JSON

クイックスタート

python3 gui.py                       # graphical interface: set up, browse, inspect
python3 init_ihmt.py                 # or from the terminal: create ./ihmt_memory
python3 main.py demo                 # full walkthrough in ./demo_workspace
python3 -m unittest discover -v      # stdlib only; MCP tests skip without the SDK

続いて、独自の資料で使用します。

python3 main.py ingest ~/notes ~/project/src/Main.java
python3 main.py consolidate --force
python3 main.py search "how did we handle stock reservations"
python3 main.py ask "Luis"                    # interactive clue loop
python3 main.py conflicts                     # what changed over time

ライブラリとして使用する場合:

from ihmt import IHMT

memory = IHMT.initialize("./workspace")
memory.ingest_file("examples/InventoryService.java")
memory.ingest_file("examples/journal_personal.txt")
memory.flush()                                # close the tree up to the root

answer = memory.search("reserveStock soft hold")
print(answer.best.content)                    # the leaf
print(answer.best.path)                       # ['root', 'N1-software.java-…', 'L-software.java-…']
print(answer.node_reads)                      # how many branch files were opened

for notice in memory.notices():
    print(notice)   # "On 2024-03-11 you said user location = 'Madrid', but on 2026-02-03 you updated to 'Valencia'."

グラフィカルインターフェース

python3 gui.py                       # opens a browser at 127.0.0.1
python3 gui.py --path ~/my-memory --port 8765 --no-browser

依存関係は引き続きゼロです。サーバーには標準ライブラリの http.server を使用し、ループバックインターフェースのみで待ち受けます。また、すべての /api/* 呼び出しには、開いた URL に含まれるランダムなトークンが必要です。

画面は 4 つあります。セットアップ(システムダイアログでメモリフォルダーを選択してストアを作成し、プロジェクトごとの登録とグローバル登録のどちらかを選択します。書き込みの前に、実行されるコマンドまたは JSON の内容を正確にプレビューできます)、探索(置き換えに関する通知とともに、保存されたテキストまで展開できるツリー)、診断(信頼度、開いたファイル数と総数、たどった経路を表示する検索)、タイムライン(有効な値と履歴上の値、および検出された矛盾を表示)です。インターフェースは ES/EN の二言語対応で、メモリは読み取り専用です。リーフを削除したり編集したりすることはありません。


Claude Code から使用する(MCP)

mcp_server.py は、ツリーを Claude Code に公開し、長期メモリ、プロジェクトインデックス、セッション用スクラッチメモリの 3 つのファミリーに属する 9 つのツールを提供します。コア部分に依存関係はなく、SDK はオプションの追加機能です:

python3 -m venv .venv
.venv/bin/pip install -r requirements-mcp.txt        # mcp[cli]>=2.0

単一のプロジェクトで使用する場合は、.mcp.json.example をそのプロジェクトの .mcp.json にコピーし、絶対パスを入力します。次回のセッションで Claude Code から承認を求められます(それまでは claude mcp list に 承認待ち と表示されます):

{
  "mcpServers": {
    "ihmt-memory": {
      "command": "/absolute/path/to/IHMT-MEMORY/.venv/bin/python",
      "args": ["/absolute/path/to/IHMT-MEMORY/mcp_server.py"],
      "env": { "IHMT_HOME": "/absolute/path/to/IHMT-MEMORY" }
    }
  }
}

または、1 つのコマンドで実行します:

claude mcp add ihmt-memory --scope user \
  -e IHMT_HOME=/absolute/path/to/IHMT-MEMORY \
  -- /absolute/path/to/IHMT-MEMORY/.venv/bin/python /absolute/path/to/IHMT-MEMORY/mcp_server.py

IHMT_HOME はストア($IHMT_HOME/ihmt_memory)を指定します。ストアは初回使用時に作成されます。複数のプロジェクトを同じディレクトリに向けると、プロジェクト間で共有される 1 つのメモリを使用できます。または、プロジェクトごとに異なるディレクトリを指定することもできます。

ツール動作
search_memory(query, clue=None, detail="compact")ツリーを検索します。コンパクト出力では、最適なメモリとその日付、OUTDATED の通知を表示し、ほかの一致候補は 1 行ずつ表示します。detail="full" を指定すると、ID、ツリー内のパス、抜粋が追加されます。曖昧なクエリには推測で答える代わりに、候補を列挙した AMBIGUOUS ブロックを返します。その場合は clue を指定して再度呼び出してください。一致するものがない場合、および最も近いエントリに無関係な単語しか共通していない場合も、その旨を示します(NOT FOUND)。
save_memory(content, domain="general", content_type="auto", replaces="")テキストを分類、分割して保存し、日付付きの事実を抽出して、ツリーを整理された状態に保ちます。どのように保存されたかを報告し、保存内容が以前の記憶と矛盾する場合は、ユーザーに伝える通知も報告します。replaces に以前のメモリを表す数語を指定すると、保存内容はその修正として記録されます。古いメモリには OUTDATED のフラグが付き、検索結果では新しい内容が先に返されます。
mark_outdated(old_id, new_id)save_memory が replaces に対する候補を複数見つけて ID を列挙した場合に、一方のメモリが別のメモリによって修正されたことを示すフラグを付けます。
project_map(path, detail="files", subpath="")コードベースのコンパクトなマップを作成します。ファイルのサイズをトークン数で表示し、detail="symbols" を指定すると、各メソッドとその行範囲も表示します。同期マニフェストから作成するため、リーフを開きません。
find_code(query, path, scope="main", subpath="", clue=None, max_tokens=1500)クエリに答えるシンボルのみを、file:first-last + コードの形式で返します。scope は main(テストを除外)、test、all のいずれかです。
read_file(path, force=False)ファイルを読み込み、このセッションで読み込んだ内容を記録します。同じファイルを再度読み込むと、UNCHANGED または統合差分のみを返します。
note(text) / recall(query, clue=None)セッション用スクラッチメモリです。コンテキストの圧縮後も維持され、セッションの終了時に消えます。
digest_output(text, label="output")長いログを要約し、先頭行、エラー、失敗、テストの合計、末尾の行を残します。全文は引き続き検索できます。
セッション内でのトークン節約

長期メモリはセッション間のトークンを節約します。プロジェクトツールはセッション内でトークンを節約します。節約の対象となるコストは、同じファイルを何度も読み直すことです。ProjectIndex (ihmt/project_index.py) は、$IHMT_PROJECTS_DIR(デフォルトは $IHMT_HOME/ihmt_projects)の下に、プロジェクトごとのプライベートストアを保持します。

  • シンボルごとに1つのリーフ — code_chunk_mode="symbol" により、検索結果としてファイルではなくメソッドが返されます。
  • 呼び出しのたびにチェックサムを同期 — まずサイズと更新日時を確認し、変更があったファイルのみ SHA-256 を確認します。変更されたファイルは再取り込みされ、削除されたファイルは削除され、ブランチは再構築されます。古いコードが提供されることはありません。
  • パス順のブランチ — 各ファイルにパス順での順位を付けるため、各ブランチは隣接するファイルを網羅し、その要約は下位項目へたどる際にも意味を保ちます。
  • コードを考慮したランキング — ナビゲーターはカタログの scope/path_prefix で絞り込み、クエリで指定されたファイルを優先し、指定がない限りテストの順位を下げ、インポート行の順位も下げます。

Spring Boot の55ファイルからなるプロジェクトで、よくある質問8件を使って測定したところ、回答に必要なファイルを読むには3,613トークンかかりましたが、find_code は8件すべてで該当メソッドを正確に返し、必要なトークンは1,071でした。プロジェクトのマップは660トークンで、プロジェクト全体を読む場合の13,157トークンより少なくて済みます。

この節約効果は、ファイル全体を読むエージェントとの比較です。実際のヘッドレス Claude Code セッション22件を使った A/B テストでは、Claude はバッチ処理した grep/sed -n を選び、自発的にプロジェクトツールを呼び出すことはありませんでした。強制的に使用させると、セッションのコストは42~71%増加しました。Claude Code は MCP ツールを必要に応じて読み込むため、サーバーを有効にしておくコストは会話あたり約460トークンです。IHMT の主な価値はセッション間のメモリにあります。プロジェクトツールは任意として扱い、CLAUDE.md で使用を必須にしないでください。

このサーバーは MCP SDK 2.x(MCPServer)、1.x(FastMCP)、およびスタンドアロンの fastmcp パッケージを透過的にサポートします。

~/.claude/CLAUDE.md にある使用方法の説明(テンプレート)では、各ツールをいつ使うかを Claude Code に伝えます。以前のセッションに依存する内容に回答する前に検索すること、日付とともに長期的に有用な事実を保存すること、AMBIGUOUS の場合は決して推測しないこと、OUTDATED は必ず伝えること、そして秘密情報を保存しないことを指示します。


ストレージの構成

すべてのデータは、場所を変更できる1つのディレクトリに格納されます。

ihmt_memory/
  root.json                 # the trunk: domains, topics, top branches, counters
  layer_0/<domain>/*.txt    # the leaves: raw UTF-8 text + a strict JSON header
  layers/1/*.json           # branches: summaries of leaves
  layers/2..N/*.json        # branches: summaries of summaries
  state/catalog.json        # index: id -> path, domain, parent, timestamp
  state/facts.json          # the fact timeline
  ihmt.config.json          # branch factor, token budgets, backend

root.json は ihmt_memory/ の内部にあるため、ストアは自己完結しています。ディレクトリをコピーすれば、メモリも一緒に移動します。

リーフは、自分自身について説明する通常のテキストファイルです。そのため、カタログが失われても意味を保ちます。

<<<IHMT-META
{
  "leaf_id": "L-software.java-0001-84130ee123",
  "timestamp": "2026-09-09T17:45:00Z",
  "data_type": "CODE",
  "domain": "software.java",
  "tags": ["method:reserveStock", "class:InventoryService", "lang:java", "type:code"],
  "parent_id": "N1-software.java-5571a7baac",
  "span": {"start_line": 43, "end_line": 68},
  "checksum": "sha256:…",
  "extra": {"context": "public final class InventoryService {"}
}
IHMT-META>>>
    public Optional<String> reserveStock(Sku sku, int quantity) {
        …

ブランチノードには、各子ノードのタイトル、抜粋、キーワードが埋め込まれています。これにより、下位項目を一つも開かずにブランチをランキングでき、下位項目へたどるコストを抑えられます。


5つのコンポーネント

1. UniversalIngestor — 検出、分割、拡充、保存

DomainDetector は、拡張子と英語およびスペイン語の語彙的特徴から、各ドキュメントのタイプ(CODE、NARRATIVE、CLINICAL、PERSONAL、PROCESS、GENERIC)とドメイン(software.java、medicine.clinical、process.cooking、personal、…)を分類します。--domain / --type で、どちらも上書きできます。

タイプによってスプリッターが選択されます。すべてのスプリッターは、次の不変条件に従います。

論理ブロックが途中で分割されることはありません。 1つのブロックが max_tokens を超える場合は、全体をそのまま保存し、oversized としてフラグを付けます。トークン予算を守ることよりも、ブロックの完全性を優先します。

  • コード(chunkers/code.py)— Python には標準ライブラリの ast を使用します。Java/JS/TS/C/C++/C#/Go/Rust/Kotlin/Swift/PHP には、コメント、文字列リテラル、文字リテラル、テンプレートリテラル、プリプロセッサ行を読み飛ばしながら、中括弧の深さを追跡する文字単位のスキャナー BraceScanner を使用します。インポートはまとめられ、各クラス/関数が1つのブロックになります。大きすぎるクラスはメンバーごとに分割され、外側のクラスヘッダーはテキストに挿入されず、リーフの extra.context に格納されます。ファイルのリーフを連結すると、テストで検証されているとおり、ファイルをバイト単位で完全に再現できます。
  • ナラティブ — 段落単位で扱い、***、---、Chapter/Capítulo を明確な境界とします。max_tokens を超える段落だけを分割し、その場合も文の境界で分割します。
  • 時間的データ(日誌、チャット、診療記録)— 日付のある各記録は分割されず、日付の変化が明確な境界となるため、1つのリーフに複数の診療記録が混在することはありません。**テキストから見つかった日付がリーフのタイムスタンプになります。**これにより、再現性の重み付けが取り込み時点ではなく、何がいつ真実だったかを表せます。
  • プロセス(レシピ、プロトコル、ランブック)— 手順や材料のリストは、見出しと一緒に保持されます。

リーフ ID は (domain, source, position, content) から導出されるため、変更のないドキュメントを再取り込みしても、リーフが重複するのではなく、同じリーフが書き換えられます。

2. RecursiveSummarizer — 要約イベント

レイヤー 0 を監視します。あるドメインで親を持たないリーフが branch_factor 個に達すると、要約イベントを発生させます。リーフをレイヤー 1 のノードにまとめ、そのノードを書き込んでから、その後に限り子に parent_id を設定します。これにより、実行が中断されても、グループが孤立するのではなく再処理されます。同じルールがレイヤー 1 からレイヤー 2 へと適用され、ツリーが収束するまで続きます。その後、root.json が書き換えられます。

consolidate() は冪等です。flush()(--force)を実行すると、未完了のグループも昇格され、ツリーが完全に閉じます。まだ統合されていないものは、すべてトランクから直接参照されるため、ストア内のデータがルートから到達不能になることはありません。

3. SemanticNavigator — 降下とインタラクティブな手がかりのループ

ランキングには、各候補のタイトル、キーワード、タグ、抜粋に対して Okapi BM25 を使用します。フィールドの重みとドキュメント頻度は、現在のレベルにある兄弟ノード全体から算出されます。これは降下に必要な識別力を、追加の I/O コストなしで実現します。探索では、各レベルで beam_width 個の分岐をビームに保持します。

信頼度は、互いに独立した2つのシグナルを組み合わせます。

confidence = 0.6 × coverage + 0.4 × margin

網羅性は「このリーフに、尋ねられた内容が実際に含まれているか」を問い、マージンは「競合候補と区別できるか」を問います。よくある名は前者で高得点、後者でほぼゼロになるため、システムが推測してはならないのは、まさにこのような場合です。

$ python main.py ask "Luis"

"Luis" is ambiguous (3 memories match this query equally well, confidence 0.62).
It could belong to any of these branches:
  1. [personal] journal_personal.txt · 2024-07-22 — Vacaciones en Benidorm con Luis, mi primo…
  2. [personal] journal_personal.txt · 2026-08-30 — Fin de semana en la playa de El Saler con Luis…
  3. [personal] journal_personal.txt · 2024-11-30 — Cierre de trimestre… Luis Marín revisó el pull request…
Give me a clue to narrow it down (e.g. a place, a date, a project):
> vacaciones en Benidorm

query: "Luis + vacaciones en Benidorm" · confidence 0.74 · 5 node reads, 3 leaf reads, depth 2
  1. [personal] journal_personal.txt · 2024-07-22
     path  root → N2-personal-ea34db33ae → N1-personal-59bf8bc291 → L-personal-0002-a17b3c8f35

手がかりによって共同クロスリファレンスが実行されます。両方の用語グループに一致する候補は加点(×1.6)され、片方だけに一致する候補は減点(×0.7)されます。このループは max_clue_rounds 回まで実行され、ユーザーが断ると早期に終了します。曖昧なクエリを、ユーザーに知らせずに確信を持った回答へ変換することはありません。

clue_provider には任意の呼び出し可能オブジェクトを指定できるため、ターミナルを使う人間(input)にも、LLM が独自の追加質問を提示できるエージェントにも対応します。

4. ConflictResolver — 新しさの重み付けとタイムライン

ファクトは (subject, attribute, value, timestamp, source_leaf) の形式で、record_fact() によるプログラムからの記録、または取り込み時のパターンルール(vivo en X / I live in X、 mi stack es Y、trabajo en Z、Diagnóstico:、Tratamiento:、Medicación: など。add_pattern で拡張可能)によって抽出されます。

各 (subject, attribute) には日付付きのタイムラインが保持されます。最新の値は ACTIVE となり、それ以前の値はすべて superseded_by と valid_from/valid_to の期間が設定された HISTORICAL になります。何も削除されないため、次の両方の質問に回答できます。

memory.resolver.active_state()["user::location"].value      # 'Valencia'  (now)
memory.resolver.state_at("2024-12-31")["user::location"].value  # 'Madrid'  (back then)

後日、同じ値を繰り返すのは矛盾ではなく確認です。実際に値が変更された場合は、透明性のある通知が生成されます — 「2024-03-11 にはユーザーの所在地を『Madrid』とおっしゃっていましたが、2026-02-03 に『Valencia』に更新されました。」 — また、置き換えられたリーフには注釈が付けられるため、古い内容を取得すると、その訂正も必ず一緒に提示されます(SearchResult.notices)。

リーフ自体は ACTIVE のままです。そこに記載された内容は、そのリーフの日付時点では正しかったものであり、過去についての質問には今も正しい答えです。変わるのは、その内容を現時点の情報として読めなくなることです。

5. 要約バックエンド
class SummarizerBackend(Protocol):
    name: str
    def summarize(self, children, *, domain: str, layer: int) -> NodeSummary: ...
  • HeuristicSummarizer(デフォルト)— 標準ライブラリを使った抽出的要約です。EN/ES のストップワードを使った TF による用語のランキングと、代表的な文の選択を行います。オフラインで動作し、決定的な結果が得られるため、テストスイートでツリー構造を検証できます。
  • AnthropicSummarizer(オプション)— 選択されており、かつ anthropic パッケージと ANTHROPIC_API_KEY の両方が存在する場合にのみ使用されます。SDK の欠落、キーの欠落、ネットワークエラー、解析不能な応答など、あらゆる失敗時にはヒューリスティックバックエンドにフォールバックするため、モデルに到達できないことが原因で統合が失われることはありません。
python3 init_ihmt.py --backend anthropic     # model set by summarizer_model in ihmt.config.json

ほかのモデルやローカルランタイムも、同じプロトコルを実装し、IHMT(..., backend=MyBackend()) に渡すことで接続できます。


CLI リファレンス

コマンド目的
init [--branch-factor N] [--target-tokens N] [--force]ストアを作成します
ingest <paths…|-> [--domain D] [--type T] [--tag X] [--no-consolidate]ファイル、ディレクトリ、または標準入力を取り込みます
consolidate [--force]保留中の要約イベントを実行します
search <query> [--top-k N] [--full]ツリーをたどって検索します
ask <query> [--clue TEXT] [--top-k N]手がかりのループを使って検索します
tree [--depth N]階層の概要を表示します
stats、facts [--subject S]、conflicts [--subject S]検査します
rebuildファイルからカタログ、タイムライン、幹を再構築します
demoエンドツーエンドの手順を実演します

--path はストアディレクトリを指定し、--json は機械可読形式で出力します。どちらもサブコマンドの前後で指定できます。

設定

ihmt_memory/ihmt.config.json:

キーデフォルト意味
branch_factor8各ブランチの子ノード数。取得コストの対数の底です
target_tokens / max_tokens2000 / 3000リーフサイズの目標値と超過のしきい値
beam_width3各レベルで保持するブランチ数
confidence_threshold0.45この値を下回ると手がかりを求めます
ambiguity_margin0.18候補が同点とみなされるスコア差のしきい値
max_clue_rounds3手がかりループの反復回数
summarizer_backend / summarizer_modelheuristic / claude-sonnet-5要約
code_chunk_modepacksymbol はクラスメンバーごとに 1 つのリーフを格納します(プロジェクトのインデックスで使用)

小規模なコーパスでは、小さなブランチ係数が適しています。デモでは、少数のドキュメントでも実際に複数階層のツリーが構築されるよう、branch_factor=4, target_tokens=400 を使用します。

テスト

python3 -m unittest discover -v          # from the project root

187 件のテストがあり、そのうち 25 件は MCP サーバー用で、SDK がない場合はスキップされます。対象は、Java と Python のバイト単位で正確な再構築と境界深度の不変条件、シーン/日付/セクションの原子性、サイズ超過ブロックの処理、リーフヘッダーの往復、カタログの復旧、要約のしきい値、上位への伝播、冪等性、ルートからの完全な到達可能性、降下コストの上限、手がかりループ、最近性の重み付け、過去の記録の保持、プロジェクトのインデックス、MCP ツール、グラフィカルインターフェース、CLI です。

設計上の注意点と制限

  • 検索はスキャンではなく降下です。 これがこの仕組みの要点であり、幹の時点で刈り込まれた枝は再訪されません。ドメインレベルの刈り込みは、クエリに幹で実際のシグナルがある場合にのみ行われます。シグナルがなければ、すべてのドメインが候補に残り、ビームがその 1 階層下で適用されます。降下範囲が広くなった場合の復旧手段が、手がかりループです。
  • セマンティックではなく、語彙ベースです。 アクセント記号を除去し、CamelCase を分割したトークンに対して BM25 で照合します。どの言語でも動作し、モデルも不要ですが、同義語には一致しません。BM25Ranker に埋め込み再ランキングを組み込むのが自然な拡張方法です。ツリー構造は変わりません。
  • トークン数は推定値です。 1 トークンあたり約 4 文字として見積もります。予算は正確である必要はなく、一貫していれば十分です。
  • 事実抽出はパターンベースです。 同梱のルールは、一般的な英語/スペイン語の言い回しと臨床分野の見出しを対象としています。確実な方法は record_fact() を使うことで、add_pattern() でルールを拡張できます。
  • 書き込みは単一ライターを前提とします。 書き込みはアトミックに行われ(tmp + os.replace)、カタログの再構築時にはロックファイルを取得しますが、ストアは一度に 1 つのライターのみを想定しています。
  • initialize(force=True) が破棄するのは派生状態(ブランチ、カタログ、タイムライン)のみです。残存するリーフは切り離され、次の統合時に階層が再構築されます。リーフの内容が削除されることはありません。

レイアウト

ihmt/
  api.py                    IHMT facade wiring everything together
  config.py                 IHMTConfig
  models.py                 MemoryLeaf, BranchNode, ChildRef, RootIndex, Fact, Contradiction
  storage.py                MemoryStore: atomic I/O, catalog, recovery
  textutils.py              tokenizing, keywords, entities, extractive summary, timestamps
  detectors.py              DomainDetector
  chunkers/                 base · code · narrative · temporal · process · generic
  summarizers.py            SummarizerBackend · Heuristic · Anthropic
  universal_ingestor.py     UniversalIngestor
  recursive_summarizer.py   RecursiveSummarizer
  semantic_navigator.py     SemanticNavigator, BM25Ranker, ClueRequest, scope/path filters
  project_index.py          ProjectIndex: per-project code cache with checksum sync
  conflict_resolver.py      ConflictResolver + timeline manager
ihmt_gui/                   local graphical interface (stdlib only)
mcp_server.py               MCP server: the nine tools
ihmt_launcher.py            the `ihmt-memory` command of the PyPI package (~/.ihmt by default)
pyproject.toml · server.json   PyPI package · MCP Registry entry
init_ihmt.py · main.py · gui.py · examples/ · tests/
GUIDE.md                    installation and usage guide
INSTALL.md                  installation instructions for AI agents
templates/                  memory-instructions.md: the usage rules agents append to CLAUDE.md / AGENTS.md

ライセンス

MIT © 2026 Gonzalo Román Márquez (gonzaroman)

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。