Skip to content
stevenke1981Public

About

No description, website, or topics provided.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

rlm-mcp

Standalone RLM (Recursive Language Model) MCP server in Rust.

Implements the MIT CSAIL paper pattern: context is external — load long text into sessions, filter with peek, map with paginated chunks, reduce in the agent.

Independent project — no dependency on codebase-memory-mcp or any graph index.

When to use which MCP

Need Use
Long logs, docs, transcripts, multi-file text analysis rlm-mcp (this repo)
Code graph, symbol lookup, call-path tracing cbm-mcp (separate repo)
Both long-context sessions and graph search Run both MCP servers side by side — separate processes, no code coupling

Quick start

cd D:\rlm-mcp
.\install.ps1
rlm-mcp --version

install.ps1 / install.sh download the latest GitHub Release binary by default. Agents can install directly from a checkout without compiling Rust.

For agents and automation: run .\install.ps1 from the checkout, or run the raw release installer URL below. Do not compile or use target/release unless you explicitly pass -FromSource.

Install

From GitHub Release

Windows:

irm https://raw.githubusercontent.com/stevenke1981/rlm-mcp/main/packaging/windows/install.ps1 | iex

Linux:

curl -fsSL https://raw.githubusercontent.com/stevenke1981/rlm-mcp/main/packaging/linux/install.sh | bash

macOS Apple Silicon:

curl -fsSL https://raw.githubusercontent.com/stevenke1981/rlm-mcp/main/packaging/macos/install.sh | bash

The release installer verifies SHA256SUMS.txt, installs the binary to a stable path, and registers both OpenCode and Codex MCP entries automatically. On Windows, if the stable binary is currently locked by a running agent, the installer installs a versioned side-by-side binary and configures agents to use that path.

From checkout without compiling

Windows

.\install.ps1

Downloads the latest release archive, verifies SHA256SUMS.txt, installs to %USERPROFILE%\.config\rlm-mcp\bin\rlm-mcp.exe, registers OpenCode and Codex, and copies the rlm skill for Codex, Claude Code, OpenCode, and agents.

Linux / macOS

chmod +x install.sh
./install.sh

Installs to ~/.config/rlm-mcp/bin/rlm-mcp and symlinks ~/.local/bin/rlm-mcp.

Pin a version:

.\install.ps1 -Version v0.1.7
RLM_VERSION=v0.1.7 ./install.sh

Build from source checkout

Only use this for development or local unreleased changes:

.\install.ps1 -FromSource
./install.sh --from-source

MCP configuration

Templates: packaging/mcp/ (OpenCode, Codex, Claude, generic).

{
  "rlm-mcp": {
    "type": "local",
    "command": ["rlm-mcp"],
    "enabled": true,
    "timeout": 120000
  }
}

Replace command with the absolute path from install.ps1 / install.sh, or use {{RLM_BINARY}} in templates.

The installer updates both existing opencode.json and opencode.jsonc files and %USERPROFILE%\.codex\config.toml. Restart the agent or open a new session after installation because MCP tools are loaded when a session starts.

The MCP protocol boundary uses the official Rust SDK, rmcp 3.x (the exact version is pinned in Cargo.lock), for stdio framing, protocol negotiation, capabilities, request IDs, and error envelopes. The 33-tool contract remains locked by packaging/mcp/tools-list.snapshot.json. Stdout is protocol-only in MCP mode; diagnostics are written to stderr.

Stable binary path:

OS Path
Windows %USERPROFILE%\.config\rlm-mcp\bin\rlm-mcp.exe
Linux / macOS ~/.config/rlm-mcp/bin/rlm-mcp (symlinked from ~/.local/bin/rlm-mcp)

Releases

Push a version tag to trigger the GitHub release workflow:

git tag v0.1.0
git push origin v0.1.0

Artifacts: per-target .zip / .tar.gz + SHA256SUMS.txt. Local packaging:

cargo build --release
.\scripts\package-release.ps1
cargo build --release
./scripts/package-release.sh

Docker

Images are published to GitHub Container Registry on every main push and on version tags:

Event Tags on ghcr.io/stevenke1981/rlm-mcp
Push to main latest, sha-<git-sha>
Tag vX.Y.Z X.Y.Z, X.Y, latest
# Pull published image (public package; first publish may need package visibility = Public)
docker pull ghcr.io/stevenke1981/rlm-mcp:latest

# Run in MCP stdio mode (for agent integration)
echo '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1.0"}}}' | docker run -i --rm ghcr.io/stevenke1981/rlm-mcp:latest

# Run CLI command
docker run -i --rm ghcr.io/stevenke1981/rlm-mcp:latest workflow --json

# Pin a release
docker run -i --rm ghcr.io/stevenke1981/rlm-mcp:0.1.7 workflow --json

