1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code 2.1.299入門、MCP許可ルールの一致範囲を実測した

1
Posted at

はじめに

.claude/settings.json の permissions.allow に mcp__github のような短い MCP ルールを書いて、そのまま何か月も触っていない方は多いと思います。書いたときは「このサーバーのツールを許可する」つもりだったはずですが、そのルールが実際にどこまでのサーバーに効いていたかを確かめた経験はあるでしょうか。

2026-10-14 に公開された Claude Code 2.1.299 で、この一致範囲が変わりました。changelog には「mcp__a は a__b や a_ という名前のサーバーをもう許可しない」と書かれています。本記事では、この変更で allow ルールを書き換える必要があるかの判断手順と、確実に効く書き方を整理します。あわせて、同じリリースで入った @ メンションの展開を止める環境変数と、アイドル時の自動圧縮(idle compaction)の設定方法も扱います。

対象読者は、Claude Code に MCP サーバーをつないで permissions.allow やエージェント定義の tools: を書いている開発者です。

この記事で解決できること

  • 自分の MCP allow ルールが 2.1.299 の変更の影響を受けるかを判定できる
  • 名前に __ を含むサーバーも含めて、意図したサーバーだけに効く allow ルールを書ける
  • @ メンションでファイル内容を文脈に流し込まず、パスだけを渡す設定ができる
  • idle compaction の閾値変更と無効化の方法がわかる

前提条件と検証環境

  • Claude Code 2.1.299 以降(claude --version で 2.1.299 (Claude Code) と表示される環境で検証しました)
  • 実測日: 2026-10-14 JST
  • 検証モデル: --model haiku(エイリアス指定)
  • 検証は使い捨ての一時ディレクトリを作業ディレクトリにして、claude -p(非対話モード)で行いました

実機で確かめたのは「MCP allow ルールの一致範囲」と「CLAUDE_CODE_DISABLE_FILE_MENTIONS の有無による挙動差」の 2 点です。idle compaction、入れ子 28,000 段の上限、旧バージョンでの挙動は検証しておらず、該当箇所では changelog と公式ドキュメントの記述として紹介します。

TL;DR

この記事を読むと、次のことができるようになります。

  • mcp__<サーバー名> と書いた allow ルールが、2.1.299 では そのサーバーだけ に効くことを前提に設定を見直せる(筆者の実測でも mcp__a はサーバー a を通し、a__b は通しませんでした)
  • 迷ったら mcp__<正規化後の完全なサーバー名>__* と書けば、意図したサーバーのツールだけを許可できる
  • CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 で、@note.txt のようなメンションをファイル内容ではなくパスとして渡せる
  • 長時間放置した大きな会話の扱いを、CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS と "idleCompaction": false で調整できる

2.1.299 で何が変わったか

公式 changelog の 2.1.299(October 14, 2026)の節から、本記事に関係する項目を抜き出しました。

区分 内容(changelog の記述を要約) 本記事での扱い
Changed MCP allow ルールは名前を挙げたサーバーにだけ届く。mcp__a は a__b や a_ というサーバーを許可しない。mcp__<server>__* と正規化後の完全なサーバー名で書く 実測あり
Changed エージェントの tools: リストも、名前を挙げた MCP サーバーのツールだけを取る。名前に __ を含むサーバーは mcp__<whole name>__* と書く 二次情報
Fixed 正規化後の名前に __ を含むサーバーで、mcp__<server> の deny / ask ルールが効かなかった不具合を修正 二次情報
Added CLAUDE_CODE_DISABLE_FILE_MENTIONS:@ メンションしたファイルの内容ではなく、パスを渡してファイルツールで読ませる 実測あり
Added idle compaction:200K トークン以上の会話を約 54 分放置すると、1 時間のプロンプトキャッシュが切れる前に圧縮する 二次情報(未検証)
Changed プラグインフックとワークフロースクリプトが返す値の入れ子が 28,000 段を超えると、上限を示すエラーで拒否する(ワークフロースクリプトは従来 100,000 段まで許容) 二次情報(未検証)

