JavaScriptをがんばるブログ

React,OSS,ソフトウェア開発が中心のブログです👨‍💻

Claude Codeの初期コンテキスト肥大化を削減する — Skills、Plugins、MCPの活用術

/context 1発で分かる問題

新しいClaude Codeセッションを開いて「hi」と入力したあと /context を実行してみてください。ガッツリ使い込んでる構成(MCPサーバー22個以上、スキル150個以上、プラグイン半ダース)だと、ライブウィンドウはこんな具合になります:

Context Usage — Opus 4.7
16.8k / 200k tokens (8%)

Estimated usage by category
- System prompt:        2.8k   (1.4%)
- System tools:         2k     (1.0%)
- Custom agents:        1.4k   (0.7%)
- Memory files:         2.2k   (1.1%)
- Skills:               8.3k   (4.2%)   ← 操作可能な最大の項目
- Messages:             13 tokens
- Free space:           150.2k (75.1%)
- Autocompact buffer:   33k    (16.5%)  ← 予約領域、ハードコード

MCP tools · /mcp (loaded on-demand)      ← 上記には含まれない

入力する前に常駐しているのは実質約16.8Kだけで、そのほとんどは動かしようがありません(システムプロンプト、組み込みの非遅延ツール、回収不能な33KのAutocompact予約)。22個以上のMCPサーバーと組み込みの遅延ツールは、このライブの数値にはまったく乗っていません。Tool Searchはツールの名前だけをリストアップして、スキーマは必要な時にだけフェッチします。だから別途「loaded on-demand」のバケツに収まっていて、ウィンドウの中には居ないわけです。

実際に削れる中で一番大きいのはSkillsです。


Resident vs. Deferred — 実際にロードされるもの

起動時のペイロードは、固定のシステムプロンプトに加えて動的に発見される複数のリソースの合計です。旧版の説明が落としていたポイント: Tool Searchはそのペイロードを2つのバケツに分けます。公式MCPドキュメントもこうはっきり書いています — "Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront."

  • Resident(常駐) — セッションが開いた瞬間からライブウィンドウに計上される。
  • Deferred(遅延) — 発見されて名前はリストされるが、完全な定義はオンデマンドでフェッチ。ライブウィンドウには計上されない
