mcpField
G
Graylog MCP Server

Graylog MCP Server

ローカル
github.com/jperelliデータ・分析215 週間前に更新

Graylog MCP Server について

Graylog MCP Serverは、複数の設定済みインスタンスにも対応する、Graylogログ検索・分析用のJavaScriptサーバーです。運用担当者やエージェントが実在するフィールドを確認し、検索条件の不一致、ログのない期間、インデックス遅延を区別できます。

主な機能

  1. 01ストリーム横断のログ検索
  2. 02フィールド集計と時間ヒストグラム
  3. 03ストリームとインデックス済みフィールドの確認
  4. 04メッセージドキュメント全体の取得
  5. 05空の検索結果とインデックス遅延の説明
  6. 06複数のGraylogインスタンスへのクエリ

活用シーン

  1. 01指定した時間帯のエラー調査
  2. 02エラーが多いサービスやコンテナの特定
  3. 03絞り込み前の実在フィールド名と値の確認
  4. 04本番環境とステージング環境のログ比較

MCP 対応

Graylogのストリーム検出、ログ検索、集計、フィールド検出、メッセージ全体の取得をMCPツールとして提供します。クライアントはAPIトークンを使い、設定済みの1つ以上のGraylogインスタンスを検索できます。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"jperelli-graylog": {
"command": "npx",
"args": [
"-y",
"@jperelli/graylog-mcp"
],
"env": {
"GRAYLOG_BASE_URL_INSTANCE_1": "<GRAYLOG_BASE_URL_INSTANCE_1>",
"GRAYLOG_API_TOKEN_INSTANCE_1": "<GRAYLOG_API_TOKEN_INSTANCE_1>",
"GRAYLOG_LABEL_INSTANCE_1": "<GRAYLOG_LABEL_INSTANCE_1>"
}
}
}
}
起動コマンドnpx -y @jperelli/graylog-mcp
設定が必要な環境変数
GRAYLOG_BASE_URL_INSTANCE_1Base URL of the first Graylog instance, e.g. http://graylog.example.com:9000
GRAYLOG_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 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@jperelli/graylog-mcp1.3.0

ツール

5

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

パラメーター型必須説明
limitnumberいいえ返すストリームの最大数。デフォルト:50。
instanceenumいいえクエリ対象の Graylog インスタンス。アクティブ:"instance_1"。デフォルト:"instance_1"。instance_1
titleContainsstringいいえストリームタイトルに対する大文字と小文字を区別しない部分文字列フィルター。

詳細

Graylog MCP サーバー

CI npm version npm downloads node license

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つあります。

  1. 何が失敗しているかを特定します。 メッセージフィールド(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
    
  2. フィルターに使う値を先に見つけます。 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

コメント

MCP は初めてですか?

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

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