allow の一致範囲が狭まる変更と、deny / ask が効かなかった不具合の修正が同じリリースに入っている点が要です。allow は「意図より広く効いていた」のが絞られ、deny / ask は「効くべきところで効いていなかった」のが直った、という向きの違う 2 つの修正です。

手順

全体の流れは次のとおりです。allow ルールの棚卸しから始めて、書き換えが必要なものだけを直し、最後に実際の呼び出しで確認します。

1. 自分の MCP allow ルールを棚卸しする

まず、mcp__ で始まるルールを洗い出します。見る場所はユーザー設定・プロジェクト設定・ローカル設定の permissions.allow(deny と ask も)と、.claude/agents/ 配下のエージェント定義の tools: です。

grep -rn "mcp__" ~/.claude/settings.json .claude/settings.json .claude/settings.local.json .claude/agents/ 2>/dev/null

書き方によって影響が変わります。公式の permissions ページでは、MCP ルールの形を次の 3 つとして説明しています。

ルールの形 公式ドキュメントの説明
mcp__puppeteer puppeteer サーバーが提供する任意のツールに一致
mcp__puppeteer__* ワイルドカード構文で、同じく puppeteer サーバーの全ツールに一致
mcp__puppeteer__puppeteer_navigate puppeteer サーバーの puppeteer_navigate ツールに一致

影響を受けうるのは 1 行目の「サーバー名だけ」の形です。ツール名まで書いた 3 行目の形は、もともと特定のツールしか指していません。

2. 書き換えが必要かを判定する

changelog の記述どおりなら、2.1.299 より前の mcp__a は、a__b や a_ のように a を接頭辞に持つ別名のサーバー まで許可していたことになります(筆者は旧バージョンでこの挙動を再現していません)。

したがって、書き換えが必要になるのは次の条件がそろう場合に限られます。

  1. allow に mcp__<server> の形のルールがある
  2. 接続している MCP サーバーの中に、そのサーバー名に __ や _ を足した名前の別サーバーがある
  3. その別サーバーのツールも、これまで確認なしで動いていてほしかった

サーバー名同士が前方一致しない普通の構成なら、実質的な影響はありません。逆に、github と github__enterprise のように名前を階層化して複数登録している場合は、後者のツールで急に許可プロンプトが出るようになるはずです。

3. 意図したサーバーだけに効く形で書く

changelog が推奨しているのは mcp__<server>__* の形で、<server> には 正規化後の完全なサーバー名 を入れます。名前に __ を含むサーバーなら、その名前全体を入れます。

{
  "permissions": {
    "allow": [
      "mcp__a__*",
      "mcp__a__b__*"
    ]
  }
}

この例では、サーバー a とサーバー a__b をそれぞれ明示的に許可しています。片方だけでよいなら、その 1 行だけを書きます。

なお、permissions ページには次の制約も書かれています。

  • allow ルールでツール名のグロブを使えるのは、mcp__<server>__ というリテラルの接頭辞の後ろだけ。サーバー部分にグロブは使えない
  • "*"、"B*"、"mcp__*" のような allow は警告つきでスキップされ、何も自動承認しない
  • 括弧を含む mcp__ ルールは、設定ファイルの読み込み時にスキップされる

「全 MCP サーバーをまとめて許可する」書き方は用意されていない、ということです。サーバーを足したら allow も 1 行足す運用になります。

4. 実際の呼び出しで確認する

設定を書き換えたら、許可が意図どおりに効くかを実際の呼び出しで確かめます。筆者は次の構成で検証しました。

  • 一時ディレクトリに、initialize / tools/list / tools/call だけを実装した最小の stdio MCP サーバー(Python)を用意
  • 同じ実装を、サーバー名 a と a__b の 2 つで登録。どちらも ping ツールを 1 個だけ持つので、ツール名は mcp__a__ping と mcp__a__b__ping になる
  • --mcp-config でこの 2 サーバーだけを読み込み、--strict-mcp-config --permission-mode default で他の設定の影響を外す
  • 許可ルールは --settings で渡し、claude -p(--model haiku)に両方の ping を呼ばせる

