WinDbg MCP の紹介

Last Update:
このエントリーをはてなブックマークに追加

こんにちは、Japan Developer Support Core チームの松井です。

2026 年 10 月にリリースされた WinDbg 1.2610.1001.0 では、新機能として WinDbg MCP が追加されました。WinDbg MCP の詳細は、2026 年 10 月 6 日に公開された WinDbg 製品チームのブログ記事 で紹介されています。本記事では、Visual Studio Code の GitHub Copilot から WinDbg MCP を利用する手順を、クラッシュ ダンプの調査と複数ターゲットの比較を例に説明します。

WinDbg MCP の概要

WinDbg MCP は、WinDbg のデバッグ セッションを Model Context Protocol (MCP) 経由で AI クライアントに公開する機能です。WinDbg はさまざまな問題の調査に使用できるデバッガーですが、効果的に活用するには、適切なコマンドの選択や実行結果の解釈などを含むデバッグに関する高度な知識が必要です。

WinDbg MCP を使用すると、AI エージェントが WinDbg を操作し、クラッシュ ダンプや Time Travel Debugging (TTD) トレースなどのデバッグ ターゲットを調査できるようになります。ユーザーは自然言語で調査を指示し、WinDbg のコマンド出力や調査結果について、自然言語による説明を受け取ることができます。

WinDbg に慣れていないユーザーは、個々のコマンドや機能を熟知していなくても、AI エージェントの支援を受けながらデバッグを進められます。また、熟練した WinDbg ユーザーにとっても、デバッガーの操作や定型的な調査を自動化し、デバッグ作業を効率化できるという利点があります。

WinDbg MCP のアーキテクチャ

WinDbg MCP の MCP サーバーとしての機能 (ツール、プロンプト、リソース) は、WinDbg に同梱されている DbgX.Mcp.Proxy.exe によって MCP クライアントに公開されます。DbgX.Mcp.Proxy.exe はローカル名前付きパイプを経由して各デバッグ セッションの MCP Service と通信を行い、MCP ツールの呼び出しとその結果を中継します。WinDbg MCP を利用して操作する WinDbg では、MCP Service を有効にしておく必要があります。

flowchart LR A["MCP Client\n(Visual Studio Code / GitHub Copilot CLI)"] -->|stdio MCP| B["DbgX.Mcp.Proxy.exe"] B -->|local named pipe| C1["Debug session 1\n(WinDbg - MCP Service)"] B -->|local named pipe| C2["Debug session 2\n(WinDbg - MCP Service)"] B ~~~ CMore["..."] B -->|local named pipe| Cn["Debug session n\n(WinDbg - MCP Service)"] style CMore fill:none,stroke:none

WinDbg MCP のアーキテクチャの詳細については、公式ドキュメントもあわせて参照してください。

セキュリティとプライバシー

WinDbg MCP を使用する前に、WinDbg MCP のセキュリティに関する説明と組織の規則を確認してください。特に、次の点に注意が必要です。

  • モデルへ送られる情報: デバッガーのコンテキストやコマンド出力が MCP クライアントからモデル サービスへ送信される場合があります。顧客データ、個人情報、資格情報、機密性の高いソース パスを送信できるか事前に判断してください。
  • Secure Mode: Secure Mode は既定で有効であり、.shell などの危険性が高い操作を制限します。完全な保護を適用するには、ターゲットを読み込む前に MCP Service を開始します。後から開始した場合は Partial Secure Mode です。
  • プロンプト インジェクション: クロス プロンプト インジェクションに対する保護には、クライアントによる MCP sampling のサポートが必要です。利用するクライアントと構成で sampling が有効かを確認し、ダンプやシンボルに由来する文字列を信頼された指示として扱わないでください。
  • 診断ログ: 接続問題の調査で収集する診断ログには、実行したコマンドやターゲットの情報が含まれる場合があります。共有前に内容を確認し、保存先と共有範囲を制限してください。
  • AI の回答: AI の調査結果は権威ある診断ではありません。重要な判断は、WinDbg のコマンド出力、シンボル、ソース コード、再現結果などで検証してください。

WinDbg MCP の有効化とインストールの手順

