@modular-intelligence/detection-rules
v1.0.0
Published
MCP server for Sigma & YARA rule validation, conversion, and scanning
Downloads
59
Readme
Detection Rules MCP Server
An MCP server for validating, converting, and scanning detection rules using Sigma and YARA formats. Enables Claude and other MCP clients to work with security detection rules for SIEM platforms, threat hunting, and malware analysis.
Features
- Sigma Rule Support: Validate Sigma rules and convert them to multiple SIEM backends (Splunk, Elasticsearch, QRadar, etc.)
- YARA Rule Support: Validate YARA rules and scan files/directories for malware patterns
- Multi-Backend Conversion: Support for numerous conversion targets with optional processing pipelines
- Real-time Scanning: Scan files and directories with customizable timeouts
- Security-First: File path validation, rule content size limits, and backend name sanitization
- Error Handling: Detailed validation errors and warnings with rule metadata extraction
Tools
| Tool | Purpose |
|------|---------|
| sigma_validate | Validate Sigma rule YAML for syntax and semantic correctness |
| sigma_convert | Convert Sigma rules to target SIEM query languages (SPL, KQL, etc.) |
| sigma_list_backends | List all available Sigma conversion backends |
| yara_validate | Compile and validate YARA rules for syntax errors |
| yara_scan | Scan files or directories with YARA rules |
sigma_validate
Validates a Sigma rule YAML file for correctness using the sigma-cli.
Input Schema:
{
"rule": "string (Sigma rule YAML content, min 10 chars)"
}Output:
{
"valid": true,
"errors": [],
"warnings": [],
"rule_title": "File Access via Uncommon Extension",
"rule_level": "medium",
"rule_status": "test"
}Example Usage:
# Input
{
"rule": """
title: Suspicious Process Creation with Network Activity
id: 12345678-1234-1234-1234-123456789012
status: test
description: Detects unusual process creation followed by network connection
logsource:
product: windows
service: sysmon
detection:
process_creation:
EventID: 1
Image|endswith:
- 'powershell.exe'
- 'cmd.exe'
network_connection:
EventID: 3
DestinationPort:
- 445
- 139
filter:
Image|contains: 'system32'
condition: process_creation and network_connection and not filter
level: high
"""
}
# Output
{
"valid": true,
"errors": [],
"warnings": ["Field 'description' should use proper formatting"],
"rule_title": "Suspicious Process Creation with Network Activity",
"rule_level": "high",
"rule_status": "test"
}sigma_convert
Converts a Sigma rule to a target SIEM backend query language. Supports optional processing pipelines for backend-specific transformations.
Input Schema:
{
"rule": "string (Sigma rule YAML content, min 10 chars)",
"backend": "string (Target backend name: splunk, elasticsearch, qradar, etc.)",
"pipeline": "string (optional, Processing pipeline name e.g., sysmon, windows)"
}Output:
{
"backend": "splunk",
"pipeline": "sysmon",
"converted_query": "index=main Image=*powershell.exe OR Image=*cmd.exe (DestinationPort=445 OR DestinationPort=139) NOT Image=*system32*",
"warnings": []
}Example Usage:
Converting a Sigma rule to Splunk SPL:
# Input
{
"rule": """
title: Process Creation with Command Line Args
id: 11111111-2222-3333-4444-555555555555
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 1
Image|endswith: 'powershell.exe'
CommandLine|contains:
- 'DownloadString'
- 'IEX'
- 'Invoke-WebRequest'
condition: selection
level: high
""",
"backend": "splunk",
"pipeline": "sysmon"
}
# Output
{
"backend": "splunk",
"pipeline": "sysmon",
"converted_query": "index=main EventID=1 Image=*powershell.exe (CommandLine=*DownloadString* OR CommandLine=*IEX* OR CommandLine=*Invoke-WebRequest*)",
"warnings": []
}sigma_list_backends
Lists all available Sigma conversion backends supported by the sigma-cli installation.
Input Schema:
{}Output:
{
"backends": [
{
"name": "splunk",
"description": "Splunk Processing Language (SPL)"
},
{
"name": "elasticsearch",
"description": "Elasticsearch Query Language (KQL)"
},
{
"name": "qradar",
"description": "IBM QRadar Query Language"
},
{
"name": "sentinel",
"description": "Microsoft Azure Sentinel KQL"
},
{
"name": "graylog",
"description": "Graylog Query Language"
}
]
}Example Usage:
# Input
{}
# Output (sample)
{
"backends": [
{"name": "splunk", "description": "Splunk Processing Language"},
{"name": "elasticsearch", "description": "Elasticsearch Query Language"},
{"name": "qradar", "description": "IBM QRadar"},
{"name": "sentinel", "description": "Microsoft Sentinel KQL"},
{"name": "windows-defender", "description": "Windows Defender Advanced Threat Protection"},
{"name": "crowdstrike", "description": "CrowdStrike Falcon"}
]
}yara_validate
Compiles and validates a YARA rule for syntax errors. Extracts rule names from the provided rule content.
Input Schema:
{
"rule": "string (YARA rule content, min 10 chars)"
}Output:
{
"valid": true,
"errors": [],
"rule_names": ["malware_strings", "suspicious_imports"]
}Example Usage:
# Input
{
"rule": """
rule malware_strings {
meta:
description = "Detects common malware strings"
severity = "high"
strings:
$a = "CreateRemoteThread"
$b = "WinExec"
$c = /kernel32\.dll/i
condition:
2 of them
}
rule suspicious_imports {
meta:
description = "Detects suspicious API imports"
strings:
$import1 = "GetProcAddress"
$import2 = "LoadLibrary"
condition:
all of them
}
"""
}
# Output
{
"valid": true,
"errors": [],
"rule_names": ["malware_strings", "suspicious_imports"]
}yara_scan
Scans a file or directory with a YARA rule. Returns all matching rules and the specific strings that matched.
Input Schema:
{
"rule": "string (YARA rule content, min 10 chars)",
"target": "string (Absolute file or directory path)",
"recursive": "boolean (optional, default: false, scan directories recursively)",
"timeout": "integer (optional, default: 60, range: 5-300 seconds)"
}Output:
{
"target": "/path/to/file",
"match_count": 2,
"matches": [
{
"rule": "malware_strings",
"file": "/path/to/file.exe",
"strings": [
{
"identifier": "$a",
"offset": "0x1234",
"data": "CreateRemoteThread"
},
{
"identifier": "$b",
"offset": "0x5678",
"data": "WinExec"
}
]
}
],
"scan_time_ms": 245
}Example Usage:
Scanning a file for malware patterns:
# Input
{
"rule": """
rule ransomware_indicators {
meta:
description = "Detects common ransomware patterns"
author = "Security Team"
strings:
$bitcoin_wallet = /bitcoin:\/\/[a-zA-Z0-9]{26,35}/
$file_operations = "SetFilePointer"
$registry_run = "Software\\\\Microsoft\\\\Windows\\\\Run"
$mutex = {4D 5A 90 00} // MZ header + suspicious pattern
condition:
3 of them
}
""",
"target": "/home/user/Downloads/suspicious.exe",
"recursive": false,
"timeout": 30
}
# Output
{
"target": "/home/user/Downloads/suspicious.exe",
"match_count": 1,
"matches": [
{
"rule": "ransomware_indicators",
"file": "/home/user/Downloads/suspicious.exe",
"strings": [
{
"identifier": "$file_operations",
"offset": "0x4a2f",
"data": "SetFilePointer"
},
{
"identifier": "$registry_run",
"offset": "0x7c1d",
"data": "Software\\Microsoft\\Windows\\Run"
},
{
"identifier": "$mutex",
"offset": "0x0400",
"data": "MZ"
}
]
}
],
"scan_time_ms": 523
}Scanning a directory recursively:
# Input
{
"rule": """
rule webshell_patterns {
strings:
$php = "<?php"
$shell_var = "$_GET"
$system_call = "system("
condition:
2 of them
}
""",
"target": "/var/www/html",
"recursive": true,
"timeout": 120
}
# Output
{
"target": "/var/www/html",
"match_count": 3,
"matches": [
{
"rule": "webshell_patterns",
"file": "/var/www/html/uploads/shell.php",
"strings": [
{"identifier": "$php", "offset": "0x0", "data": "<?php"},
{"identifier": "$shell_var", "offset": "0x45", "data": "$_GET"},
{"identifier": "$system_call", "offset": "0x89", "data": "system("}
]
},
{
"rule": "webshell_patterns",
"file": "/var/www/html/admin/upload.php",
"strings": [
{"identifier": "$php", "offset": "0x0", "data": "<?php"},
{"identifier": "$system_call", "offset": "0x120", "data": "system("}
]
},
{
"rule": "webshell_patterns",
"file": "/var/www/html/api/handler.php",
"strings": [
{"identifier": "$php", "offset": "0x0", "data": "<?php"},
{"identifier": "$shell_var", "offset": "0x78", "data": "$_GET"}
]
}
],
"scan_time_ms": 1847
}Prerequisites
The server requires two command-line tools to be installed and available in your PATH:
sigma-cli
The Sigma rule toolkit for validation and conversion.
Installation:
pip install sigma-cliWhat it does:
- Validates Sigma rule YAML syntax and semantics
- Converts Sigma rules to multiple SIEM query languages
- Provides rule checking and linting capabilities
- Supports custom processing pipelines
Verify installation:
sigma --version
sigma list backendsYARA
A tool for malware research and detection using pattern matching.
Installation (macOS):
brew install yaraInstallation (Linux - Ubuntu/Debian):
sudo apt-get install yaraInstallation (Linux - RHEL/CentOS):
sudo yum install yaraInstallation (from source):
git clone https://github.com/VirusTotal/yara.git
cd yara
./bootstrap.sh
./configure
make
sudo make installWhat it does:
- Compiles and validates YARA rule syntax
- Scans files and directories for pattern matches
- Provides detailed match output with offsets and matched strings
- Supports recursive directory scanning
Verify installation:
yara --version
yarac --helpInstallation
Prerequisites
- Node.js 18+ or Bun runtime
- npm or bun package manager
- sigma-cli (Python)
- YARA
Setup with Bun
- Clone or download the server directory:
cd /path/to/detection-rules- Install dependencies:
bun install- Build the server:
bun run buildThis produces a compiled bundle in the dist/ directory.
Setup with npm
If you prefer npm instead of bun:
npm install
npm run buildUsage
Running the Server
With Bun:
bun run src/index.tsOr use the built distribution:
bun dist/index.jsWith Node.js:
node dist/index.jsThe server runs in stdio mode and is designed to be invoked by MCP clients (Claude, etc.) via configuration.
Claude Desktop Configuration
Add the following to your Claude Desktop configuration file:
Location: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"detection-rules": {
"command": "/usr/local/bin/bun",
"args": [
"/path/to/detection-rules/src/index.ts"
],
"disabled": false
}
}
}Or if using the built distribution:
{
"mcpServers": {
"detection-rules": {
"command": "bun",
"args": [
"/path/to/detection-rules/dist/index.js"
],
"disabled": false
}
}
}For Node.js users:
{
"mcpServers": {
"detection-rules": {
"command": "node",
"args": [
"/path/to/detection-rules/dist/index.js"
],
"disabled": false
}
}
}Claude Code MCP Settings
If using Claude Code or other MCP clients, configure as follows:
{
"mcpServers": {
"detection-rules": {
"command": "bun",
"args": [
"/path/to/detection-rules/src/index.ts"
]
}
}
}Example Queries in Claude
Once configured, you can ask Claude:
"Validate this Sigma rule and convert it to Splunk SPL"
"Scan /home/user/malware with this YARA rule"
"List all available Sigma conversion backends"
"Check if this YARA rule compiles without errors"
Security
File Path Validation
The server implements strict file path validation:
Blocked Paths: Access to system-critical paths is prevented:
/etc/shadowand/etc/passwd/procand/sys/dev
Path Resolution: Paths are normalized and resolved to absolute paths to prevent directory traversal attacks
Existence Checking: Paths must exist before scanning
Example:
# This will be rejected
target: "/etc/passwd" # Error: Access not allowed
# This will be accepted
target: "/home/user/suspicious_file.exe"Rule Content Size Limits
Both Sigma and YARA rules are subject to size validation:
- Maximum Size: 100 KB per rule
- Minimum Size: 10 characters (must contain meaningful content)
Example:
# This will be rejected (too small)
rule: "rule test" # Error: Content too small
# This will be rejected (too large)
rule: "..." # (100KB+ content) Error: Rule too largeBackend Name Sanitization
Backend names are validated using strict alphanumeric rules:
- Allowed Characters: Letters (a-z, A-Z), numbers (0-9), hyphens (-), underscores (_)
- Validation: Prevents injection attacks and invalid backend names
Example:
# Valid backend names
backend: "splunk"
backend: "elasticsearch"
backend: "windows-defender"
backend: "custom_backend"
# Invalid backend names (will be rejected)
backend: "splunk; rm -rf /" # Error: Invalid characters
backend: "$(malicious)" # Error: Invalid charactersCommand Execution
- CLI tools are executed with proper sandboxing using Node.js
execFile - 30-second default timeout for all commands (configurable for scans)
- 5 MB output buffer limit to prevent memory exhaustion
- Temporary file cleanup ensures no sensitive data persists
Troubleshooting
sigma CLI not found
If you see "sigma CLI not found. Install: pip install sigma-cli":
# Ensure Python and pip are installed
python3 --version
pip3 --version
# Install sigma-cli
pip3 install sigma-cli
# Verify installation
sigma --versionYARA not found
If you see "yara not found. Install: brew install yara":
# macOS
brew install yara
# Linux
sudo apt-get install yara # Ubuntu/Debian
sudo yum install yara # RHEL/CentOS
# Verify installation
yara --version
yarac --helpTimeout errors
If scans are timing out:
- Increase the
timeoutparameter inyara_scan(range: 5-300 seconds) - For large directories, use
recursive: truewith longer timeouts - Check system resources; scanning very large files may require optimization
Rule validation errors
If rules fail validation:
- Check YAML/rule syntax carefully
- Review warning messages for hints
- Use
sigma_list_backendsto verify backend names - For YARA rules, ensure proper syntax for meta, strings, and condition blocks
Development
Project Structure
src/
index.ts # MCP server initialization and tool registration
schemas.ts # Zod validation schemas
security.ts # Path and content validation
types.ts # TypeScript interfaces
cli-executor.ts # Command execution utilities
tools/
sigma-validate.ts # Sigma rule validation
sigma-convert.ts # Sigma rule conversion
sigma-list-backends.ts # Backend listing
yara-validate.ts # YARA rule validation
yara-scan.ts # YARA file scanning
dist/
index.js # Compiled output (generated by build)Adding New Tools
To add a new tool:
- Create a new file in
src/tools/with the tool name - Export a schema object (e.g.,
toolNameSchema) using Zod - Export an async function with the tool logic
- Import and register in
src/index.tsusingserver.tool()
Example:
// src/tools/custom-tool.ts
import { z } from "zod";
export const customToolSchema = z.object({
input: z.string().describe("Input parameter"),
});
type CustomToolInput = z.infer<typeof customToolSchema>;
export async function customTool(input: CustomToolInput) {
return { result: "output" };
}Building and Testing
# Build
bun run build
# Run the server
bun run src/index.ts
# Or run tests (if added)
bun testLicense
MIT
Contributing
Contributions are welcome! Please ensure:
- All tools have proper input validation
- Security checks are in place for file operations
- Error messages are clear and helpful
- Code follows existing style conventions