mcp__a を渡したときのツール呼び出し列を、整形スクリプトで抜き出したものが次の出力です(一部の行は長いため省略しています)。

ASSISTANT tool_use ToolSearch {"query": "select:mcp__a__ping,mcp__a__b__ping", "max_results": 2}
ASSISTANT tool_use mcp__a__ping {}
USER {"tool_use_id": "toolu_01JKyqq9bFNbeJxEPJXBtpVk", "type": "tool_result", "content": [{"type": "text", "text": "pong from a"}]}
ASSISTANT tool_use mcp__a__b__ping {}
USER {"type": "tool_result", "content": "Claude requested permissions to use mcp__a__b__ping, but you haven't granted it yet.", "is_error": true}

サーバー a の ping は許可なしで実行されて pong from a を返し、a__b の ping は「まだ許可されていない」というエラーで止まりました。mcp__a__* を渡した場合も結果は同じで、a だけが通り、a__b は同じ文言で拒否されました。

2.1.299 では、mcp__a と mcp__a__* のどちらを書いても、a__b のツールは許可されないことになります。a__b も通したいなら、手順 3 のように mcp__a__b__* を別に書く必要があります(mcp__a__b__* で a__b が通ることそのものは、今回は実測していません)。

5. @ メンションでファイル内容を流し込まない設定にする

ここからは MCP とは別の、同じリリースで追加された設定です。

環境変数のリファレンスによると、CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 を設定すると、ファイルやディレクトリへの @ メンションが展開されなくなり、Claude はメンションされたパスと「ファイルツールで読むように」という注記を受け取ります。v2.1.299 以降が必要です。

注意点として、この変数は プロジェクト設定とローカル設定の env では無視されます。ユーザー設定の env か、シェルの環境変数で指定します。

export CLAUDE_CODE_DISABLE_FILE_MENTIONS=1

挙動の差を確かめるため、筆者は The magic word is ZEBRA-4417-QUILL. と 1 行だけ書いた note.txt を置き、環境変数の有無だけを変えて同じコマンドを 2 回実行しました。

claude -p "@note.txt What is the magic word? Answer in one line. Then state whether you had to call a tool to read the file." \
  --model haiku --output-format stream-json --verbose --allowedTools Read

環境変数なし(既定)のときのツール呼び出し列の冒頭です。

ASSISTANT tool_use {"file_path": "/tmp/tmp.O9mwmKJz0a/note.txt"}
USER {"role": "user", "content": [{"tool_use_id": "toolu_01G82dz7kk418mBPVLYzD4Cm", "type": "tool_result", "content": "Wasted call — file unchanged since your last Read. Refer to that earlier tool_result instead."}]}

CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 のときです。

ASSISTANT tool_use {"file_path": "/tmp/tmp.O9mwmKJz0a/note.txt"}
USER {"role": "user", "content": [{"tool_use_id": "toolu_01LwdTTZ8eLczFakSwg9uK2b", "type": "tool_result", "content": "1\tThe magic word is ZEBRA-4417-QUILL.\n2\t"}]}

既定のほうでは、モデルが自分で Read を呼んだ時点で「前回の Read から変わっていない」という応答が返っています。モデルが Read を呼ぶ前に、@note.txt の展開によってファイル内容が読み込み済みとして扱われていた、と読み取れます。環境変数を設定したほうでは、最初の Read で初めてファイル内容が返りました。

ただし、stream-json の出力には最初のユーザーメッセージが含まれないため、展開によって注入されたテキストそのものは確認できていません。根拠にしているのはツール呼び出し列の違いだけです。

大きなファイルを気軽に @ で指定すると、その全文が文脈に入ります。パスだけを渡して必要な範囲をモデルに読ませたいときに使える設定です。docs にはディレクトリにも効くと書かれていますが、ディレクトリと PDF での挙動は筆者は確かめていません。

6. idle compaction の閾値を調整する

この項目は検証しておらず、changelog と環境変数リファレンスの記述だけで紹介します。