WinDbg MCP を使用するためには、あらかじめ WinDbg で MCP サーバーの機能を有効化した上で、Visual Studio Code の MCP サーバーの設定に WinDbg MCP の構成を追加する必要があります。本記事でも手順をまとめますが、将来変更される可能性もあるため、最新の手順については WinDbg MCP の設定と使用 もあわせて確認してください。

WinDbg MCP の有効化

  1. WinDbg を起動し、[File] タブを選択します。 File タブの選択
  2. [Settings] メニューを選択します。 Settings メニューの選択
  3. [Settings] ダイアログで [MCP service settings] を選択し、[Enable Server] にチェックが入っていること、Client に [VS Code] が選択されていることを確認します。 MCP service settings の構成
  4. [OK] ボタンを押下して [Settings] ダイアログを閉じます。

WinDbg MCP のインストール

  1. WinDbg の [Home] タブを選択し、[Install MCP] ボタンを押下します。 Install MCP ボタンの押下
  2. 既定のブラウザー経由で Visual Studio Code を起動して MCP サーバーのインストール画面が開くか確認が求められますので、開きます。 MCP サーバーのインストール画面を開く
  3. MCP サーバーのインストール画面で [Install] ボタンを押下します。 Install ボタンの押下

WinDbg MCP を使用したデバッグ

シナリオ 1: クラッシュ ダンプを調査する

このシナリオでは、WinDbg MCP を使用して AI エージェントに単一のユーザー モード クラッシュ ダンプの原因を調査させます。

クラッシュ ダンプの準備

  1. WER を使って Dump を採取する の記事に沿ってダンプ ファイルを出力する構成を行います。

  2. PowerShell を起動して以下のコマンドを実行します。

    1
    [System.Environment]::FailFast("Intentional crash for dump analysis")

クラッシュ ダンプの調査

  1. WinDbg を起動します。

  2. WinDbg で [Home] タブを選択し、[MCP Service] ボタンを押下します。 MCP Service の有効化

  3. MCP Service の有効化について確認が求められますので、内容を確認して [Yes] ボタンを押下します。 プライバシーとセキュリティの警告

  4. WinDbg にクラッシュ ダンプ ファイルをドラッグ & ドロップして開きます。

  5. Visual Studio Code を起動し、GitHub Copilot Chat へ次のプロンプトを入力します。

    #windbg WinDbg で PowerShell のクラッシュ ダンプを開いています。セッションに接続してクラッシュした原因を調査して説明してください。

  6. WinDbg MCP の各ツールの実行などで承認が求められる場合は、内容を確認して承認操作を行ってください。

なお、MCP Service の有効化は新しく WinDbg を起動して WinDbg MCP を使用するときに毎回必要になります。また、MCP Service はターゲットに接続する前 (ファイルを開いたりプロセスにアタッチしたりする前) に有効化しておくことをお勧めします。ターゲットに接続した後で MCP Service を有効にした場合、WinDbg は "Partial Secure Mode" で動作することになります。(参考情報: WinDbg の概要 - セキュア モード)

チャットの応答例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
User: #windbg WinDbg で PowerShell のクラッシュ ダンプを開いています。セッションに接続してクラッシュした原因を調査して説明してください。

GitHub Copilot: アクティブな WinDbg セッションを特定して接続し、まず例外解析と障害スレッドのスタックから原因を絞り込みます。機密値は表示せず、クラッシュ原因に必要な情報だけを確認します。

Ran `list_sessions`
Completed with input: {}

対象は `powershell.exe.14012.dmp` を開いている PID `12136` です。このセッションへ接続し、WinDbg の標準クラッシュ解析を実行します。

Ran `connect_session`
Completed with input: {
"pid": 12136
}

接続できました。次に `!analyze -v` で例外コード、障害命令、スタック、推定モジュールをまとめて取得します。

Ran `show_output`
Completed with input: {
"cmd": "!analyze -v",
"commandDescription": "Run verbose automatic crash analysis to identify the exception, faulting thread, instruction, stack, and likely module."
}

標準解析コマンドの出力取得に失敗したため、デバッガの状態を確認して、停止状態やダンプ初期化の問題かを切り分けます。



