◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り5日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り5日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/開発ツール
⟐ 開発ツール/2026-10-19中級

MCP のタイムアウトを 10 分にしたのに 1 分で切れる — 値を決めている層を順に辿る

Gemini CLI で MCP サーバーの timeout を長くしたのに、想定より早く切れる。設定ファイルの層ごとに値を並べ、単位の取り違えや拡張側の上書きを見つける小さなスクリプトと、切り分けの順番を書き残します。

Gemini CLI10MCP7timeout3settings.jsontroubleshooting61Python52

MCP サーバーの timeout を 10 分に伸ばしたのに、処理が 1 分で打ち切られてしまうという報告を読み返していた夜、私は自分の設定ファイルを開いて、手が止まりました。timeout を書ける場所が、思っていたより多かったからです。

設定は変えたのに、効いていないようです。こういうとき、私はまず「Gemini CLI の不具合だろうか」と疑います。ただ、その疑いを持ったまま調べ始めると、たいてい遠回りになります。先に確かめるべきなのは、値を決めている場所が一か所ではないという事実のほうでした。

同じような症状は、gemini-cli の Issue でも「設定した時間より短く切れる」という趣旨で報告されています。原因は環境ごとに違うため、この記事は「犯人を一つに決める」ことはいたしません。代わりに、手元で順に潰していける切り分けの手順と、そのためのスクリプトをお伝えします。

まず、timeout は何の単位で、どこに書けるのか

MCP サーバーの設定には timeout というキーがあり、単位はミリ秒です。指定しなければ 600,000(10 分)が既定値として使われます。

一見して分かりにくい点が二つあります。

  • 単位がミリ秒なので、"timeout": 600 と書くと 0.6 秒です。10 分のつもりで 600 と書いてしまう取り違えは、起こりやすいはずです
  • 設定を書ける場所が複数あります。ユーザー全体の ~/.gemini/settings.json、プロジェクト直下の .gemini/settings.json、そして拡張機能が持つ gemini-extension.json です

同じ名前の MCP サーバーが二か所に書かれていると、どちらの値が採用されるかは層の優先順位に左右されます。優先順位は版によって変わりうるので、私は「どちらが勝つか」を覚えるより、全部の層の値を並べて目で見るほうを選んでいます。

全部の層を一度に並べる小さなスクリプト

次のスクリプトは、ユーザー設定・プロジェクト設定・インストール済み拡張の 3 種類を読み、サーバー名ごとに timeout を一覧します。勝者は断定せず、食い違いと単位の疑いだけを知らせる作りです。

#!/usr/bin/env python3
"""MCP サーバーの timeout が、どの設定ファイルで決まっているかを一覧する。"""
import json
import sys
from pathlib import Path
 
DEFAULT_MS = 600_000  # 設定が無いときの既定値(公式ドキュメント記載の値)
 
 
def humanize(ms):
    if ms < 1000:
        return f"{ms} ms"
    if ms < 60_000:
        return f"{ms / 1000:g} 秒"
    return f"{ms / 60_000:g} 分"
 
 
def layers(home: Path, project: Path):
    yield "user", home / ".gemini" / "settings.json"
    yield "project", project / ".gemini" / "settings.json"
    ext_dir = home / ".gemini" / "extensions"
    if ext_dir.is_dir():
        for p in sorted(ext_dir.glob("*/gemini-extension.json")):
            yield f"extension:{p.parent.name}", p
 
 
def collect(home: Path, project: Path):
    found = {}  # サーバー名 -> [(層, ファイル, timeout or None)]
    for label, path in layers(home, project):
        if not path.is_file():
            continue
        try:
            data = json.loads(path.read_text(encoding="utf-8"))
        except json.JSONDecodeError as e:
            print(f"! {path}: JSON が壊れています ({e})", file=sys.stderr)
            continue
        for name, conf in (data.get("mcpServers") or {}).items():
            found.setdefault(name, []).append((label, path, conf.get("timeout")))
    return found
 
 
def report(found):
    suspicious = 0
    for name, rows in sorted(found.items()):
        print(f"[{name}]")
        for label, path, t in rows:
            shown = "未指定(既定値)" if t is None else f"{t} → {humanize(t)}"
            flag = ""
            if isinstance(t, (int, float)) and t < 1000:
                flag = "  ← 秒で書いていませんか(単位はミリ秒)"
                suspicious += 1
            print(f"  {label:<24} {shown}{flag}")
        values = {t for _, _, t in rows if t is not None}
        if len(values) > 1:
            print(f"  ※ {len(values)} 通りの値が定義されています。優先順位を確かめてください")
            suspicious += 1
        if not values:
            print(f"  (どの層にも無し → 既定の {humanize(DEFAULT_MS)})")
    return suspicious
 
 
if __name__ == "__main__":
    home = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.home()
    project = Path(sys.argv[2]) if len(sys.argv) > 2 else Path.cwd()
    sys.exit(1 if report(collect(home, project)) else 0)

なぜ勝者を決めないのか、と思われるかもしれません。優先順位の仕様は更新で変わることがあり、スクリプトに埋め込むと、古い知識が静かに誤った結論を出してしまうからです。事実だけを並べて、判断は人に残しました。

