madeleine について
madeleine は AI エージェント向けのローカル優先メモリーシステムです。場所、時刻、テキスト、画像、音声などの手がかりから関連する記憶を自動的に呼び起こし、明示的な検索にも対応します。SQLite に保存し、MCP サーバーと Python ライブラリを提供します。
主な機能
- 01複数の感覚的な手がかりで記憶を照合
- 02明示的な検索と手がかりによる想起
- 03HTTP API で手がかりを受信
- 04テレメトリーなしで SQLite にローカル保存
- 05MCP ツールと Python ライブラリを提供
活用シーン
- 01関連する場所や時間に過去の記憶を提示
- 02センサーやメディアの手がかりから想起を起動
- 03各プロンプトで保留中の想起をエージェントに取得させる
MCP 対応
MCP サーバーは remember、recall、sense、pending_recollections など 7 つのツールと、recollections://pending リソースを提供します。標準の stdio で接続でき、streamable HTTP トランスポートにも対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
7掲載時のツール一覧 · 1 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| at | any | いいえ | 発生時刻。ユーザーのローカルオフセット付き ISO 8601 形式で指定します(例:'2026-06-01T21:30:00+02:00')。デフォルト:現在。 |
| lat | any | いいえ | 緯度(度単位、WGS84)。lon が必要です。 |
| lon | any | いいえ | 経度(度単位、WGS84)。lat が必要です。 |
| tags | any | いいえ | 自由形式のラベル(例:['family'])。 |
| content | string | はい | 後で思い出したい形で記録する内容(通常は1~2文)。そのテキストは 'text' チャネルにも埋め込まれます。 |
| geohash | any | いいえ | 場所を geohash で指定します(精度は1~12)。lat/lon より優先されます。 |
| signals | any | いいえ | 追加の生データ。各チャネルにつき最大1つです(各フィールドを参照)。 |
| metadata | any | いいえ | メモリとともに保存する任意の文字列キー/値注釈(埋め込みや照合には使用しません)。例:{"app": "notes"}。 |
| salience | any | いいえ | 重要度。0(些細)から1(人生を変えるほど)までです。デフォルトは0.5です。重要なメモリほど想起されやすくなります。 |
| media_ref | any | いいえ | 関連メディアへの任意のポインター(URI/パス)。開かれることはありません。 |
詳細