# Build locally instead of pulling
docker build -t rlm-mcp .

# Compose (uses GHCR image by default; see docker-compose.yml)
docker compose up -d

See docker-compose.yml for cache volumes, resource limits, and sandboxed command provider mounts. CI builds the image on every PR (no push); only main and release tags push to GHCR.

Environment

Variable Default Purpose
RLM_CACHE_DIR %LOCALAPPDATA%\rlm-mcp / ~/.cache/... Dedicated cache root (auto-creates rlm-sessions, rlm-artifacts, …)
RLM_ALLOW_SYSTEM_TEMP unset Set 1 only if you must use bare OS temp as cache
RLM_MAX_FILE_BYTES 524288 Max single file size
RLM_MAX_TOTAL_BYTES 8388608 Max total session bytes
RLM_MAX_CHUNKS 10000 Max chunks per session
RLM_MAX_SESSIONS 50 Max persisted sessions
RLM_SESSION_TTL_SECS 3600 Session expiry
RLM_CHUNK_LINES 200 Lines per chunk
RLM_ALLOW_NETWORK unset (offline) Set to 1 to enable openai provider
RLM_OPENAI_API_KEY — OpenAI-compatible API key (never persisted)
RLM_OPENAI_BASE_URL https://api.openai.com/v1 Compatible API base URL
RLM_OPENAI_MODEL gpt-4o-mini Model name for sub-calls
RLM_OPENAI_TIMEOUT_SECS 120 Async HTTP request timeout for openai provider
RLM_PROVIDER_COMMAND — Executable for command provider
RLM_PROVIDER_ARGS [] JSON array or whitespace-separated args
RLM_PROVIDER_SANDBOX warn Sandbox mode: strict, warn, or off (see security)
RLM_PROVIDER_ALLOWED_DIRS — Semicolon-separated allowed directories (strict mode)
RLM_PROVIDER_MAX_WALL_SECS 300 Kill command provider after N seconds (0 = no limit)
RLM_PROVIDER_MAX_OUTPUT_BYTES 1048576 Positive byte cap per command stdout/stderr pipe and OpenAI HTTP response body; exceeding it fails the call
RLM_PROVIDER_MAX_RETRIES 3 Provider retry attempts
RLM_PROVIDER_RETRY_DELAY_MS 200 Base delay between retries (exponential backoff)
RLM_LOG_FORMAT pretty stderr logs: pretty or json
RLM_OPENAI_PROMPT_COST_PER_1K — Optional USD/1K prompt tokens for cost est.
RLM_OPENAI_COMPLETION_COST_PER_1K — Optional USD/1K completion tokens

RLM loop

Phase Tools Purpose
Load rlm_scan, rlm_env_info Load path or text into session; inspect metadata
Filter rlm_peek, rlm_slice Narrow candidates (substring, glob, regex, line range)
REPL rlm_env_info, rlm_slice, rlm_transform, rlm_artifact_* Safe snippet transforms and derived artifacts
Map rlm_chunk, rlm_map_plan, rlm_map_claim, rlm_map_complete Paginated chunks; coordinated parallel workers
Reduce rlm_reduce_schema, rlm_reduce_merge Merge worker JSON; decide if recursion needed
Recurse rlm_task_create, rlm_task_list, rlm_task_result, rlm_task_reduce Sub-tasks (mock/dry-run offline; command/openai opt-in)
Observe rlm_trajectory_get, rlm_trajectory_final, rlm_budget_status Trajectory + budget/tail-cost reporting
Control rlm_budget_configure, rlm_task_cancel Session limits, fail-fast/soft-warning, cancel trees
Help rlm_workflow, rlm_tools_reference Phase guidance + full tool schema

Also: rlm_session_list, rlm_session_delete, rlm_benchmark_list, rlm_benchmark_run

Full parameter reference: docs/tools.md

Walkthrough and examples: docs/rlm-loop.md, examples/

Paper ↔ implementation map: docs/paper-mapping.md

Limitations and benchmarks: docs/limitations.md, docs/benchmarks.md

CLI (non-MCP)

Run without args to start MCP stdio server. With a subcommand, outputs JSON:

Try this offline walkthrough in PowerShell after installation. It uses synthetic text and the mock provider; no API key or paid model is required. Keep the same RLM_CACHE_DIR for all commands so separate CLI processes share the session.