flowchart TB
    Start([Claude Codeセッション開始]) --> R[Resident<br/>ライブウィンドウ内]
    Start --> D[Deferred<br/>Tool Searchがオンデマンドでフェッチ]

    R --> SP[システムプロンプト 約3K · 固定]
    R --> BT[組み込みの非遅延ツール 約2K · 固定<br/>Read/Edit/Bash/Glob/Grep/Skill/ToolSearch]
    R --> SKL[Skillsリスト<br/>SKILL.mdごとのname + description]
    R --> MEM[メモリ · CLAUDE.md + MEMORY.md]
    R --> AGT[カスタムエージェント · ~/.claude/agents/]
    R --> MCPI[MCPサーバーinstructions<br/>遅延されない — issue #48680]
    R --> AC[Autocompact予約 33K · ハードコード]

    D --> MCPT[MCPツール定義<br/>全サーバー + claude.aiコネクタ]
    D --> BTD[組み込み遅延ツール<br/>WebFetch/WebSearch/Cron*/Notebook*]

    classDef control fill:#ffe0e0,stroke:#cc3333,stroke-width:2px,color:#000
    classDef free fill:#d4f8d4,stroke:#2e7d32,color:#000
    class SKL,MCPI control
    class MCPT,BTD free

赤いノードが手をつける価値のある常駐コストです: SkillsリストMCPサーバーinstructions。緑のノード — MCPツール定義(巨大なclaude.aiコネクタカタログも含む)と組み込みの遅延ツール — はTool Searchのおかげで帳簿から落ちています。それ以外は固定(システムプロンプト、組み込みツール、autocompactバッファ)か影響が小さい(メモリ、エージェント)ものです。

公式ドキュメントによる各ローダーの説明場所

ローダー 挙動 ソース
Tool Search ツール定義(MCP + 組み込み)を遅延させ、オンデマンドでフェッチ。結果ライブウィンドウから消える — 常駐の合計値が小さい理由 Claude Code MCPドキュメント, Tool Search SDK, APIリファレンス
MCPツール定義 他のツールと同じくTool Searchで遅延: 名前はリスト、スキーマはオンデマンドでフェッチ Claude Code MCPドキュメント
MCPサーバーinstructions 接続された各サーバーはinstructions文字列を寄与する — 遅延されず常駐、サーバーあたり2KB上限。次セクションでメカニズムと計測方法を解きほぐす。 Claude Code MCPドキュメント, Issue #48680
claude.aiコネクタ Pro/Maxサインインでアカウントコネクタ(Gmail、Linear、Notion…)が使えるようになる。ツール定義は他と同じく遅延されるので、常駐するのは2KB以下のinstructionsだけ — CLIでは ENABLE_CLAUDEAI_MCP_SERVERS=false で無効化 Claude Code MCPドキュメント, Issue #50062
Skills SKILL.md のフロントマター(name + description)が連結されてリストになり、システムプロンプトに常駐で含まれる — 操作可能な最大の1行 Claude Code Skills, agentskills.io spec
Skill発見パス 4箇所をスキャン: ~/.<client>/skills/~/.agents/skills/、およびプロジェクトレベル相当 Agent Skills client implementation
プラグイン マーケットプレースプラグインはhooks/agents/skills/commandsを plugins/cache/ に配置する。プラグインのスキルは skillOverrides で制御不可 Pluginドキュメント, Skills overrideノート
Autocompactバッファ ウィンドウの先頭に33K予約。環境変数オーバーライドはトリガー閾値をずらすだけで、予約サイズ自体は変わらない Issue #12053, Issue #31806

初期の地ならしをしてくれた2つのコミュニティ記事: Scott Spence氏のOptimising MCP Server Context Usage と atcyrus氏のMCP Tool Search Context Pollution Guide。ただし時代背景に注意してください。彼らの派手なbefore/after数字は、まだTool Searchが遅延してくれない頃のものです。彼らが解説したメカニズムは今でも重要 — ただし今は60Kのツールスキーマの壁ではなく、残りのinstructionsコストに対して効いてきます。そしてその残りのコストは見た目以上に捉えどころがない — /context 自体にその行がないのです。


なぜMCP instructionsは /context に出てこないのか

MCPサーバーを20個以上繋いだセッションで /context を実行してinstructionsコストを探しても、行は見つかりません。目の錯覚ではなく — /context 自体にそのカテゴリがないのです。固定の8バケツのタクソノミ(System promptSystem toolsMCP toolsMCP tools (deferred)Custom agentsMemory filesSkillsMessages)から表示を組み立てて、それぞれを名前付きの行として出力する作りになっています。「MCP instructions」行は無いし、これまでもありませんでした。

ではどこにあるのかというと、セッション開始時にClaude Codeは、接続された各サーバーのinstructions文字列を1つの # MCP Server Instructions ブロックにまとめて発行します — トランスクリプトでは <system-reminder> としてインラインに見えるやつで、内部の mcp_instructions_delta チャネル経由で流れてきます(チャネル名はv2.1.153のバンドル内部で確認済み)。このブロックは静的なシステムプロンプトの一部ではなくメッセージ添付として届けられ、isMeta: true フラグが立てられています。これを拾うべき2つのカウンタがどちらもスキップします:

  • 「System prompt」バケツは静的なシステムプロンプトのセクションだけをカウント — メッセージストリーム添付は素通り。
  • 「Messages」カウンタは isMeta ブロックを明示的にスキップ。

これが計測上の死角です。最初の実ターンが走る前は、/context の合計値は可視バケツの合計です。どちらのバケツもMCP instructionsをカウントしないので、合計はライブコンテキストをちょうどその分過小評価します。最初の実ターン後はヘッドラインがAPIの実トークン使用量(input + cache reads)に切り替わり、その分を黙って取り込みます — それでも明細行はやっぱり無し。

なので自分で測ることになります:

知りたいもの やり方
生のinstructionsテキスト セッションJSONLを ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl で開き、本文が # MCP Server Instructions で始まる添付を探す
実際の常駐コスト(差分) サーバーを繋いだ状態で実ターンを1回流して /context、次にサーバーを切って(コネクタなら ENABLE_CLAUDEAI_MCP_SERVERS=false、それ以外は .mcp.json から削除)もう1回 /context。ヘッドラインの差分がコスト
1ペイロードのコスト JSONLからテキストをコピーして /v1/messages/count_tokenssystem ブロックとして貼り付ける — Claude Codeが内部で /context の明細行を出すのと同じエンドポイント
上限 各サーバーのinstructions文字列は2048 UTF-16文字で切り詰められる。常駐合計は ≤ N × 2KB

両方とも — 8バケツのタクソノミと isMeta スキップ — v2.1.153のバンドルで検証できます: strings ~/.local/share/claude/versions/2.1.153 | grep -E 'mcp_instructions_delta|getMcpInstructionsDeltaAttachment' を叩けば、チャネル名と注入を行うgetterが返ってきます。


3つのレバー

flowchart LR
    A[常駐コンテキスト] --> L1[Lever 1<br/>Skills]
    A --> L2[Lever 2<br/>プラグイン → ローカルスキル]
    A --> L3[Lever 3<br/>MCP instructions]

    L1 --> R1[skillOverrides name-only<br/>+ maxSkillDescriptionChars 0]
    L2 --> R2[使う資産を ~/.claude/ に昇格<br/>プラグインを無効化]
    L3 --> R3[ENABLE_CLAUDEAI_MCP_SERVERS false<br/>+ 冗長で使わないサーバーを無効化]

    R1 --> S1[最大の効果<br/>スキル数に応じてスケール]
    R2 --> S2[プラグインごとに1〜3K<br/>+ skillOverridesの届く範囲を回復]
    R3 --> S3[常駐instructionsを削る<br/>コネクタの定義は既に遅延済み]

各レバーは常駐の発見パスを狙います — 最初のプロンプトが処理される前にローダーがライブウィンドウに抱え込んでいるもの。効果が大きい順に並んでいます: Skills が現状一番動かせる行なので1番目、MCP は Tool Search が既にほとんど仕事をやってくれているので最後。


Lever 1 · Skills — skillOverrides を正しく使う

Skillsバケットに何が入っているか

起動時に発見される各 SKILL.md は、name(数トークン)と descriptionmaxSkillDescriptionChars まで、デフォルト1536)をシステムプロンプトのスキルリストに寄与します。これは常駐 — 遅延しません。150個のスキル全部フルdescriptionだと15Kトークンを軽く超え、上の /context の8.3Kはすでに最適化後の数字です。ここから手をつけます。