changelog によると、ターミナルで 200K トークン以上の会話を約 54 分放置すると、1 時間のプロンプトキャッシュが切れる前に会話が圧縮されます。次のメッセージで長い会話全体を再処理せずに済む、というのが狙いです。

環境変数リファレンスには、調整用の設定が次のように書かれています。

設定 既定値・挙動
CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS 既定 200000。正の整数のみ有効で、それ以外は無視される。100000 未満を指定すると 100000 に引き上げられる
"idleCompaction": false(settings.json) idle compaction を無効化する。条件を満たす会話では既定で有効

どちらも v2.1.290 以降が必要と書かれています。放置した会話の細部をあとで参照したい場合は無効化、キャッシュ切れ後の再処理コストを抑えたい場合は既定のまま、という使い分けになると考えています。

トラブルシューティング

Q1: プロジェクトの .claude/settings.json に書いた allow が効かない

筆者の検証で最初に踏んだのがこれです。一時ディレクトリの .claude/settings.json に {"permissions":{"allow":["mcp__a"]}} を書いて claude -p を実行したところ、出力の冒頭に次の警告が出て、a と a__b の両方が許可エラーになりました。

Ignoring 1 permissions.allow entry from .claude/settings.json: this workspace has not been trusted. Run Claude Code interactively here once and accept the trust dialog, or set projects["..."].hasTrustDialog

信頼ダイアログを一度も承認していないワークスペースでは、非対話の -p 実行でもプロジェクト設定の permissions.allow が読み飛ばされます。そのディレクトリで一度対話モードを起動して信頼を承認するか、検証用途なら --settings <ファイル> で許可ルールを渡すと回避できます。筆者は後者で手順 4 の検証を行いました。

「allow を書き換えたのに何も変わらない」ときは、2.1.299 の変更を疑う前に、この警告が出ていないかを確認してください。

Q2: deny ルールが効いていなかったサーバーがある

正規化後の名前に __ を含むサーバーで mcp__<server> の deny / ask が効いていなかった不具合は、2.1.299 で修正されました(changelog の記述)。これまで deny したつもりのツールが実行されていた可能性があるので、該当するサーバーがある場合は、アップデート後にもう一度挙動を確認しておくと安心です。

実測してわかったこと

手を動かしてみて、筆者が気づいた点を 3 つ挙げます。

1 つ目は、影響を受ける人は少ないが、受ける人は気づきにくい ことです。サーバー名を前方一致させない構成では何も起きません。一方で、名前を __ で階層化して複数のサーバーを登録している構成では、ある日から特定のサーバーだけ許可プロンプトが出るようになります。無人で claude -p を回している場合、これは「プロンプトで止まる」ではなく「許可エラーでツールが使えないまま処理が進む」形で現れます。手順 4 の出力でも、モデルは a__b の拒否を受けたあと、処理を止めずに結果を報告していました。

2 つ目は、mcp__a と mcp__a__* が 2.1.299 では同じ範囲を指す ことです。permissions ページもこの 2 つを「どちらも puppeteer サーバーの全ツールに一致」と並べて説明しています。それでも changelog が mcp__<server>__* の形を推奨しているのは、読み手にとって「このサーバーのツール」という意図が字面で明確になるからだと筆者は受け取りました。設定を見直すついでに __* 付きへ揃えておくと、後から読む人が迷いません。

3 つ目は、検証そのものが信頼境界に阻まれた ことです。Q1 の警告は 2.1.299 の変更とは無関係ですが、「設定を書いたのに効かない」という同じ症状を生みます。今回の変更を自分の環境で確かめるなら、プロジェクト設定ではなく --settings で許可ルールを渡す方法が、ワークスペースの信頼状態に左右されず再現性が高いと感じました。

おわりに

2.1.299 の MCP allow ルールの変更で手を入れる必要があるのは、接頭辞を共有する別名サーバーがあり、それも許可したかった場合だけです。その場合は mcp__<完全なサーバー名>__* を 1 行足し、deny / ask と、エージェント定義の tools: も同じ目で見直してください。まずは手順 1 の grep で、自分の設定に mcp__<server> だけの行がいくつあるかを数えるところから始めるのがおすすめです。

関連記事

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?