わざと食い違わせた設定で動かしてみました

仕組みの確認のために、検証用の設定を手で作りました。実際の私の環境ではなく、動作確認のためのサンプルです。

  • ユーザー設定に docs サーバー(timeout 600000)と、timeout 無指定の files サーバー
  • プロジェクト設定に files サーバー(timeout 600)
  • 拡張機能 docs-helper に、同じ名前の docs サーバー(timeout 60000)

実行すると、次のように出力されました。

[docs]
  user                     600000 → 10 分
  extension:docs-helper    60000 → 1 分
  ※ 2 通りの値が定義されています。優先順位を確かめてください
[files]
  user                     未指定(既定値)
  project                  600 → 600 ms  ← 秒で書いていませんか(単位はミリ秒)

docs では、10 分と 1 分が同居しています。冒頭で私が見た「きっかり 1 分」は、こういう拡張側の値が採用されていた場合と、症状としてはよく似ています。files では 600 と書いたために 0.6 秒になる設定が見つかりました。どちらも、CLI を疑う前に目で見えるはずの食い違いです。

なお、この検証が示せるのは「スクリプトが食い違いを拾えること」までです。あなたの環境で 1 分の切断が拡張に由来するかどうかは、実行して初めて分かります。

食い違いが見つかったあとの直し方

docs のように層をまたいで値が割れていたら、私は次の三つのうち一つを選びます。

  1. 拡張側の値を正とするなら、ユーザー設定の docs を消して、定義を一か所に寄せます
  2. 自分の値を正とするなら、同じサーバーを拡張に頼らず自前の設定へ移し、拡張から該当サーバーを外します
  3. どちらとも決められないなら、サーバー名を変えて二つに分け、それぞれに目的の timeout を書きます

単位の取り違えのほうは、もっと簡単です。600 を 600000 に直すだけですが、数字のゼロを数え間違えやすいので、私は 10 * 60 * 1000 のように式で書いた値を一度別のメモに計算しておき、そのまま写すようにしています。JSON に式は書けないため、数字だけを丁寧に写す作業になります。

直したあとは、もう一度スクリプトを走らせて、終了コードが 0 になるのを確かめます。共有のリポジトリで使うなら、コミット前のフックに入れておくと、チームの誰かが同じ食い違いを持ち込む前に止められます。終了コードが 1 のときは何かしら疑わしい点が残っている、という約束にしてあるのは、そのためです。

一覧で見つからなかったときの切り分け

スクリプトが何も見つけなければ、設定ファイルの外に原因があります。私は次の順で確かめています。

  1. サーバー側の制限。MCP サーバー自身や、その先の API が、独自の制限時間を持っていないか
  2. 間に挟まるもの。プロキシやリバースプロキシが、長く無応答の接続を切っていないか
  3. 進捗の通知。処理中に何も返さない設計だと、途中の層が「無通信」とみなす場合があります
  4. CLI の版。既知の不具合の一覧に当たっていないかを、更新履歴と Issue で確かめます

3 を試すときは、処理を小さく刻んで途中経過を返す形に直すのが手堅い方法です。時間を伸ばすより、長く黙らない設計のほうが、どの層でも壊れにくくなります。

私が引いた線

今回の件で、はっきりしたことがあります。**設定を変えたら、効いた値を読み戻します。**書いた値ではなく、実際に採用されている値を確かめるところまでを一つの作業にしました。

次に timeout を触るときは、まず find_mcp_timeouts.py を一度走らせてから、値を書き換えてみてください。MCP の組み方そのものは Gemini CLI で MCP サーバーを使う に、増えたツールの整理は つないだ MCP を初めて外した日 に、既知の不具合を先に引く方法は 既知バグ早見表を先に grep する話 に書き残しております。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ 開発ツール2026-09-21
つないだ MCP を初めて外した日 — 常時有効にするツールを選ぶ基準
MCP サーバーを足し続けると、API の上限である 512 個の関数宣言に当たる手前で応答の質が落ちます。Gemini CLI の includeTools と excludeTools を使い、常時有効にするツールを選ぶ基準と外し方をまとめます。
⟐ 開発ツール2026-10-17
止まるときは静かに止まる — 定期実行の Gemini 呼び出しに、タイムアウト・空出力・多重起動の殻をかぶせる
cron などで `gemini -p` を呼ぶ定期実行が、応答待ちで止まる・終了コード 0 で空を返す・前回分と重なる、の 3 つから身を守る外側のシェルスクリプトです。替え玉コマンドで測った終了コードと所要秒数、タイムアウトが子プロセスをどこまで止めるかも載せました。
⟐ 開発ツール2026-09-29
Gemini CLI に新しいキーを渡しても「API key not valid」。読まれていたのは三か所目の古いキーでした
Google ログインから有料 API キーへ Gemini CLI の認証を切り替えたのに、400 の「API key not valid」が消えませんでした。キーの出どころはシェル・作業ディレクトリの .env・ホームの .env・settings.json の四か所あり、順に照らす小さなスクリプトで原因を一つに絞ります。