4つの状態 (2026年5月修正)

skillOverridesスキル単位のオブジェクトで、ディレクトリ名がキーになります。以前自分のリサーチノートで公開していた推奨設定で文字列形式 ("skillOverrides": "user-invocable-only") を使っていましたが、これはJSONスキーマ検証で弾かれます。オブジェクト形式しかサポートされていません。

以下のstate図は、4つの正当な値と、コストを段階的に下げていく遷移をまとめたものです: デフォルトの on 状態、2つのコスト削減状態(name-only は自動呼び出しを維持、user-invocable-only は明示的スラッシュ呼び出しを要求)、そして完全に隠す off 状態。

stateDiagram-v2
    [*] --> on
    on: on (default), 名前と説明をロード、自動・スラッシュ呼び出し可能

    state "Cost reduced" as Reduced {
        nameonly: name-only, 名前のみ、名前から自動呼び出し可、スラッシュ呼び出し可
        userinv: user-invocable-only, 名前のみ、自動呼び出し不可、スラッシュ呼び出し可
    }

    state "Hidden" as Hid {
        off: off, どこにもロードされない、呼び出し不可
    }

    on --> nameonly: descriptionロードを削減
    on --> userinv: スラッシュ名のみに固定
    on --> off: 完全に隠す
    nameonly --> userinv: 自動呼び出しを停止
    userinv --> off: 完全に隠す

