FerryCat について
FerryCatは、別々のデスクトップIDEホストで動くAIエージェント向けのローカルなタスク引き継ぎ・レビュー用バスです。MCPサーバーとSQLite WALを使い、契約で検証したタスクを渡し、ファイル指紋で古いレビューコンテキストを検出します。
主な機能
- 01ホスト間のタスク引き継ぎ
- 02契約に基づく出力検証
- 03SHA-256によるファイル整合性確認
- 04トランザクション管理されたSQLiteの状態
- 05確認と検証のためのCLI
活用シーン
- 01IDEエージェント間でコードレビューを依頼する
- 02レビュー結果の提出前にファイル変更を確認する
- 03ワーカーエージェントの構造化結果を検証する
- 04ローカルの引き継ぎ契約を確認・検証する
MCP 対応
FerryCatはローカルMCPサーバーとして動作し、タスク契約の配布、取得、検証、完了、確認のツールを提供します。複数のMCPホストが同じローカルSQLite WALデータベースとワークスペースファイルを共有します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
8掲載時のツール一覧 · 2 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| title | string | はい | 依頼の目的を要約する簡潔な契約タイトル(1~120文字)。 |
| pointers | array | はい | 改ざん検出のため、完全なファイル SHA-256 とスナップショット境界を使ってハッシュ化する、1~50個の対象ファイルポインターの配列。 |
| task_type | enum | はい | 契約タスクの種類。段階別のデフォルト実行 TTL:code_review/architecture_audit は1800s、implementation/test_generation は300s。code_review | architecture_audit | implementation | test_generation |
| exec_ttl_sec | integer | いいえ | CLAIMED 後の実行 TTL(秒)(デフォルト:レビュー/監査は1800s、実装/テストは300s)。Worker はこの期間内に完了、延長、解放、または失敗の処理を行う必要があります。 |
| target_agent | string | はい | この契約を取得して実行する対象 Worker Agent の識別子(例:"workbuddy"、"antigravity")。 |
| queue_ttl_sec | integer | いいえ | 状態が SUBMITTED の間のキュー有効期限 TTL(秒)(デフォルト:1800s / 30m)。期限前に取得されない場合、TIMED_OUT に遷移します。 |
| workspace_root | string | はい | 両ホストからアクセスできる共有ローカルワークスペースディレクトリの正規絶対パス(例:"F:/git/FerryCat")。パス逸脱と機密ファイルはブロックされます。 |
| context_summary | string | はい | Worker Agent 向けの詳細なタスク指示、監査の重点領域、アーキテクチャ上の制約、背景情報(1~20000文字)。 |
| contract_schema | object | いいえ | structured_output の検証に使用する任意の Draft-07 JSON Schema。上限は1MB、最大深度は32です(FC-302)。 |
| requester_agent | string | いいえ | 依頼元 Agent の識別子。デフォルトは AGENT_NAME 環境変数です(例:"antigravity"、"workbuddy")。 |
詳細
FerryCat:契約駆動型クロスホスト AI エージェント引き継ぎバス
英語 • 中文
FerryCat(
ferrycat)は、Model Context Protocol(MCP)と Node.js 組み込みのnode:sqlite(WAL モード)を基盤とする、軽量かつ決定論的なクロスホスト AI エージェントの引き継ぎ・コードレビュー用バスです。
Google Antigravity、WorkBuddy、Claude Code、Cursor など、分離されたデスクトップ IDE エージェントホストを、コンテキストのずれや古いファイルに対する盲目的なレビューを招くことなく、別々の OS プロセス間で安全に橋渡しできるように設計されています。
📖 詳しく読む:FerryCat の開発を始めた理由:2 つの AI コーディングホストが同じデスクトップで稼働するとき
主な課題とエンジニアリングによる解決策
公式の MCP Tasks 仕様(2025-11 / 2026-07)は、単一の Client ↔ Server 接続内での長時間実行オペレーションには対応していますが、開発者のワークステーションにおけるホスト間の連携は解決していません。
stdioプロセスの分離:デスクトップ IDE は、メモリー空間が分離され、それぞれ異なる Node.js ランタイムで動作するローカル MCP サーバーを、独立した子プロセスとして起動します。- 古いコードに対する気付かれない盲目的なレビュー(
Stale Context):タスクをホスト A からホスト B に引き継ぐ際、IDE の未フラッシュのバッファー、ブランチの切り替え、レビュー中の編集などにより、引き継ぎ先のエージェントが古いコードを監査し、もっともらしくても無効な結論を出すことがあります。 - コンテキストウィンドウの肥大化:チャットウィンドウ間で何百行ものソースコードを貼り付けると、両側でトークン消費が重複します。
- 構造化されていない引き継ぎ結果:自由形式の文章による応答では、決定論的なスキーマを強制できません。そのため、後続処理での利用が不安定になり、無限の再試行ループに陥りやすくなります。
FerryCat は、人がスケジュールを管理する契約駆動型の SQLite WAL バスによって、これらの障害要因を解消します。
[Developer] [Host A: Antigravity] [~/.ferrycat/mesh.db] [Host B: WorkBuddy]
| | | |
|-- 1. "Dispatch review" --->| | |
| |-- dispatch_contract() -------->| Write status = SUBMITTED |
| | (Full SHA-256 + Line Bounds) | Store size / sha256 snapshot |
| | | |
|-- 2. Switch IDE: "Poll" ---|--------------------------------|------------------------------>|
| | |<-- poll_next_task() ----------|
| | | (Atomic claim changes===1 |
| | | + Verify disk SHA-256) |
| | | |-- Read local files
| | |<-- fulfill_contract() --------|-- Re-verify SHA-256
| | | (Validate Ajv JSON Schema | & submit JSON
| | | -> status = COMPLETED) |
| | | |
|-- 3. Switch IDE: "Inspect" | | |
| |-- inspect_mesh_state() ------->| Read-only query of COMPLETED |
|<-- Present structured res -| | |
アーキテクチャの主要な柱
1. 決定論的な7状態マシン
すべての状態遷移は、楽観的同時実行制御(changes === 1)を伴う明示的な SQL トランザクションにバインドされ、幽霊状態や宙に浮いた状態を排除します。
dispatch_contract()
│
▼
┌───────────┐
│ SUBMITTED │ (Queue TTL: default 1800s)
└─────┬─────┘
│
poll_next_task()
┌────────────────┼────────────────┐
│ (Queue TTL) │ (Hash Match) │ (Missing / Size Diff / SHA-256 Mismatch)
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────────┐
│ TIMED_OUT │ │ CLAIMED │ │ POINTER_STALE │ (Terminal: Rejects blind review)
└───────────┘ └─────┬─────┘ └───────────────┘
▲ │ (Exec TTL: default 300s)
│ fulfill_contract()
│ ┌────────────────┼────────────────┬────────────────┐
└──┤ (Exec TTL) │ (Schema Valid) │ (Retries > 2) │ (Mid-Review File Edit)
│ ▼ ▼ ▼
│ ┌───────────┐ ┌───────────────────┐ ┌───────────────┐
└──────────│ COMPLETED │ │ VALIDATION_FAILED │ │ POINTER_STALE │
└───────────┘ └───────────────────┘ └───────────────┘
CLAIMED 状態のコントラクトに対するホルダー側のライフサイクル制御(すべて agent_id === target_agent が必要です):
| 呼び出し | 遷移 | ガード条件 |
|---|---|---|
release_contract | CLAIMED → SUBMITTED(キューの末尾、新しいキュー期間) | extend_count をリセットします(更新回数の上限はホルダーごとです)が、retry_count は保持します。スキーマ検証失敗時のサーキットブレーカーはコントラクト単位の割り当てなので、解放してリトライ回数の上限を回避することはできません。絶対有効期限を過ぎると拒否されます。コントラクトごとに最大3回まで解放できます。 |
extend_ttl | CLAIMED → CLAIMED(claimed_at = now) | 有効期間内に呼び出す必要があります。ホルダーごとに最大5回まで更新でき、now ≥ created_at + 4 × queue_ttl_sec になると拒否されます。 |
fail_contract | CLAIMED → FAILED(終端状態) | reason が必要で、WORKER_FAILED: <reason> として保存されます。有効期間が終了した後に報告が届いた場合は、理由を付けて TIMED_OUT になります。 |
2. ファイル全体の SHA-256 フィンガープリント、事前検証と TOCTOU ソフト失敗のバッファリング(ADR-0004)
- ディスパッチ時のスナップショット:
dispatch_contractはディスク上の対象ファイルを読み取り、バイト数のsize、ファイル全体のsha256(64桁の16進数)、first_line、last_lineを記録します。ファイルが過去3秒以内に変更されていた場合、未保存の IDE バッファが存在する可能性を依頼者に知らせるwarningが出力されます。 - クレーム時の検証:
poll_next_taskは存在確認 -> バイト数 -> ファイル全体の SHA-256の順に検証します(何も変更しない IDE の保存を許容するため、mtime_msのみを理由に拒否することはありません)。不一致の場合は、IDE による一時的な書き込みを除外するため150ms待機して一度再試行し、その後コントラクトをPOINTER_STALEとしてマークします。 - 事前検証(
verify_contract):ワーカーやスクリプトが送信前にポインターの健全性(valid: true、または変更されたファイルの一覧を伴うvalid: false)を監査できる、厳密な読み取り専用チェックです。 - TOCTOU ソフト失敗のバッファリング:
fulfill_contractはディスク上のポインターのフィンガープリントをチェックします。変更されたポインターが検出された場合:- 1回目のストライクでは
RETRY_NEEDEDを返し、コントラクトをCLAIMEDのまま維持して実行期間を更新し、復旧手順(git stash/git checkout -- <file>)とともに変更されたファイルを一覧表示します。 - 2回目のストライクでは終端状態の
POINTER_STALEに遷移し、送信されたレビューのペイロード全体をsalvaged_result_jsonに保存するため、レビュー作業が失われることはありません。
- 1回目のストライクでは
- TOCTOU 競合の縮小:ディスク上のバイト列を読み取ってからデータベースの行をコミットするまでに発生するマイクロ秒単位の競合は、ファイルベースのシステムでは排除できません。しかし、FerryCat の二重検証(
poll時とfulfill時)により、TOCTOU の時間枠を数分間の無検証レビューから、ミリ秒未満のアトミックな SQL 遷移境界まで大幅に縮小します。
3. 上限付きスキーマ検証(RETRY_NEEDED $\le 2$)
- 出力はキャッシュされた Ajv バリデーターを使用してコントラクトの JSON Schema に照らして検証され、エラーは簡潔な1行のパスにまとめられます(例:
["/passed: must be boolean"])。 - 検証に失敗しても、最大2回まではコントラクトを
CLAIMEDのまま維持し、すぐに自己修正できるようRETRY_NEEDEDを返します(拒否のたびに実行期間も更新されます)。3回目の失敗では、コントラクトは終端状態のVALIDATION_FAILEDに遷移します。
4. 2段階 TTL と読み取り後書き込み方式のスイープ
queue_ttl_sec(SUBMITTEDの場合はデフォルトで1800秒)とexec_ttl_sec(claimed_atから計測)を分離し、キュー期間の終盤でクレームされたタスクが実行中に早期タイムアウトするのを防ぎます。exec_ttl_secのデフォルトはtask_typeに応じて段階化されています。code_review/architecture_auditは1800秒(深い推論や人間が介在する処理)、implementation/test_generationは300秒です。exec_ttl_secが明示的に指定された場合は、常にその値が優先されます。poll_next_taskは期限切れの行に対してUPDATEを試みる前に、ロックフリーのSELECT COUNT(*)プローブを実行します。inspect_mesh_stateは厳密な読み取り専用です。
5. 多層防御によるパスセキュリティ
dispatchとworkerの両方の検証パスで、workspace_root内にパスが収まるよう強制し、機密ファイルのパターン(.env*、*.pem、*.key、id_rsa*、*credentials*、*secret*、.npmrc、.git/config)をブロックします。- パス解決:
workspace_rootには絶対パスを指定することを強く推奨します。相対パスが指定された場合は、path.resolveを使用してprocess.cwd()を基準に決定的に解決されます。
6. 脅威モデルとセキュリティ上の前提(ローカルワークステーション IPC)
- 信頼環境の前提:FerryCat は、同じ OS ユーザーアカウントで動作する分離された IDE ホストをつなぐ、信頼されたローカルワークステーションバスとして意図的に設計されています。呼び出し元とワーカーは、ローカルファイルシステム(
workspace_root)と SQLite データベース(~/.ferrycat/mesh.db)を共有します。 - 防御範囲:パスの包含チェック(
assertSafePointerPath)と機密ファイルパターンのフィルターにより、引き継ぎ時の意図しないワークスペース外へのアクセス、シンボリックリンクのたどり、認証情報や秘密情報を含むファイルの偶発的な漏えいを防ぎます。 - 対象範囲外(非目標):FerryCat は、悪意のあるローカルプロセスや
AGENT_NAMEを偽装する敵対的なエージェントに対する、敵対的なサンドボックス化、マルチテナント分離、ネットワーク認可を提供しません。
適用範囲の境界(FerryCat を使用すべきでない場合)
- 分離されたファイルシステム:FerryCat はファイル参照によってコンテキストを引き渡すため、両方のホストが同じローカル
workspace_rootにアクセスできる必要があります。 - 単純な単一ターンのクエリ:ホスト間の引き継ぎごとに、人間が明示的にウィンドウを3回切り替える必要があります(約15~25秒のオーバーヘッド)。
- 無人のバックグラウンドパイプライン:デスクトップ IDE ホストはリクエスト/レスポンスモデルに従うため、アイドル状態の MCP サーバーから非同期に起動することはできません。無人のマルチステップパイプラインには、PatchCat のようなスタンドアロンの DAG ワークフローエンジンを使用してください。
クイックスタート
1. 推奨:ゼロインストールでの MCP マウント(npx を使用)
ローカルへのクローンや手動コンパイルは不要です。npx -y ferrycat を使用して、IDE の MCP 設定に直接マウントします。
Antigravity の設定
%USERPROFILE%\.gemini\antigravity\mcp_config.json(macOS/Linux では ~/.gemini/antigravity/mcp_config.json)を編集します。
{
"mcpServers": {
"ferrycat": {
"command": "npx",
"args": ["-y", "ferrycat"],
"env": {
"AGENT_NAME": "antigravity"
}
}
}
}
WorkBuddy / Claude Code / Cursor / Codex の設定
対象ホストの MCP 設定で、対応する AGENT_NAME を設定します。
{
"mcpServers": {
"ferrycat": {
"command": "npx",
"args": ["-y", "ferrycat"],
"env": {
"AGENT_NAME": "workbuddy"
}
}
}
}
2. グローバルインストールとソースからのビルド
- グローバル CLI インストール:
次に、MCP 設定でnpm install -g ferrycat"command": "ferrycat"を設定するだけです。 - ローカルソースからのビルド(コントリビューター向け):
ローカルパスを使用してマウントします。git clone https://github.com/GuoBug/FerryCat.git cd FerryCat npm install npm run build npm test"command": "node"、"args": ["--experimental-sqlite", "/path/to/FerryCat/dist/index.js"]。
CLI をすぐに使える環境(ferrycat-cli)
IDE 内で動作する MCP サーバーとして機能するだけでなく、FerryCat は本格的な CLI ユーティリティ(ferrycat-cli または npx ferrycat-cli)も提供します。同じ ~/.ferrycat/mesh.db SQLite WAL データベースと Zod 検証コントラクトを共有するこの CLI を使うと、開発者はターミナルを離れることなく、メッシュの状態を調べ、ワーキングツリーの安全性を検証し、自動化された CI/Git スクリプトと連携できます。
1. ターミナルでの視覚的な確認(ASCII ステータステーブル)
ホスト間のすべての引き継ぎとエラー理由を、ASCII テーブル形式で確認します。
# View all contracts in an ASCII table
npx ferrycat-cli inspect
# Filter by target agent (e.g., only tasks for antigravity)
npx ferrycat-cli inspect --target antigravity
2. 事前検証(変更前の監査)
レビュー作業をコミットする前に、ディスク上のポインターファイルの整合性をコントラクトのベースライン SHA-256 と照合して監査し(ADR-0004)、誤検出による受け渡しを排除します。
npx ferrycat-cli verify <CONTRACT_ID>
3. ローカル CI とヘッドレスワーカーの実行
キューをポーリングしてタスクを取得し、失敗時に自動でクローズしながら、ローカルのレビュー/テストスクリプトを実行します。
# Safely run a script upon task arrival (no shell quotation hazards)
npx ferrycat-cli worker --agent codex --mode=exec --exec-file ./scripts/review.sh
公開されている MCP ツール
| ツール名 | 役割 | トランザクションの動作 |
|---|---|---|
dispatch_contract | リクエスター | パスのブラックリストを適用 $\to$ ファイル全体の SHA-256 と行の範囲を計算 $\to$ SUBMITTED を挿入します。 |
poll_next_task | ワーカー | 期限切れの TTL を走査(読み取り後に書き込み) $\to$ changes === 1 で確保(CLAIMED) $\to$ ディスク上の SHA-256 を検証(または POINTER_STALE に設定)します。 |
fulfill_contract | ワーカー | SHA-256 を再検証(TOCTOU ガード) $\to$ Ajv JSON Schema を検証(RETRY_NEEDED による再試行は最大 2 回、3 回目は VALIDATION_FAILED に設定) $\to$ COMPLETED に設定します。 |
release_contract | ワーカー(保持者) | CLAIMED のコントラクトをキューの末尾に SUBMITTED として戻します。retry_count は保持されます(コントラクト単位のサーキットブレーカー)。extend_count はリセットされます。リリースは最大 3 回で、絶対有効期限を過ぎると拒否されます。 |
extend_ttl | ワーカー(保持者) | ハートビート:実行ウィンドウを再開(claimed_at = now)します。更新は最大 5 回で、合計有効期間には上限があります。 |
fail_contract | ワーカー(保持者) | 必須の reason を指定して、CLAIMED のコントラクトを終端状態の FAILED に設定します。 |
verify_contract | ワーカー/任意(読み取り専用) | 事前チェック:コントラクトの状態を変更せずに、ディスク上のポインターファイルをベースラインの SHA-256 と照合して検証します(ADR-0004)。 |
inspect_mesh_state | 任意(読み取り専用) | コントラクトの状態、出力、および動的な is_logically_expired フラグを純粋に読み取り専用で照会します。 |
💡 アーキテクチャ決定記録とエンジニアリング検証:
- ADR-0001:クロスホスト SQLite WAL バスと人手によるスケジュール設定のポーリングモデル(60 秒のブロッキング待機や単一接続の MCP Tasks ではなく、
node:sqliteWAL とpoll_next_taskを採用する理由)- ADR-0002:ファイル全体の SHA-256 フィンガープリント、TOCTOU ガード、クロスモデル監査(コンテキストの陳腐化を防ぐ仕組みと、実環境でのクロスホスト検証記録)
- ADR-0003:GUI サンドボックスと CLI プロセスのハイブリッドレイヤリングアーキテクチャ、および起動境界(デスクトップの HITL 承認と社内 CLI のデュアルチャネル自律性)
- ADR-0004:レビューと変更の分離(SRM)、TOCTOU のソフトフェイルバッファリング、イミュータブルなベースラインプロトコル(同時編集や善意のレビュアーによる編集でレビューが中断されるのを防ぐ方法)
- FerryCat の要件バックログとロードマップ
著者について
Guo Qiang(GuoBug)、プラットフォームエンジニアリングとグロースを専門とするプロダクトエンジニアです。現在は AI ワークフローのオーケストレーション、DAG 状態機械、決定論的システムアーキテクチャに注力しています。
オープンソースとホームページ:https://github.com/GuoBug · https://guobug.github.io
ワークフローエンジンのアーキテクチャ、トポロジカルスケジューリング、開発者体験に関するお問い合わせや議論を歓迎します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。