ブリッジは橋ではなく役割。file bridgeとMCPとIDE連携を切り分けて理解する
これを調べようとした経緯
LLM同士のやり取りを実装しているときに、一方向だけなら考えやすいのに、双方向になると急に見通しが悪くなる瞬間がありました。
そこに何か中継の仕組みが要る。その代表例として出てくるのが bridge です。bridge とは結局何なのか。MCP と同じものなのか、ただの別名なのか。そのあたりが自分の中でずっと曖昧でした。
そこで、「つなぐ役割」と「その実装方式」を分けて考え直してみた記録です。
CLI で AI に作業を頼んでいると、妙に会話が長くなる瞬間があります。たとえば「今見ている関数だけ直して」と言いたいのに、実際にはファイルパス、選択範囲、修正先、確認方法まで全部ことばで渡し直す必要がある。
こちらは一行で済ませたいのに、AI 側は文脈が足りず、確認の往復だけが増えていく。あのもたつきの正体をたどると、結局は「CLI と IDE のあいだに、何が渡っていないのか」という話に行き着きます。
調べていく中で面白かったのは、ここでいう bridge が単なる機能名ではなく、かなり設計寄りの言葉として扱えることでした。しかも、その bridge を実装する手段として MCP が出てくる。
最初は同じものに見えます。けれど、少しずつ分けていくと景色が変わります。bridge は「何をつなぐ役か」という話で、MCP は「どういう約束でつなぐか」という話でした。
先に、この記事で何度も出てくる言葉だけ短く置いておきます。
- CLI: コマンドを打って AI に指示を出す側
- IDE: エディタや差分表示を受け持つ画面側
- bridge: その 2 つのあいだで文脈や操作を受け渡す仕組み
- Companion: CLI と IDE をつなぐ公式の連携口。文脈共有や差分表示を担当する
- file bridge: ファイルを介した bridge。補助的に IDE 操作を渡す経路
- openDiff: IDE に「この変更案を差分表示して」と頼むための呼び出し
- closeDiff: 開いている差分表示を閉じるための呼び出し
- ide/contextUpdate: IDE 側が「今見ているファイルや選択範囲」を送る通知
- discovery file: CLI が「どの IDE につなぐか」を見つけるための情報ファイル
- Bearer token: 接続先が正しい相手かを確かめるための合言葉のようなもの
この違いが見えるだけで、Companion と file bridge の整理、openDiff が成功してもまだ受諾ではない理由、なぜ discovery file や Bearer token が必要なのかまで、一気に筋が通ります。
まずは、bridge があると何が減るのかを、軽いデモで見たほうが早いです。
毎回「どのファイルの話ですか」と聞き直される不便
bridge がないと、AI は IDE の画面を当然ながら直接見ていません。だからユーザーは、いま開いているファイル、選択している範囲、どこに差分を当てたいかを、会話の中で何度も明示することになります。作業自体はできます。でも、じわじわ面倒です。
bridge がない場合は、見ている file と選択範囲を毎回 prompt に書く必要があり、修正案の確認もテキスト中心になります。
bridge がある場合は、IDE 側が ide/contextUpdate で最近の文脈を送り、差分は Diff UI で受け取れる。ここで効いているのは派手な自動化ではなく、「会話に載せなくてよい文脈を、別経路で運ぶ」 という発想です。
この時点で、bridge はまだ技術名ではありません。むしろ「運び役」です。CLI は推論と実行を担当し、IDE は開いているファイル、選択、Diff の受諾 UI を担当する。そのあいだで必要な情報を中継する役割。それが bridge です。
まず bridge を概念として見る
ここが最初の分かれ道でした。bridge をいきなり MCP や HTTP や JSON で理解し始めると、話がすぐ実装に落ちてしまいます。
けれど、その一段上にある考え方から見ると整理しやすくなります。まず「何のために橋が要るのか」を押さえ、そのあとで「どんな方式でつなぐのか」を見るほうが迷いません。
- 概念: 異なる責務を持つ二者のあいだで、必要な文脈と操作を渡す役
- 理論: 推論する側と表示・承認する側を分け、責務を混ぜない
- 実装: その役割を、MCP や JSON ファイルや別の IPC で実際に動かす
この三段を分けると、かなり楽になります。bridge はまず概念です。CLI と IDE のどちらにも全部を背負わせず、片方は頭脳、片方は手と目に寄せる。その境界に橋を置く。だから bridge は「機能一覧」よりも「設計思想」に近い。
代表例を並べると分かりやすいです。
- IDE bridge: CLI と IDE をつなぎ、open files、selected text、Diff 承認を渡す
- WebView bridge: WebView とネイティブアプリをつなぎ、イベントやデータを渡す
- 言語間 bridge: JavaScript と Python のような異なる実行系をつなぎ、呼び出しと結果を渡す
このどれも bridge ですが、必ずしも MCP ではありません。つまり bridge は、最初から MCP より広い言葉です。
分類をいじりながら見るデモも置いておきます。抽象と具体が混ざると、一気に分かりにくくなるので。
MCP は橋そのものではなく、橋を作るときの共通ルールに近い
では MCP は何か。こちらは Model Context Protocol。AI と外部のツールやデータを、なるべく共通の作法でつなぐための標準化された枠組みです。
ファイルを読む、ブラウザを動かす、GitHub を触る、IDE と連携する。そうした外部能力を、AI が独自仕様だらけにならずに使えるようにするための約束ごと、と考えるのがいちばんしっくりきました。
だから MCP は bridge 専用の言葉ではありません。ファイルシステム用の MCP サーバーもあれば、ブラウザ操作用の MCP もある。つまり MCP は、「IDE 連携のためのもの」よりも広く、AI と外部機能をつなぐ共通ルールとして見るほうが自然です。
ここが大事です。
- bridge は「つなぐ役割」
- MCP は「つなぐための標準化された方式」
この順番を逆にしないほうが混乱しません。bridge が先、MCP はその有力な実装手段のひとつ。もちろん、MCP で bridge を作れます。けれど bridge そのものが MCP である、とは言い切れない。
代表例を軸ごとに並べると、こんな見え方になります。
たとえば IDE Companion は、役割としてははっきり bridge です。一方で、その輸送路は MCP over HTTP です。
逆に、file bridge も同じく bridge ですが、実装は JSON の request/response を使う形でした。同じ役割でも、作法が違う。ここを一緒くたにすると、後の説明が全部ぼやけます。
Companion と file bridge は、同じ役割を別の作法で果たしている
ここでいちばん腹落ちしたのは、両者は競合製品というより、まず役割の置き方が違うということでした。
- Companion: 公式。IDE 文脈共有と native Diff を担う正規経路
- file bridge: 独自。ファイルを介した bridge で、外部 agent やスクリプトから IDE 操作を投げる補助経路
Companion 側には discovery file と認証があります。discovery file は、CLI が「どの IDE とつながるべきか」を見つけるための名札のようなものです。
たとえば次のような情報を持ちます。
{
"port": 12345,
"workspacePath": "C:\\repo;D:\\other",
"authToken": "secret-token",
"ideInfo": {
"name": "vscode",
"displayName": "VS Code"
}
}
この JSON の意味は地味ですが重要です。CLI は親プロセスの PID や workspacePath をたどって「自分が今つながるべき IDE はどれか」を見つけ、さらに Bearer token で認証する。
つまり Companion は、ただ情報を渡すだけでなく、違う window や違う workspace に誤接続しないためのルールまで持っています。ここが bridge の理論を、きちんと運用に耐える実装へ落とした部分です。
一方、file bridge はもっと局所的です。request 側に JSON を書き、watcher がそれを拾い、response 側に返す。watcher は、ファイルの変化を監視して反応する仕組みだと思えば十分です。
明示的で分かりやすい反面、公式 Companion の discovery や認証思想とは別物です。だから通常は、Companion を主、file bridge を従として扱うほうが安全です。
流れを一度に見ると、この差が見やすくなります。
Diff が「開けた」と「受け入れた」で分かれている理由
個人的にいちばん面白かったのは Diff の扱いでした。openDiff が成功しても、それはまだ「差分ビューを開けた」という意味にすぎません。
ユーザーがその差分を accept したか reject したかは、そのあと非同期に ide/diffAccepted または ide/diffRejected で返ってきます。
この分離は、一見まどろっこしいのに、実はかなり筋がいいです。なぜなら最終判断はユーザーの UI 操作だからです。CLI が差分を提案した瞬間に、採否まで同期的に決めることはできない。そこで、
- CLI が
openDiff(filePath, newContent) を呼ぶ
- IDE が差分ビューを開く
- ユーザーが内容を確認し、必要なら手で直す
- その結果だけがあとから
diffAccepted か diffRejected で返る
という二段構えにしている。なるほど、と思いました。closeDiff も reject ボタンではなく、あくまで view を閉じる操作です。この切り分けを知らないまま実装を読むと、「成功したのに、なぜまだ終わっていないのか」で確実に迷います。
この非同期性を触りながら見られるデモも置いてあります。
どちらを選ぶかは、誰が最終確認するかで変わる
では実際に何を選ぶのか。かなり実務的に考えると、通常は Companion を優先し、追加の要求だけ file bridge を使うのが安全です。
これは機能の多寡というより、最終確認をどこで行うかの違いです。
- 人間が IDE の Diff を見て承認したい:
Companion
- 外部 agent やスクリプトから project-local に IDE を少し動かしたい:
file bridge
- どちらも必要:
Companion を主、file bridge を補助
ここでも bridge は役割です。レビューのための橋なのか、補助操作のための橋なのか。その役割が先にあり、そのあとで MCP over HTTP にするのか、JSON request/response にするのかが決まる。
選び分けを軽く試せるデモを最後に置きました。
こうして見ていくと、bridge という言葉を先に概念として受け取っておくだけで、全体の温度がぐっと下がります。言い換えると、慌てなくて済みます。MCP を知っている人ほど「同じことでは」と思いやすいのですが、実際には軸が違う。bridge は設計の役割、MCP は標準化された接続方式。重なるけれど一致しない。その一歩引いた見方があるだけで、Companion も file bridge も、必要以上に神秘的に見えなくなります。
ついでに言うと、VS Code 系の周辺まで追っていくと、IDE 側で何を操作できるかの感覚もだんだん見えてきます。bridge の理論を読んだあとだと、「どこまでが UI 側の責務なのか」が前より分かりやすくなります。
ここまでの要点
- bridge はまず 役割 です。CLI と IDE のあいだで、文脈や差分承認を中継するための考え方でした。
- MCP はまず 標準化された接続方式 です。bridge を実装するのにも使えるし、ファイルやブラウザなど別の外部能力にも使えます。
Companion は MCP で実装された bridge、file bridge は JSON request/response で実装された bridge と見ると混乱が減ります。
openDiff の成功と diffAccepted の受諾は別物です。差分を開くことと、ユーザーが採用することを分けているから、最終確認の責務が崩れません。
- Companion を使うときに discovery file や token が必要なのは、単に面倒な儀式ではなく、正しい IDE と正しい workspace にだけつなぐため でした。
参考になる公式情報
ここで書いた話を、元の仕様や公開ドキュメント側から追いたいなら、このあたりが入口になります。bridge の全体像をつかむなら IDE integration、細かい契約を追うなら companion spec、実装を見たいなら repository、という順番で辿ると分かりやすいです。