Ran `get_output_history`
Completed with input: {}

Ran `get_logs`
Completed with input: {}

ダンプには CLR の致命的例外 `0x80131623` が記録され、停止位置は `clr!EEPolicy::HandleFatalError` です。これは結果であって根本原因ではないため、例外コンテキストと全スレッドのスタックを個別コマンドで確認します。

Ran `show_output`
Completed with input: {
"cmd": ".ecxr; kv",
"commandDescription": "Switch to the stored exception context, then display a verbose stack trace for the faulting thread."
}

Ran `show_output`
Completed with input: {
"cmd": "~* k",
"commandDescription": "Display call stacks for every thread to identify the managed failure path and any secondary activity."
}

障害スレッドは PowerShell パイプライン上で `SystemNative::FailFast` を明示的に呼んでいます。自然発生したアクセス違反ではなく、スクリプトまたは呼び出されたコードによる強制終了の可能性が高いため、マネージド引数と PowerShell の呼び出し元を確認します。

Ran `show_output`
Completed with input: {
"cmd": ".ecxr; !clrstack -a",
"commandDescription": "Restore the exception context and show the managed stack with arguments and local references to identify the PowerShell expression that called FailFast."
}

マネージドスタックで `System.Environment.FailFast(System.String)` の直接呼び出しが確定しました。呼び出し引数の型、終了メッセージ、実行中のスクリプト情報を確認し、どのコードが強制終了を要求したか特定します。

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637dc7b80; !do 000001c637df7910; !do 000001c637dfa548",
"commandDescription": "Inspect the managed Type and message arguments passed to the dynamic FailFast call, then inspect the active PowerShell script command processor for source metadata."
}

終了メッセージは `Intentional crash for dump analysis` で、意図的なクラッシュだと明示されています。最後にスクリプトブロックのメタデータを確認し、ファイル由来か対話入力かと実行式を裏付けます。

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637dfa450; !do 000001c637dfa668",
"commandDescription": "Inspect the PowerShell ScriptBlock and CommandInfo objects to determine whether the FailFast invocation came from a script file or interactive command and recover available source metadata."
}

このコマンドは `_fromScriptFile = false` で、スクリプトファイルではなく対話入力または動的スクリプトブロック由来です。保持されている AST 情報から、実行された式を確認します。

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637dfa480",
"commandDescription": "Inspect the compiled script block data to locate its AST and source text metadata for the interactive FailFast command."
}

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637df9fe8",
"commandDescription": "Inspect the PowerShell AST root to locate its source extent and recover the exact interactive expression."
}

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637df7ec8",
"commandDescription": "Inspect the AST source extent object to identify the stored command text or file source for the FailFast invocation."
}

AST は 69 文字の対話コマンドを保持しています。ソース保持オブジェクトをたどって、式そのものを確定します。

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637df6700",
"commandDescription": "Inspect the PowerShell AST position helper that owns the interactive command text referenced by the source extent."
}

Ran `show_output`
Completed with input: {
"cmd": "!do 000001c637df0f58",
"commandDescription": "Display the stored interactive PowerShell command text that produced the explicit FailFast termination."
}

**調査結果**

クラッシュ原因は、対話入力された次の PowerShell コマンドによる意図的な強制終了です。

[System.Environment]::FailFast("Intentional crash for dump analysis")

根拠:

- 例外コード: `0x80131623`(CLR FailFast)
- 障害スレッド: `System.Environment.FailFast(System.String)`
- メッセージ: `Intentional crash for dump analysis`
- スクリプトファイル由来ではなく、対話入力または動的スクリプトブロック由来
- アクセス違反、PowerShell 本体、PSReadLine の不具合ではありません

つまり、このダンプはテスト目的で明示的に生成されたクラッシュです。

シナリオ 2: 複数のターゲットを同時に調査する

このシナリオでは、WinDbg MCP を使用して AI エージェントに複数のダンプ ファイルからマネージド ヒープの状態を比較して調査させます。

