目次
はじめに
Claude Code で MCP(Model Context Protocol)サーバーを複数利用していたところ、WSL2 環境でメモリ使用量が 7.7 GiB、ロードアベレージが 57超 に達し、システムがほぼ操作不能になるという事象に遭遇しました。
業務時間が半日溶けました(しかし、Claude Codeの利用で生産性が2倍以上になっているので、おつりは返ってきますが、、)orz
本記事では、原因調査から恒久対策までの全過程を共有します。
同じ構成で Claude Code を使っている方の参考になれば幸いです。
環境
- OS: WSL2(Ubuntu 24.04)
- RAM: 16 GB
- CPU: 12コア
- Claude Code: v2.1.x
- MCP サーバー数: 9種(Atlassian, AWS系, GitHub, Playwright 等)
何が起きたか
ある日、Claude Code の応答が劇的に遅くなり、ターミナル操作すらままならない状態に。htop を見ると異常な値が並んでいました。
ちなみに、WSLの動作も激重になりました。
Memory: 7.7 GiB / 15 GiB (通常時の約4倍)
Load Average: 57.93 (12コアの約5倍、完全に過負荷)
Ctrl+C で Claude Code を終了しても状況は改善しません。ps aux で調べると、同一の MCP サーバープロセスが大量に起動 していました。
計測データ
| 項目 | 値 |
|---|---|
| 孤立 MCP プロセス数 | 43個 |
| 孤立プロセスのメモリ合計 | 約 4.2 GB(RSS 合計) |
| 全 MCP プロセス数 | 54個 |
| セッション1回あたりの起動プロセス数 | 約 30〜40個 |
本来9プロセスで済むはずの MCP サーバーが、54個も起動 していたのです。
根本原因
調査の結果、2つの設定ミスの複合 が原因でした。
原因1: .mcp.json の多階層重複
Claude Code は起動時に、カレントディレクトリから親方向へ .mcp.json を再帰的に探索・マージします。以下のように3階層に .mcp.json が配置されていました。
~/.claude/.mcp.json ← グローバル設定(6種)
└── ~/dev/.mcp.json ← プロジェクト設定(6種、グローバルと完全重複)
└── ~/dev/my-project/.mcp.json ← サブプロジェクト設定(11種)
サブプロジェクトのディレクトリで Claude Code を起動すると、3階層すべてが読み込まれ、同じ MCP サーバーが最大3インスタンスずつ起動されます。
| MCP サーバー | グローバル | プロジェクト | サブプロジェクト | 起動数 |
|---|---|---|---|---|
| aws-documentation-mcp-server | ✅ | ✅ | ✅ | 最大3つ |
| cdk-mcp-server | ✅ | ✅ | ✅ | 最大3つ |
| Context7 | ✅ | ✅ | ✅ | 最大3つ |
| aws-cli-mcp-server | ✅ | ✅ | ✅ | 最大3つ |
| serena | ✅ | ✅ | ✅ | 最大3つ |
| mcp-atlassian | ✅ | ✅ | ✅ | 最大3つ |
6種 × 3インスタンス = 18プロセスの無駄な多重起動
原因2: claude_code MCP サーバーによる再帰的プロセス生成
さらに深刻だったのが、.mcp.json に含まれていた以下の定義です。
"claude_code": {
"command": "claude",
"args": ["mcp", "serve"],
"env": {}
}
これは Claude Code 自身を MCP サーバーとして子プロセス起動する 設定です。
claude mcp serve とは何か
claude mcp serve は Claude Code 公式のサブコマンド で、Claude Code を他のツール(別の AI エージェント等)から MCP サーバーとして呼び出すための機能です。つまり、外部ツールが Claude Code の能力を利用するためのインターフェースとして設計されています。
しかし、Claude Code 自身の MCP 設定に定義するためのものではありません。
この定義が .mcp.json に含まれていた経緯として、claude mcp add コマンドや MCP セットアップ時に自動追加された可能性が高いと考えられます。公式機能として存在するコマンドが、自分自身の設定に入ると再帰ループを引き起こすという、いわば 「正規機能の誤配置」による罠 です。
何が起きるか
フォークボムに近い挙動 で、OS のリソース制限に到達するまでプロセスが増殖し続けます。
さらに、セッション終了後のプロセス孤立化の流れも図示します。
悪化要因: WSL2 のシグナル伝搬問題
Claude Code セッション終了時(Ctrl+C)に、子プロセスへ SIGTERM が正常に伝搬されません。
- プロセスの親が WSL の
Relayプロセスまたはinit(PID=1)に引き取られる - 孤立プロセス(orphan process)は Claude Code のライフサイクルから切り離される
- セッションを終了しても孤立プロセスは永続化 し、次回セッション起動で さらに蓄積
これが「Claude Code を終了してもメモリが減らない」原因でした。
発生メカニズムの全体像
Claude Code 起動(~/dev/my-project/ にて)
│
├─ Phase 1: 設定ファイルのマージ読み込み
│ ├─ ~/.claude/.mcp.json → 6種
│ ├─ ~/dev/.mcp.json → 6種(重複)
│ └─ ~/dev/my-project/.mcp.json → 11種(重複 + claude_code)
│
├─ Phase 2: MCP サーバープロセスの起動
│ ├─ 重複定義 → 約 24〜27 プロセス
│ └─ claude_code → 再帰的に +11〜27 プロセス
│
├─ Phase 3: 1セッションあたり合計 約 30〜40 プロセス
│
└─ Phase 4: セッション終了
├─ Claude Code 本体は終了
└─ 子プロセスに SIGTERM 不達(WSL2 固有)
└─ 孤立プロセスとして永続化
└─ 数セッション後: 43個 / 4.2GB 消費
対策
対策1: MCP 設定の公式準拠な一元管理
Claude Code の公式ドキュメントによると、MCP 設定の保存場所は以下の通りです。
| スコープ | 保存場所 |
|---|---|
| ユーザー/ローカル |
~/.claude.json(mcpServers フィールド) |
| プロジェクト | プロジェクトルートの .mcp.json
|
| 管理 | システムディレクトリの managed-mcp.json
|
全 MCP サーバーを ~/.claude.json の mcpServers フィールドに一元管理 し、それ以外の .mcp.json はすべて削除しました。
変更前
~/.claude.json (mcpServers) → 10種(claude_code 含む)
~/.claude/.mcp.json → 6種(重複)
~/dev/.mcp.json → 6種(重複)
~/dev/my-project/.mcp.json → 11種(重複 + claude_code)
変更後
~/.claude.json (mcpServers) → 9種(唯一の定義箇所、公式準拠)
その他すべて → 削除
集約した 9 種の MCP サーバー
| # | MCP サーバー名 | コマンド | 用途 |
|---|---|---|---|
| 1 | atlassian-mcp-server | npx (mcp-remote) | Jira/Confluence 連携 |
| 2 | awslabs.aws-documentation-mcp-server | uvx | AWS ドキュメント検索 |
| 3 | awslabs.cdk-mcp-server | uvx | AWS CDK 操作支援 |
| 4 | Context7 | npx (@upstash/context7-mcp) | ライブラリドキュメント取得 |
| 5 | aws-cli.mcp-server | uvx | AWS CLI 操作 |
| 6 | serena | uv (serena-mcp-server) | コードナビゲーション |
| 7 | github | npx (@modelcontextprotocol/server-github) | GitHub 操作 |
| 8 | playwright | npx (@playwright/mcp --vision) | ブラウザ自動操作 |
| 9 | Azure MCP Server | npx (@azure/mcp) | Azure 操作 |
対策2: claude_code MCP サーバーの完全排除
claude_code(claude mcp serve)を MCP サーバーとして定義しないこと。これが再帰的プロセス生成の元凶です。
絶対にやってはいけない設定
"claude_code": {
"command": "claude",
"args": ["mcp", "serve"],
"env": {}
}
この設定は Claude Code 自身を MCP サーバーとして再帰起動し、フォークボムに近い状態を引き起こします。
対策3: 孤立プロセスのクリーンアップ用シェル関数
WSL2 のシグナル伝搬問題に備えて、~/.bashrc または ~/.zshrc に以下を追加しておくと安心です。
claude-cleanup() {
echo "孤立MCPプロセスをクリーンアップ中..."
local pids=$(ps -eo pid,ppid,args | awk '
($2==1 || $2==2033) && $0 ~ /mcp|playwright|context7|uvx|serena|azure/ {print $1}
')
local count=$(echo "$pids" | grep -c '[0-9]')
if [ "$count" -gt 0 ]; then
echo "$pids" | xargs kill -9 2>/dev/null
echo "${count}個の孤立プロセスを終了しました"
else
echo "孤立プロセスはありません"
fi
}
孤立プロセスの確認だけしたい場合:
ps -eo pid,ppid,tty,rss,args | awk '
$2==1 || $2==2033 {
if ($0 ~ /mcp|playwright|context7|uvx|serena|azure/) {
sum+=$4; count++; print
}
}
END {printf "\n孤立プロセス数: %d / 合計メモリ: %.0f MB\n", count, sum/1024}
'
対策の効果
Before / After
| 指標 | 対策前 | 対策後 | 改善率 |
|---|---|---|---|
| メモリ使用量 | 7.7 GiB | 1.8 GiB | 77% 削減 |
| 孤立 MCP プロセス数 | 43個 | 0個 | 100% 解消 |
| ロードアベレージ | 57.93 | 正常値 | 大幅改善 |
| 1セッションの MCP プロセス数 | 30〜40個 | 9個 | 75% 削減 |
恒久対策後の定常値
| 指標 | 値 |
|---|---|
| MCP サーバー起動数/セッション | 9個(各1インスタンスのみ) |
| MCP サーバーの合計メモリ | 約 1.2 GB |
| セッション終了後の孤立プロセス | 0個 |
| ロードアベレージ | 0.75(12コアに対して極めて低負荷) |
再発防止チェックリスト
Claude Code で MCP サーバーを利用する際、以下を守れば同じ問題は発生しません。
やってはいけないこと
| NG 項目 | 理由 |
|---|---|
複数階層に .mcp.json を配置 |
マージにより同一サーバーが多重起動される |
claude_code(claude mcp serve)を MCP サーバーに定義 |
再帰的プロセス生成(フォークボム類似) |
_amazon-q_disabled 等の非対応サーバーを定義 |
機能せずリソースだけ消費 |
やるべきこと
| 推奨事項 | 方法 |
|---|---|
MCP 設定は ~/.claude.json に一元管理 |
公式ドキュメント準拠のユーザースコープ |
| 起動後に MCP プロセス数を確認 | ps aux | grep -E 'mcp|playwright|context7|uvx|serena|azure' | grep -v grep |
WSL2 ユーザーは claude-cleanup 関数を用意 |
シグナル伝搬問題への保険 |
検証コマンド
Claude Code 再起動後、以下で正常性を確認できます。
# MCP プロセスの確認(各サーバーが1プロセスのみであること)
ps aux | grep -E 'mcp|playwright|context7|uvx|serena|azure' | grep -v grep
# 孤立プロセスの確認(0個であること)
ps -eo pid,ppid,tty,rss,args | awk '
($2==1 || $2==2033) && $0 ~ /mcp|playwright|context7|uvx|serena|azure/ {count++}
END {printf "孤立プロセス数: %d\n", count}
'
補足: なぜ他の PC では発生しなかったか
同じ WSL2 + 類似 MCP 構成の他 PC では再現しませんでした。差異は以下の通りです。
-
.mcp.jsonが階層的に重複配置されていない(グローバル1箇所のみ) -
claude_codeMCP サーバーが定義されていない - 作業ディレクトリが
~/dev/直下で、サブディレクトリの.mcp.jsonがマージ対象にならない
つまり、MCP サーバーを多数使いつつ、複数プロジェクトをサブディレクトリで管理している環境 で発生しやすい問題です。
まとめ
| 問題 | 原因 | 対策 |
|---|---|---|
| MCP サーバーの多重起動 |
.mcp.json の多階層重複 |
~/.claude.json に一元管理 |
| 再帰的プロセス増殖 |
claude_code MCP サーバー定義 |
定義を完全排除 |
| セッション終了後のプロセス残留 | WSL2 のシグナル伝搬問題 |
claude-cleanup シェル関数 |
Claude Code + MCP は非常に強力な組み合わせですが、設定の重複と再帰的定義には要注意です。特に WSL2 環境ではプロセスの孤立化が起きやすいため、定期的なプロセス確認を推奨します。
この記事が同様の問題に直面した方のお役に立てれば幸いです。
