Claude Media
claude-code-actionのallowedToolsで列挙外のMCPツールが送られ続ける理由

claude-code-actionのallowedToolsで列挙外のMCPツールが送られ続ける理由

claude-code-actionの--allowedToolsは実行を止めるだけで、列挙外のMCPツール定義はモデルに送られ続けるという報告です。トークンの無駄を抑える設定側の手順をまとめます。

claude-code-actionで--allowedToolsにMCPツールを1〜2個だけ書いても、そのMCPサーバーが持つ他のツール定義は、リクエストのたびにモデルへ送られる。2026年10月13日に起票されたIssue #1899は、この挙動を指摘しています。許可リストは「実行してよいツール」を決めるだけで、「モデルに見せるツール」は決めません。見せる範囲を絞る手段は--disallowedToolsや--mcp-configの側にあります。

報告されている挙動 — 実行は止まるが定義は残る

Issue #1899のタイトルは「--allowedTools does not keep unlisted MCP tools out of the model context」です。本文の主張は次の3点です。

  • --allowedToolsが制御するのは、Claudeが実行できるツールだけ
  • --mcp-configで渡したMCPサーバーの全ツールは、--disallowedToolsに挙げない限りモデルへ送られる
  • GitHub MCPサーバーのような大きなサーバーから1〜2個だけ使う構成では、未使用ツールの定義ぶんが毎ターンの入力トークンになる(報告者の見立てでは、リクエストあたり数千トークン規模)

報告者は、回避に必要な作業も具体的に書いています。

手順

現状の回避手順(Issueの記述)

  1. 1

    ツール一覧を集める

    実行ログのsystem/initイベントから、各サーバーが公開する全ツール名を取り出します。

  2. 2

    使わないツールを列挙する

    使わないツールをすべて--disallowedToolsに書き写します。

  3. 3

    サーバー更新のたびに見直す

    サーバー側でツールが増えたら、リストも更新します。

Issue #533も、ユーザー側から同じ問題(トークンの大量消費)を報告したものとして挙げられています。コメント欄には、特定ユーザーへのメンションだけの投稿が1件あります。

提案されているopt-in入力とその前提

報告者はdisallow_unlisted_mcp_tools: "true"のような任意入力の追加を提案しています。仕組みは次のとおりです。

  1. Claudeの起動前に、--allowedToolsが一部のツールだけを挙げたサーバーへアクションが接続する
  2. tools/listを呼ぶ
  3. 挙げられていないツールを--disallowedToolsへ自動で追記する

対象外の条件も明示されています。サーバー全体を許可した場合(mcp__serverやmcp__server__*)と、--allowedToolsに登場しないサーバーはそのままです。mcp__server__get_*のようなワイルドカードは、一致するツールを全部残します。到達できないサーバーは警告つきで飛ばし、現状と同じ動きにします。

既定で有効にしない理由も書かれています。disallowされたツールはbypassPermissionsでも使えないため、既定オンにすると既存ワークフローの挙動が変わるからです。これは提案であり、アクションに入力として存在するという意味ではありません。アクションの入力一覧(usageドキュメントのInputs表)にこの名前は載っておらず、workflowに書いても効く保証はありません。

実際にどれだけ送られるかはtool searchで変わる

ここで切り分けが必要です。Issueは「全ツールが毎回送られる」と書いていますが、Claude Code本体のドキュメントでは、MCPツールの扱いが設定で変わります。

  • 既定(ENABLE_TOOL_SEARCH未設定)では、MCPツールは遅延ロードされ、セッション開始時にはツール名とサーバー指示だけが載る
  • ENABLE_TOOL_SEARCH=falseなら、すべてのMCPツールが最初から読み込まれる
  • ANTHROPIC_BASE_URLが第一者ではないホストを指すと、既定では先読みに切り替わる(trueで遅延を維持)
  • Opus 4やSonnet 4より前のモデルでも、先読みになる

Issueの本文は、アクション実行時にtool searchが有効だったかどうかに触れていません。したがって、定義がフルで送られるのは「先読みになる構成」で最も問題になる、と読むのが安全です。遅延ロードの構成でも、名前の一覧とサーバー指示は載ります。仕組みの全体像はMCPのツール定義はなぜコンテキストを圧迫するのかにまとまっています。

自分のworkflowがどちらなのかは、initイベントのモデル名と環境変数で見当がつきます。プロキシやゲートウェイ経由、あるいはAzure上のFoundryを使っているなら、先読みになっている可能性を先に疑う価値があります。

アクションが自動で足すMCPサーバーにも注意する

列挙外のツール定義を送ってくるのは、自分で--mcp-configに書いたサーバーだけとは限りません。claude-code-actionのFAQには、アクションが次の2つのMCPサーバーを自動で設定すると書かれています。

  • GitHub MCPサーバー(GitHub APIの操作用)
  • ファイル操作サーバー(高度なファイル操作用)

同じFAQは、これらのサーバーのツールもclaude_argsの--allowedToolsで明示して初めて使える、とも説明しています。つまり許可の仕組みは自前のサーバーと同じで、--allowedToolsに挙げたツール以外の定義がモデルに届くかどうかも、Issue #1899と同じ論点になりえます。GitHub連携のツールを1〜2個しか使わないworkflowで入力トークンが多いときは、自分で渡したサーバーだけでなく、アクションが足したサーバーのツールもinitイベントで数えてみてください。

