rlg-mcp
Summary: rlg-mcp turns a local rlg (RustLogs) log file into three read-only tools an AI agent can call to inspect, filter and summarize log records.
tail_log— return the last N parseable records (default 100) from a log file, newest last, for a quick glance at recent activity.filter_log— select records by minimum severity (TRACE–CRITICAL) and/or exact component name, and render the matches in any rlg LogFormat (defaults to Logfmt, e.g. JSON).summarize_errors— scan a log and produce counts of ERROR-and-above records grouped by component, as a fast failure taxonomy for triage.
All three take a filesystem path to a line-delimited Logfmt/JSON log, and are marked read-only, idempotent and non-destructive — the server only reads and reports, never writes, rotates or deletes logs.
Contents
Getting started
Install — Cargo for the libraries,
cargo installfor the CLIs and the MCP serverRequirements — toolchain floor, platforms
Quick Start — one structured record, fired and flushed
The rlg ecosystem
The rlg ecosystem —
rlg,rlg-cli,rlg-report,rlg-mcp,rlg-otlp,rlg-redact,rlg-tower,rlg-test,rlg-wasm,rlg-ebpf
Library reference
Capabilities at a glance — the current surface by theme
Ecosystem comparison — short matrix; full table at
docs/COMPARISON.mdBenchmarks — headline numbers; full table at
docs/BENCHMARKS.mdFeatures — module-level capability list
Configuration — core options
Examples — runnable example index
Operational
When not to use rlg — limitations
Development — make targets, fuzzing, CI
Security — guarantees and compliance
Documentation — all reference docs
Stability guarantees — SemVer axis, output stability, minimum toolchain discipline
Related MCP server: log-mcp
Install
As a Rust library
[dependencies]
rlg = "0.0.14"Satellites install the same way, all at the same version:
[dependencies]
rlg-otlp = "0.0.14" # ship records to an OpenTelemetry Collector
rlg-tower = "0.0.14" # per-request access logs for tower services
rlg-redact = "0.0.14" # scrub secrets and PII before they are written
[dev-dependencies]
rlg-test = "0.0.14" # assert on captured records in testsCommand-line tools
cargo install rlg-cli # `rlg`: filter and convert log files
cargo install rlg-report # `rlg-report`: summaries by level, component and message
cargo install rlg-mcp # `rlg-mcp`: log files as tools for AI agentsFrom a checkout, make install builds the three binaries and installs
them with their manpages and bash, zsh and fish completions under
/usr/local (PREFIX and DESTDIR are honoured; make uninstall
reverses it). The binaries generate both themselves:
rlg --manpage > rlg.1, rlg --completions zsh > _rlg.
rlg-mcp is also published as a container image,
ghcr.io/sebastienrousseau/rlg-mcp, and listed in the MCP registry.
Requirements
Rust 1.88.0 or newer (edition 2024). CI builds every library and binary on 1.88.0; see the toolchain policy.
macOS or Linux for the native sinks (
os_log,journald). Everywhere else, including Windows, rlg writes to a file or stdout.
Quick Start
use rlg::log::Log;
use rlg::log_format::LogFormat;
fn main() {
// Keep the guard for the life of the program: dropping it flushes
// pending records and stops the background thread.
let _guard = rlg::init().unwrap();
Log::info("User authenticated")
.component("auth-service")
.with("user_id", 42)
.format(LogFormat::JSON)
.fire();
}fire() checks the level, pushes the record into a ring buffer and
returns; the flusher thread formats it as JSON and writes it to the
platform sink. This block is compiled and run by cargo test.
The rlg ecosystem
Ten crates at lockstep version 0.0.14, released together.
Component | Purpose | Use case |
The engine: 65,536-slot ring buffer, background flusher, 14 formats, native sinks | Structured logging in any Rust program | |
The |
| |
The | On-call triage, daily error digests | |
MCP server: four tools, one prompt, two resources over stdio, streamable HTTP or HTTP+SSE | AI agents reading production logs | |
OTLP/HTTP exporter to a local OpenTelemetry Collector | Honeycomb, Datadog, Grafana through a Collector | |
Scrubs cards, JWTs, bearer tokens, emails, IPv4 addresses and AWS keys in one pass | GDPR and audit-trail safety | |
| axum, hyper and other | |
Capture records in a test and assert on them | Libraries testing their own log output | |
| Browsers, Deno, Workers, wasmtime hosts | |
Process enrichment, portable; an eBPF enricher scaffold on Linux | Host context on every record |
Capabilities at a glance
Area | Capability | Status |
Ingestion | Atomic level filter, ring-buffer push, no lock on the caller's thread | Stable |
Formats | JSON, NDJSON, ECS, GELF, Logstash, OTLP, MCP, logfmt, CLF, CEF, ELF, W3C, Apache, Log4j XML | Stable |
Sinks |
| Stable |
Sinks |
| Scaffold |
Configuration | TOML load, validation, polling hot-reload ( | Stable |
Bridges |
| Stable |
Export | OTLP/HTTP to a local Collector ( | Stable |
Agents | MCP server over stdio, streamable HTTP and HTTP+SSE ( | Stable |
Enrichment | eBPF kernel context ( | Scaffold |
Ecosystem comparison
rlg trades tracing's span model for an event-only engine that keeps
formatting and I/O off the application thread and ships native sinks,
many formats and an agent interface in the box.
Project | Formatting off the caller's thread | Built-in formats | Native |
rlg | yes | 14 | yes |
| add-on | text, JSON | add-on |
| add-on | add-on | add-on |
| no | text | no |
See docs/COMPARISON.md for the evidence and complete matrix.
Benchmarks
The competitive_bench suite times rlg's fire() against
tracing::info! and log::info! for single records, records with
attributes, 10,000-record bursts and latency distribution. It runs in
CI on every release tag, and its results are published as workflow
artifacts.
Scenario | Result | Environment |
rlg | 598 ns | GitHub-hosted |
| 591 ns | same run |
rlg | 947 ns ( | same run |
On the calling thread rlg now costs about what tracing costs, without
formatting there; what it buys is that the caller never waits on the
sink's I/O.
See docs/BENCHMARKS.md for methodology and full results.
Features
Everything optional is off by default.
Feature | Crate | Adds |
|
|
|
|
| A live terminal dashboard, started with |
|
|
|
|
| An eight-shard ring buffer for many concurrent producers |
|
| The |
|
|
|
Configuration
Config loads from TOML, validates, and creates the log paths it needs.
# rlg.toml
version = "1.0"
profile = "production"
log_file_path = "/var/log/rlg.log"
log_level = "INFO"
logging_destinations = [
{ type = "File", value = "/var/log/rlg.log" },
{ type = "Stdout" },
]
log_rotation = { Size = 10485760 } # 10 MiBLoad it with Config::load(Some("rlg.toml")), or with the tokio
feature Config::load_async, and follow edits with
Config::hot_reload_async. RUST_LOG sets the level too. The
crate README lists every field.
Examples
Example | Shows | Run |
| All 14 formats side by side |
|
| TOML config, async load, hot-reload |
|
| The logging macros |
|
| A full MCP session against |
|
| Exporting through a local Collector |
|
CI runs every example on each pull request (examples-smoke.yml), except
example_config and example_utils, async demos whose behaviour the
crate's own tests cover.
When not to use rlg
Low volume. Below about a hundred records a second, a background thread and a 65k-slot buffer buy nothing a synchronous logger does not already give you.
Spans are your model. rlg records events. If hierarchical spans are what you analyse, use
tracingdirectly; rlg's layer only bridges its events.Windows Event Log. There is no native Windows sink; rlg writes to a file or stdout there.
Every record must survive a crash. Records wait in memory until the flusher writes them; a process killed before the
FlushGuarddrops loses what is still buffered.You need a stable API. rlg is at
0.0.x: any release may break, and it has one maintainer.
Development
make verify # everything CI runs on a pull request
make demo # re-render .github/demo.gif from .github/demo.tapeDEVELOPMENT.md lists every gate with its local
command: Miri, Loom and Kani for the engine's concurrency and memory
safety, four fuzz targets, cargo-deny and cargo-vet for the dependency
tree, cargo-semver-checks, a 95% coverage floor and complexity ceilings.
Contribution and signing rules are in CONTRIBUTING.md
and AGENTS.md.
Security
Reporting: privately, by email or GitHub's advisory form; never in a public issue. The process and response time are in
SECURITY.md.Memory safety:
unsafeis denied across the workspace except the documented macOSos_logFFI incrates/rlg/src/sink.rs. The engine runs under Miri on every push.Resource limits: the ring buffer is bounded at 65,536 records and evicts the oldest when full;
rlg-otlpcaps a collector's response headers at 16 KiB and times out every request.Fuzzing: four cargo-fuzz targets (record parsing, format names, config loading, redaction) run on every pull request; see
docs/OSS-FUZZ.mdfor OSS-Fuzz status.Supply chain: every dependency passes cargo-deny and cargo-vet; releases publish through crates.io Trusted Publishing with sigstore-signed SBOMs (
pkg/VERIFY.md).
Report vulnerabilities according to SECURITY.md.
Documentation
Document | For |
Tutorials, how-to guides, architecture, ADRs (source) | |
Every public item, per crate on docs.rs | |
Toolchain, local gates, test layout, release model | |
How the engine and satellites fit together | |
What changed in each release | |
Coming from |
Stability guarantees
SemVer axis: rlg is at
0.0.x, so under Cargo's rules every release may be breaking. Breaking changes are marked Breaking in the CHANGELOG, and cargo-semver-checks runs on every pull request so none slips through unannounced.Output stability: the bytes a format produces are an interface. A change to them for the same record is breaking even when no signature moves, and is recorded the same way.
Minimum toolchain: Rust 1.88.0, enforced in CI; a rise is its own CHANGELOG entry with the reason.
docs/POLICIES.mdhas the full policy.
License
Dual-licensed under either of
Apache License, Version 2.0 (
LICENSE-APACHE)MIT license (
LICENSE-MIT)
at your option. Unless you state otherwise, any contribution you submit for inclusion in rlg is dual-licensed as above, without additional terms.
Available Tools
3 toolsfilter_logFilter rlg log recordsARead-onlyIdempotent
Select rlg records by minimum severity and/or component and render them in any rlg LogFormat. Use this to narrow a log to what matters (e.g. WARN-and-above for one service); use tail_log for a raw recent slice and summarize_errors when you only need per-component error totals.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Filesystem path to an rlg log file to read. | |
| format | No | rlg LogFormat name to render matched records in (e.g. Logfmt, JSON). Defaults to Logfmt. | Logfmt |
| component | No | Keep only records whose component matches this exact value. Omit to keep all components. | |
| min_level | No | Keep only records at or above this severity. Omit to keep all levels. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already state readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds behavioral context: it filters and renders records in a specified format, which is not in annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exactly two sentences, front-loaded with the core action, and every sentence adds value. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's 4 parameters, no output schema, and good annotations, the description covers purpose, parameters, usage guidance, and alternatives comprehensively. It is complete for an AI agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description references 'minimum severity and/or component', which maps to min_level and component parameters, but does not add significant meaning beyond what the schema already provides (e.g., format has defaults and examples in schema).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs and resources: 'Select rlg records by minimum severity and/or component and render them in any rlg LogFormat.' It clearly distinguishes itself from siblings by naming alternatives (tail_log, summarize_errors) and their purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: 'Use this to narrow a log to what matters (e.g. WARN-and-above for one service); use tail_log for a raw recent slice and summarize_errors when you only need per-component error totals.' This tells both when to use this tool and when to use alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_errorsSummarize rlg errors by componentARead-onlyIdempotent
Group ERROR-and-above rlg records by component and count them, giving a quick error taxonomy for triage. Use this for an at-a-glance failure breakdown; use filter_log when you need the underlying records rather than counts.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Filesystem path to an rlg log file to scan for ERROR-and-above records. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, non-destructive behavior. The description adds context that it groups by component and only includes ERROR-and-above severity, which is useful beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, no unnecessary words. Second sentence provides usage guidance with sibling tool reference.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and no output schema, the description completely explains what it does, how to use it, and when to choose alternatives. Annotations cover safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single parameter 'path'. The description does not add new parameter details beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool groups ERROR-and-above rlg records by component and counts them, providing a quick error taxonomy. It distinguishes from sibling tool filter_log by noting it gives counts rather than underlying records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use this tool ('for an at-a-glance failure breakdown') and when to use filter_log instead ('when you need the underlying records rather than counts').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tail_logTail rlg log fileARead-onlyIdempotent
Return the last N parseable rlg (RustLogs) records from a log file, newest last. Use this to glance at the most recent activity in a log; use filter_log when you need to select records by level or component, and summarize_errors for an aggregated error count.
| Name | Required | Description | Default |
|---|---|---|---|
| n | No | How many of the most recent parseable records to return (default 100). | |
| path | Yes | Filesystem path to an rlg log file (Logfmt/JSON records, one per line). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as read-only, idempotent, non-destructive. The description adds that it returns only parseable records and newest-last ordering, which are behavioral details beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no redundancy. First sentence states purpose and behavior; second sentence provides usage guidance. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tail tool with 2 parameters and no output schema, the description fully covers purpose, output ordering, file format (rlg, parseable), and usage context including siblings. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds context about log format (rlg) and ordering ('newest last'), which enriches understanding beyond the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the last N parseable rlg records from a log file, newest last. It distinguishes from siblings (filter_log, summarize_errors) by naming them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool (glance at recent activity) and when to use alternatives (filter_log for level/component selection, summarize_errors for aggregated count).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
- First observed
filter_log - First observed
summarize_errors - First observed
tail_log
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: filter_log selects by severity/component, summarize_errors provides aggregated counts, and tail_log returns recent raw records. There is no overlap, and the descriptions explicitly guide when to use which.
All tool names follow a consistent verb_noun pattern in snake_case: filter_log, summarize_errors, tail_log. The verbs (filter, summarize, tail) are descriptive and predictable.
Three tools is an appropriate count for a focused logging server. Each tool provides a necessary operation (tail, filter, summarize) without redundancy or bloat.
The tool set covers the core operations for log analysis: tailing raw logs, filtering by severity/component, and summarizing errors. Minor gaps like searching by pattern could exist, but for the stated domain of rlg records, it is largely complete.
Maintenance
Related MCP Connectors
Syslog receiver and MCP server for homelab log intelligence.
Syslog receiver and MCP server for homelab log intelligence.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server that connects Claude (or any MCP compatible client) to your existing log infrastructure. Query, summarize, and trace logs in plain English across GCP Cloud Logging, AWS CloudWatch, Azure Log Analytics, Grafana Loki, and Elasticsearch without writing filter expressions or leaving your editor.27 npm3MIT
- AlicenseAqualityDmaintenanceMCP server for log file analysis. Gives LLMs the ability to efficiently analyze large log files without loading them into context.7100MIT
- AlicenseAqualityBmaintenanceA read-only MCP server that exposes local coding-agent session logs as three tools for introspection of recent work, debugging tool failures, and tracking token usage and estimated cost without parsing log files.3MIT
- AlicenseAqualityDmaintenanceMCP server that stream-parses NDJSON log files without loading them into memory — filter by pattern, detect error spikes via Z-score analysis, summarize severity timelines by time window.839 npmMIT