MCP サーバ
zanei mcp が公開する read-only な MCP(Model Context Protocol)サーバ — ツール・スキーマ・エラー・登録方法。
zanei mcp は記録された行動履歴を MCP クライアントへ公開します。対象は、ターミナル型 agent(Claude Code・Codex・opencode・Hermes Agent)と、CLI を実行できない chat クライアント(Claude Desktop)です。
ChatGPT は対象外です。ChatGPT のコネクタは remote HTTPS の MCP サーバしか受け付けませんが、zanei mcp は自らネットワーク接続を開かないローカルの stdio プロセスです。公開 URL へブリッジすればストアをネットワーク上に置くことになるため、OpenAI 系 agent には Codex を使ってください。agent が読み取った結果をどう扱うかは別の話です — セキュリティ境界を参照してください。
| サーバ名 | zanei |
| サーババージョン | initialize 結果の serverInfo.version は Zanei の build に使われた package version。zanei --version が示す version 番号と同じ |
| 起動コマンド | zanei mcp |
| トランスポート | stdio のみ(stdin/stdout 上の JSON-RPC 2.0)。ネットワークは一切使わない |
| capability | tools のみ。resources / prompts は未提供(将来拡張参照) |
サーバはローカルストアへの read-only ビューです。記録デーモンとは独立プロセスで動き、記録の開始・停止も、capture-time フィルタを含む設定の変更もできません。query_events の app / bundle_id は保存済みデータへの query-time の絞り込みであり、プライバシー境界ではありません。
時間表現・イベント型・イベントエンベロープの共通規約は、CLI リファレンスとイベントリファレンスに一致します。
ツール
3 つのツールはすべて読み取り専用・副作用なしです。
get_timeline
指定範囲の LLM-ready タイムラインを返します。zanei timeline と等価。agent が最もよく呼ぶツールです。
入力
| パラメータ | 型 | 既定値 | 説明 |
|---|---|---|---|
since |
string | "1h" |
遡り開始。相対(15m・2h・1d)または RFC3339 |
until |
string | now |
終了 |
format |
"markdown" または "structured" |
"markdown" |
出力の形 |
token_budget |
integer | 4000 |
概算トークン上限(下限 34)。超過分は粒度を粗くして収める |
granularity |
"coarse" または "fine" |
"coarse" |
セッション単位か操作単位か |
出力(format: "markdown")。以下は省略した例で、token estimate は生成された完全な content によって変わります。
{
"range": { "since": "2026-08-16T08:00:00.000Z", "until": "2026-08-16T09:00:00.000Z" },
"format": "markdown",
"content": "# Zanei timeline\n\nRange: 2026-08-16T08:00:00.000Z — 2026-08-16T09:00:00.000Z\nEstimated tokens: 3810\nTruncated: no\n\n## 2026-08-16T08:12:00.000Z — 2026-08-16T08:31:00.000Z · Safari\n\nTitle: PR #42 のレビュー\n- Browsed 3 pages on github.com\n- Edited text in \"PR #42 のレビュー\"\n...",
"token_estimate": 3810,
"truncated": false
}
format: "structured" の場合、結果は CLI リファレンスの timeline --format json と同一の sessions[] 構造です。result は skipped_unknown_types を含み、各 session は 0 を含めて常に content_snapshots を持ちます。event_ids は最大 100 件で、event_ids_truncated は常に出力されます。token budget をなお満たせない場合は session を削除する前に全 ID が省略されます。Markdown は snapshot 件数が 0 でない session だけ、activity の後に Content snapshots: N を追加します。snapshot 本文は inline しません。
query_events
条件に合う生イベントを返します。zanei query と等価。粒度の細かい検証や、特定アプリ・型の抽出に使います。
入力
| パラメータ | 型 | 既定値 | 説明 |
|---|---|---|---|
since |
string | "15m" |
遡り開始 |
until |
string | now |
終了 |
types |
string[] | [] |
イベント型。browser.* 等のワイルドカード可。空配列は通常 activity を返すが content.* は除外。content.snapshot または content.* を明示して取得 |
app |
string | — | アプリ名で絞り込み |
bundle_id |
string | — | バンドル ID で絞り込み |
limit |
integer | 200 |
最大件数。有効範囲は 1〜1000 |
出力
{
"range": { "since": "2026-08-16T08:45:00Z", "until": "2026-08-16T09:00:00Z" },
"count": 42,
"truncated": false,
"skipped_unknown_types": 0,
"events": [
{
"v": 1, "id": "evt_01J...", "ts": "2026-08-16T08:46:12.120Z", "mono_ns": 128374651234,
"source": "macos.applescript", "type": "browser.navigate",
"app": { "name": "Google Chrome", "bundle_id": "com.google.Chrome", "pid": 501 },
"window": { "title": "PR #42", "id": 42 },
"element": null,
"data": { "url": "https://github.com/...", "tab_title": "PR #42", "mode": "normal", "transition": "navigate" },
"truncated": false,
"redaction": { "applied": false, "rules": [] }
}
]
}
limit を超えた場合は truncated: true。skipped_unknown_types は、この binary が type を認識できず skip した store row の件数です。イベント内容は捕捉時点でプライバシー処理(secure field 除外・redaction)済みのものが格納されており、MCP 層で除外済みの情報が復元されることはありません。
Content snapshot は 1 件 32 KiB までで、他人が書いた message や document を含み得ます。明示的な type、狭い since / until、小さい limit でだけ取得してください。ユーザーの明示要求なしに本文を現在の task 外へ送ってはいけません。
get_status
agent 向けの軽量チェック:記録は動いているか。zanei status のサブセットです。
入力:なし({})
出力
{
"running": true,
"paused": false,
"last_event_ts": "2026-08-16T08:59:58Z",
"events_dropped": 2,
"degraded": {},
"collector_failures": { "eventtap": 1 },
"retention_hours": 48,
"oldest_event_ts": "2026-08-14T09:00:00Z",
"capture": { "sources": ["app", "window", "ui", "input", "browser"], "text_content": false, "content_snapshot": false },
"permissions_ok": true
}
| フィールド | 意味 |
|---|---|
events_dropped |
本来記録対象だったが、backpressure・queue full・切断などの配送障害で実際に失われたイベントの累計。app または window に帰属できず記録対象外となる入力と、crash / SIGKILL で失われた未 flush データは含まない |
degraded |
component ごとの現在の collector / runtime 劣化状態。責任を持つ site の回復時に削除される。AX reason は現在の failure を安定した phase / kind で分類し、取得できる場合は native operation と数値 code、未解消の PID / operation site が複数ならその件数を報告する。成功時に削除するのは対応する site だけ |
collector_failures |
collector ごとの累積処理失敗回数。非ゼロであることだけでは現在劣化中を意味しない |
capture.content_snapshot |
前面ウィンドウの content snapshot が有効か。snapshot が存在するのは true のときだけ。scope 詳細は CLI の zanei filter show で確認 |
permissions_ok |
heartbeat が新鮮な間は実行中 recorder 自身の権限判定。recorder 不在時はローカル probe の結果 |
running: false を見た agent は、推測で答えるのではなく「PC 操作履歴は現在記録されていない」とユーザーに伝えられます。
エラー
| 状況 | 挙動 |
|---|---|
| ストア未初期化 / 記録未実施 | get_status が running: false を返す(エラーにしない)。get_timeline / query_events は空結果 |
| 権限不足による空 | 空結果。get_status の permissions_ok: false で判別可能 |
| 暗号化されたストアの鍵を取得できない(鍵がない・一致しない・ログインキーチェーンがロック中・アクセス拒否) | 3 ツールとも JSON-RPC -32603(Internal error)と store is locked: ... のメッセージ。「記録なし」としては報告しない。ストアファイル自体がない場合は引き続き 1 行目の挙動 |
不正な時間・範囲・イベント型pattern、1〜1000の範囲外の limit、34未満の token_budget など、ツール引数が不正 |
JSON-RPC -32602(Invalid params) |
| 設定・store・権限確認・timeline構築・serializeなどの内部処理に失敗 | JSON-RPC -32603(Internal error) |
MCP サーバは記録の開始も権限付与も行いません。CLI で zanei start → 権限付与 → zanei stop && zanei start → zanei doctor の順に設定します。
登録方法
zanei setup --agent <name> が以下をすべて自動化します。クライアント別の手順は agent セットアップを参照してください。stdio サーバ共通の JSON の形は次のとおりです。
{
"mcpServers": {
"zanei": {
"command": "zanei",
"args": ["mcp"]
}
}
}
将来拡張
現在は未提供です。いずれも同じ read-only ストアビューの上に増設され、記録デーモンへの書き込み権限は将来も追加されません。
- resources — 直近タイムラインや現在の設定を read-only リソースとして公開(resources を好むクライアント向け)。
- prompts — 「作業を再開する」定型プロンプトのサーバ提供。
- notifications — 新規セッション検出時の push(需要が出れば)。
セキュリティ境界
- サーバ自体は外部送信を行いません(stdio のみ)。
- ツール結果を受け取った agent がそれを LLM プロバイダへ送るのは agent 側の責務です。PC 操作履歴の機微性を踏まえ、同梱の skill ファイルは送信前に対象範囲を絞るよう agent に指示しています。
- ストア内容は捕捉時点でプライバシー処理済みです。入力内容と content snapshot は別々の opt-in で、どちらも既定 off です。