FAQにはこの2サーバーが持つツール名の一覧は載っていないため、--disallowedToolsに書く名前は、実行ログのinitに出たものから拾います。

設定側で絞る4つの手段

アクションのallowed_tools・disallowed_tools・mcp_configの各入力は非推奨で、claude_argsへの移行が案内されています。以下はすべてclaude_argsに書く前提です。

対処

MCPの定義量を減らす手段

  • 1. --disallowedToolsで名指しする

    裸のツール名は、該当ツールをClaudeのコンテキストから取り除きます。mcp__github__create_issueのようにツール単位でも、mcp__github__*のようにサーバー単位でも書けます。

  • 2. 使わないサーバーを渡さない

    --strict-mcp-configを付けると、--mcp-configで渡したサーバー以外の設定を無視します。リポジトリの.mcp.jsonが意図せず混ざる事故も防げます。アクションが自動で足すサーバーにこの指定が及ぶかは、ドキュメントに記載がありません。

  • 3. tool searchを維持する

    ENABLE_TOOL_SEARCHをfalseにしない、非標準のベースURL利用時はtrueを明示する、が基本です。

  • 4. alwaysLoadを使い分ける

    常用するサーバーだけ"alwaysLoad": trueにし、それ以外は遅延のままにします。"alwaysLoad": falseなら、サーバー作者が先読み指定したツールも遅延に戻せます(v2.1.287以降)。

--disallowedToolsのMCP向け書式は、権限ルールの書式に従います。ツール名の全形はmcp__<server>__<tool>で、mcp__*は全サーバーの全MCPツールにマッチします。注意点として、権限設定ファイルのmcp__ルールは括弧つきだとスキップされます。引数まで絞りたい拒否ルールは、--disallowedToolsで渡します。

workflowの書き方 — 許可と除外を対にする

1つのツールだけ使うGitHub MCPの例を、claude_argsで組むと次の形になります(ツール名は説明用の例です)。

- uses: anthropics/claude-code-action@v1
  with:
    anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
    prompt: "PRの差分を読み、結果をコメントする"
    claude_args: |
      --mcp-config ./mcp.json
      --strict-mcp-config
      --allowedTools "mcp__github__get_pull_request_diff"
      --disallowedTools "mcp__github__create_issue,mcp__github__merge_pull_request"

許可リストに載せたツールと、除外リストに載せたツールは別の役割です。除外リストへ書いたツールは、bypassPermissionsでも使えません。Issueが慎重に既定オフを提案した理由はここにあります。

--disallowedToolsは拒否が最優先なので、あとから「やはりこのツールも使いたい」となったとき、除外側から外し忘れると、許可リストに足しても動きません。変更のたびに両方を見る運用が安全です。

ツール一覧を取り出す方法

除外リストを作る入口は、Issueが挙げるsystem/initイベントです。アクションの実行ログ、または手元でSDK出力を取ったときのinitメッセージに、そのセッションで見えているツールとMCPサーバーの状態が載ります。

claude -p "ok" --output-format stream-json --verbose \
  --mcp-config ./mcp.json --strict-mcp-config \
  | jq -c 'select(.type=="system" and .subtype=="init")'

出力されたツール名のうち、使うものを許可リストへ、使わないものを除外リストへ振り分けます。--strict-mcp-configを付けた状態で、アクションが足すGitHub連携のツールがinitに残るかどうかも、ここで確認できます。サーバーの更新でツールが増えた場合に備え、除外リストはリポジトリで管理しておくと差分が追えます。

症状別の切り分け

切り分け

入力トークンが想定より多いとき

  1. QMCPサーバーを複数渡していますか?
    答えが次の確認へ

    --strict-mcp-configで必要なサーバーだけに絞ります。

    答えがはい
  2. Q`ENABLE_TOOL_SEARCH=false`、または非標準のベースURLを使っていますか?
    答えが次の確認へ

    MCPツールが先読みされています。trueへの変更か、--disallowedToolsによる除外を検討します。

    答えがはい
  3. Q大きなサーバーから数個だけ使っていますか?
    答えが定義以外(プロンプトや出力量)も疑います

    使うツールを許可リストに、残りを--disallowedToolsに書きます。

    答えがはい

定義の量を減らせた

次の実行のinitで、見えているツールが減ったことを確かめます。

CLIを直接起動する場合の許可・拒否の書き分けは、allowedTools/disallowedToolsの解説に、claude_argsの渡し方はGitHub Actionsのパラメータの解説にあります。ツール説明文の長さで定義量を抑える設定はMCPツール説明文の文字数上限で扱っています。

実装の行方を見るときの視点

Issue #1899にはenhancement・performance・mcp・feature-request・p3のラベルが付いています。優先度ラベルはp3で、短期間で入力が追加されるとは限りません。報告者は実装を用意していると書いており、PRが出た時点で入力名や挙動が変わる余地もあります。

当面の現実解は、除外リストを自分で管理するか、先読みを避ける構成に寄せるかの二択です。ツール数が少ない小さなサーバーしか使わないworkflowでは、影響は小さいままです。逆に、GitHub MCPのようにツールが多いサーバーを毎回の自動実行に載せているチームでは、initのツール数を一度確かめておく価値があります。

この記事を共有:XはてブLinkedIn