graylog-server
A lightweight and easy-to-use MCP server for querying and retrieving logs from Graylog. Integrate your AI assistants (like Cursor and Claude) with your Graylog instance.
Installation
npx graylog-mcp-serverAsk AI about graylog-server
Powered by Claude Β· Grounded in docs
I know everything about graylog-server. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Graylog MCP Server
An MCP (Model Context Protocol) server for Graylog that enables AI assistants to search logs, filter by fields, view surrounding context, list streams, and discover field values.
Features
- Multi-connection support β configure and switch between multiple Graylog instances
- Advanced log search β query logs with field-level filters (env, level, source, logger_name, etc.)
- Advanced time ranges β flexible time specifications (
1h,30m,2d) and absolute ranges - Log aggregations β histograms, field statistics, and time-series analysis
- Exact match by default β queries use exact matching unless explicitly set to fuzzy/wildcard
- Surrounding messages β view messages around a specific log entry by message ID or timestamp
- Pagination β page through large result sets
- Stream listing β list all available Graylog streams
- Field value discovery β find distinct values for any field (top N by count)
- Default fields β returns only key fields by default, reducing noise from internal Graylog fields
Requirements
- Node.js 18+
- Graylog 6.x (tested on 6.2.10)
Installation
git clone git@github.com:jagadeesh52423/graylog-mcp.git
cd graylog-mcp
npm install
Configuration
Create a config file at ~/.graylog-mcp/config.json:
{
"connections": {
"nonprod": {
"baseUrl": "http://your-graylog-server:9000",
"apiToken": "your_graylog_api_token",
"defaultFields": ["timestamp", "gl2_message_id", "source", "env", "level", "message", "logger_name"]
},
"prod": {
"baseUrl": "http://prod-graylog:9000",
"apiToken": "your_prod_api_token"
}
},
"defaultFields": ["timestamp", "message", "level", "source", "PODNAME"]
}
Configuration options:
| Option | Level | Description |
|---|---|---|
connections | Root | Named Graylog instances with baseUrl and apiToken |
defaultFields | Root | Global default fields for all connections (optional) |
defaultFields | Connection | Override default fields for a specific connection (optional) |
Field resolution priority:
- Connection-specific
defaultFields(highest) - Global
defaultFields - All fields (
*) if neither is set
Use with an MCP Client
Add this server to your MCP client configuration. Common locations:
- Claude Code:
~/.claude/mcp.json - Cursor:
~/.cursor/mcp.json - Claude Desktop (macOS):
~/Library/Application Support/Claude/claude_desktop_config.json
Example config using npx (recommended):
{
"mcpServers": {
"graylog": {
"command": "npx",
"args": ["graylog-mcp-server"],
"env": {
"GRAYLOG_CONFIG_PATH": "/path/to/your/config.json"
}
}
}
}
The GRAYLOG_CONFIG_PATH environment variable is optional. If not set, it defaults to ~/.graylog-mcp/config.json.
Or with a local clone:
{
"mcpServers": {
"graylog": {
"command": "node",
"args": ["/path/to/graylog-mcp/src/index.js"]
}
}
}
Time Range Specifications
The MCP server supports flexible time range specifications:
Relative Time Ranges
Use simple time expressions for relative ranges:
1h- 1 hour30m- 30 minutes2d- 2 days1w- 1 week3M- 3 months
Supported units: s (seconds), m (minutes), h (hours), d (days), w (weeks), M (months), y (years)
Absolute Time Ranges
Specify exact time windows with from and to parameters:
- ISO timestamps:
2024-01-15T10:30:00.000Z - Date strings:
2024-01-15 10:30:00 - Unix timestamps:
1705312200000
Examples
# Last 2 hours of error logs
timeRange: "2h", filters: {"level": 3}
# Specific time window
from: "2024-01-15T09:00:00Z", to: "2024-01-15T17:00:00Z"
# Last 30 minutes (default if no time specified)
timeRange: "30m"
Available Tools
list_connections
List all configured Graylog connections.
use_connection
Connect to a specific Graylog instance by name. Must be called before using other tools.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Connection name from config |
fetch_graylog_messages
Search and fetch log messages from Graylog.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | No | * | Search query |
filters | object | No | Field filters (e.g. {"env": "marketplace_loki", "level": 7}) | |
exactMatch | boolean | No | true | Wrap query in quotes for exact match. Set false for fuzzy/wildcard |
timeRange | string | No | 15m | Time range (e.g., 1h, 30m, 2d) |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range | |
pageSize | number | No | 50 | Messages per page |
page | number | No | 1 | Page number |
fields | string | No | default set | Comma-separated fields, or * for all |
Default fields returned: timestamp, gl2_message_id, source, env, level, message, logger_name, thread_name, PODNAME
get_surrounding_messages
View messages around a specific log entry. Useful for understanding context.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
messageId | string | No* | gl2_message_id of the target message (preferred) | |
messageTimestamp | string | No* | ISO timestamp (fallback) | |
surroundingSeconds | number | No | 5 | Time window (Β± seconds) |
query | string | No | * | Additional query filter |
filters | object | No | Field filters | |
exactMatch | boolean | No | true | Exact match for query |
limit | number | No | 50 | Max messages to return |
fields | string | No | default set | Comma-separated fields, or * for all |
*Either messageId or messageTimestamp must be provided.
list_streams
List all available Graylog streams in the active connection. No parameters required.
list_field_values
Discover distinct values for a field, sorted by message count (descending).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
field | string | Yes | Field name (e.g. source, env, logger_name) | |
query | string | No | * | Scope the results |
filters | object | No | Field filters to narrow scope | |
exactMatch | boolean | No | true | Exact match for query |
timeRange | string | No | 1h | Time range (e.g., 1h, 30m, 2d) |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range | |
limit | number | No | 20 | Max distinct values |
get_log_histogram
Get a time-based histogram of log messages. Shows message counts over time intervals.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | No | * | Query to filter messages |
filters | object | No | Field filters (e.g. {"env": "production", "level": 3}) | |
exactMatch | boolean | No | true | Exact match for query |
timeRange | string | No | 15m | Time range (e.g., 1h, 30m, 2d) |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range | |
interval | string | No | auto | Time interval for buckets (e.g., 1m, 5m, 1h) |
get_field_aggregation
Aggregate log messages by field values with statistics. Get counts, sums, averages, etc. for field values.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
field | string | Yes | Field to aggregate on (e.g., source, env, logger_name) | |
query | string | No | * | Query to filter messages |
filters | object | No | Field filters (e.g. {"env": "production"}) | |
exactMatch | boolean | No | true | Exact match for query |
timeRange | string | No | 15m | Time range (e.g., 1h, 30m, 2d) |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range | |
limit | number | No | 20 | Maximum number of field values |
metrics | array | No | ["count"] | Metrics to calculate (count, sum, avg, min, max) |
valueField | string | No | Numeric field for sum/avg/min/max calculations |
get_field_time_aggregation
Two-dimensional aggregation: field values over time. Shows how field values change over time intervals.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
field | string | Yes | Field to aggregate on (e.g., source, env, level) | |
query | string | No | * | Query to filter messages |
filters | object | No | Field filters (e.g. {"env": "production"}) | |
exactMatch | boolean | No | true | Exact match for query |
timeRange | string | No | 15m | Time range (e.g., 1h, 30m, 2d) |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range | |
interval | string | No | auto | Time interval for buckets (e.g., 1m, 5m, 1h) |
limit | number | No | 10 | Maximum number of field values |
debug_histogram_query
Debug helper to test if the histogram query finds any messages at all. Use this if histogram returns empty buckets.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | No | * | Query to test |
filters | object | No | Field filters to test | |
exactMatch | boolean | No | true | Exact match for query |
timeRange | string | No | 15m | Time range to test |
from | string | No | Start time for absolute range | |
to | string | No | End time for absolute range |
Example Prompts
Basic Search
Connect to nonprod and show me the latest error logs from prefr-management in marketplace_loki
Show me logs from the last 2 hours with level 3 errors
Field Discovery
List all available sources in the last hour
What environments are available?
Log Aggregations
Show me a histogram of error logs over the past day with 1-hour intervals
Get aggregated error counts by service for the last 6 hours
Show me how error levels have changed over time in the last 4 hours
Advanced Time Ranges
Show me logs from January 15th 9 AM to 5 PM
Get field statistics for the production environment over the past week
Context Analysis
Show me the surrounding messages for this log entry: 01KH5PDR893AZJQBYJJ87AQTW5
Find error patterns in the marketplace_loki environment over the last day
Project Structure
src/
βββ index.js β Server bootstrap, routing, and handlers
βββ config.js β Connection config and default fields
βββ query.js β Query building, Graylog API client, message extraction
βββ tools.js β Tool schema definitions
βββ timerange.js β Advanced time range parsing and utilities
βββ aggregations.js β Log aggregation and statistical analysis
Troubleshooting
Basic Setup
- Ensure
~/.graylog-mcp/config.jsonexists with valid connections - Verify Node.js version is 18+ (
node --version) - Run
npm installif dependencies are missing - Use
list_connectionsto verify your config is loaded - Use
use_connectionbefore any search tools
Aggregation Issues
Empty Histogram Buckets:
- Use
debug_histogram_querywith same parameters to test if query finds any data - Try shorter time ranges (e.g.,
"30m"instead of"2d") - Simplify query (try
"*"to search all messages) - Check if your time range has any log activity
400 Bad Request Errors:
- The server now tries multiple fallback approaches automatically
- Check server console logs for detailed error information
- Ensure your Graylog version supports pivot aggregations (6.x+)
Field Aggregation Working but Histogram Failing:
- Use the
debug_histogram_querytool to isolate the issue - The server will automatically try:
working-patternβchartβsimple-pivotβcomplex-pivot - Enhanced logging shows which approach succeeds
Feature Status
- β Field Aggregation: Fully working
- β Advanced Time Ranges: Fully working
- β Field-Time Aggregation: Fully working
- π§ Log Histogram: Fixed with multiple fallback approaches
Log Clustering (Drain3)
Group similar log messages into structural templates. Templates are learned per
connection and persisted at ~/.graylog-mcp/templates/<connection>.json.
Tools
cluster_log_messagesβ fetch and cluster a sample of messageslist_log_templatesβ list learned templatesdelete_log_templateβ remove a templaterename_log_templateβ give a template a human-readable labelexport_log_templatesβ dump library as JSONimport_log_templatesβ bulk load templates (merge or replace)
Example
After selecting a connection with use_connection:
{
"tool": "cluster_log_messages",
"arguments": {
"query": "level:ERROR",
"timeRange": "1h",
"sampleSize": 500,
"minClusterSize": 2,
"includeSamples": 3
}
}
The response groups the 500 sampled messages into a small number of templates, each with a count, sample messages, and the set of sources where it appeared. Subsequent calls reuse and reinforce the same templates.
Adding a new clustering algorithm
- Create
src/clustering/strategies/<name>.jsimplementing the strategy contract (hydrate,serialize,cluster) β seedrain3.jsfor reference. - Import and
register("<name>", strategy)insrc/clustering/index.js. - Pass
algorithm: "<name>"tocluster_log_messages.
No other code changes required.
License
MIT
