本稿は、AIエージェント時代の「最強のロックファイル」再考 の続編にあたります。前作で提唱した設計思想をさらに進化させた実務者向けの解決策を詳述します。
TL;DR
- プロセスの多重起動を根絶: 同一プロジェクト配下で複数のインスタンスが同時起動することを物理的に防止し、推論の矛盾(ハルシネーション)の原因となる環境の不一致を排除する
- セッショントークン認証 (HMAC): 親プロセスから継承したトークンによる HMAC-SHA256 署名を導入。同一UID内であっても、正当な承認を持たない第三者プロセスによる制御権の奪取を厳格に封じ込め
- 決定論的ハンドシェイク (SAVED ➔ ACK): 通信切断(EOF)の曖昧さを排除。「状態保存の完了」を新インスタンスが ACK で認可してから既存プロセスが終了する、二段階の合意形成フローを確立
- 進捗ハートビートと動的ウォッチドッグ: 保存処理中も継続的に進捗を送信し、ハングアップと長時間処理を正確に識別。新インスタンスが不必要に SIGKILL を送信するリスクを回避
-
運用モード制御:
OBSERVE/WARN/AUTOによる、環境に応じた段階的な導入を可能に
対象読者: 本稿は、MCP サーバーを自作している開発者、AI エージェントの安定運用に悩むエンジニア、そして「プロセスの唯一性」を OS レベルで保証したい設計者に向けた内容です。
一言でいうと
Highlander Protocolとは:
「プロセスを排除するのではなく、安全に状態を継承させながら、必ず1つに収束させる仕組み」
導入:なぜ今、プロセスの「唯一性」が問われているのか?
AIエージェントの普及に伴い、MCP(Model Context Protocol)サーバーは推論と物理世界(OS)を繋ぐ不可欠なインターフェースとなりました。しかし、その急速な普及の裏で、エンジニアを悩ませる深刻な問題が浮上しています。それが 「プロセスの多重起動」 です。
VS Code、Cursor、Claude Desktop といったモダンなエージェント・クライアントを併用したり、IDE を再起動したりすると、知らぬ間に背後で複数の MCP サーバーが同一プロジェクトに対して立ち上がってしまうことがあります。
その結果何が起きるか?
「以前の操作で作成したはずのファイルが見つからない」「意図しないタイミングでコードが書き換えられている」といった、物理環境と推論の不一致(不整合)が発生します。これはLLMにとって致命的な「ノイズ」となり、ハルシネーションの連鎖を引き起こす直接的な原因となります。
環境の唯一性を保つことは、もはや単なる「作法の問題」ではなく、AIエージェントの知能を正常に機能させるための、物理的な「防衛線」なのです。
本稿では、以下のステップでシングルトン設計の正解を解き明かします:
- なぜロックファイル方式が本質的に破綻するのか
- Highlander Protocol がどのように唯一性を保証するのか
- 実務でどう導入し、どう運用すべきか
“Highlander Protocol” の由来:排除から継承へ
本プロトコルの名称は、映画『ハイランダー』に登場する有名な台詞 “There can be only one(生き残れるのは一人だけ)” に由来します。
従来の排他制御(ロックファイル方式等)は、既存のプロセスを「拒絶」するか、力ずくで「排除」することに主眼が置かれていました。しかし、Highlander Protocol はその思想を一歩進め、**「継承(Succession)」**へと昇華させました。
古いインスタンスが保持していた「状態」を安全に保存させ、新しいインスタンスがその役割を確実に引き継ぐ。この「スムーズな政権交代」によってのみ、システムの唯一性は無停止で守られます。
ライフサイクル全体像:起動から継承までのロードマップ
Highlander Protocol がどのようにして「唯一の勝者」を決定し、状態を継承していくのか。その全体像を以下の図に示します。
第1章:ロックファイルはもう限界だ —— 一般的な実装の落とし穴
MCPサーバーに限らず、特定のプロジェクトに対してインスタンスのシングルトン性を保証する際、.lock ファイル等の有無をフラグとするファイルベースの排他制御は最も一般的なアプローチです。
しかし、この方式は以下の 3 つの脆い前提の上に成り立っています。
- ファイルによる一意性: ファイルがあれば既存プロセスが動いていると見なす
- 正常な終了処理: プロセスは必ず自らロックを消して死ぬはずだ
- ファイルシステムの整合性: ファイルの有無は嘘をつかない
実運用において、これらの前提は容易に崩壊します。IDE の強制終了、OS のクラッシュ、通信の断絶。これらが発生した瞬間、ロックファイルは「嘘」をつき始め、後続プロセスの起動を阻む壁となるか、あるいは多重起動を許すザルと化します。
第2章:unlink しても消えない“ゴーストファイル”の正体
ファイルベース管理の限界を象徴するのが、Unix系ファイルシステムにおける 「参照の残存による不整合」 です。
プロセスの強制終了時、新プロセスが「掃除」のためにロックファイルを削除(Unlink)しても、旧プロセスがそのファイル記述子(fd)を開き続けている場合、ディスク上の実体は消えません。
新プロセスは「ファイルがなくなったから安全だ」と判断して新しいロックファイルを作りますが、裏では旧プロセスが消えたはずの古い実体へ書き込みを続けています。
この「物理的な乖離」こそが、AIの推論を狂わせる ゴースト・データ の正体です。
第3章:ロックファイル方式の論理的な限界
ここで重要なのは、これらの問題は「実装が甘い」からではないという点である。
flock は設計として「収束」を保証しない
つまり、どれだけ丁寧に実装しても:
- 壊れた状態は残る
- 2つが同時に存在する
この前提が覆らない限り、問題は再発します。単に「ロックを確保する」という静的なアプローチは、実運用において「状態の不整合」か「プロセスの立ち往生」のいずれかを招く結果となります。
第4章:排他ではなく“継承”へ —— ソケットが開いた新しい道
前述の問題を克服するため、設計思想を根本から転換しました。その中核にあるのは、Unix ドメインソケット の採用です。
ソケットの採用は、単なる「場所取り」としてのフラグを置き換えるだけではありません。
- 存在確認の確実性: ソケットはプロセスの終了と同時にOSによって確実にクリーンアップされるため、「残留したロック」による誤認が排除される
- 通信プロトコルによる制御権の移行: 通信路が存在することで、新インスタンスは旧プロセスに対して直接「状態の保存」を促し、相互の合意のもとでリソースを解放させることが可能になる
- ローカル権限管理の容易さ: TCP/IPと異なり、ソケットファイル自体に対してOSのファイルシステム権限(chmodやUID認証)をそのまま適用できるため、セキュアなシングルトン環境の構築が極めて容易である
「既存プロセスがあるから諦める(拒絶)」のではなく、「旧プロセスのリソースを解放させ、確実に役割を引き継ぐ(動的な継承:Succession)」。このプロアクティブなアプローチへの転換こそが、Highlander Protocol の要諦です。
第5章:技術的構成:検証可能な継承シーケンス
Highlander Protocol は、以下の技術的レイヤーによって安全な継承を担保します。本プロトコルは、平常時のメイン通信路(stdio)とは独立した「管理専用レーン」として機能するため、既存のビジネスロジックに影響を与えることなくシングルトン性を保証することが可能です。
5.1 セッショントークンによる HMAC 署名
起動時に親プロセスから受け取った HIGHLANDER_TOKEN を用いた HMAC-SHA256 署名を導入し、正当な権限を持たない第三者プロセスによる制御権の奪取を厳格に防止します。
HMAC(Hash-based Message Authentication Code)とは、共通の秘密鍵を用いてメッセージの真正性を検証する仕組みです。これを用いることで、ソケット経由の要求が「正しい秘密鍵を継承したプロセス」から送信されたものであることを数学的に証明できます。
5.2 決定論的多段ハンドシェイクと PROGRESS
新旧インスタンスが状態の保存と継承を相互に承認するフローを確立しました。
特に PROGRESS メッセージの送信は、大規模なプロジェクトフォルダのインデックス保存など、処理が長時間に及ぶ状況において重要な役割を果たします。新インスタンスはこれを受信し続けることで、既存プロセスが「ハングアップ」したのか「正常に保存中」なのかを正確に判別でき、不用意な SIGKILL によるデータの破損(Save Corruption)を未然に回避することが可能となります。
5.3 決定論的空間配置と実体検証
- プロジェクト・ハッシュによる隔離: プロジェクトパスから算出されたハッシュ値をソケット名に含め、プロジェクトごとの独立性を確保
-
OSレイヤーによる実体検証: Linux 環境では
/procファイルシステムを介し、接続先プロセスの実行バイナリパスおよび引数を検証。ソケットパスを偽装した他プロセスへの誤接続を防止
5.4 セーフガード:通信不全への自浄作用
既存プロセスが完全にハングアップしている場合は、決定論的なタイムアウトに基づき、強制排除(SIGKILL)とソケットファイルの強制破棄を行い、新インスタンスが安全にバインドできる環境を再構築します。
第6章:結論:唯一性は「拒絶」ではなく「継承」で守る
不確実性の残るファイルシステム上の「ロック」という状態管理を、検証可能な「対話プロトコル」へと整理したことが、Highlander Protocol の特徴です。
- 整合性の保証: 物理的な不整合(unlink等)が避けられないロックファイルを捨て、対話型ソケットと HMAC 署名による「権限の委譲と継承」を選択
- ロックファイルの役割: ロックはもはや単なる進入禁止のフラグではない。それは「正当な後継プロセスからの継承リクエストを受け付けるための、公式な通信インターフェース」へと再定義された
DAD (Design-Action-Decision) 要約
| 観点 | 技術的決断 |
|---|---|
| Design (設計) | 排他制御の完成度を、「いかに立ち入らせないか」ではなく、**「いかに安全に状態を継承するか」**の精度で評価する |
| Action (行動) | SAVED ➔ ACK_SUCCESSION の多段承認により、状態保存の完遂を論理的な合意で担保 |
| Decision (決定) | 物理的な不整合が避けられない静的なロック方式を脱却し、対話型ソケットと HMAC 署名による動的な秩序を選択する |
実務での導入と運用のヒント
Highlander Protocol を実際に導入し、安定運用するためのポイントをまとめました。
1. 自作 MCP サーバーへの導入
既に stdio で通信しているサーバーに組み込む場合、メインロジックとは別スレッドまたは非同期タスクで Highlander.ensureSingleton() を呼び出すのが一般的です。これにより、ビジネスロジックを汚さずにシングルトン性を注入できます。
2. ロックファイル方式からの移行
既存の .lock ファイルがある場合、そのファイルを「削除」するのではなく、Highlander Protocol の管理下に置くようにリファクタリングします。具体的には、ソケットでの接続確認を第一優先とし、接続できない場合にのみロックファイルの「掃除」を行うシーケンスに変更します。
3. モードの段階的な適用
実稼働環境での挙動が不安な場合は、以下の順序での適用をお勧めします。
- OBSERVE: ログ出力のみを行い、既存の動作には介入しない
- WARN: 多重起動を検知した際に警告を発するが、強制排除は行わない
- AUTO (デフォルト): 完全に自律的な継承・排除を実行する
まとめ
プロセスの唯一性と状態の整合性は、AIエージェントが「環境」という不確実な現実を扱うための、決定論的な基礎要件です。
「排他」という静的な拒絶ではなく、「継承」という動的な秩序を選択する。これこそが、物理世界と推論の一貫性を守り抜くための、シングルトン設計における一つの着地点です。
