mcpField
S
stuckgo

stuckgo

ローカル
github.com/GillMacedo開発ツール02 週間前に更新

stuckgo について

stuckgoは、goroutineダンプから停止状態を調べるGo開発者向けのMCPサーバー兼コマンドラインツールです。スタックを分類し、一般的なアイドル状態を除外して原因候補を順位付けします。サービスに接続せず、ダンプを比較してリークも調査できます。

主な機能

  1. 01Go goroutineダンプのレビュー
  2. 02一致するスタックトレースの分類
  3. 03一般的なアイドルgoroutineの除外
  4. 04ブロック原因候補の順位付け
  5. 052つのダンプを比較して増加を確認
  6. 06JSON出力または重大度に応じたCI失敗

活用シーン

  1. 01ダンプから停止したGoサービスを調査
  2. 02ダンプを比較してgoroutineリークを確認
  3. 03ロックやデータベース接続を待つgoroutineの特定

MCP 対応

MCP サーバーは、テキストまたはファイルから1つのgoroutineダンプをレビューするツールと、同じプログラムの2つのダンプを比較するツールを提供します。ダンプデータを解析し、サービスには接続しません。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"gillmacedo-stuckgo": {
"command": "npx",
"args": [
"-y",
"stuckgo"
]
}
}
}
起動コマンドnpx -y stuckgo

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmstuckgo0.1.0

ツール

2

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
afterstringいいえ後の時点で取得した goroutine ダンプのテキスト
beforestringいいえ前の時点で取得した goroutine ダンプのテキスト
after_pathstringいいえ後の時点で取得したダンプを含むファイルのパス
before_pathstringいいえ前の時点で取得したダンプを含むファイルのパス

詳細

stuckgo:この Go プログラムはなぜ停止しているのでしょうか?

npm CI MIT license

Go のゴルーチンダンプを読み取り、プログラムが何を待っているのかを知らせる MCP サーバーおよび CLI です。ゴルーチンリーク、ロックの滞留、データベース接続プールの枯渇、タイムアウトのない HTTP 呼び出しを見つけます。ダンプのテキストだけを使うため、サービスに接続することはありません。

停止したサービスには数千のゴルーチンが存在することがありますが、そのほとんどは正常です。リスナー、読み取りループ、アイドル状態のワーカーなどです。stuckgo は同一のスタックをまとめ、通常アイドル状態のものを除外し、残ったものを優先度順に並べます。40 個のゴルーチンがミューテックスを待っている場合は、それを保持している可能性のあるものも特定します。

エージェントに質問できること

  • 「Go サービスが停止しています。ゴルーチンダンプはこちらです。」
  • 「ゴルーチンリークはありますか? 10 分間隔で取得したダンプが 2 つあります。」
  • 「このサービスでデータベース接続が足りなくなっているのはなぜですか?」
  • 「このミューテックスを保持しているのは何ですか?」

インストール

Claude Code プラグインとして:

claude plugin marketplace add GillMacedo/stuckgo
claude plugin install stuckgo@stuckgo-marketplace

任意のクライアント用の MCP サーバーとして:

{"mcpServers": {"stuckgo": {"command": "npx", "args": ["-y", "[email protected]", "serve"]}}}

Node 18 以降を使う CLI として:

npx stuckgo review dump.txt

または、Go 1.27 以降を使う場合:go install github.com/GillMacedo/stuckgo@latest。

使い方

net/http/pprof をインポートしているサービスからダンプを取得します。プログラムは停止しません。

curl 'http://localhost:6060/debug/pprof/goroutine?debug=2' > dump.txt

kill -QUIT <pid> でもダンプを出力できますが、プロセスは終了します。クラッシュ時の出力も使えます。また、GOTRACEBACK=all を設定すると、失敗したゴルーチンだけでなく、すべてのゴルーチンが表示されます。

以下は、このリポジトリをクローンして実行した、examples/ にある架空のサービスの実際のダンプです。

$ go run . review examples/dumps/mutex-late.txt
43 goroutines, 1 normally idle

Groups:
      40  sync.Mutex.Lock, up to 2 min  main.(*store).Get (app/main.go:109)
       1  chan receive, up to 2 min  main.mutex (app/main.go:130)
       1  select, up to 2 min  main.(*store).Refresh (app/main.go:118)

