Graylog MCP Server について
Graylog MCP Serverは、複数の設定済みインスタンスにも対応する、Graylogログ検索・分析用のJavaScriptサーバーです。運用担当者やエージェントが実在するフィールドを確認し、検索条件の不一致、ログのない期間、インデックス遅延を区別できます。
主な機能
- 01ストリーム横断のログ検索
- 02フィールド集計と時間ヒストグラム
- 03ストリームとインデックス済みフィールドの確認
- 04メッセージドキュメント全体の取得
- 05空の検索結果とインデックス遅延の説明
- 06複数のGraylogインスタンスへのクエリ
活用シーン
- 01指定した時間帯のエラー調査
- 02エラーが多いサービスやコンテナの特定
- 03絞り込み前の実在フィールド名と値の確認
- 04本番環境とステージング環境のログ比較
MCP 対応
Graylogのストリーム検出、ログ検索、集計、フィールド検出、メッセージ全体の取得をMCPツールとして提供します。クライアントはAPIトークンを使い、設定済みの1つ以上のGraylogインスタンスを検索できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @jperelli/graylog-mcpGRAYLOG_BASE_URL_INSTANCE_1Base URL of the first Graylog instance, e.g. http://graylog.example.com:9000GRAYLOG_API_TOKEN_INSTANCE_1シークレットAPI token for the first Graylog instance (used as the HTTP Basic username).GRAYLOG_LABEL_INSTANCE_1Optional human-readable label for the first instance (default: instance_1).ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
5掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| limit | number | いいえ | 返すストリームの最大数。デフォルト:50。 |
| instance | enum | いいえ | クエリ対象の Graylog インスタンス。アクティブ:"instance_1"。デフォルト:"instance_1"。instance_1 |
| titleContains | string | いいえ | ストリームタイトルに対する大文字と小文字を区別しない部分文字列フィルター。 |
詳細
Graylog MCP サーバー
Graylog と連携する、JavaScript 製の最小限の MCP(Model Context Protocol)サーバーです。
特長
- JavaScript 製の MCP サーバー
- ツール:
search(複数のストリームから一致するログ行を読み取る)、analyze(フィールドごとに一致結果を集計し、任意で時間ヒストグラムを表示する)、list_fields(存在するフィールドを確認する)、list_streams(読み取り可能なストリームを見つける)、get_message(ドキュメント全体を1件取得する) - 検索結果が空の場合、その理由を説明します。 検索結果が0件の場合、クエリが誤っているのか、指定期間中にログがないのか、Graylog がまだログをインデックス化していないのかを報告します。通常は見分けがつかず、エージェントが堂々巡りに陥る3つの原因です
- 推測ではなく、実際の情報を調べられます。
list_fieldsとanalyzeのvalueContainsを使えば、実在するフィールド名や値を調べられます。誤った名前や値を推測するとヒット数が0になり、「ログが存在しない」と受け取られるためです - トークン効率を考慮した設計です。
searchはデフォルトで重要度の高いフィールドを簡潔に返し、verboseを指定するとドキュメント全体を取得できます - サーバーレベルの「instructions」マニュアルにより、クライアントはクエリ構文、ストリームのスコープ設定ルール、重要度に関する注意点を最初に把握できます
- 複数インスタンスに対応しており、1つの MCP サーバーから複数の Graylog サーバーにクエリできます
必要条件
- Node.js 18+
設定
番号付きの環境変数を使って、1つ以上の Graylog インスタンスを設定します。
| 変数 | 必須 | 説明 |
|---|---|---|
GRAYLOG_BASE_URL_INSTANCE_N | はい | インスタンス N の Graylog ベース URL |
GRAYLOG_API_TOKEN_INSTANCE_N | はい | インスタンス N の API トークン |
GRAYLOG_LABEL_INSTANCE_N | いいえ | 人が読みやすいラベル(デフォルト:instance_N) |
N を 1、2、3、…に置き換えて、必要な数のインスタンスを登録します。BASE_URL と API_TOKEN の両方が設定されているインスタンスのみが有効になります。
MCP クライアントでの使用
インストールは不要です。npx がサーバーを自動的にダウンロードして実行します。
Claude Code
claude mcp add graylog-mcp \
-e GRAYLOG_BASE_URL_INSTANCE_1=http://your-graylog-production.example.com:9000 \
-e GRAYLOG_API_TOKEN_INSTANCE_1=your_production_token \
-e GRAYLOG_LABEL_INSTANCE_1=production \
-e GRAYLOG_BASE_URL_INSTANCE_2=http://your-graylog-staging.example.com:9000 \
-e GRAYLOG_API_TOKEN_INSTANCE_2=your_staging_token \
-e GRAYLOG_LABEL_INSTANCE_2=staging \
-- npx -y @jperelli/graylog-mcp@latest
または、~/.claude.json に手動で追加します。
{
"mcpServers": {
"graylog-mcp": {
"command": "npx",
"args": ["-y", "@jperelli/graylog-mcp@latest"],
"env": {
"GRAYLOG_BASE_URL_INSTANCE_1": "http://your-graylog-production.example.com:9000",
"GRAYLOG_API_TOKEN_INSTANCE_1": "your_production_token",
"GRAYLOG_LABEL_INSTANCE_1": "production",
"GRAYLOG_BASE_URL_INSTANCE_2": "http://your-graylog-staging.example.com:9000",
"GRAYLOG_API_TOKEN_INSTANCE_2": "your_staging_token",
"GRAYLOG_LABEL_INSTANCE_2": "staging"
}
}
}
}
Cursor
~/.cursor/mcp.json に追加します。
{
"mcpServers": {
"graylog-mcp": {
"command": "npx",
"args": ["-y", "@jperelli/graylog-mcp@latest"],
"env": {
"GRAYLOG_BASE_URL_INSTANCE_1": "http://your-graylog-production.example.com:9000",
"GRAYLOG_API_TOKEN_INSTANCE_1": "your_production_token",
"GRAYLOG_LABEL_INSTANCE_1": "production",
"GRAYLOG_BASE_URL_INSTANCE_2": "http://your-graylog-staging.example.com:9000",
"GRAYLOG_API_TOKEN_INSTANCE_2": "your_staging_token",
"GRAYLOG_LABEL_INSTANCE_2": "staging"
}
}
}
}
Claude Desktop
設定ファイルの場所:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/claude-desktop/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
上記の Cursor 向けのものと同じ JSON 構造を使用してください。
使用方法
設定が完了すると、ツールが利用可能になり、必要に応じて自動的に呼び出されます。通常は、トークンが読み取れるすべての内容を対象とする Default Stream(000000000000000000000001)を検索し、analyze でパターンを見つけ、search で個々の行を読み取り、get_message でヒットした項目を1件ずつ全体表示します。特定の名前付きストリームに対象を絞る場合にのみ、list_streams を使用してください。プロンプトの例:
Search Graylog for errors in the payments namespace in the last 15 minutes.
Query the "staging" instance.
Which containers produced the most errors in the last hour?
Which namespaces have "payments" in the name?
エージェントにフィールド名や値を推測させないでください。 存在しないフィールドや値を指定したクエリは何も一致せず、「ログが存在しない」場合とまったく同じに見えます。list_fields で存在するフィールドを確認でき、valueContains を指定した analyze で、そのフィールドに実際にどのような値があるかを確認できます。
利用可能なツール
list_streams
設定済みの API トークンで読み取り可能なストリーム(ID とタイトル)を一覧表示します。読み取り可能なもののみが返されます。
通常、これは必要ありません。search/analyze に Default Stream の ID 000000000000000000000001 を渡せば、トークンで読み取り可能なすべての内容を対象にできます。クラスターには数千のストリームが存在する場合があるため(執筆者の環境では 1,205 件)、出力には上限があります。名前が特定のストリームを探す場合は titleContains を使用してください。
Parameters:
instance(string, optional): クエリ対象の Graylog インスタンスのラベルです。デフォルトでは、最初に設定されたインスタンスが使用されます。titleContains(string, optional): ストリームタイトルに対する、大文字と小文字を区別しない部分文字列フィルターです(例:catalogue)。limit(number, optional): 返すストリームの最大数です。デフォルト:50。Default Stream は常に含まれ、上限数にはカウントされません。
list_fields
インデックスに実際に存在するメッセージフィールドを一覧表示します。結果で見たことのないフィールドを使って検索する前に、名前を推測せずに済むよう、これを使用してください。
クラスターには数千のフィールドがインデックスされています(執筆者の環境では 3,269 件)。名前がよく似たフィールドも多く、namespace_name、Pod_namespace、pod_namespace、Namespace がすべて存在していても、shipper によって値が設定されるのはそのうち 1 つだけという場合があります。絞り込むには contains を渡してください。
Parameters:
contains(string, optional): フィールド名に対する、大文字と小文字を区別しない部分文字列フィルターです。例:namespace、pod、level。limit(number, optional): 返すフィールド名の最大数です。デフォルト:100。instance(string, optional): インスタンスのラベルです。デフォルトでは、最初に設定されたインスタンスが使用されます。
search
1 つ以上のストリームから一致するログ行を読み取り、新しい順にまとめて返します。デフォルトでは、重要度の高いフィールド(timestamp、source、level、container_name、pod_name、namespace_name、application_name、service、logger_name、name、msg、err、stack、message)を簡潔に投影し、各ヒットの _id/_index を加えます。また、生の message 本文は 500 文字に切り詰められるため、エージェントのコンテキストを小さく保てます。すべての値が設定されたフィールドを切り詰めずに取得するには、verbose: true を設定するか、明示的に fields を渡してください。ストリーム ID は必須です。すべてのストリームを対象とする検索は暗黙には実行されません。権限が制限されたトークンでは 403 Not authorized が返されるためです。
name/msg/err/stack が含まれているのは、JSON ログ行(pino、bunyan、structlog)を解析する shipper が、そのキーを実際のフィールドとして抽出するためです。これらのフィールドがイベントの要約であり、取得コストも低くなります。それらを含む生の message 本文はそうではないため、デフォルトで大幅に切り詰められます。
searchの前にanalyzeを使ってください。 生のログ行は、このサーバーが返すデータの中で最もコストがかかります。同じエラーが 100 回繰り返された場合、searchではanalyzeによる集約済みの 1 行と比べて 100 倍のコストがかかるうえ、得られる情報は少なくなります。必要なログ行が分かってからsearchを使ってください。
ヒント: 名前付きストリームにルーティングされていないメッセージも含め、トークンから見えるすべての内容を検索するには、Default Stream の ID
000000000000000000000001を渡してください。list_streamsにも表示されます。
Parameters:
query(文字列、必須):Graylog/Elasticsearch 構文を使用した検索クエリです。例:msg:Error、namespace_name:app-payments-qa AND error、source:api-*、*。streams(文字列、必須):検索対象のストリーム ID をカンマ区切りで指定します。list_streamsで取得してください。instance(文字列、任意):クエリ対象の Graylog インスタンスのラベルです。デフォルトでは、最初に設定されたインスタンスが使用されます。searchTimeRangeInSeconds(数値、任意):秒単位の相対時間範囲です。デフォルト:900(15 分)。from/to(文字列、任意):ISO-8601 UTC 形式で指定する絶対時間範囲です(例:2026-07-11 14:00:00)。両方を指定すると相対時間範囲より優先されます。既知のインシデントの時間範囲を調査するときに使用してください。searchCountLimit(数値、任意):メッセージの最大件数です。デフォルト:50。messageChars(数値、任意):各ヒットの生メッセージ本文の最大文字数です。デフォルト:500。必要な詳細が解析済みフィールドではなく生本文にある場合に限り、増やしてください。verbose(ブール値、任意):簡潔な射影ではなく、値が入力されているすべてのフィールドを省略せずに返します。デフォルト:false。fields(文字列、任意):返すフィールドをカンマ区切りで明示的に指定します。簡潔な射影より優先されます。
レスポンスは { returned, total_matched, streams, messages, note?, projection?, why_no_results? } です。total_matched はストリーム全体のヒット総数であり(searchCountLimit によって上限が設定される returned を超える場合があります)、その場合は note に追加の結果を表示する方法が記載されます。
検索結果がない場合は、その理由が示されます。 単に total_matched: 0 と表示されても曖昧です。原因によって必要な対応が異なるため、why_no_results には該当する理由が示されます。
- 時間範囲内にメッセージはあるものの、一致するものがありません。 ストリームと時間範囲は正しいため、クエリに誤りがあります。通常は、フィールド名または値の推測が原因です。
list_fields/analyzeで確認してください。 - 時間範囲内にメッセージがなく、インデックス作成は最新です。 これらのストリームは実際に静かな状態です。
- 時間範囲内にメッセージがなく、最新のインデックス済みメッセージは数時間前のものです。 Graylog でインデックス作成が続いています。 ログは存在し、受信済みですが、まだ検索できる状態になっていません。レスポンスにはインデックス作成の遅延時間とジャーナルのバックログが示されます。ログが欠落していると判断しないでください。時間範囲を広げるか、再試行してください。
最後のケースは「このサービスはログを出力していない」と誤解されやすく、負荷時にパイプラインが取り込みより数時間遅れることがあるという、このプロジェクトが現在の形になった理由でもあります。
ログレベルに関する注意 — 深刻度は推測せず、確認してください。 サービスによっては、トップレベルの Graylog
levelを出力します(syslog:3=error、4=warn)。一方、JSON をログ出力するサービスもあり、シッパーはそのキーをサービス独自のフィールドとして抽出します。pino の{"level":50,"msg":"Error","name":"SvcX"}は通常、msgとnameのフィールドになりますが、数値のlevelは失われます。コンテナー独自のlevel(多くの場合7)と衝突するため、エラーが明らかに存在していても、level:50とlevel:ERRORはどちらも何にも一致しません。level:ERROR OR level:50 OR error OR exception OR fatalのような OR 条件を推測しても、エージェントの試行を無駄にします。代わりにlist_fields(contains: "level"、"msg"、"err")を実行し、続いてmsgを対象にanalyzeを実行して実際の値を確認してください。自由入力のerrorは代替手段として使えますが、exceptionやfatalが存在するとは限りません。また、"level":50をクエリとして使用しないでください。:の前に引用符で囲んだ文字列を置くのは、無効な Lucene 構文です。
analyze
生の行を返す代わりに、フィールドの上位の値ごとに一致するメッセージを集計します。たとえば、指定した期間のエラーをどの source、container_name、level が占めているかを確認できます。必要に応じて、一致した件数の合計を示す時間ヒストグラムも追加できます。用途は2つあります。
-
何が失敗しているかを特定します。 メッセージフィールド(
msg、またはlist_fieldsで確認できる短い要約フィールドなど)で集計すると、同じエラーが千回繰り返されても、件数付きの1行にまとめられます。name/container_name/sourceで集計すれば、どの対象がエラーを出しているかを確認できます。「何かおかしいことが起きているか?」から答えにたどり着く最短の方法です。同等のsearchで数万トークンかかるところを、数百トークンで済ませられます。analyze field:msg → 1386 Error 60 rabbitmq pub/sub: publishing to …exchange failed analyze field:name → 1290 CatalogueService 96 ShippingService -
フィルターに使う値を先に見つけます。
valueContainsを設定すると、名前をうろ覚えのネームスペース/ポッド/サービスの正確な名前を検索できます。Elasticsearch は先頭のワイルドカードを拒否するため、namespace_name:*catalogue*は空の結果ではなくエラーになります。値の部分文字列検索には、この方法を使う必要があります。
パラメーター:
field(string、必須):分類に使うフィールドです。例:source、namespace_name、container_name、level。結果で見たことがない場合は、list_fieldsで存在を確認してください。streams(string、必須):カンマ区切りのストリーム ID、または Default Stream の ID です。query(string、任意):集計前に適用する Lucene フィルターです。デフォルト:*。valueContains(string、任意):返される値に対する、大文字と小文字を区別しない部分文字列フィルターです。広範囲のバケット検索を行い、ローカルで適用されます。instance(string、任意):インスタンスのラベルです。デフォルトでは、設定済みの最初のインスタンスが使われます。searchTimeRangeInSeconds(number、任意):相対的な範囲を秒数で指定します。デフォルト:900。または、絶対的な期間を指定する場合はfrom/toを使用してください。size(number、任意):返す上位の値の数です。デフォルト:20。histogramInterval(string、任意):minute、hour、day、week、monthのいずれかです。設定すると、レスポンスに一致件数の時間ヒストグラムも含まれます。
レスポンスは { field, query, streams, total_matched, top_values: [{ value, count }], not_in_top_values, histogram?, note?, warning?, failed_streams?, why_no_results? } です。not_in_top_values は、返された値では件数を説明できない一致数を示します。フィールドに値がないメッセージと、上限を超えたバケットが含まれます。
トークンで読み取れないストリームがあっても、致命的なエラーにはならず、スキップされます。読み取り可能なストリームでの集計結果に加えて、除外されたストリームを示す failed_streams と warning が同じレスポンスに含まれます。
Graylog の Views/Aggregations API(
POST /api/views/search/sync)を使って実装されています。この API は、すべてのストリームを1つのリクエストで処理します。以前使われていた旧式のsearch/universal/*/termsと/histogramエンドポイントは Graylog 6.0 で削除されており、同バージョンでは404を返します。
get_message
search で返された _id と _index を使って、単一メッセージの完全な未切り詰めドキュメントを取得します。簡潔な search の後に使用すると、すべての結果を詳細な形式で取得せずに、1件のヒットを詳しく調べられます。
パラメーター:
messageId(string、必須):検索結果の_idです。index(string、必須):検索結果の_indexです。instance(string、任意):インスタンスのラベルです。デフォルトでは、設定済みの最初のインスタンスが使われます。
設計の根拠
ここにあるツールは、Graylog REST API の各エンドポイントをそのまま再現するのではなく、AI エージェントが実際にうまく使える MCP サーバーの構築に関する公開ガイダンスをもとに設計されています。主な考え方と、その出典は次のとおりです。
-
API の構成ではなくエージェントのタスクに合わせて設計し、成果を重視した少数のツールを用意します。 Sentry の David Cramer は、多くの MCP サーバーはエージェントが実行する必要のある作業ではなく、生のエンドポイントをラップしているため、依然として有用性が低いと指摘しています。Sentry はその代わりに、厳選した小規模なツールセットを提供しています。そのため、このサーバーはエンドポイントごとのラッパーではなく、タスクに合わせた 4 つのツール(検出 → 集計 → 読み取り → 詳細調査)を公開します。 , David Cramer, MCP Is Not Good Yet · Yes, Sentry has an MCP Server (…and it's pretty good)
-
情報量の高いコンテキストを返し、トークンの予算を守ります。 Anthropic のガイダンスでは、ツールは簡潔で関連性の高い結果を返し、生データをモデルのコンテキストにそのまま大量に投入するのではなく、フィルタリング、切り捨て、ページネーションに対応するべきとされています。そのため、
searchはデフォルトで簡潔な形式に整えた結果を返し(verboseとget_messageは必要に応じて追加で利用できます)、結果数に上限を適用した場合はnoteを出力します。 , Anthropic, Writing effective tools for agents -
生データの取得と集計・分析ツールを組み合わせます。 New Relic のログ用 MCP は、ログ行を一覧表示するだけではありません。キーワード検索に加え、エラーパターンや繰り返し発生する問題を示す分析ツールを提供しています。
analyzeは Graylog で同様の役割を果たし、フィールドの上位値と任意のヒストグラムを返します。これにより、エージェントは個々の行を読む前に、効率よくパターンを見つけられます。 , New Relic, MCP tool reference -
「ユーザーマニュアル」は各ツールの説明ではなく、サーバーのインストラクションに記載します。 MCP プロジェクトは、ツール間で共通するワークフロー、制約、特記事項を最上位の
instructionsフィールドに記載し、個々のツールの説明は簡潔に保つことを推奨しています。このサーバーのinstructionsでは、クエリ構文、必須のストリーム範囲指定ルール(範囲が限定されたトークンでは、指定しないと403が返されます)、および pino の数値重大度に関する注意点を、あらかじめ一度に説明します。 , Model Context Protocol, Server Instructions: Giving LLMs a user manual for your server
トラブルシューティング
- 少なくとも
GRAYLOG_BASE_URL_INSTANCE_1とGRAYLOG_API_TOKEN_INSTANCE_1が設定されていることを確認してください。 - Node.js 18 以降がインストールされていることを確認してください。
- 詳細なログを標準エラー出力に出すには、環境変数に
DEBUG=trueを設定してください。
クレジット
現在の実装は Julian Perelli によるものです。Leo Ruellas による以前の取り組みをもとにしています。lcaliani/graylog-mcp。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。