はじめに
自作の VBA 管理ツール(shu-vba-manager)を MCP サーバー化して、ふだんは Claude Code から使っています。開いたままの Excel ブックに相乗りして、マクロの一覧・取得・置換までを会話で済ませる道具です。
これを Google の Antigravity でも使おうとしたら、動きませんでした。
原因にたどり着くまでに、AI(Gemini)の「自白」が二回崩れました。今回はその捜査記録です。ツールの話というより、「AIの説明をどうやって検証するか」の話になります。
TL;DR
- Antigravity 上の Gemini に vba-manager を使わせたら「Excel が起動していません」。実際には Excel は開いている
- 問い詰めると「仮想コンテナに閉じ込められていて、設定ではどうにもならない」と自白 → 裏取りしたら崩れた
- 真相は二段構えだった
- エージェントのターミナルは実機の中の別デスクトップで動いていて、そこから COM は届かない(Geminiの報告による)
- そして MCP サーバーはそもそも起動していなかった。設定の
"command": "py"を IDE が解決できていなかった
- Python の絶対パスに書き換えて IDE を再起動したら解決。開いたままのブックへの相乗りが Antigravity でも動いた
- 検証はぜんぶ「物証」でやった。プロセス一覧と、答えを先に押さえた上での抜き打ちテスト
前提:vba-manager の方式
vba-manager は、起動中の Excel を GetActiveObject で掴む方式です。ファイルを開き直さず、いま画面に開いているブックをそのまま操作します。この方式の生命線は、同じデスクトップセッションの COM(ROT:Running Object Table)が見えることです。
Claude Code に MCP サーバーとして登録してあり、常駐 COM で 1 コマンド 0.01〜0.2 秒程度で応答します。ここまでが平常運転です。
第一の異変:「Excel が起動していません」
Antigravity で同じことをやらせると、「Excel が起動していません」と返ってきます。目の前で Excel は開いています。
Gemini は最初、別の原因をいろいろ挙げて作業を続けました。どれも当たりません。5回ほど問い詰めたところで、こう白状しました。
いつの間にか仮想コンテナに閉じ込められていて、設定ではどうにもなりません
なるほど、と一瞬納得しかけました。仮想環境の中からは実機の Excel が見えない。筋は通っています。
裏取りで自白が崩れる
念のため(別の AI に)調べさせると、話が合いません。
- Antigravity のターミナルサンドボックスは、解説記事を見る限り macOS 専用(Apple の Seatbelt 機構を利用)。Windows でターミナルを仮想化するという記載は見当たらない
- 「設定ではどうにもならない」はずの設定(Agent security mode、Enable Terminal Sandboxing)が普通に存在する
こちらの環境は Windows です。macOS 専用のサンドボックスに閉じ込められた、という筋書きは成立しません。
つまり、追い詰められて出てきた自白は、それらしいだけの作文だった可能性が高い。AI は問い詰められると「相手が納得しそうな罪」を自白することがあります。自白にも裏取りが要ります。
実機での物証その1:仮想ではなく「別室」
Gemini に実機確認をさせました。hostname と whoami の結果は、実機と完全に一致。仮想マシンでもコンテナでもありません。
では何が違うのか。Windows API に「自分が今立っているデスクトップの名前」を直接答えさせるワンライナーを、両方の環境で実行して比べました。
py -c "import ctypes; u=ctypes.windll.user32; k=ctypes.windll.kernel32; h=u.GetThreadDesktop(k.GetCurrentThreadId()); buf=ctypes.create_unicode_buffer(256); n=ctypes.c_ulong(); u.GetUserObjectInformationW(h, 2, buf, 512, ctypes.byref(n)); print(buf.value)"
結果、通常のターミナルは Default、Antigravity のエージェントターミナルは agy-(ランダム文字列)。Antigravity はエージェントのコマンドを、実機の中に作った別のデスクトップで実行していました。
これなら全部の観測と辻褄が合います。Windows の COM の名簿(ROT)は、別のデスクトップからは見えません。py も pywin32 も動くのに Excel だけ見えなかったのは、あの別室から見える世界には本当に Excel がいなかったからです。「Excel が起動していません」というエラー自体は、一度も嘘をついていませんでした。
途中で踏んだ地雷:黙って死体解剖に切り替わる
捜査の途中、一度だけ「マクロ一覧が一瞬で出た」ことがありました。速くなった理由を聞くと、こう説明されました。
Excel への接続を待つのではなく、デスクトップの .xlsm ファイルを直接読み込み、内部の VBA をバイナリ解析してマクロ名を取り出す方法に切り替えました
これは相乗りではありません。最後に保存した時点のファイルを解剖しているだけです。保存していない変更は見えませんし、この方式のまま書き込みに進めば、開いているブックと衝突して本物の破壊事故になります。
正規の道具が使えないとき、AI は黙って迂回路に切り替えて「できました」と報告することがあります。迂回そのものより、聞かれるまで言わないことのほうが危ない。この時点で「ファイル直読みは読み取り専用、開いているブックへの直接書き込みは厳禁」と釘を刺しました。
実機での物証その2:サーバーはそもそも立っていなかった
「別室」の正体がわかっても、MCP 経由なら動くはずでした。MCP サーバーはエージェントのターミナルではなく IDE 本体が起動する子プロセスなので、別室問題を構造的に迂回できるからです。
それでも動かない。Gemini の説明は「権限の違いや Excel のビジー状態で、COM 接続がすべて拒否された」。
ここで Claude Code 側から、実機のプロセス一覧を見ました。
- Antigravity IDE 本体:起動中。レンダラー、言語サーバー、ターミナルまで全部見える
- その配下の vba_mcp_server.py:存在しない。起動を試みた痕跡すらゼロ
持っていない道具は、拒否のされようもありません。「権限」「ビジー」はまた作文で、真相はサーバーが一度も起動していなかったでした。
原因は単純で、MCP 設定の "command": "py" を IDE が解決できていなかったのです。絶対パスに書き換えます。
"vba-manager": {
"command": "C:\\Users\\shu\\AppData\\Local\\Python\\bin\\python.exe",
"args": ["c:/Users/shu/Desktop/.../python_scripts/vba_mcp_server.py"]
}
パスは Python インストールマネージャーが作る bin のシム(実体のバージョンフォルダを指す別名)にしました。Python を更新してもパスが変わりません。
IDE を再起動すると、プロセス一覧に新しい行が現れました。
python.exe ← vba_mcp_server.py(12:40:06 起動)
親: language_server_windows_x64.exe(Antigravity)
今度は家系図が証言と一致しています。
最後の試金石:抜き打ちの点呼
接続の最終確認は、こういうテストにしました。
- Claude Code 側で、いま開いているブックを先に実測しておく(正解を握る)
- 直前にブックを入れ替えておく(履歴や「最近使ったファイル」ではカンニングできない状態を作る)
- Gemini に list-open を実行させる
Gemini の回答は、入れ替えた直後のブック名までぴたりと一致。生きた COM で今の Excel を見ていないと出せない答えです。合格。Antigravity からの相乗りが、今度こそ本当に動きました。
これは vba-manager に限った話ではありません
看板は自作ツールのトラブル記ですが、構造は一般的なものです。
-
commandの解決失敗は、ローカル起動型の MCP サーバー全般で起きます。pyに限らず、npx(Node 系サーバーの定番)やuvxも同じです。コマンドが解決できるかは「どうインストールしたか × クライアントがどんな環境でプロセスを起動するか」の掛け算で決まり、シェルの設定で PATH を通しているタイプ(nvm 経由の Node、Store 版 Python など)は IDE から見えないことがあります。対処も共通で、絶対パスで書く - 失敗が本人(AI)に伝わらないのも共通です。サーバーが立っていないことをエージェントは知らされないので、「権限が」「ビジーで」と、それらしい説明を組み立てるしかなくなります
- 診断法も共通です。プロセス一覧で、クライアントの配下にサーバーのプロセスがいるかを見る。いなければ、接続以前の問題です
つまりこの記事は実質、「Antigravity で MCP サーバーが繋がらないときの調べ方」の一例です。
まとめ
技術的な結論は一行です。MCP 設定の command は絶対パスで書く。 それだけでした。
ただ、そこにたどり着くまでの教訓のほうが大きかったので、三つ書いておきます。
自白にも裏取りが要ります。 AI は問い詰められると、それらしい自白をします。今回は「仮想コンテナ」「権限」「ビジー」と三つの説明が出て、三つとも作文でした。しかも作文には本物の部品が織り込まれるので、聞いただけでは見分けがつきません。説明の中身ではなく、プロセス一覧・コマンドの実行結果・答え合わせといった物証で判定するのが確実です。私は AI の説明を疑ってかかる習慣があったのでここで済みましたが、AI の説明をそのまま信じるタイプの人がこの状況に入ると、存在しない原因を延々と直し続けることになります。この記事が検索で引っかかる理由が、たぶんそれです。
エージェントは、自分の檻の中から檻を調べられません。 Gemini の調査コマンドは全部、問題のある環境の中で実行されていました。何をどう調べても歪んだ答えしか返らない。外側に立っていて、正解(動いている環境)を手元に持っている者だけが消去法を回せます。これは Gemini が劣っているという話ではなく、同じ檻に入れば Claude でも同じ壁にぶつかる、構造の問題です。
「点呼」は使い回せます。 開いているブックを入れ替えた直後に list-open をやらせて答え合わせする、というテストは、履歴のカンニングが効かないので確実です。AI の Excel 接続が本物かどうか怪しいとき、一発で白黒つきます。
道具を疑い、説明を疑い、物証で確かめる。遠回りに見えて、これがいちばん速い道でした。