ダンプ ファイルの準備

  1. WER を使って Dump を採取する の記事に沿ってダンプ ファイルを出力する構成を行います。

  2. PowerShell を起動して以下のコマンドを実行します。意図的にメモリ リークを発生させるコードですので、長時間実行させないでください。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $timer = New-Object System.Timers.Timer
    $timer.Interval = 100

    $global:objs = @()

    Register-ObjectEvent `
    -InputObject $timer `
    -EventName Elapsed `
    -Action { $global:objs += New-Object byte[] (1MB) }

    $timer.Start()
  3. タスク マネージャーを起動します。

  4. [詳細] タブのプロセス一覧で "powershell.exe" を選択し、右クリックしてコンテキスト メニューから [メモリ ダンプ ファイルの作成] を選択します。

  5. 30 秒ほど時間を空けてもう一度 [メモリ ダンプ ファイルの作成] を行います。

  6. PowerShell を終了します。

複数のダンプ ファイルの調査

  1. WinDbg を起動します。

  2. WinDbg で [Home] タブを選択し、[MCP Service] ボタンを押下します。 MCP Service の有効化

  3. MCP Service の有効化について確認が求められますので、内容を確認して [Yes] ボタンを押下します。 プライバシーとセキュリティの警告

  4. WinDbg に 1 つ目のダンプ ファイルをドラッグ & ドロップして開きます。

  5. 新しく WinDbg を起動し、手順 2~4 と同じ操作で 2 つ目のダンプ ファイルを開きます。

  6. Visual Studio Code を起動し、GitHub Copilot Chat へ次のプロンプトを入力します。

    #windbg powershell.exe のメモリ使用量が増え続けているため、少し時間を空けて 2 つのダンプ ファイルを取得しました。それぞれ WinDbg で開いているので、セッションに接続して原因を調査してください。

  7. WinDbg MCP の各ツールの実行などで承認が求められる場合は、内容を確認して承認操作を行ってください。

チャットの応答例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
User: #windbg powershell.exe のメモリ使用量が増え続けているため、少し時間を空けて 2 つのダンプ ファイルを取得しました。それぞれ WinDbg で開いているので、セッションに接続して原因を調査してください。

Copilot: 2 つの WinDbg セッションを特定し、同じ観点のヒープ統計を比較して増加元を絞り込みます。まず利用可能な WinDbg 接続・照会ツールを読み込みます。

Search Tools

list_sessions
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-list_sessions"}

connect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-connect_session"}

get_target_state
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_target_state"}

Search Tools

1 個目のダンプから、仮想メモリ内訳・ネイティブヒープ・CLR 種別を採取します。続いて同じコマンドを 2 個目に適用し、差分の大きい領域を詳しく掘ります。

show_output
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-show_output"}

show_output
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-show_output"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search Tools

disconnect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-disconnect_session"}

connect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-connect_session"}

show_output
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-show_output"}

new_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-new_script"}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^===|Debug session time|Process Uptime|Usage Summary|MEM_COMMIT|MEM_RESERVE|I...`

Read , lines 91 to 142
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791392826133-copilot-tool-output-2207926f909d48888985b163062678a3.txt",
"view_range": [
91,
142
]
}

Read , lines 143 to 170
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791392826133-copilot-tool-output-2207926f909d48888985b163062678a3.txt",
"view_range": [
143,
170
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^===|GC Heap|generation|Total Size|Free space|Statistics:|MT\s+Count|System\....`

Read , line 166 to the end
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791392837197-copilot-tool-output-068d784a049047e492e86fa46568916c.txt",
"view_range": [
166,
-1
]
}

disconnect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-disconnect_session"}

connect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-connect_session"}

get_target_state
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_target_state"}

new_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-new_script"}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^===|Debug session time|Process Uptime|MEM_PRIVATE|MEM_COMMIT|PAGE_READWRITE|...`

Search for `Statistics:|Total [0-9]+ objects|Free$|System\.Byte\[\]|System\.String|System...`

Search for `^Total [0-9]+ objects|^Total [0-9]|Free$`

Read , lines 2160 to 2235
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791392866273-copilot-tool-output-990b13e3049d431c8c2696ccae855143.txt",
"view_range": [
2160,
2235
]
}