2つのコスト削減値の決定的な違いは自動呼び出しです。user-invocable-only は名前通りのことしかやりません — スキルは /skill-name 経由でしか辿りつけません。自動呼び出しはオフなので、タスクが自然にそのスキルを呼ぶような場合でもモデルは自発的に手を伸ばしません。name-only はリストに名前を残しつつ、自動呼び出しも生かしておきます。だから、タスクが必要とすればモデルが自分でロードして実行できます。

その差が、自分が全部 name-only を選んだ理由です。自分のフローの多くは /goal "do X" 形式の自然言語指示で、モデル(あるいは産み出されたサブエージェント)が「あ、これは qa-team スキルの出番だな」と気づいて、スラッシュコマンドを打たなくてもロードしてくれる必要があります。user-invocable-only だとそれを殺してしまうので、スキル名を全部覚えて打つはめになります。user-invocable-only は明示呼び出しでゲートしたい稀なスキル用に取っておくつもりですが、実際のところ今はそのバケツは空です。

セットアップ

# ローカルで発見できる全スキルにname-onlyを適用
SKILLS=$(find ~/.claude/skills ~/.agents/skills -maxdepth 2 -name "SKILL.md" 2>/dev/null \
  | sed 's|.*/skills/||; s|/SKILL.md$||' | sort -u)

OVERRIDES=$(echo "$SKILLS" | jq -R . | jq -s 'map({(.): "name-only"}) | add')

jq --argjson o "$OVERRIDES" '
  .skillOverrides = $o |
  .maxSkillDescriptionChars = 0 |
  .skillListingBudgetFraction = 0.005
' ~/.claude/settings.json > /tmp/s.json && mv /tmp/s.json ~/.claude/settings.json

3つの設定、3つの目的:

設定 デフォルト 自分の値 理由
skillOverrides {} { <every-skill>: "name-only" } descriptionを落とし、自動/サブエージェント呼び出しは残す
maxSkillDescriptionChars 1536 0 descriptionを完全にドロップ — 名前だけ残る。オーバーライドし忘れたスキル用のハードな安全網
skillListingBudgetFraction 0.01 0.005 スキルリストがウィンドウのどれだけを消費できるかの上限

編集後はClaude Codeを完全に再起動してください — スキルリストは現在のセッションでキャッシュされます。/contextSkills 行を確認しましょう。

