mcpField
G
Graylog MCP Server

Graylog MCP Server

本地服务
github.com/jperelli数据与分析215 周前更新

关于 Graylog MCP Server

Graylog MCP Server 是用于查询和分析 Graylog 日志的 JavaScript 服务,支持配置多个实例。它帮助运维人员和 Agent 发现实际字段,并区分查询无匹配、时间段无日志与索引延迟。

主要功能

  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 令牌查询一个或多个已配置的 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

一个使用 JavaScript 编写、与 Graylog 集成的精简 MCP(模型上下文协议)服务。

功能

  • JavaScript MCP 服务
  • 工具:search(读取多个流中的匹配日志行)、analyze(按字段聚合匹配项,并可选生成时间直方图)、list_fields(查看有哪些字段)、list_streams(发现可读取的流)和 get_message(获取一份完整文档)
  • 空结果会说明原因。 零匹配的搜索会报告是查询有误、时间窗口内没有日志,还是 Graylog 尚未索引日志——这三种情况原本看起来完全一样,会让 Agent 陷入反复尝试
  • 主动发现,而非猜测。 list_fields 和 analyze 的 valueContains 可让 Agent 查找真实的字段名和值,而不是凭空猜测,因为猜错会返回 0 条结果,看起来就像“没有日志”
  • 设计上注重节省令牌:默认情况下,search 仅返回简洁的高信号字段;使用 verbose 可选择返回完整文档
  • 服务级别的“说明”手册会预先向客户端介绍查询语法、流范围规则和严重级别方面的特殊情况
  • 支持多个实例,可通过单个 MCP 服务查询多个 Graylog 服务

要求

  • Node.js 18+

配置

使用带编号的环境变量配置一个或多个 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 完整检查一条匹配结果。只有需要限定到特定命名流时,才使用 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?

不要让 Agent 猜测字段名或值。 查询不存在的字段或值时不会匹配任何内容,看起来就像“没有日志”。list_fields 会告诉你有哪些字段,使用 valueContains 的 analyze 则会告诉你某个字段实际有哪些值。

可用工具

list_streams

列出已配置的 API 令牌可读取的流(id + 标题)。仅返回可读取的流。

通常不需要使用此工具:将默认流 id 000000000000000000000001 传递给 search/analyze,即可涵盖令牌可读取的所有内容。一个集群可以容纳数千个流(作者的集群有 1,205 个),因此输出会受到限制——要查找特定名称的流,请使用 titleContains。

参数:

  • instance(字符串,可选):要查询的 Graylog 实例标签。默认为第一个已配置的实例。
  • titleContains(字符串,可选):对流标题进行不区分大小写的子字符串筛选(例如 catalogue)。
  • limit(数字,可选):最多返回的流数。默认值:50。默认流始终包含在内,且不计入上限。
list_fields

列出索引中实际存在的消息字段。在搜索结果中尚未见过的字段之前,先使用此工具,这样就不会猜字段名。

一个集群会为数千个字段编制索引(作者的集群有 3,269 个),而且常有名称相近的字段——namespace_name、Pod_namespace、pod_namespace 和 Namespace 可能都存在,但只有一个字段被日志采集器填充。传入 contains 可缩小范围。

参数:

  • contains(字符串,可选):对字段名进行不区分大小写的子字符串筛选,例如 namespace、pod、level。
  • limit(数字,可选):最多返回的字段名数量。默认值:100。
  • instance(字符串,可选):实例标签。默认为第一个已配置的实例。
search

跨一个或多个流读取匹配的日志行,并按时间从新到旧合并。默认情况下,它会返回精简投影,包含高信号字段(timestamp、source、level、container_name、pod_name、namespace_name、application_name、service、logger_name、name、msg、err、stack、message),以及每条命中的 _id/_index;原始 message 正文会截断至 500 个字符,以缩小 Agent 的上下文。设置 verbose: true(或传入明确的 fields)可获取所有已填充字段,且不截断。必须提供流 ID;不会隐式执行全流搜索,因为权限受限的令牌会收到 403 Not authorized。

name/msg/err/stack 这些字段之所以存在,是因为能解析 JSON 日志行的日志采集器(pino、bunyan、structlog)会将其中的键提取为实际字段。这些字段就是事件摘要,而且开销很低——包含这些内容的原始 message 正文则不是,因此默认会大幅截断。

优先使用 analyze,再使用 search。 原始日志行是此服务返回的开销最高的内容。通过 search 获取同一错误的一百条重复记录,开销是 analyze 返回一条聚合记录的一百倍,提供的信息却更少。确定要查看哪条日志后,再使用 search。

**提示:**要搜索令牌可见的所有内容(包括未路由到具名流的消息),请传入默认流 id 000000000000000000000001。list_streams 也会显示该流。

参数:

  • 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 是所有流中的命中总数(可能超过 returned,后者受 searchCountLimit 限制);如果超过,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 这样的析取查询,只会让 Agent 浪费轮次。应改为运行 list_fields(contains: "level"、"msg"、"err"),然后对 msg 运行 analyze,查看实际取值。自由文本 error 可作为后备方案;不要假设 exception 或 fatal 字段存在。另外,避免将 "level":50 用作查询,因为冒号前的带引号字符串不是有效的 Lucene 语法。

