mcp-grafanaでPromQLを実行し、p95・p99を出す手順
mcp-grafanaのPrometheusツール群(query_prometheus・メタデータ系・query_prometheus_histogram)の使い分けと、p50〜p99を安全に出すための権限設計をまとめます。
mcp-grafanaには、Grafanaに登録済みのPrometheusデータソースへ問い合わせる専用ツールが6つあります。生のPromQLを投げるquery_prometheus、メトリクス名やラベルを探す4つのメタデータ系、そしてp50・p90・p95・p99を出すquery_prometheus_histogramです。使い分けの軸は「何を知りたいか」と「どのPromQLをモデルに書かせるか」の2点に絞れます。
Prometheus向けの6ツールは何ができるか
READMEのPrometheus Querying節は、機能を3系統に分けています。ツール名と必要権限はRBAC表に載っています。
| 系統 | ツール名 | できること |
|---|---|---|
| クエリ実行 | ツール名query_prometheus | できることPromQLの実行。instant(瞬間値)とrange(期間)の両方 |
| メタデータ | ツール名list_prometheus_metric_names | できること使えるメトリクス名の一覧 |
| メタデータ | ツール名list_prometheus_metric_metadata | できることメトリクスのメタデータの取得 |
| メタデータ | ツール名list_prometheus_label_names | できることセレクタに合致するラベル名の一覧 |
| メタデータ | ツール名list_prometheus_label_values | できること特定ラベルの値の一覧 |
| パーセンタイル | ツール名query_prometheus_histogram | できることhistogram_quantileによるp50・p90・p95・p99の算出 |
6ツールとも、必要なRBAC権限はdatasources:queryとdatasources:readです。スコープはdatasources:uid:prometheus-uidのようにUID単位で絞れます。データソースのUIDは、同じくREADMEにあるlist_datasourcesやget_datasourceで調べます。
導入そのものはmcp-grafanaの導入とRBAC設計で扱っています。Prometheus自体にMCPサーバーを立てる構成はPrometheus連携の記事が対象です。ここでは、Grafana経由で既存のデータソースを使う前提で進めます。
手順:クエリ用の最小構成で起動する
パーセンタイルを出すだけなら、書き込み系のツールは要りません。起動引数の--disable-writeで止めておきます。不要なカテゴリは--disable-<category>で個別に止められます(Prometheus側のカテゴリ名はprometheusなので、これは止めずに残します)。
claude mcp add-json grafana \
'{"command":"uvx","args":["mcp-grafana","--disable-write"],"env":{"GRAFANA_URL":"https://myinstance.grafana.net","GRAFANA_SERVICE_ACCOUNT_TOKEN":"<トークン>"}}'サービスアカウントには、対象のPrometheusデータソースに限ったdatasources:readとdatasources:queryを付けます。READMEの例では、特定のPrometheusだけを許す場合のスコープはdatasources:uid:prometheus-prodのように書かれています。Editorなどの組み込みロールでも動きますが、READMEは最小権限から外れると明記しています。
query_prometheus_histogramでパーセンタイルを出す
ヒストグラムのパーセンタイルは、PromQLではhistogram_quantile()で計算します。READMEのquery_prometheus_histogramは、この関数で算出するp50・p90・p95・p99用のツールです。パラメータの細目はREADMEに載っていないため、依頼文でメトリクス名と出したいパーセンタイルを伝え、Claudeに引数を組み立てさせる形になります。
依頼文は、たとえば次のような形です。メトリクス名は仮のものです。
Grafanaのprometheusデータソースで、http_request_duration_seconds の
p95とp99を直近10分の窓で出して。まずメトリクス名とラベルが
実在するか確認してから計算して。「実在確認から」と頼む理由は、メトリクス名の取り違えを避けるためです。list_prometheus_metric_namesとlist_prometheus_label_namesを先に呼ばせれば、存在しない名前で空の結果を受け取る事故を減らせます。
手書きPromQLで計算するときの式の形
query_prometheus_histogramで足りない切り口、たとえばジョブ別のp99を出したいときは、query_prometheusで式を直接実行します。式の形は次のとおりです。
| 対象 | 式 |
|---|---|
| クラシックヒストグラム(全体のp90) | 式histogram_quantile(0.9, sum by (le) (rate(http_request_duration_seconds_bucket[10m]))) |
| クラシックヒストグラム(ジョブ別) | 式histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m]))) |
| ネイティブヒストグラム(全体) | 式histogram_quantile(0.9, sum(rate(http_request_duration_seconds[10m]))) |
クラシックヒストグラムではleラベルが必須で、sum byにleを含めないと計算が成立しません。leのないサンプルは黙って無視されます。ClaudeがPromQLを組むときに最も落としやすい箇所なので、依頼文かCLAUDE.mdに書いておく価値があります。
## PromQLの書き方(Grafana MCP経由)
- パーセンタイルは histogram_quantile(rate(..._bucket[窓])) で計算する
- クラシックヒストグラムの sum by には必ず le を含める
- サマリー型の quantile ラベルを avg() で平均しない
- 実行前に list_prometheus_metric_names でメトリクス名を確認する3項目目の理由は、サマリーが事前計算したパーセンタイルを平均しても、統計的に意味を持たない値になるためです。
計測側がヒストグラムかサマリーかを先に確かめる
histogram_quantileが使えるのは、ヒストグラム型のメトリクスだけです。quantileラベルが付いたサマリー型は、パーセンタイルが計測側で事前計算されています。両者の違いは次のとおりです。
| 比較軸 | ネイティブヒストグラム | クラシックヒストグラム | サマリー |
|---|---|---|---|
| パーセンタイルの指定 | ネイティブヒストグラムPromQLで後から自由に指定 | クラシックヒストグラムPromQLで後から自由に指定 | サマリー計測時に固定 |
| 集計(複数インスタンスの合算) | ネイティブヒストグラム可能 | クラシックヒストグラム可能(バケット境界が揃っていれば) | サマリー不可 |
| 誤差を決めるもの | ネイティブヒストグラム設定した解像度 | クラシックヒストグラム該当バケットの幅 | サマリー設定したφ方向の誤差 |
メタデータ系ツールで_bucketサフィックスの有無やquantileラベルを確認させれば、どの式が使えるかを実行前に判断できます。複数レプリカをまたぐ全体のp99が欲しいのにサマリー型だった場合は、サマリーのパーセンタイルを平均しても意味のある値にならないため、計測側をヒストグラムにする選択肢を検討します。
ダッシュボードのように同じ式を何度も評価する場面では、計算が重くなることがあります。そうした場面では記録ルール(recording rule)で事前計算しておきます。
結果を読むときの注意:パーセンタイルは推定値
パーセンタイルは、サーバー側で計算したものも含めてすべて推定値です。ヒストグラムでは、値が入っているバケットの幅が誤差の上限になります。
たとえば、実際は220ms付近に集中しているリクエストがle="0.3"(200〜300msのバケット)に入ると、推定値は295msになります。SLOが300msなら「ぎりぎり」に見えますが、実態は余裕がある状況です。実測の220msと推定の295msの差は75msで、200〜300msという100ms幅のバケットの内側に収まっています。Claudeが返したp95が閾値に近いときは、バケット境界の設定を確認する前提で読むと誤読を避けられます。
もう1つ、バケット数が単調増加でない異常データでは、histogram_quantileは補正した上で情報レベルの注釈を付けます。注釈が出たら、入力データ側の問題を調べます。
依頼文の型:窓・集計軸・時間範囲を明示する
パーセンタイルの値は、rateの窓と集計軸で変わります。時間窓はrate()の角括弧で指定します。式の形が決まるのは、依頼文に次の3点が入っているときです。
| 伝える項目 | 依頼文の例 | 式に効く場所 |
|---|---|---|
| 窓 | 依頼文の例「直近10分」「5分窓」 | 式に効く場所rate(...[10m])の角括弧 |
| 集計軸 | 依頼文の例「ジョブ別」「全体で1本」 | 式に効く場所sum by (job, le)かsum by (le) |
| 時間範囲 | 依頼文の例「今の値」「過去6時間の推移」 | 式に効く場所instant(今)かrange(推移) |
query_prometheusはinstantとrangeの両方に対応するので、「今の値」と「推移」で使い分けを依頼文に書いておくと迷いません。障害の切り分けでは、まず直近の窓でp99を見て、悪化していれば推移を取る流れが自然です。
窓を短くすると、直近の変化には敏感になりますが、リクエスト数が少ないサービスでは推定が不安定になりやすくなります。この点はPrometheusの仕様上の記述ではなく、一般的な統計の性質からの見立てです。
最大値と最小値の推定には、次の書き方もあります。histogram_quantile(1, ...)が推定最大値、histogram_quantile(0, ...)が推定最小値です。外れ値の上限を知りたいときに役立ちます。
既存ダッシュボードのPromQLを出発点にする
自前でPromQLを組む前に、チームがすでにGrafanaに置いている式を拾う手があります。READMEにはget_dashboard_panel_queriesというダッシュボード用のツールがあり、パネルのタイトル、クエリ、データソースのUIDと種別を取得できます。必要な権限はdashboards:readです。
p95のパネルがすでにあるなら、その式のrateの窓やby句をそのまま使えます。「このダッシュボードのレイテンシのパネルと同じ式で、p99を出して」と頼めば、チームの既存の定義とずれにくくなります。ダッシュボード全体のJSONを読ませると、READMEが警告するとおりコンテキストウィンドウを大きく消費します。パネルのクエリだけを取るこのツールか、get_dashboard_summaryのほうが軽く済みます。
結果を人の目で確かめたいときは、generate_deeplinkでGrafana上の画面へのリンクを作れます。READMEのNavigation節には、データソースを指定したExploreのリンクを生成できると書かれています。Claudeの出した数値を、Exploreで同じ式を流して照合する使い方です。
権限と運用の設計
クエリ実行ツールは、データの中身を読み出せます。READMEの--disable-queryは、データソースへクエリを投げるツールを登録から外すフラグです。対象にはquery_prometheusとquery_prometheus_histogramが含まれ、メタデータ系は残ります。「探索はさせるが数値は読ませない」という構成に使えます。
Claude Code側でも許可を絞れます。Claude CodeのMCPツールのルールはmcp__<サーバー名>__<ツール名>の形で書き、サーバー名の後にワイルドカードを置けます。サーバー名をgrafanaとした場合の許可設定の例は次のとおりです。
{
"permissions": {
"allow": [
"mcp__grafana__list_prometheus_metric_names",
"mcp__grafana__list_prometheus_label_names",
"mcp__grafana__query_prometheus_histogram"
]
}
}この例では、探索系2つとパーセンタイル計算だけを確認なしで許可しています。手書きPromQLのquery_prometheusは許可リストに入れず、都度確認を挟む形です。mcp__ルールに括弧で引数条件を付けることはできません。引数単位の制御が必要なら、--disallowedToolsか、Grafana側のスコープで絞ります。
よくあるつまずき
空の結果が返る: メトリクス名かラベルの取り違えが大半です。メタデータ系ツールで実在を確認してから、計算に進みます。
ツールが見えない: --disable-prometheusや--disable-queryを付けていないか確認します。カテゴリ単位の無効化は、サーバー起動引数で決まります。
権限エラーになる: datasources:queryだけでなくdatasources:readも必要です。スコープのUIDがデータソースと一致しているかも見ます。
ネイティブ用の式をクラシックに当ててしまう: ネイティブヒストグラムの式は_bucketサフィックスを持たず、sum byにleも要りません。クラシック用の式をそのまま流すと、leのないサンプルは無視される仕様のため、期待した値になりません。メタデータ系ツールで、対象のメトリクス名に_bucketが実在するかを確かめます。
ジョブ別を頼んだのに全体の値が返る: 集計軸が依頼文になければ、式はsum by (le)の全体集計になりえます。「ジョブ別」「インスタンス別」と書いて、by句に入れる軸を指定します。
Lokiも同時に調べたい: ログ側のクエリはLogQL検索の記事にまとめています。
Claude Codeから繋ぐ構成を前提にしましたが、READMEのクイックスタートはClaude DesktopやCursorなど他のMCPクライアントも想定しています。
まとめ
mcp-grafanaのPrometheus向けツールは、探索(メタデータ4つ)、汎用クエリ(query_prometheus)、パーセンタイル(query_prometheus_histogram)の3層で考えると整理できます。p50〜p99の定型は専用ツール、ジョブ別などの切り口は手書きのhistogram_quantile、という分担です。
結果は推定値であり、バケット幅が誤差を決めます。権限はdatasources:queryをUID単位で絞り、--disable-writeと許可リストで運用を固めると、読み取りに専念させやすくなります。