The MCP Graylog Server provides a Model Context Protocol (MCP) interface to Graylog, enabling AI assistants to query logs, analyze data, and manage streams through a standardized API.
- Log Search: Search logs using Elasticsearch query syntax
- Stream Management: List and search Graylog streams
- Analytics: Get log statistics and aggregations
- System Info: Retrieve Graylog system information
- Connection Testing: Test connectivity to Graylog server
- Python 3.8+
- Graylog server with REST API access
- Graylog username and password
-
Clone the repository:
git clone <repository-url> cd mcp_graylog
-
Install dependencies:
pip install -r requirements.txt
-
Configure environment variables:
cp env.example .env # Edit .env with your Graylog credentials -
Run the server:
python run_server.py
| Variable | Description | Required | Default |
|---|---|---|---|
GRAYLOG_ENDPOINT |
Graylog server URL | Yes | - |
GRAYLOG_USERNAME |
Graylog username | Yes | - |
GRAYLOG_PASSWORD |
Graylog password | Yes | - |
GRAYLOG_VERIFY_SSL |
Verify SSL certificates | No | true |
GRAYLOG_TIMEOUT |
Request timeout (seconds) | No | 30 |
MCP_SERVER_PORT |
MCP server port | No | 8000 |
MCP_SERVER_HOST |
MCP server host | No | 0.0.0.0 |
LOG_LEVEL |
Logging level | No | INFO |
LOG_FORMAT |
Log format (json/text) | No | json |
Both username and password are required.
The MCP server now includes comprehensive request validation to ensure all requests conform to Graylog API specifications:
- Relative ranges:
1h,24h,7d,30m,1w - Absolute ranges: ISO 8601 format (e.g.,
2024-01-01T00:00:00Z)
- Queries cannot be empty
- Must be valid Elasticsearch syntax
- Proper escaping for special characters
limit: 1-1000 for search queriessize: 1-100 for aggregationsoffset: Non-negative integers
Search logs using Elasticsearch query syntax.
Warning: Request must be a JSON object, not a string.
Parameters:
query(string, required): Search query (Elasticsearch syntax)time_range(string, optional): Time range (e.g., '1h', '24h', '7d'). Defaults to '1h'fields(array, optional): Fields to returnlimit(integer, optional): Maximum number of results (1-1000, default: 50)offset(integer, optional): Result offset (default: 0)sort(string, optional): Sort fieldsort_direction(string, optional): Sort direction ('asc' or 'desc', default: 'desc')stream_id(string, optional): Stream ID to search in
Example:
{
"query": "level:ERROR AND source:web-server",
"time_range": "24h",
"fields": ["message", "level", "source", "timestamp"],
"limit": 100,
"sort": "timestamp",
"sort_direction": "desc"
}Search logs within a specific Graylog stream.
Warning: Request must be a JSON object, not a string.
Parameters:
stream_id(string, required): Stream ID to search inquery(string, required): Search querytime_range(string, optional): Time range (default: '1h')fields(array, optional): Fields to returnlimit(integer, optional): Maximum number of results (1-100, default: 50)
Example:
{
"stream_id": "5abb3f2f7bb9fd00011595fe",
"query": "level:ERROR",
"time_range": "7d",
"fields": ["message", "level", "source"],
"limit": 50
}Get log statistics and aggregations from Graylog.
Warning: Request must be a JSON object, not a string.
Parameters:
query(string, required): Search querytime_range(string, required): Time rangeaggregation_type(string, required): Aggregation typefield(string, required): Field to aggregate onsize(integer, optional): Number of buckets (1-100, default: 10)interval(string, optional): Time interval for date histograms
Valid aggregation types:
terms: Count occurrences of field valuesdate_histogram: Time-based aggregationscardinality: Count unique valuesstats: Statistical aggregationsmin,max,avg,sum: Mathematical aggregations
Example:
{
"query": "level:ERROR",
"time_range": "7d",
"aggregation_type": "terms",
"field": "source",
"size": 10
}List all available Graylog streams.
Returns: JSON string containing list of streams with their IDs and metadata.
Search for Graylog streams by name or partial name.
Parameters:
stream_name(string, required): Partial or full stream name to search for
Example:
search_streams_by_name("1c_eventlog")Get detailed information about a specific Graylog stream.
Parameters:
stream_id(string, required): The ID of the stream to get information for
Example:
get_stream_info("5abb3f2f7bb9fd00011595fe")Get error logs from the last specified time range.
Parameters:
time_range(string, optional): Time range to search (default: '1h')limit(integer, optional): Maximum number of results (1-1000, default: 100)
Example:
{
"time_range": "24h",
"limit": 50
}Get log count aggregated by log level.
Parameters:
time_range(string, optional): Time range to analyze (default: '1h')
Example:
{
"time_range": "24h"
}Get Graylog system information and status.
Returns: JSON string containing system information.
Test connection to Graylog server.
Returns: JSON string indicating connection status.
Get the last event from a specific Graylog stream.
Parameters:
stream_id(string, required): The ID of the stream to get the last event fromtime_range(string, optional): Time range to search in (default: '1h')
Example:
{
"stream_id": "5abb3f2f7bb9fd00011595fe",
"time_range": "1h"
}The MCP server ensures all requests conform to Graylog API specifications:
- Endpoint:
/api/search/universal/relative - Method: GET
- Parameters: Query parameters for filtering and pagination
- Endpoint:
/api/search/universal/relative/{aggregation_type} - Method: POST
- Body: JSON with query, range, field, and aggregation parameters
- Relative ranges: Converted to seconds (e.g.,
1h→3600) - Absolute ranges: ISO 8601 format preserved
- Validation: Ensures proper format before sending to Graylog
The server provides comprehensive error handling:
- Validation errors: Clear messages for invalid parameters
- Authentication errors: Specific handling for 401 responses
- Connection errors: Graceful handling of network issues
- Graylog API errors: Proper error propagation from Graylog
export GRAYLOG_USERNAME="your-username"
export GRAYLOG_PASSWORD="your-password"export GRAYLOG_VERIFY_SSL="true"- Use appropriate
limitvalues (1-1000) - Implement pagination with
offset - Filter results with specific
fields
- Use relative ranges for recent data (
1h,24h) - Use absolute ranges for historical analysis
- Avoid overly broad time ranges
# Good: Specific query
{"query": "level:ERROR AND source:web-server"}
# Avoid: Too broad
{"query": "*"}{
"query": "level:ERROR",
"fields": ["message", "level", "source", "timestamp"]
}# Test connection before making queries
test_connection()# All functions return JSON with error details
result = search_logs(request)
if "error" in result:
print(f"Error: {result['error']}")Error: Authentication failed (401)
Solution: Verify username and password in environment variables.
Error: Connection test failed
Solution: Check Graylog server URL and network connectivity.
Error: Invalid time range format
Solution: Use supported formats: relative (1h, 24h) or ISO 8601.
Error: Query parameter is required
Solution: Ensure query is not empty and uses valid Elasticsearch syntax.
Enable debug logging for detailed request/response information:
export LOG_LEVEL="DEBUG"Use the health check endpoint to verify server status:
curl http://localhost:8000/health_checkpytest tests/# Run linting
flake8 mcp_graylog/
# Run type checking
mypy mcp_graylog/- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.