analyze

按某个字段的高频值聚合匹配的消息,而不是返回原始行,例如查看某个时间窗口内的错误主要来自哪个 source、container_name 或 level。还可以选择添加匹配总量的时间直方图。有两种用途:

  1. 找出故障来源。 按消息字段(msg,或 list_fields 显示的其他简短摘要字段)聚合,将同一错误的上千条重复记录合并为一行并显示计数;按 name / container_name / source 聚合,则可以查看这些消息来自哪里。这是从“有没有异常?”最快找到答案的途径——相比之下,使用 search 查出同样结果需要数万 token,而此方法只需几百 token:

    analyze field:msg    → 1386  Error
                             60  rabbitmq pub/sub: publishing to …exchange failed
    analyze field:name   → 1290  CatalogueService
                             96  ShippingService
    
  2. 先发现值,再按该值筛选。 将 valueContains 设为你只大致知道的命名空间、Pod 或服务的名称,以查找确切名称。Elasticsearch 会拒绝前置通配符,因此 namespace_name:*catalogue* 会直接报错,而不是返回空结果——这是唯一能按子串匹配值的方法。

参数:

  • field(字符串,必填):用于分类的字段,例如 source、namespace_name、container_name、level。如果尚未在结果中看到该字段,请使用 list_fields 确认它存在。
  • streams(字符串,必填):以逗号分隔的流 ID,或 Default Stream id。
  • query(字符串,可选):聚合前应用的 Lucene 筛选条件。默认值:*。
  • valueContains(字符串,可选):对返回的值应用不区分大小写的子串筛选,在本地对宽范围桶扫描结果进行筛选。
  • instance(字符串,可选):实例标签。默认为第一个已配置实例。
  • searchTimeRangeInSeconds(数字,可选):相对时间范围,单位为秒。默认值:900。也可以使用 from/to 指定绝对时间范围。
  • size(数字,可选):返回的高频值数量。默认值:20。
  • histogramInterval(字符串,可选):可选值为 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 的视图/聚合 API(POST /api/views/search/sync)实现,该 API 会在单个请求中处理所有流。此功能最初使用的旧版 search/universal/*/terms 和 /histogram 端点已在 Graylog 6.0 中移除,在该版本中会返回 404。

get_message

根据消息的 _id 和 _index(两者均由 search 返回)获取单条消息的完整、未截断文档。在简洁的 search 后使用此工具,可以详细检查一条命中结果,而无需拉取所有结果的完整内容。

参数:

  • messageId(字符串,必填):搜索结果中的 _id。
  • index(字符串,必填):搜索结果中的 _index。
  • instance(字符串,可选):实例标签。默认为第一个已配置实例。

设计理念

这里的工具基于已发布的指导原则设计,旨在构建 AI Agent 能够有效使用的 MCP 服务,而不是逐个端点照搬 Graylog REST API。核心理念及其来源如下:

  • 围绕 Agent 的任务设计,而非 API 表面;工具应更少且以结果为导向。 David Cramer(Sentry)指出,大多数 MCP 服务仍然表现不佳,因为它们封装的是原始端点,而不是 Agent 需要完成的工作;Sentry 则提供了一套精心挑选且适度精简的工具集。因此,本服务提供 4 个围绕任务设计的工具(发现 → 聚合 → 读取 → 深入查看),而不是每个端点都提供一个封装工具。 , David Cramer,MCP 目前还不够好 · 是的,Sentry 有 MCP 服务(……而且相当不错)

  • 返回高信号上下文,并保护令牌预算。 Anthropic 的指导原则是,工具应返回简洁、相关的结果,并支持过滤、截断和分页,而不是将原始数据倾倒到模型的上下文中。因此,search 默认返回精简的结果视图(可选择使用 verbose 和 get_message 获取更多信息),并在结果数量达到上限时发出 note。 , Anthropic,为 Agent 编写有效的工具

  • 将原始数据检索与聚合/分析工具配套使用。 New Relic 的日志 MCP 不仅会列出日志行,还提供关键字搜索和分析工具,用于展示错误模式和反复出现的问题。Graylog 的 analyze 承担了这一角色(返回字段的高频值,并可选择提供直方图),让 Agent 能够在读取单独的日志行之前,以较低成本发现模式。 , New Relic,MCP 工具参考

  • 将“用户手册”放在服务说明中,而不是重复写进每个工具描述。 MCP 项目建议使用顶层 instructions 字段说明适用于多个工具的工作流、限制和特殊情况,同时精简各个工具的描述。本服务的 instructions 会一次性说明查询语法、必须限定流的规则(否则权限有限的令牌会收到 403),以及 pino 数字严重级别的注意事项。 , Model Context Protocol,服务说明:为大模型提供服务用户手册

故障排除

  • 确保已设置至少 GRAYLOG_BASE_URL_INSTANCE_1 和 GRAYLOG_API_TOKEN_INSTANCE_1。
  • 确认已安装 Node.js 18+。
  • 在环境变量中设置 DEBUG=true,即可启用向 stderr 输出的详细日志。

致谢

当前实现由 Julian Perelli 完成。基于 Leo Ruellas 之前的工作:lcaliani/graylog-mcp。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。