HIGH   SG107 main.(*store).Get (app/main.go:109)
  40 goroutines waiting for a mutex, waiting up to 2 minutes. Possible holder, not proven: main.(*store).Refresh (app/main.go:118), in select.
  Try: Look at what the holder does while it holds the lock. Don't hold a lock across network calls, channel operations or slow work.

リークを確認するには、時間を空けて取得した 2 つのダンプを比較します。同じゴルーチン ID が同じ場所に残ったままスタックが増えている場合は、単一のダンプよりはるかに強い証拠になります。

$ go run . compare examples/dumps/leak-early.txt examples/dumps/leak-late.txt
Goroutines: 344 -> 637 (+293)

Growing:
    +293  342 -> 635  chan send  main.lookupPrice.func1 (app/main.go:79)

Same goroutine IDs in the same place in both dumps:
     342  chan send, up to 2 min  main.lookupPrice.func1 (app/main.go:79)

Go 1.27 以降では、Go 自体にチェックさせることもできます:/debug/pprof/goroutineleak?debug=2。stuckgo はその出力も読み取ります。

JSON を出力するには --json を追加します。CI で終了コード 1 を返すには --fail-on high を追加します。標準入力から読み取るには - を使います。

検出内容

ルール検出内容
SG101Go 自身が検出する「すべての goroutine がスリープ中」のデッドロック
SG102パニックまたは致命的エラーと、その発生箇所
SG103Go のリークプロファイルでリークとして報告される goroutine
SG104nil チャネルへの送信または受信。処理が戻ることはありません
SG105空き database/sql 接続を待機している goroutine
SG106長時間待機している送信 HTTP 呼び出し
SG107mutex で待機している goroutine の滞留と、ロックを保持している可能性のある goroutine
SG108完了していない WaitGroup と、その開始元
SG109チャネルへの送信で停止している goroutine。一般的なリークです
SG110チャネル受信または select を待機している多数の goroutine
SG111ネットワーク I/O の長時間待機
SG112システムコールの長時間実行
SG113sync.Cond.Wait での長時間待機
SG114同じ行でスリープしている多数の goroutine
SG115複数のスタックにまたがって、ほとんどの goroutine を開始した関数
SG116実行中、または CPU を待機中の多数の goroutine
SG117debug=1 のダンプで同じ行に多数の goroutine が停止している状態。停止理由は示されません

深刻度は、関与する goroutine の数と待機時間によって決まります。これらのしきい値は判断に基づくものです。

MCP ツール

ツール機能
go_goroutine_reviewテキストまたはファイルから、単一のダンプを確認します
go_goroutine_compare1 つのプログラムの 2 つのダンプを比較します

制限事項

  • 検出結果は手がかりです。 ダンプはある瞬間の状態です。各検出結果をコードと照らし合わせてください。
  • ロックの保持者を特定することはできません。 Go のダンプには記録されません。「保持している可能性のある goroutine」とは、同じ型のメソッド内にいる別の goroutine です。
  • Go 自身のリークプロファイルを除き、単一のダンプだけではリークを証明できません。 アイドル状態のワーカープールもリークと同じように見えるため、2 つのダンプを比較してください。
  • debug=1 で得られる情報は少なくなります。 件数はわかりますが、待機時間や goroutine ID はなく、goroutine が何を待っているかもほとんど表示されません。可能であれば debug=2 を使ってください。
  • 待機時間はおおよその値です。 Go が待機時間を出力するのは 1 分以上の場合に限られ、計測はガベージコレクション時に始まるため、時間が表示されていなくても待機時間が短いとは限りません。
  • CPU 使用率は確認できません。 停止中の goroutine がないのにプログラムが遅い場合は、CPU プロファイルを取得してください。
  • 通常はアイドル状態となるスタックの一覧は限られています。 Go ランタイム、net/http、database/sql、gRPC、golang.org/x/net/http2 です。その他のライブラリのバックグラウンドループはグループとして表示されますが、検出結果になることはほとんどありません。
  • ダンプには、ファイルパスやプログラムの値が含まれることがあります。stuckgo はローカルマシン上で動作しますが、MCP クライアントはツールの結果をモデルに送信します。