2 個目では 28 秒間で GC ヒープが約 729 MB から約 2.57 GB に増え、主成分は `System.Object[]` 約 1.80 GB と、3,145 万個の boxed `System.Byte` 約 755 MB です。次に巨大配列の保持ルートを追い、どの PowerShell 機構/コマンドが保持しているか確定します。

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !dumpheap -type System\.Object\[\] -min|^Address\s+MT|System\.Object\[\]...`

Read , lines 2231 to 2245
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791392924361-copilot-tool-output-2eac0bf0e58e4686862b553fb44045e8.txt",
"view_range": [
2231,
2245
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !gcroot|HandleTable|ROOT:|System\.Management\.Automation|System\.Collect...`

Search for `^=== !gcroot|Found [0-9]+ unique roots|Found [0-9]+ roots|Scan Thread|HandleT...`

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !dumpheap -stat -live|^=== ~\*e !clrstack|^Total [0-9]+ objects|System\....`

Search for `^=== !dumpheap -stat -live|^=== ~\*e !clrstack|^Total [0-9]+ objects`

Read , lines 4070 to 4145
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393240925-copilot-tool-output-4ea812a18a7043739c92ace3845bf010.txt",
"view_range": [
4070,
4145
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !dumpheap -type System\.Object\[\] -min 1000000 -live|^Total [0-9]+ objects`

Read , lines 4316 to 4328
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393386641-copilot-tool-output-dca96cadaa2442c08174bdc427dbcd61.txt",
"view_range": [
4316,
4328
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !gcroot 0000029055af1020|^=== !do 0000029055af1020|Found [0-9]+ unique r...`

Search for `^=== !gcroot 0000029055af1020|^=== !do 0000029055af1020|Found [0-9]+ unique r...`

Read , lines 4325 to 4375
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393399038-copilot-tool-output-d99cdc17047548f790dc18f9d5ee50fb.txt",
"view_range": [
4325,
4375
]
}

Search for `GetContentCommand|WriteObject|Pipe\.Add|PipelineProcessor|CommandProcessor|Pr...`

Read , lines 4180 to 4315
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393399038-copilot-tool-output-d99cdc17047548f790dc18f9d5ee50fb.txt",
"view_range": [
4180,
4315
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !do 0000028fa50d3140|^=== !dumpheap -type System\.Management\.Automation...`

Read , lines 4371 to 4455
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393557961-copilot-tool-output-b9b53ab40bd14851b46937ce21b9a18c.txt",
"view_range": [
4371,
4455
]
}

Read , lines 4590 to 4645
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393557961-copilot-tool-output-b9b53ab40bd14851b46937ce21b9a18c.txt",
"view_range": [
4590,
4645
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !do 0000028fa50d30f8|^=== !do 0000028fa50e0818|^=== !do 0000028fd1470c68...`

Read , lines 5016 to 5083
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393573875-copilot-tool-output-c262ef5baa8345ccb31f769aedefdbaa.txt",
"view_range": [
5016,
5083
]
}

Read , lines 5084 to 5135
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393573875-copilot-tool-output-c262ef5baa8345ccb31f769aedefdbaa.txt",
"view_range": [
5084,
5135
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !do 0000028fa50e0928|^=== !do 0000028fa50e06f0|^=== !do 0000028fa50d73f0`

Read , lines 5178 to 5238
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393586852-copilot-tool-output-bbcc7a4a45904a2890f966b964be153a.txt",
"view_range": [
5178,
5238
]
}