注意点

  • プラグインのスキルは skillOverrides の影響を受けない。 これがLever 2の存在理由です。
  • ビルドバージョンが大事。 skillOverrides はv2.1.129まで壊れていました — 旧ビルドでは常に on を返すスタブでした (Issue #50631)。claude --version で確認を。(skillOverrides組み込みスキルにも届くかは未確定です。これらを無効化したい機能リクエスト Issue #26838 はduplicateでクローズされました)。
  • フロントマター側の disable-model-invocation: trueuser-invocable: false も同じことをやってくれますが、一括適用なら skillOverrides の方が早いです。

Lever 2 · プラグイン → ローカルスキル

マーケットプレースプラグインは便利ですが、hooks/agents/skills/commandsをまとめてバンドルで配信します。プラグインに含まれるスキルは ~/.claude/plugins/cache/.../skills/ に置かれ — 公式ドキュメント通り — skillOverrides で黙らせることができません。なので、自動呼び出ししないお喋りなスキル5個をプラグインが含んでいる場合、何をしようがその5個のdescriptionが毎セッション常駐で読み込まれます。

回避策は、実際に使うパーツをユーザー空間に昇格させてから、プラグインを無効化することです。

flowchart LR
    PC[plugins/cache/foo/]:::plug --> S1[skills/*]
    PC --> A1[agents/*]
    PC --> H1[hooks/*]
    PC --> C1[commands/*]

    S1 -- cp -r --> US[~/.claude/skills/foo-*]:::user
    A1 -- cp -r --> UA[~/.claude/agents/foo-*]:::user
    H1 -.使わなければskip.-> X((✕))
    C1 -.使わなければskip.-> X

    PD[settings.json<br/>enabledPlugins.foo = false]:::cfg --> Disable[プラグイン無効化<br/>キャッシュロード停止]

    classDef plug fill:#fff3cd,stroke:#c79100,color:#000
    classDef user fill:#d4f8d4,stroke:#2e7d32,color:#000
    classDef cfg fill:#e3f2fd,stroke:#1565c0,color:#000

手順

  1. プラグインが何を含んでいるか確かめる。 各プラグインのキャッシュディレクトリは、ソースの skills/agents/hooks/commands/ をそのままミラーしたものです。
   ls ~/.claude/plugins/cache/<plugin>@<marketplace>/
  1. 使うものだけユーザー空間にコピーする。
   cp -r ~/.claude/plugins/cache/codex@openai-codex/skills/codex-cli-runtime \
         ~/.claude/skills/

   cp -r ~/.claude/plugins/cache/coderabbit@claude-plugins-official/agents/code-reviewer \
         ~/.claude/agents/
  1. プラグインを無効化する。 ~/.claude/settings.jsonenabledPlugins からそのキーを削除するか、claude plugin uninstall <plugin>@<marketplace> を実行します。

  2. ローカル化したスキルを skillOverrides に追加。 もうユーザースキルなので、Lever 1が効きます。状況に応じて name-only または user-invocable-only を。

  3. プラグインが更新されたら、再コピーが必要です。 トレードオフは承知の上です: 自動更新を捨てて、skillOverrides の制御権と低いsteady-stateコンテキストコストを取る、ということ。たまにしか使わないプラグインなら、このトレードは引き合います。

最近ローカル化したもの

プラグイン 残したもの 無効化 回収トークン
codex@openai-codex codex-rescue エージェント、codex-cli-runtime / codex-result-handling / gpt-5-4-prompting スキル yes 約1.4K (加えて skillOverrides のリーチ回復)
coderabbit@claude-plugins-official code-reviewer エージェント、autofix / code-review スキル yes 約1K
figma@claude-plugins-official グローバルでは何も — zumen-fe プロジェクト内でのみ .claude/settings.local.json で有効化 yes (ユーザーレベル) 約1.4K
claude-md-management@claude-plugins-official 何も — 使わなかった yes

figmaのケースには触れておきたい4つ目のパターンがあります: プラグインを1プロジェクトにスコープする。ユーザーレベルで無効化し、単一プロジェクトの .claude/settings.local.json で再有効化:

{ "enabledPlugins": { "figma@claude-plugins-official": true } }

そのプロジェクトに cd した時だけプロジェクトがロードされます。


Lever 3 · MCP — Tool Searchが遅延できないものを削る

ここは旧版が真逆のことを書いていたレバーです。現行のClaude Codeでは、MCPツール定義はTool Searchが遅延してくれます — ライブウィンドウには乗りません。公式ドキュメントもはっきり書いています: "Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront." 旧版の「claude.aiコネクタをブロックして約100K節約」というアドバイスは、本物の遅延が入る前の時代の話でした (Issue #50062、completedでクローズ済み)。今はコネクタのツール定義も他と同じく遅延します。本当に常駐するコストとして残るのは2つ:

  1. MCPサーバーinstructions。 接続された各サーバーは、いつ自分に手を伸ばすべきかをモデルに伝えるinstructions文字列を載せられる — 計測の死角セクションで定量化した残余コスト。遅延されず (Issue #48680)、サーバーあたり2KBの上限 (Claude Code MCPドキュメント)。冗長なサーバー(Serenaの操作ガイド、DeepWikiのツールカタログ)は毎セッションその予算を使い切ります。
  2. そもそも遅延しない設定。 Tool SearchはVertex AIではデフォルトでオフ、ANTHROPIC_BASE_URL がファーストパーティ以外のプロキシを指す時もオフ。ENABLE_TOOL_SEARCH=false だと全ての定義がウィンドウに戻ります。(HTTP/Streamableツールが全く遅延しないという以前のレポート Issue #40314not-plannedでクローズされ、現行ドキュメントはHTTPツールも他と同じく遅延すると確認しています。)

なのでこのレバーの守備範囲は今や狭い: instructionsが要らないサーバーを無効にして、そして — サブスクで認証するなら — claude.aiコネクタをCLIから外す。

claude.aiコネクタを無効化する (メインのレバー)

コネクタはサブスクリプション経由で届くもので、claude mcp add 経由ではありません。Web上の claude.ai/customize/connectors で追加して(Gmail、Linear、Notion、Google Drive、Google Calendar、Exa、Figma…; TeamとEnterpriseプランでは admin だけが追加可能)、同じClaude.aiアカウントでClaude Codeにサインインすれば自動的に使えるようになります — マシンごとに claude mcp add する必要はありません。 MCP config precedence では最後に位置し(local、project、user、plugin servers の後)、自分のサーバーとはエンドポイントでマッチされ、/mcp ではClaude.ai由来としてフラグが立ちます。アクティブな認証がClaude.aiサブスクリプションの時だけフェッチされます — ANTHROPIC_API_KEYANTHROPIC_AUTH_TOKEN、Bedrock、Vertexの下では絶対にフェッチされません。

Tool Searchがあればコネクタのツール定義は遅延しますが、instructionsと名前リストは常駐で同乗してきます。v2.1.63 からは、ドキュメント化された純正のスイッチがあり、CLIから完全に外せます — false にセット:

ENABLE_CLAUDEAI_MCP_SERVERS=false claude

恒久化するには settings.jsonenv ブロックに入れましょう(下記参照)。これが正規のopt-outリクエスト #50062 が追っていたスイッチで、env varがshipした時点でcompletedとしてクローズされました。並行する別のトグルリクエスト #44112#47881#56773 はすべてnot-plannedでクローズ。#20412 は「自動注入が非力なマシンをOOMさせる」という広めの懸念でまだOPENです。コネクタはclaude.aiとClaude Desktopでは引き続き使えます — 無視するのはClaude Codeだけです。

1枚の図で対比 — デフォルト挙動はコネクタinstructionsを常駐させ、ENABLE_CLAUDEAI_MCP_SERVERS=false はコネクタを完全にスキップ:

%%{init: {'themeVariables': {'signalColor': '#1a1a1a', 'signalTextColor': '#1a1a1a', 'noteTextColor': '#1a1a1a', 'noteBkgColor': '#f8f8f8', 'noteBorderColor': '#666'}}}%%
sequenceDiagram
    autonumber
    participant CLI as claude (起動)
    participant Auth as Claude.ai認証
    participant Local as ~/.claude.json
    participant CTX as ライブコンテキスト

    rect rgb(255, 230, 230)
    Note over CLI,CTX: デフォルト + Tool Search
    CLI->>Auth: サブスクトークン
    Auth-->>CLI: アカウントコネクタ一覧
    CLI->>Local: mcpServersを読み込み
    CLI->>CTX: ツール定義は遅延 · instructionsは保持
    Note over CTX: スキーマはオンデマンド、<br/>コネクタinstructionsは常駐
    end

    rect rgb(230, 255, 230)
    Note over CLI,CTX: ENABLE_CLAUDEAI_MCP_SERVERS=false (v2.1.63)
    CLI->>Local: 自分のサーバーのみ読み込み
    CLI->>CTX: コネクタは完全にスキップ
    Note over CTX: コネクタツール無し、<br/>コネクタinstructions無し
    end

なぜinstructionsレベルのトグルが無いのか

上のコネクタスイッチがinstructionsを落とせるのは、サーバーの接続自体を切る副作用としてです — Claude Codeが接続を開かないので initialize レスポンスが来ず、何も注入されない。サーバーのツールは保ちつつinstructionsだけを落とす、という純正のスイッチは存在しません。バンドル (v2.1.153) でもそのギャップが確認できます: 常駐ブロックを組み立てる関数は無条件です。接続されたサーバーのMCP initialize 結果に空でない instructions フィールドがあれば、その文字列はそのまま追加されます。env var、setting、flagはどれも参照されません。

この欠落は、姉妹機能にはトグルが付いているので目立ちます。Skillsにはリストを省略するためのターン単位 suppressNextSkillListing フラグがあり、git関連ガイダンスにはブロック全体をスキップする CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS env varがあります。MCPサーバーinstructionsには同等品が来たことが無く、#48680 は結果のコストに対してオープンですが、フレーミングは抑制トグルではなく遅延を中心にしたものです。

冗長なサーバーのinstructionsには耐えられないがツールは使いたい、という場合、唯一の手段はサーバー側です: サーバーの initialize レスポンスを編集して instructions を省略する。自分の所有でないサーバーなら、レスポンスを途中で書き換える小さなMCPプロキシが唯一の機械的な選択肢です — 文書化も非サポートもされていないので、両端を自分で制御している時にだけ載せる前提で扱いましょう。

何がinstructionsコストをカットしない

設定 / 挙動 なぜ効かないか
ENABLE_TOOL_SEARCH=true (デフォルト) ツールスキーマだけを遅延 — instructionsチャネルは切り離されていて影響なし
サーバーあたり2KB上限 ダメージは上限内に収まる; ゼロにはならない。N サーバーで最大 N × 2KB 常駐
サーバーのツールに permissions.deny ツール呼び出しをブロック; instructionsは接続時に既に注入済み
--mcp-config <file> 単体 加算的 — デフォルトソースが既にロードしたものに追加されるだけ。スコープするには --strict-mcp-config とペア
Transport / alwaysLoad / プラグイン同梱サーバー これらのどれも initialize instructionsが注入されるかどうかには関係しない

Tool Searchはオンのままで

このレバー全体は、Tool Searchが遅延をやってくれている前提です — そしてデフォルトでオン。ただ、ENABLE_TOOL_SEARCHfalse にされたり、auto モードが閾値を超えても起動に失敗したり (Issue #18370) すると、全てのMCPツール定義がライブウィンドウに戻ってきて、旧来の60Kの壁を眺めることになります。true を明示的にセットして(下記の設定ブロック参照)、/context でMCPサーバーが「loaded on-demand」の下に表示されていて、トークン行ではないことを確認しましょう。


現在の settings.json (削減後)

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "env": {
    "ENABLE_TOOL_SEARCH": "true",
    "ENABLE_CLAUDEAI_MCP_SERVERS": "false",
    "CLAUDE_CODE_ENABLE_TELEMETRY": "0",
    "MAX_MCP_OUTPUT_TOKENS": "200000",
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
    "CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
    "CLAUDE_CODE_EFFORT_LEVEL": "max"
  },
  "skillOverrides": {
    "<every-skill-name>": "name-only"
  },
  "maxSkillDescriptionChars": 0,
  "skillListingBudgetFraction": 0.005,
  "enabledPlugins": {
    "figma@claude-plugins-official": false,
    "codex@openai-codex": false,
    "coderabbit@claude-plugins-official": false,
    "claude-md-management@claude-plugins-official": false
  }
}

このセットアップを支えるのは2つのenv varです。ENABLE_TOOL_SEARCH: "true" が肝心 — MCPと組み込みツール定義をライブウィンドウから遅延させてくれます。ENABLE_CLAUDEAI_MCP_SERVERS: "false" はサブスクコネクタをCLIから外します。CLIを1つの明示的なサーバーファイルにピンしたい時だけ、--strict-mcp-config フラグを追加してください。


検証

flowchart TD
    Start([settings.json を編集]) --> Restart[Claude Codeを<br/>完全に再起動]
    Restart --> Ctx{/context}
    Ctx -->|Skills 行 減った?| Y1[Lever 1 効いてる]
    Ctx -->|Plugins 行 減った?| Y2[Lever 2 効いてる]
    Ctx -->|MCP は loaded on-demand 表示?| Y3[Lever 3 効いてる]
    Y1 --> Done([完了])
    Y2 --> Done
    Y3 --> Done

    Ctx -->|Skills 変わらず| Debug1[claude --version 確認<br/>≥ v2.1.129、再起動]
    Ctx -->|MCP がトークン行| Debug2[Tool Search オフ —<br/>ENABLE_TOOL_SEARCH=true をセット]
    Debug1 --> Done
    Debug2 --> Done

具体的には:

# 1. コンテキストの内訳を確認 — MCPは「loaded on-demand」であってトークン行ではないはず
/context

# 2. Skills行がまだ大きい場合
claude --version   # v2.1.129以上である必要あり
jq '.skillOverrides | length' ~/.claude/settings.json   # スキル数と一致するはず

# 3. claude.aiコネクタが消え、自分のサーバーだけが残っているか確認
/mcp

# 4. プラグインが無効か確認
jq '.enabledPlugins' ~/.claude/settings.json

注視すべき既知バグ

Issue ステータス なぜ重要か
#48680 OPEN MCP サーバーinstructions はTool Searchで遅延されない — 計測の死角セクションで定量化し、Lever 3がターゲットにする残余コスト。純正の抑制トグルなし。Lever 3のなぜinstructionsレベルのトグルが無いのかを参照
#40314 CLOSED · not-planned HTTP/Streamable MCPツールが遅延しなかった(120K前掲)と報告; not-plannedでクローズされ、現行ドキュメントはHTTPツールもTool Searchで遅延と確認 — 自分のトランスポートで /mcp/context を見て確認
#54716 OPEN 組み込み遅延ツールにはまだopt-outなし — 遅延されている間は無害だが追っておく価値はあり
#41809 CLOSED · not-planned 無効化したMCPサーバーが以前は遅延リストに残っていた — 無効化後に確認
#12053, #31806 CLOSED · not-planned / duplicate Autocompactバッファ (約33K) はハードコード; CLAUDE_AUTOCOMPACT_PCT_OVERRIDE はトリガー閾値をずらすが予約は解放できず、閾値をデフォルト以上には上げられない
#50631 v2.1.129で修正 skillOverrides は旧ビルドではno-op(常に on を返すスタブ)だった — 計測前にアップグレードしたか確認を
#50062 COMPLETED · #44112 / #47881 / #56773 not-planned · #20412 OPEN 混在 クライアント単位のコネクタトグルが ENABLE_CLAUDEAI_MCP_SERVERS=false (v2.1.63) としてship: 正規リクエスト #50062 はcompletedでクローズ、重複トグルリクエストはnot-plannedでクローズ、#20412 は非力マシンOOM観点でOPENのまま
#18370 OPEN Tool Search auto モードが閾値を超えても起動失敗することがある — ENABLE_TOOL_SEARCH=true を明示的にセットしないと遅延が黙って止まる

より深いところを言えば: 遅延は土台になっているアーキテクチャで、ちゃんと動いています。残っているのはほとんど周りのリークパス — 遅延しないinstructions、たまに起動に失敗するモード。修正は「遅延を切る」ことではなく、「遅延がリークする余地を残さない」こと、そして遅延が設計上カバーしようとしなかった少数のものを削っていくことです。それが3つのレバーが達成することそのものです。


採用しなかったもの

検討して却下したオプションをいくつか:

  • ANTHROPIC_API_KEY 認証に切り替える。 APIキー(およびBedrock/Vertex)セッションは、claude.aiコネクタをそもそも取りに行きません。とはいえそのためだけに認証を変える必要はありません: ENABLE_CLAUDEAI_MCP_SERVERS=false ならMaxプランの請求はそのままにコネクタだけ外せます。
  • ~/.claude.jsoncachedGrowthBookFeatures.tengu_claudeai_mcp_connectors を編集する。 サーバーが次のハンドシェイクで上書きします — #44112 参照。ドキュメント化されたenv varを使いましょう。
  • 全スキルを off にする。 クリーンな /context 出力には魅力的ですが、自動発見を全部失います。スキル名を全部覚えて打つ羽目になります。name-only の方が無難なデフォルトです。
  • Autocompactを無効化する。 構造的にハードコードされています。CLAUDE_AUTOCOMPACT_PCT_OVERRIDE がトリガーを遅らせるだけで、予約は解放しません。

参考文献

公式ドキュメント

この記事の元ネタになったコミュニティ記事

言及したツール

  • agent skills CLI — クロスクライアントスキルインストール用 npx skills

この演習をやって違うコスト分布になった人がいたら、ぜひ聞いてみたいです — リークパスはClaude Codeのリリースごとにシフトするし、次の6ヶ月のchangelogエントリでどのレバーが一番効くかは変わっていくはずです。


原文: Cutting Claude Code's Initial Context Bloat — Skills, Plugins, and MCP Tactics (Ryota Murakami, 2026-05-21)