madeleine
AI エージェントの不随意記憶。 場所、時間、音、写真、センサーの測定値が、エージェントに尋ねられることなく、関連する記憶を呼び起こします。マドレーヌの味がプルーストの幼少期を思い出させたのと同じ仕組みです。
ローカルファースト(SQLite)· MCP サーバー+Python ライブラリ · テレメトリーなし
エージェントの記憶のほとんどは随意的です。エージェントが検索を決め、クエリを書き、結果を得ます。madeleine はもう1つの経路を加えます。すべての記憶は、エンコード時に存在した感覚的指紋とともに保存されます。どこで、いつ、何を話し、見聞きしたかです。Webhook、スマートフォン、スマートホーム、ウェアラブルから届く手がかりは、常にこれらの指紋と照合されます。十分な数のチャンネルが一致すると、記憶が不随意の想起としてキューに追加され、エージェントは次のプロンプトでそれを受け取ります。これはエージェントに応用した符号化特定性です(概念)。
60秒で始める
# 1. See the whole loop, offline (nothing is downloaded, nothing leaves your machine)
uvx madeleine-mcp demo
デモでは3つの出来事を記憶します。その後、場所と時間帯だけを含む手がかりが届きます。祖母の家から30 m、日曜日の午後です。一致する記憶が自動的に表面化し、MCP ツール pending_recollections を通じて届けられます。同じ手がかりを繰り返しても、再度は発火しません。
[madeleine 0.80 via geo+time] Sunday afternoons in grandmother's kitchen: lime-blossom tea and a madeleine (2019-04-14)
channel similarity geo=0.97, time=1.00; salience x1.16, age decay x0.70
# 2. Give Claude Code the tools
claude mcp add madeleine -- uvx madeleine-mcp serve
- 不随意の想起がすべてのプロンプトに届くようにします。
.claude/settings.jsonに次を追加します。
{"hooks": {"UserPromptSubmit": [{"hooks": [
{"type": "command", "command": "uvx madeleine-mcp hook claude-code", "timeout": 10}
]}]}}
このフックは、クライアントが MCP 通知を無視する場合でも機能します。--sense-prompt などのオプションについては、examples/claude_code を参照してください。このオプションを使うと、入力した内容も手がかりとして扱われます。
その他の MCP クライアント
このサーバーは標準的な stdio MCP サーバー(uvx madeleine-mcp serve)なので、どの MCP クライアントでも7つのツールを利用できます。すべてのプロンプトでの不随意の配信(上記の手順3)は Claude Code 向けに構築されています。他のクライアントでは、サーバーの指示に従って、各ターンの開始時にエージェントが pending_recollections を呼び出すことで想起を受け取ります。
Claude Desktop、Cursor、VS Code、OpenCode、Docker
Claude Desktop(claude_desktop_config.json)と Cursor(~/.cursor/mcp.json):
{"mcpServers": {"madeleine": {"command": "uvx", "args": ["madeleine-mcp", "serve"]}}}
VS Code(.vscode/mcp.json):
{"servers": {"madeleine": {"type": "stdio", "command": "uvx", "args": ["madeleine-mcp", "serve"]}}}
OpenCode(opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {"madeleine": {"type": "local", "command": ["uvx", "madeleine-mcp", "serve"], "enabled": true}}
}
Docker(記憶は madeleine-data ボリュームに保持されます):
docker build -t madeleine-mcp https://github.com/fabianimv/madeleine.git
docker run -i --rm -v madeleine-data:/data madeleine-mcp # stdio MCP server
意味ベースのテキストには
[text]エクストラが必要です。 基本インストールは小さく、オフラインで動作します。エクストラなしの場合、テキストはハッシュ化埋め込み器によって字句的に照合されるため、「car」と「automobile」は無関係な語として扱われます。実際の文埋め込みを使うには(PyTorch がインストールされます):claude mcp add madeleine -- uvx --from 'madeleine-mcp[text]' madeleine-mcp serve画像(
[image]、open_clip)と音声([audio]、LAION CLAP)も同様にオプトインで追加できます。[all]を指定すると、すべてがインストールされます。モデルは初回使用時に必要に応じてダウンロードされ、インポート時にダウンロードされることはありません。
仕組み
flowchart LR
subgraph Sources
HA[Home Assistant] -->|webhook| HTTP
IOS[iOS Shortcuts] -->|webhook| HTTP
AG[Agent] -->|MCP tools| MCP
end
HTTP[HTTP API /cues] --> ENG
MCP[MCP server] --> ENG
subgraph ENG[engine]
direction TB
CH["channels<br/>adapter → embedder → similarity"] --> FU["fusion<br/>base · coverage · salience · decay"]
FU --> RF{"push?<br/>threshold + refractory"}
end
ENG <--> DB[(SQLite + sqlite-vec)]
RF -->|enqueue| Q[(recollection queue)]
Q -->|drain| HOOK[Claude Code hook]
Q -->|drain / notify| MCP
- チャネルは、差し替え可能な感覚です。それぞれに、アダプター(生信号 → 正規化された観測)、埋め込み器(観測 → ベクトル)、類似度関数(→ [0, 1])があります。組み込みのチャネルは、
text、time(時刻、曜日、季節。いずれも周期的)、geo(球面上の距離)、biometric、image、audioです。smellは、将来の電子鼻向けにドキュメント化されたスタブです。 - 想起では、手がかりと記憶が共有するチャネルについてチャネルごとの類似度を組み合わせ、手がかりがどの程度カバーされているかに応じて調整し、顕著な記憶を強調したうえで、経過時間に応じて減衰させます。ただし下限を設けているため、数十年前の記憶にもアクセスできます。計算式は簡潔で説明可能です。各結果には、一致したチャネルが示されます(ADR 0001)。
- 2 つのモード。 プル:エージェントが要求します(
recall)。プッシュ:手がかりが届くと(sense、POST /cues)、誰からも要求されなくても、しきい値を超えた記憶がキューに追加されます。 - 馴化。 発火した記憶は、不応期(デフォルトでは 6 時間)の間は再び発火しません。同じカフェの前を午後ずっと通りかかっても、思い出すのは 1 回だけです。
- コンテキストだけでは発火しません。 「午前 9 時」は午前 9 時に作られたすべての記憶と一致するため、
time(およびbiometric)は一致を強めることはあっても、それだけで発火することはありません。
手がかりの送信
madeleine serve --transport http # REST + MCP (streamable HTTP at /mcp/) on 127.0.0.1:8765
curl -s localhost:8765/cues -H 'content-type: application/json' \
-d '{"lat": 48.30195, "lon": 1.24650, "signals": [{"channel": "text", "value": "smell of lime-blossom tea"}]}'
| ルート | 用途 |
|---|---|
POST /cues | 汎用の手がかり:signals、at、geohash または lat/lon、tags、source |
POST /cues/{generic,home_assistant,ios_shortcuts} | これらのツールから直接送信するペイロード(例) |
POST /memories、POST /recall、GET/PATCH/DELETE /memories/{id} | MCP ツールと同じです |
GET /recollections/pending · POST /recollections/drain | キューにある非自発的な想起を確認/取得します |
すぐに使える連携機能:Home Assistant(帰宅、メディアの再生開始、ウェアラブルセンサー)、iOS Shortcuts(「場所に到着」時の個人用オートメーション)、curl。
MCP のインターフェース:
- ツール:
remember、recall、sense、pending_recollections、get_memory、update_memory、forget。 - リソース:
recollections://pending。何かが表面化すると、resources/updated通知が送信されます。これらの通知は、データベースを共有するプロセス間でも機能します。
プライバシーとセキュリティのデフォルト設定
- ローカル優先。 すべてのデータは 1 つの SQLite ファイル(
~/.madeleine/madeleine.db、所有者のみがアクセス可能な権限)に保存されます。テレメトリーもクラウドもありません。 - 生のメディアは保持されません。 画像と音声のバイト列は埋め込みに変換された後、破棄されます。
store_raw=True(呼び出しごと、またはMADELEINE_STORE_RAW=1)を渡さない限り、保存されるのはベクトルとメタデータのみです。 - デフォルトではローカルファイルにアクセスしません。 クライアントはメディアのバイト列を送信する必要があります。ファイルパスを許可するには、
madeleine serve --allow-file-urisを指定します。 - HTTP は 127.0.0.1 にバインドされます。 ホストと Origin のチェックにより、DNS リバインディングをブロックします。ベアラートークンを必須にするには、
MADELEINE_API_TOKENを設定します。トークンなしで別のインターフェースにバインドする場合は、--insecure-no-authを指定しない限り拒否されます。 forgetはすべての場所から削除します:記憶、ベクトル、生のバイト列、トリガー履歴、キューにある想起を削除し、SQLite のsecure_deleteも有効にします。- 想起はデータであり、指示ではありません。 フックは想起を区切り文字で囲み、データであることを明示します。記憶を書き込める人は、エージェントのコンテキストにテキストを追加できます。そのため、書き込みアクセスは自分だけに限定してください。SECURITY.md を参照してください。
ベンチマーク(およびその限界)
madeleine bench は、3 都市にまたがる 500 件の記憶、既知の正解データを持つ 300 件の手がかり、妨害データ、および難しい負例を使った合成ベンチマークを実行します。両方のテキストバックエンドについて結果を報告します。完全な表、方法論、盲点については docs/benchmarks.md をご覧ください。
madeleine bench # offline hash text backend
madeleine bench --text-backend sentence-transformers # semantic, needs the [text] extra
| hash(オフライン、デフォルト) | semantic([text]、MiniLM) | |
|---|---|---|
| 想起 R@1 / R@10 | 0.69 / 0.81 | 0.74 / 0.82 |
| 無意識に想起が起きた場合の適合率 | 0.69 | 0.70 |
| 記憶の想起を引き起こす正の手がかり | 0.53 | 0.67 |
| 負例での誤発火率 | 0.00 | 0.00 |
手がかりのカテゴリ別(ヒット率=正しい記憶が自発的に浮かび上がる頻度):
| 手がかりのカテゴリ | hash:ヒット率 | semantic:ヒット率 | semantic:適合率 |
|---|---|---|---|
| 場所+時刻 | 0.81 | 0.81 | 0.56 |
| テキストの言い換えのみ | 0.21 | 0.67 | 1.00 |
| テキスト+場所+時刻 | 0.67 | 0.76 | 0.76 |
| 完全に同じ写真/音声 | 1.00 | 1.00 | 1.00 |
| 少し変更した写真/音声 | 0.00 | 0.00 | – |
| 数年前の記憶 | 0.40 | 0.60 | 0.64 |
| 負例(妨害データ、時刻のみ、同じ場所+別の話題) | 発火 0 件 | 発火 0 件 |
記憶が 500 件ある場合の純粋な Python でのレイテンシ:hash バックエンドでは sense が p50 11 ms/p95 23 ms、semantic バックエンドでは p50 32 ms/p95 63 ms(CPU)。
正直な限界
- 無意識の想起は保守的になるよう調整されています。負の手がかりは一度も発火しませんでしたが、正の手がかりの 3 分の 1(semantic)から半分(hash)は、依然として記憶を呼び起こしません。
- 両方のテキストバックエンドは、ベンチマーク生成器(シード 1)に合わせてキャリブレーションされています(結果はシード 0 によるもので、シード 2 と 3 でも一致しています)。キャリブレーションを行わない場合、hash バックエンドは言い換えを過小評価し、MiniLM は無関係な文を過大評価しました。データは合成英語テキストのため、実環境での数値は異なります。
- 画像と音声には hash エンベッダーを使うこのベンチマークでは、変更したメディアは一度も一致しません。これには CLIP と CLAP の追加機能が必要ですが、その類似度の再スケーリングは合成入力でしかキャリブレーションされていません。
- 場所+時刻の手がかりは飽和します(手がかりごとに 3 件が発火)。そのうち厳密な正解データの「同じ場所、同じ時刻 ±1 時間」に該当するのは 56 % のみです。
- 統合には学習された方式ではなく、手作業で設計した数式を使っています。複数ユーザー認証も UI もありません。嗅覚チャネルはスタブです。
- 時刻は各タイムスタンプ固有の UTC オフセットを使います。ローカルのオフセット(
+02:00)を送信してください。そうしないと、「夕方」は UTC の夕方を意味します。
設定
| 環境変数 | デフォルト | 意味 |
|---|---|---|
MADELEINE_DB | ~/.madeleine/madeleine.db | SQLite のパス(:memory: も使用可能) |
MADELEINE_TEXT_BACKEND | auto | auto(インストール済みなら sentence-transformers)、sentence-transformers、hash |
MADELEINE_CHANNELS | すべての組み込みチャネル | 有効にするチャネルをカンマ区切りで指定 |
MADELEINE_STORE_RAW | オフ | メディアの生バイト列を永続化 |
MADELEINE_ALLOW_LOCAL_FILES | オフ | メディアシグナルでローカルファイルを参照可能にする |
MADELEINE_API_TOKEN | 未設定 | HTTP API(およびフックの --url モード)用の Bearer トークン |
MADELEINE_ALLOWED_HOSTS | ループバック | HTTP サーバーが許可する追加の Host/Origin 名 |
CLI:madeleine serve | remember | sense | recall | pending | show | edit | forget | demo | bench | hook claude-code
(madeleine --help)。
Python ライブラリとして
from madeleine.config import load_config
from madeleine.core.serde import context_from_fields
from madeleine.engine import create_engine
engine = create_engine(load_config(db_path="memories.db", text_backend="hash"))
now = engine.now()
engine.remember("Ana proposed at the Eiffel Tower",
context=context_from_fields(now=now, lat=48.8584, lon=2.2945, salience=0.9))
cue = engine.build_cue(context=context_from_fields(now=now, lat=48.8585, lon=2.2946))
for rec in engine.sense(cue): # involuntary: fires on place (+ time) alone
print(rec.to_prompt_line())
独自の sense を作成するには、Adapter、Embedder、および類似度関数を使用してください(docs/channels.md)。ImageBind はライセンスが CC-BY-NC であるため、意図的に依存関係から除外していますが、Embedder として自分で組み込むことはできます。
開発
CONTRIBUTING.md をご覧ください。最初に uv sync を一度実行し、以降はコミットの前に毎回、uv run pytest、uv run ruff check src tests、uv run mypy を実行してください。アーキテクチャについては ARCHITECTURE.md、設計上の決定については docs/adr をご覧ください。
ライセンス
Apache-2.0。LICENSE をご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。