$env:RLM_CACHE_DIR = Join-Path ([IO.Path]::GetTempPath()) ("rlm-demo-" + [guid]::NewGuid())
$scan = rlm-mcp scan --content "INFO ready`nERROR retry exhausted`nINFO stopped" --virtual-path demo.log --json | ConvertFrom-Json
$sessionId = $scan.session_id
rlm-mcp env-info --session-id $sessionId --json
$peek = rlm-mcp peek --session-id $sessionId --query error --regex --ignore-case --limit 3 --json | ConvertFrom-Json
$chunkId = $peek.matches[0].chunk_id
rlm-mcp chunk --session-id $sessionId --chunk-id $chunkId --json
$task = rlm-mcp task-create --session-id $sessionId --chunk-id $chunkId --prompt "Summarize the error" --provider mock --json | ConvertFrom-Json
rlm-mcp task-reduce --root-id $task.root_id --json
rlm-mcp session-delete --session-id $sessionId --json

The mock result validates the local workflow; it does not provide model reasoning. session-delete removes the persisted session and its chunk bodies. Other cache records may remain in the demo directory. An invalid regex returns an error (MCP: isError=true; CLI: nonzero exit with stderr). --ignore-case applies to both substring and regex searches.

Equivalent MCP calls: rlm_scan → rlm_env_info → rlm_peek → rlm_chunk → rlm_task_create(provider="mock") → rlm_task_reduce → rlm_session_delete. Read each returned session_id, chunk_id, and root_id before the next call.

Individual commands:

# Load directory
rlm-mcp scan --path . --json

# Load inline text
rlm-mcp scan --content "long prompt text" --virtual-path prompt.txt --json

# Filter
rlm-mcp peek --session-id <id> --query ERROR --limit 10 --json

# Map
rlm-mcp chunk --session-id <id> --chunk-id c-0 --json
rlm-mcp map-plan --session-id <id> --batch-size 3 --json

# Reduce
rlm-mcp reduce-schema --json
rlm-mcp reduce-merge --workers '[{"batch_id":"b0","findings":[]}]' --json

Docs

Doc Topic
docs/rlm-loop.md Load → filter → map → reduce loop
docs/security.md Sandbox, network, path safety
docs/extending.md Custom providers, transforms, plugins
docs/lazy-chunk-store.md Metadata session + on-disk chunk bodies
docs/embedding-roadmap.md Deferred semantic embedding peek
docs/paper-mapping.md Paper ↔ implementation mapping
examples/ Agent prompt templates and walkthroughs

Architecture

Agent (LLM plans filter/map/reduce)
    ↓ MCP stdio or CLI
rlm-mcp
    ↓ local sessions (RLM_CACHE_DIR/rlm-sessions)
External files / logs / docs / text blobs

rmcp implements the MCP transport boundary. The external-context, filter, map, reduce, recursion, provider, budget, and trajectory behavior remains this project's RLM implementation.

Related projects

Repo Role
rlm-mcp This repo — standalone RLM
cbm-mcp Optional separate graph MCP (not required)

Install troubleshooting

Symptom Fix
rlm-mcp not found in agent Use absolute path from install output; avoid bare rlm-mcp unless ~/.local/bin is on PATH
OpenCode shows no rlm-mcp connection after install Re-run .\install.ps1; then restart OpenCode or open a new session because MCP servers are loaded at session start
MCP server exits immediately Run without subcommand for stdio MCP; use rlm-mcp workflow --json to verify CLI
tools/list test fails after adding tools cargo test write_tools_snapshot -- --ignored then commit snapshot
Session not found across processes Same RLM_CACHE_DIR; use rlm-mcp session-list --json
Permission denied on cache dir Set RLM_CACHE_DIR to a writable directory
Windows build slow Default install does not build; use .\install.ps1 for release binary or .\install.ps1 -FromSource -SkipBuild after a local dev build
Windows says rlm-mcp.exe is being used by another process Re-run the current installer; it falls back to %USERPROFILE%\.config\rlm-mcp\bin\rlm-mcp-<version>.exe and updates agent config
Release smoke skipped Run cargo build --release then cargo test --test release_smoke --release

Development checks

Use a writable, dedicated RLM_CACHE_DIR for manual runs. Integration tests use temporary synthetic fixtures; the default suite does not call paid providers.

$env:RLM_CACHE_DIR = Join-Path ([IO.Path]::GetTempPath()) ("rlm-tests-" + [guid]::NewGuid())
cargo test --locked --test mcp_contract --test rmcp_protocol --test cli_contract
cargo test --locked --all-targets
cargo fmt --check
cargo clippy --locked --all-targets -- -D warnings

release_smoke reports skipped checks until a release binary exists. To exercise it fully, run cargo build --locked --release followed by cargo test --locked --release --test release_smoke. CI also runs a dependency audit and Docker build. Optional large/nightly fixtures and snapshot generation are ignored by the default suite.

Implementation roadmap

See TODO.md for the full paper-complete implementation backlog.

Current status: Paper-complete core (P0–P3); offline benchmarks: S-NIAH, OOLONG, CodeQA, BrowseComp-Plus, OOLONG-Pairs (mini in CI).

About

No description, website, or topics provided.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages