# Tiny ConvMem MCP Design ## 1. 文書の位置づけ 本書は `tiny-convmem-mcp` の設計、実装済み契約、制約、I/O 予算、実装状況をまとめた正本である。 過去のプロトタイプ案と本書が矛盾する場合は、本書と公開ツールの実装を優先する。 ## 2. 目的とスコープ `tiny-convmem-mcp` は、会話メッセージをローカルに永続化し、MCP 経由で読み書き、更新、検索、削除できる単一プロセスの C17 サーバーである。 現行 v1 の対象は次のとおり。 - Windows x64 / MSVC - stdio JSON-RPC / MCP - 単一プロセス、単一 writer - append-only バイナリログ、snapshot、同期 compaction - インメモリ履歴・検索・relation index - UTF-8 のメッセージと構造化 metadata - CLI による JSONL import/export 対象外は次のとおり。 - 複数 writer、ネットワークサービス、ユーザー認証 - 保存時暗号化と secure physical erase - retention、tier による自動移動・削除 - 自動保存判断、自動要約、自動 consolidation - 利用頻度による強化・減衰 - search の cursor pagination ## 3. アーキテクチャ 依存方向は次を原則とする。 ```text MCP transport / tools -> domain contracts <- storage adapters ^ | system API ``` - `src/app`: 引数処理、store/server/CLI のライフサイクル - `src/mcp`: MCP 境界、入力検証、JSON 応答、tool registry - `src/domain`: Message、metadata、検索契約 - `src/storage`: log、snapshot、replay、compaction、import transaction - `src/sys`: path、lock、file、flush、clock、random、UTF-8 境界 - `src/cli`: offline import/export - `third_party/mcpc`: MCP transport と JSON parser 永続化ロジックは `src/storage`、OS 固有処理は `src/sys` に閉じ込める。read 系 tool は永続化状態を変更しない。 ## 4. ドメインモデル Message は次の不変 identity と、追記レコードで更新される内容を持つ。 ```json { "message_id": "26-character ULID", "session_id": "session", "timestamp": 1720843200000, "updated_at": 1720843200000, "revision": 1, "role": "user | assistant | system", "content": "UTF-8 text", "metadata": { "tool_call_id": "optional", "tags": ["optional"], "memory_tier": "short | mid | long", "memory_kind": "conversation | episode | semantic | procedure | preference | summary", "importance": 0, "summary": "optional", "relations": [{"type": "derived_from", "message_id": "..."}], "source_message_ids": ["..."] } } ``` 主な上限は content 1 MiB、session/tool-call ID 256 bytes、tag 128 bytes × 32、summary 4096 bytes、relation 32、summary source 64 である。文字列は有効な UTF-8 を要求する。 `memory_tier` は現時点では分類ラベルであり、保存場所や寿命を自動変更しない。`summary`、relation、source ID は host が行う consolidation を表現するための契約である。 UPDATE は message ID、session、role、作成時刻を維持する。revision による optimistic concurrency を使い、変更のない update はレコードを書かない。 ## 5. 公開 MCP ツール ### `write_message` session、role、content と任意 metadata を受け取り、ULID と UTC millisecond timestamp を生成する。ログ書込みと durability flush が成功した後だけ成功を返す。 ### `update_message` content または metadata を部分更新する。`expected_revision` が一致しない場合は conflict とする。delta record には変更 field だけを書き、no-op は 0 write / 0 flush とする。 ### `read_messages` 次の view を持つ。 - `history`: session の時系列ページ。安定 cursor を返す - `content`: message contentをUTF-8 byte offsetとbounded limitで分割取得する - `context`: target の前後メッセージと incoming/outgoing relation を返す。relation depth は 0~2 - `sessions`: session ごとの件数、kind 集計、代表 summary、最終時刻を返す - `export`: versioned JSONL をページ出力する互換 view レスポンスは 8 MiB budget を超えない位置でページを区切る。 `content` viewは既定4096 bytes、最大65536 bytesを返す。offsetは0、末尾、またはUTF-8 code point境界だけを受理し、limit位置がcode point途中なら直前の境界まで戻す。limitが 1 code pointより小さい場合だけ、そのcode pointを完全に返して進捗を保証する。各responseの `revision`と`total_bytes`を返し、2回目以降の`expected_revision`で途中更新を`CONFLICT`として 検出する。このviewは永続data、access履歴、revisionを変更しない。message検索に必要な既存の in-memory indexは、他のread viewと同様に必要時だけ構築する。 このview追加は既存toolへのadditive schema changeだけである。既存viewのinput、response、 cursor semanticsと、保存recordおよびsnapshotのformat versionは変更しないため、data migration とrebuildは不要であり、旧binaryと新binaryは同じdataを読み込める。 ### `search_messages` content、summary、tags を対象に検索する。session、kind、tier、tag、minimum importance で絞り込める。matched fields、score と field 別 score 内訳、任意の前後 context を返す。 検索 index は ASCII case fold 後の Unicode codepoint 2/3-gram を用いる。hash candidate は元 codepoint と照合し、完全 substring を優先する。importance は relevance score ではなく tie-break に用いる。検索はアクセス履歴を保存しない。 ### `delete_message` DEL tombstone を durability flush し、対象を直ちに read/search から除外する。物理削除は compaction 後である。任意の session guard を指定できる。 ### `rebuild_index` live message だけで active log を再生成し、snapshot と全インメモリ index を再構築する。dangling relation/source は compaction 前に除去する。同期処理であり、実行中は他の request を処理しない。 ### `get_system_health` live/deleted count、sequence、log/snapshot size、snapshot/recovery 状態、論理 I/O counter、last error を返す。 store body/metadataと各in-memory indexの確保capacityに基づくmemory estimateも返す。 ## 6. ストレージと復旧 ### 6.1 Active log 各 record は magic、format version、record type、payload length、sequence、payload CRC32 と payload を持つ。PUT、UPDATE delta、DEL、generation marker を扱う。 - record length は上限を検証する - sequence は単調増加を要求する - complete record の CRC、version、type 異常は起動失敗とする - incomplete final record だけは最後の正常 offset へ truncate して復旧する - 不正な complete record を黙って skip しない ### 6.2 Snapshot snapshot は live Message、log generation、replay offset を保持する。一時ファイルへ書き、flush 後に原子的に置換する。 起動時は generation が active log と一致し、CRC と offset が妥当な snapshot だけを採用し、その後の log tail を replay する。不正 snapshot は捨て、active log の先頭から再生する。 ### 6.3 Compaction rebuild は live Message を temporary log に書き、flush、replace した後に snapshot を作る。DEL と古い UPDATE/PUT payload を物理的に除去する。log と snapshot は別ファイルのため置換間に crash window があるが、generation 不一致時は log 全 replay へ fallback する設計である。 ### 6.4 排他 `--data-dir` は必須である。`store.lock` を non-blocking exclusive lock し、同じ data directory を複数プロセスが同時に開くことを拒否する。 ## 7. JSONL import/export CLI export は先頭に format manifest を出し、live record と任意の DEL を UTF-8 JSONL として出力する。CLI import は format version、全 field、参照整合性を検証し、`overwrite` または `reject` policy で transaction 的に適用する。MCP サーバー起動中の offline import/export は lock により拒否される。 importはJSONLを行単位で読み、JSON stringをUTF-8へ完全decodeしてからfield上限を検証する。 整数は小数・指数表記を許可せず、timestamp/updated_atは0~INT64_MAX、revisionは 1~INT32_MAX、importanceは0~100とする。1行はcontent上限+4096 bytes、100,000 record、 decode後合計4 GiBが上限である。file exportはtemporary fileのflush/close成功後だけ原子的に置換する。 importは通常storeをロードせずlockだけを取得する。第1 passはcompact ID indexで全件と参照を検証し、 第2 passは選択recordをstaging logへ直接書く。stagingのflush成功後だけactive logを原子的に置換し、 失敗時は旧logを維持する。 ## 8. I/O 予算 成功応答前の durability flush を維持し、sys 境界の logical counter を合否判定に使う。 | 操作 | 最大 logical write | 最大 flush | |---|---:|---:| | write | header + serialized Message | 1 | | metadata-only update | header + changed fields | 1 | | content update | header + content + changed fields | 1 | | no-op update | 0 | 0 | | delete | fixed tombstone | 1 | | read/search/context/export/sessions | 0 | 0 | | no-op rebuild | 0 | 0 | | rebuild | live serialized bytes × 2 + bounded headers | log 1 + snapshot 1 | Release build で 20 B~1 MiB payload と 10,000 / 50,000 record corpus を測定し、根拠のない 10% 以上の回帰を許容しない。 ## 9. セキュリティと運用上の境界 - stdio 接続済み host は全 Message の読取り、追加、更新、削除、maintenance が可能である - data at rest は暗号化されず、data directory の OS ACL に依存する - CRC32 は破損検出用であり、悪意ある改変への認証ではない - content や metadata は prompt injection を含み得る。取得内容を命令として信頼するかは host 側の責任である - export は平文バックアップであり、元データと同等に保護する - secure erase は保証しない。削除後も compaction、backup、filesystem 履歴に残り得る ## 10. フィードバックの反映状況 利用者フィードバックの優先項目に対する設計上の対応は次のとおり。 | 要望 | 状況 | 実装 | |---|---|---| | バックアップ・export | 達成 | bounded transactional JSONL import、atomic file export、export view | | 保存後の更新 | 達成 | delta update、identity 維持、revision conflict | | 記憶の種類分け | 達成 | 6 kinds と検索 filter | | 2段階保存 | 部分達成 | summary/source/relation 契約。自動 consolidation は host 責務 | | 検索結果の文脈 | 達成 | score 説明、前後 context、relation traversal | | session 一覧 | 達成 | sessions view、kind 集計、代表 summary | | metadata 活用 | 達成 | tag/tier/kind/importance の更新・filter | | 自動保存判断 | 未実装 | host policy の範囲 | | 利用による強化・減衰 | 未実装 | read は 0 write のため access state を保持しない | ## 11. 実装・検証状況 構造化 metadata、UPDATE、relation index、検索説明、context、sessions、CLI import/export、再起動時の dangling reference 処理まで実装済みである。 release時に継続して実行する回帰項目は次のとおり。 - MCP protocol E2Eと有効snapshot + PUT/DEL tail replay - importの1 MiB escape round-trip、数値境界、streaming上限 - data directory ACLとbackup保護の運用文書 ## 12. 将来対応事項 現行v1の既知の設計上限と、将来版で判断・実装する事項を次に集約する。 - **常駐メモリ:** 10k/50k/100k件とlarge-content corpusについて、起動、rebuild、検索反復後の peak/steady working setを継続計測し、想定最大corpusとmemory budgetを決定する。その結果を基に Message bodyのdisk-backed/lazy load、index圧縮、retentionのいずれかを選択する。 - **crash recovery:** snapshot temporary fileの各書込み段階と、compactionのlog flush/replace、 log/snapshot置換間で強制終了するmatrix testを追加し、旧状態または新状態へ一貫して復旧することを 確認する。exportの遅延flush/close errorも直接注入できるtest seamを追加する。 - **保存時保護:** 組込み暗号化が必要になった場合は、暗号方式の導入前に鍵管理、nonce、format version、既存log/snapshot/backupのmigrationとrecovery手順を設計する。現状はOS ACLと上位暗号化 filesystemを前提とする。 - **記憶lifecycle:** 自動保存判断、自動要約・consolidation、tier移動、access reinforcement、decayは host policyのままである。server側へ移す場合はread系0 write契約、retention、監査可能性を含めて 新しい公開契約として設計する。