保持元はグローバル変数 `$objs`、実行元は `PSEventJob` のイベントアクションであることまで確認できました。最後に購読元(Timer など)と間隔を確認し、再現条件と修正案を確定します。

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !do 0000028fa50de8e8`

Read , lines 5238 to 5295
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393604509-copilot-tool-output-4a79c38867f34af589551d8d26bbd622.txt",
"view_range": [
5238,
5295
]
}

set_script_content
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-set_script_content"}

execute_script
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-execute_script"}

get_output_history
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-get_output_history"}

Search for `^=== !do 0000028fa50be7d0|^=== !do 0000028fa50d61b8`

Read , lines 5262 to 5305
Completed with input: {
"path": "C:\\Users\\user1\\AppData\\Local\\Temp\\1791393615180-copilot-tool-output-80756900a794462084f2b35a40cc0469.txt",
"view_range": [
5262,
5305
]
}

disconnect_session
Completed with input: {"serverName":"WinDbg","toolName":"WinDbg-disconnect_session"}

## 調査結果

原因は、100 ms 間隔の `System.Timers.Timer` に登録されたイベントアクションです。

```powershell
$global:objs += New-Object byte[] (1MB)
```

これは実質的なメモリ リークになっています。

### ダンプ比較

| 項目 | ダンプ 1 | ダンプ 2 | 増加 |
|---|---:|---:|---:|
| Process Uptime | 18 秒 | 46 秒 | 28 秒 |
| Commit | 約 956 MB | 約 2.65 GB | **約 1.70 GB** |
| GC Heap | 約 729 MB | 約 2.57 GB | **約 1.84 GB** |

ダンプ 2 の生存オブジェクトの主成分は次のとおりでした。

| 型 | 個数 | サイズ |
|---|---:|---:|
| `System.Byte` | 31,457,280 | 約 755 MB |
| `System.Object[]` | 945 | 約 252 MB |

最大の生存 `System.Object[]` は以下の状態でした。

- 要素数: **31,457,280**
- サイズ: **251,658,264 bytes (約 240 MB)**
- GC root: グローバル変数 **`$objs`**
- 実行元: `System.Management.Automation.PSEventJob`
- イベント: `System.Timers.Timer.Elapsed`
- Timer interval: **100 ms**
- AutoReset: 有効

### 急激に増える理由

`byte[]` は PowerShell のパイプライン上で列挙されるため、この式では 1 MB の配列が 1 個として追加されず、約 104 万個の `System.Byte` に展開・ボックス化されます。

さらに `+=` は追加のたびに新しい `System.Object[]` を作って既存要素をコピーします。したがって、

1. 各 `byte` がボックス化される
2. `$objs` が無制限に保持する
3. `+=` が巨大な配列を繰り返し再確保・コピーする
4. 使用済みの巨大配列が LOH に残り、GC まで Commit が膨らむ

という複合要因で、28 秒間に約 1.7 GB 増加しています。ダンプ 2 には GC ルートを失った 256 MB の旧配列も 2 個あり、再確保による一時的な増幅も確認できました。

## 推奨修正

配列を保持する必要があるなら、`+=` ではなく型付きリストを使います。

```powershell
$global:objs = [System.Collections.Generic.List[byte[]]]::new()

# イベントアクション
$bytes = New-Object byte[] (1MB)
$global:objs.Add($bytes)
```

保持自体が不要なら、グローバル変数へ追加しないのが根本対策です。

最小限の変更として次のように単項カンマで列挙を抑制する方法もありますが、`+=` による全配列コピーと無制限な増加は残るため推奨しません。

```powershell
$global:objs += ,(New-Object byte[] (1MB))
```

実行中の増加を止めるには、該当イベント購読を解除してください。

```powershell
Get-EventSubscriber | Unregister-Event
Get-Job | Remove-Job -Force
$global:objs = $null
[GC]::Collect()
```

結論として、PowerShell 本体のリークではなく、**100 ms Timer のイベントアクションによる `$global:objs` の無制限な蓄積、`byte` 配列の展開・ボックス化、および `+=` の配列再確保**が原因です。

まとめ

本記事では、WinDbg MCP の概要とセットアップ手順、使用例を紹介しました。WinDbg MCP を使用すると、WinDbg を使用したデバッグのさまざまなタスクを AI エージェントに実行させることができます。ただし、デバッガーが扱うダンプ ファイルやトレースなどのターゲットは機密情報を含む可能性があるため、WinDbg MCP を使用する際は取り扱う情報に注意が必要です。組織のセキュリティおよびプライバシーも確認した上で活用していただければ幸いです。


本ブログの内容は弊社の公式見解として保証されるものではなく、開発・運用時の参考情報としてご活用いただくことを目的としています。もし公式な見解が必要な場合は、弊社ドキュメント (https://learn.microsoft.com や https://support.microsoft.com) をご参照いただくか、もしくは私共サポートまでお問い合わせください。