よくある質問

Go の goroutine リークを見つけるにはどうすればよいですか? 時間を空けて 2 つのダンプを取得し、stuckgo compare を実行してください。goroutine ID が変わらないままスタックが増えている場合は、確認が必要です。

実行中の Go プログラムから goroutine ダンプを取得するにはどうすればよいですか? net/http/pprof をインポートしてから、/debug/pprof/goroutine?debug=2 を取得してください。このエンドポイントは非公開にしてください。

goroutine ダンプの [chan send, 5 minutes] は何を意味しますか? その goroutine は、受信する goroutine がいないチャネルへの送信で約 5 分間ブロックされています。SG109 がこれを検出します。

Go サービスでデータベース接続が不足するのはなぜですか? database/sql.(*DB).conn で待機している goroutine がある場合、接続プールが満杯です。SG105 がこれを検出します。クエリの遅延や、クローズされていない Rows など、接続を保持している原因を調べてください。

panicparse や goroutine-inspect とは何が違いますか? panicparse と goroutine-inspect は、人がダンプを読み解いて調査するのに役立ちます。stuckgo はエージェント向けに優先度を付けた検出結果を提示し、2 つのダンプを比較でき、通常はアイドル状態のものを除外します。

テスト済み

  • examples/programs/ 内の実際のプログラム: SG101 から SG109 までのすべてのルールに加え、SG111、SG114、SG117 が、実際に停止したプログラムのダンプ(examples/dumps/ 内)で検出されました。ほとんどは Go 1.22 でも実行されました。
  • 実際のサービス: examples/dumps/real/ 内のアイドル状態の Prometheus 3.7.3 と etcd 3.6.5 では、低より上の重要度の検出はありませんでした。Prometheus では低重要度の WaitGroup の検出が2件あり、これは通常の動作です。
  • 記述例のみ: SG110、SG112、SG113、SG115、SG116。
  • MCP ツールの呼び出しは MCP Inspector を経由しました。

本番環境のインシデントでまだ使用されておらず、新しい Claude セッションでも試されていません。

コントリビューション

個人の方も、AI エージェントと協業している方も、コントリビューションを歓迎します。CONTRIBUTING.md をご覧ください。初めての方に適した Issue はこちらに一覧があります。

プルリクエストの流れ
  1. PR を作成します。 リポジトリをフォークしてブランチで作業し、変更は1つに絞ってください。変更内容がユーザーにどう影響するかを示すタイトルを付けてください。タイトルは変更履歴の項目になるため、feat: は Added に、fix: は Fixed に分類されます。
  2. 自動チェック。 コードの変更にはテストが必要で、make test が成功しなければなりません。30行を超える変更には、リンクされたオープンな Issue(Closes #<number>)が必要で、PR の変更行数は最大800行です。不足がある場合は、修正内容をコメントでお知らせします。
  3. レビュー。 Claude が各 PR を自動的にレビューします。コードの PR では、セキュリティレビューも行われ、サンドボックスでテストされます。その後、レビューにより PR がマージされるか、変更が求められます。CI、エージェント設定、npm または Python の依存関係、ベンダーコード、ビルドファイルを変更する PR はこの方法ではマージできず、その旨をコメントでお知らせします。セキュリティレビューで承認されなかったものも同様です。
  4. リリース。 ユーザーがインストールするものに変更があるマージは、約2時間以内に新しいバージョンとしてリリースされ、GitHub Release と、プロジェクトに存在する場合は npm パッケージも公開されます。ドキュメントと CI の変更は次のリリースまで保留されます。

AI による生成について

このプロジェクトは主に Claude Code で生成され、メンテナーによるレビューを受けています。

自己紹介

私は Giulliano Macedo です。GoTech Solutions で開発者向けツールを開発しています。最新情報をチェックしたり、お気軽にご連絡ください。

stuckgo がプログラムの停止原因を見つけた場合は、スターを付けていただけると、ほかの人にも見つけてもらいやすくなります。


Giulliano Macedo 作、GoTech Solutions · LinkedIn · X

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。