blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2025.07.31 技術記事

Gemini CLIがぶっ壊れてたので1バイトのPull Requestを送ったら爆速でMergeされた話

by trapezoid

#ai #oss #gemini-cli #debug

@Trapezoid こと大竹悠人です。普段はDeNAでゲーム開発を効率化するための、プロジェクト横断的な取り組みをしています。

Google社からOSSとしてリリースされたCLIコーディングエージェントである Gemini CLI ですが、多くの方が使っていらしゃるんじゃないかと思います。

DeNAでも様々な部門で利用が広がってきている、最高にホットなプロダクトですが、まだまだリリースされたてのプロダクトかつOSSとして開発されているというのもあり、とんでもない速度で様々な機能開発/修正が行われています。

そんなGemini CLIを使う中、発生した出来事が今回のタイトルである、 Gemini CLIがぶっ壊れてたので1バイトのPull Requestを送ったら爆速でMergeされた話 です。 振る舞いから致命的な不具合の発生に気づき、止血処置をPull Requestとして投げ、マージされ、解決されるまでの短期間の軌跡を通して、 コントリビューションを厭わない気持ちをもったDeNAのAI活用の実態と、地道な調査過程とテクニックをお伝えできたらなと思います。

事の始まり

時は2025/7/11、Gemini CLIの0.1.10がリリースされた時の話です。 このバージョンからリリースされた、includeTools/excludeToolsによるMCP Serverごとの利用可能ツールのホワイトリスト/ブラックリスト設定機能をテストするために、 GitHub公式のGithub MCP Server を使った実験をしていたところ、前のバージョンに比べて、MCP Serverの提供するツールの呼び出しが、必ず1度失敗するようになっていることに気づきました。

慌ててGemini CLIを元々使っていたバージョンにダウングレードして同じプロンプトを実行しましたが、この挙動は直りませんでした。

何もしてないのに(?)壊れた….

状況把握(挙動調査)編

Gemini CLIはOpenTelemetryに対応しています。これを利用して、 Jetbrains RiderのOpenTelemetryプラグイン のCollectorに対してGemini CLIからログを投げ込ませるように構成して、調査を開始しました。

失敗している呼び出しと周囲のログをよく見てみると、本来pullNumberという名前のパラメータが必要な場面で、pull_numberという間違った名前のパラメータとして渡して呼び出してしまっていることがわかりました。 この呼出の応答として返されたエラー文から、pull_numberという引数が誤りであること(必須パラメータとなっていた pullNumber が未指定であること)を認識して、それをうけた2回目のリクエストでは pullNumber として正しくパラメータを渡すことができ、呼出に成功しているようでした。

MCPでは、MCP Serverは基本的に必要なパラメータのスキーマをJSONスキーマとしてMCP Client(エージェント)側に提示する仕組みになっています。このため、pullNumber というパラメータ名は本来、MCPとして接続しているのであれば、予期できるパラメータ名であるはずです。

つまり、MCPによって提供されるツールの引数のスキーマを、Gemini CLIが何らかの理由で正しく認識できていないのではないか? と考えました。

Gemini CLIでは /mcp schema コマンドを実行することで、登録されているツールが受け付ける入力のJSONスキーマを表示することができます。Ctrl+T でのツール表示トグルでは表示できない地味な機能ですが、これを用いることで対象のツールの引数のスキーマを、Gemini CLIがどう認識しているのかを確認できます。

結果は…

{"type": "OBJECT", "properties": {}}

でした。これは実質的には空スキーマを意味しているので、やはり、

MCPによって提供されるツールの引数のスキーマを、Gemini CLIが何らかの理由で正しく認識できていないのではないか?

という予想は概ね当たっていそうです。

ここで、Gemini CLIのバージョンをロールバックしても動作が戻らなかったのもあり、Github MCP Serverの不具合により、引数スキーマが提供されていないのではないか?という疑念も生まれました。

Postmanを使うと、任意のMCPサーバの接続設定のJSONをコピペするだけで、対象のMCP Serverに対するインスペクタとして機能するようになります。これを使って、Github MCP Serverの挙動を調査することにしました。

結果は…シロです。Github MCP Server自体は正常動作しているようでした。

となると、Gemini CLI自体に何かが起こっているのは間違いありません。その原因を、実際にコードを見て調べていくことにしました。

原因究明(デバッグ)編

MCPサーバから受け取ったJSONスキーマのハンドリングの何処かで問題が発生していることには間違いありません。

Gemini CLIのリポジトリをチェックアウトして調査したところ、 mcp-client.tsで、MCPから得たスキーマが未定義だった際の怪しいコードパス が見つかりました。

      toolRegistry.registerTool(
        new DiscoveredMCPTool(
          mcpCallableTool,
          mcpServerName,
          toolNameForModel,
          funcDecl.description ?? '',
          funcDecl.parameters ?? { type: Type.OBJECT, properties: {} },

funcDeclは出処をたどると、@google/genaimcpToToolから生成されているようです。何らかの理由で、@google/genaiによるMCP Clientから関数定義への変換処理が、期待通りに動かなくなっていることが考えられます。

より正確に状況を掴むため、Gemini CLIにVS Code上でブレークポイントを仕込み、実際にデバッガを接続して実行してみることにしました。

Gemini CLIでは、VSCode上のRun And DebugからLaunch CLIを実行すればすぐGemini CLIを立ち上げてアタッチされるように .vscode/launch.json が構成されているので、簡単にデバッガを接続できます。

デバッガでfuncDeclをインスペクションしたところ、parametersプロパティはやはりundefinedになっており、parametersJsonSchemaというプロパティに引数のJSON Schemaらしき値が入っていることがわかりました。

なぜこのようになったのかを調査したところ、 @google/genaiのこちらの変更 によって、まさにparametersが設定されなくなり、parametersJsonSchemaが設定されるようになっていることがわかりました。そりゃ、undefinedになるわけですね。

-    parameters: processJsonSchema(
-      filterToJsonSchema(
-        mcpToolSchema['inputSchema'] as Record<string, unknown>,
-      ),
-    ),
+    parametersJsonSchema: mcpToolSchema['inputSchema'],

Gemini/VertexAIで扱うJSONスキーマは、正確にはJSONスキーマではなく、 OpenAPI 3.0 Schema Objectのサブセット になっています。 そのため、@google/genaiでも

というように、もともと別のプロパティとして表現されているようです。

つまり今回の現象は、

@google/genaiがMCP Clientを通して得たツールの引数のJSON SchemaをOpenAPI 3.0 Schema Objectのサブセットとして変換してparametersを設定していたのを、行わずにparametersJsonSchemaとしてそのまま設定するようになった

ということに起因していることがわかりました。 タグごとの差分をみると、 1.9.0から導入されている ようでした。 あとはGemini CLIがこの変更に影響された原因ですが、Gemini CLIのバージョン自体をロールバックしても解決しなかったことを考えると、Gemini CLIから依存する@google/genaiのバージョンが固定化されていないのだろうということは、すぐピンときます。

調べてみると、やはり 依存バージョンは固定化されていない ことがわかりました。

  "dependencies": {
    "@google/genai": "^1.8.0",

1.8.0以上を指定しているので、新規にインストールすると@google/genai1.9.0が自動的にインストールされてしまうことになります。

このような^を使った指定になっているのはv0.1.10以前でも同様だったため、Gemini CLI自体のバージョンをロールバックしてインストールし直しても解決しなかったこととも符合します。インストールし直している時点で、ダメだったのです。

確認として、手元のチェックアウトしたGemini CLIを改変して、@google/genai1.8.0に明示的に依存するようにしてテストしたところ、正常にスキーマを認識し、ツール実行時も最初から正しいパラメータ名で正常に実行されるようになりました。

コントリビューション編

対応としてベストなのはもちろん@google/genai1.9.0に対応することですが、よくてMCPの精度がガタ落ち、悪いと全く使えなくなるほどの影響が出ていることを考えると、止血策が必要だと考えました。

先ほど行ったような、@google/genai1.8.0に明示的に依存するようにする ことは、脆弱性などへの対応が自動で取り込まれなくなる等の懸念はあるものの、最終的には1.9.0に追従する前提で考えれば、低リスクで本問題の修正を行い、1.9.0対応の時間を確保できる、良い止血策になるはずです。

この考えのもとに、 止血策としてのPull Requestを作成 して、投げてみることにしました。

-    "@google/genai": "^1.8.0",
+    "@google/genai": "1.8.0",

本質的には、^を取り除く1byteしか差分のないPull Requestです。 ここまで色々調査してきましたが、非常にシンプルな解決策に落ち着きました。

ちなみに、Gemini CLIのリポジトリではPull Requestに対してGemini Code Assistによるコードレビューが自動的に行われるのですが、抱いていた懸念がしっかり指摘されており、ちょっと感心しました。また、僕は英語が全然できないんですが、これもGemini CLIを通して翻訳/逆翻訳することで(今までの機械翻訳に比べて)特に困ることなく対応できました。 AI時代のOSS開発、便利ですね…

そして、Pull Requestを投げた約3時間半後には、爆速でマージされました!🎉

マージされたあとに気付いたのですが、 困っている人たちの報告はちょくちょく上がっていた ようです。

また、後日他のコントリビュータと協力して@google/genai@1.9.0への対応が進み、現在では本問題は根本対応も含めてすべて完了した状態になっています。

まとめ

今回は Gemini CLIがぶっ壊れてたので1バイトのPull Requestを送ったら爆速でMergeされた話 として、Gemini CLIがぶっ壊れてることに気付いてから、その原因を調査、修正し、Pull Requestを送って修正されるまでの一部始終をお話しました。

Gemini CLIは無料でも気軽に使えるコーディングエージェントであると同時に、OSSで非常に活発な開発が行われているプロダクトであるため、フットワーク軽くコントリビューションを行えます。

まだまだ発達途上のプロダクトだと思うので、自力で調査/解決する気持ちを持つことはとても大事だと感じています。

DeNAのフットワークの軽いエンジニアリングの一端も感じてもらえたら嬉しいです。

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。